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 #include <linux/init.h> 2 #include <linux/pci.h> 3 #include <linux/topology.h> 4 #include "pci.h" 5 6 #ifdef CONFIG_X86_64 ··· 566 567 #define ENABLE_CF8_EXT_CFG (1ULL << 46) 568 569 - static void enable_pci_io_ecs_per_cpu(void *unused) 570 { 571 u64 reg; 572 rdmsrl(MSR_AMD64_NB_CFG, reg); ··· 576 } 577 } 578 579 - static int __init enable_pci_io_ecs(void) 580 { 581 /* assume all cpus from fam10h have IO ECS */ 582 if (boot_cpu_data.x86 < 0x10) 583 return 0; 584 - on_each_cpu(enable_pci_io_ecs_per_cpu, NULL, 1); 585 pci_probe |= PCI_HAS_IO_ECS; 586 return 0; 587 } 588 ··· 618 return 0; 619 620 early_fill_mp_bus_info(); 621 - enable_pci_io_ecs(); 622 623 return 0; 624 }
··· 1 #include <linux/init.h> 2 #include <linux/pci.h> 3 #include <linux/topology.h> 4 + #include <linux/cpu.h> 5 #include "pci.h" 6 7 #ifdef CONFIG_X86_64 ··· 565 566 #define ENABLE_CF8_EXT_CFG (1ULL << 46) 567 568 + static void enable_pci_io_ecs(void *unused) 569 { 570 u64 reg; 571 rdmsrl(MSR_AMD64_NB_CFG, reg); ··· 575 } 576 } 577 578 + static int __cpuinit amd_cpu_notify(struct notifier_block *self, 579 + unsigned long action, void *hcpu) 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 + 601 /* assume all cpus from fam10h have IO ECS */ 602 if (boot_cpu_data.x86 < 0x10) 603 return 0; 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); 609 pci_probe |= PCI_HAS_IO_ECS; 610 + 611 return 0; 612 } 613 ··· 591 return 0; 592 593 early_fill_mp_bus_info(); 594 + pci_io_ecs_init(); 595 596 return 0; 597 }