Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 91ede005 authored by Robert Richter's avatar Robert Richter Committed by Ingo Molnar
Browse files

x86: fix: make PCI ECS for AMD CPUs hotplug capable



Until now, PCI ECS setup was performed at boot time only and for cpus
that are enabled then. This patch fixes this and adds cpu hotplug.

Tests sequence (check if ECS bit is set when bringing cpu online again):

 # ( perl -e 'sysseek(STDIN, 0xC001001F, 0)'; hexdump -n 8 -e '2/4 "%08x " "\n"' )   < /dev/cpu/1/msr
 00000008 00404010
 # ( perl -e 'sysseek(STDOUT, 0xC001001F, 0); print pack "l*", 8, 0x00400010' ) > /dev/cpu/1/msr
 # ( perl -e 'sysseek(STDIN, 0xC001001F, 0)'; hexdump -n 8 -e '2/4 "%08x " "\n"' )   < /dev/cpu/1/msr
 00000008 00400010
 # echo 0 > /sys/devices/system/cpu/cpu1/online
 # echo 1 > /sys/devices/system/cpu/cpu1/online
 # ( perl -e 'sysseek(STDIN, 0xC001001F, 0)'; hexdump -n 8 -e '2/4 "%08x " "\n"' )   < /dev/cpu/1/msr
 00000008 00404010

Reported-by: default avatarYinghai Lu <yhlu.kernel@gmail.com>
Signed-off-by: default avatarRobert Richter <robert.richter@amd.com>
Signed-off-by: default avatarIngo Molnar <mingo@elte.hu>
parent 9b4e27b5
Loading
Loading
Loading
Loading
+31 −4
Original line number Diff line number Diff line
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/topology.h>
#include <linux/cpu.h>
#include "pci.h"

#ifdef CONFIG_X86_64
@@ -565,7 +566,7 @@ static int __init early_fill_mp_bus_info(void) { return 0; }

#define ENABLE_CF8_EXT_CFG      (1ULL << 46)

static void enable_pci_io_ecs_per_cpu(void *unused)
static void enable_pci_io_ecs(void *unused)
{
	u64 reg;
	rdmsrl(MSR_AMD64_NB_CFG, reg);
@@ -575,13 +576,39 @@ static void enable_pci_io_ecs_per_cpu(void *unused)
	}
}

static int __init enable_pci_io_ecs(void)
static int __cpuinit amd_cpu_notify(struct notifier_block *self,
				    unsigned long action, void *hcpu)
{
	int cpu = (long)hcpu;
	switch(action) {
	case CPU_ONLINE:
	case CPU_ONLINE_FROZEN:
		smp_call_function_single(cpu, enable_pci_io_ecs, NULL, 0);
		break;
	default:
		break;
	}
	return NOTIFY_OK;
}

static struct notifier_block __cpuinitdata amd_cpu_notifier = {
	.notifier_call	= amd_cpu_notify,
};

static int __init pci_io_ecs_init(void)
{
	int cpu;

	/* assume all cpus from fam10h have IO ECS */
        if (boot_cpu_data.x86 < 0x10)
		return 0;
	on_each_cpu(enable_pci_io_ecs_per_cpu, NULL, 1);

	register_cpu_notifier(&amd_cpu_notifier);
	for_each_online_cpu(cpu)
		amd_cpu_notify(&amd_cpu_notifier, (unsigned long)CPU_ONLINE,
			       (void *)(long)cpu);
	pci_probe |= PCI_HAS_IO_ECS;

	return 0;
}

@@ -591,7 +618,7 @@ static int __init amd_postcore_init(void)
		return 0;

	early_fill_mp_bus_info();
	enable_pci_io_ecs();
	pci_io_ecs_init();

	return 0;
}