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: Yinghai Lu <yhlu.kernel@gmail.com>
Signed-off-by: Robert Richter <robert.richter@amd.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>

authored by Robert Richter and committed by Ingo Molnar 91ede005 9b4e27b5

+31 -4
+31 -4
arch/x86/pci/amd_bus.c
··· 1 1 #include <linux/init.h> 2 2 #include <linux/pci.h> 3 3 #include <linux/topology.h> 4 + #include <linux/cpu.h> 4 5 #include "pci.h" 5 6 6 7 #ifdef CONFIG_X86_64 ··· 566 565 567 566 #define ENABLE_CF8_EXT_CFG (1ULL << 46) 568 567 569 - static void enable_pci_io_ecs_per_cpu(void *unused) 568 + static void enable_pci_io_ecs(void *unused) 570 569 { 571 570 u64 reg; 572 571 rdmsrl(MSR_AMD64_NB_CFG, reg); ··· 576 575 } 577 576 } 578 577 579 - static int __init enable_pci_io_ecs(void) 578 + static int __cpuinit amd_cpu_notify(struct notifier_block *self, 579 + unsigned long action, void *hcpu) 580 580 { 581 + int cpu = (long)hcpu; 582 + switch(action) { 583 + case CPU_ONLINE: 584 + case CPU_ONLINE_FROZEN: 585 + smp_call_function_single(cpu, enable_pci_io_ecs, NULL, 0); 586 + break; 587 + default: 588 + break; 589 + } 590 + return NOTIFY_OK; 591 + } 592 + 593 + static struct notifier_block __cpuinitdata amd_cpu_notifier = { 594 + .notifier_call = amd_cpu_notify, 595 + }; 596 + 597 + static int __init pci_io_ecs_init(void) 598 + { 599 + int cpu; 600 + 581 601 /* assume all cpus from fam10h have IO ECS */ 582 602 if (boot_cpu_data.x86 < 0x10) 583 603 return 0; 584 - on_each_cpu(enable_pci_io_ecs_per_cpu, NULL, 1); 604 + 605 + register_cpu_notifier(&amd_cpu_notifier); 606 + for_each_online_cpu(cpu) 607 + amd_cpu_notify(&amd_cpu_notifier, (unsigned long)CPU_ONLINE, 608 + (void *)(long)cpu); 585 609 pci_probe |= PCI_HAS_IO_ECS; 610 + 586 611 return 0; 587 612 } 588 613 ··· 618 591 return 0; 619 592 620 593 early_fill_mp_bus_info(); 621 - enable_pci_io_ecs(); 594 + pci_io_ecs_init(); 622 595 623 596 return 0; 624 597 }