diff options
| -rw-r--r-- | arch/x86/kernel/cpu/mcheck/mce_64.c | 5 | ||||
| -rw-r--r-- | arch/x86/kernel/cpu/mcheck/mce_amd_64.c | 18 | ||||
| -rw-r--r-- | arch/x86/kernel/tsc.c | 6 | ||||
| -rw-r--r-- | arch/x86/pci/amd_bus.c | 52 | ||||
| -rw-r--r-- | arch/x86/pci/i386.c | 78 | ||||
| -rw-r--r-- | include/asm-x86/cpufeature.h | 2 | ||||
| -rw-r--r-- | include/asm-x86/mce.h | 1 |
7 files changed, 142 insertions, 20 deletions
diff --git a/arch/x86/kernel/cpu/mcheck/mce_64.c b/arch/x86/kernel/cpu/mcheck/mce_64.c index 65a339678ece..726a5fcdf341 100644 --- a/arch/x86/kernel/cpu/mcheck/mce_64.c +++ b/arch/x86/kernel/cpu/mcheck/mce_64.c | |||
| @@ -759,6 +759,7 @@ static struct sysdev_class mce_sysclass = { | |||
| 759 | }; | 759 | }; |
| 760 | 760 | ||
| 761 | DEFINE_PER_CPU(struct sys_device, device_mce); | 761 | DEFINE_PER_CPU(struct sys_device, device_mce); |
| 762 | void (*threshold_cpu_callback)(unsigned long action, unsigned int cpu) __cpuinitdata; | ||
| 762 | 763 | ||
| 763 | /* Why are there no generic functions for this? */ | 764 | /* Why are there no generic functions for this? */ |
| 764 | #define ACCESSOR(name, var, start) \ | 765 | #define ACCESSOR(name, var, start) \ |
| @@ -883,9 +884,13 @@ static int __cpuinit mce_cpu_callback(struct notifier_block *nfb, | |||
| 883 | case CPU_ONLINE: | 884 | case CPU_ONLINE: |
| 884 | case CPU_ONLINE_FROZEN: | 885 | case CPU_ONLINE_FROZEN: |
| 885 | mce_create_device(cpu); | 886 | mce_create_device(cpu); |
| 887 | if (threshold_cpu_callback) | ||
| 888 | threshold_cpu_callback(action, cpu); | ||
| 886 | break; | 889 | break; |
| 887 | case CPU_DEAD: | 890 | case CPU_DEAD: |
| 888 | case CPU_DEAD_FROZEN: | 891 | case CPU_DEAD_FROZEN: |
| 892 | if (threshold_cpu_callback) | ||
| 893 | threshold_cpu_callback(action, cpu); | ||
| 889 | mce_remove_device(cpu); | 894 | mce_remove_device(cpu); |
| 890 | break; | 895 | break; |
| 891 | } | 896 | } |
diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd_64.c b/arch/x86/kernel/cpu/mcheck/mce_amd_64.c index 88736cadbaa6..5eb390a4b2e9 100644 --- a/arch/x86/kernel/cpu/mcheck/mce_amd_64.c +++ b/arch/x86/kernel/cpu/mcheck/mce_amd_64.c | |||
| @@ -628,6 +628,7 @@ static void threshold_remove_bank(unsigned int cpu, int bank) | |||
| 628 | deallocate_threshold_block(cpu, bank); | 628 | deallocate_threshold_block(cpu, bank); |
| 629 | 629 | ||
| 630 | free_out: | 630 | free_out: |
| 631 | kobject_del(b->kobj); | ||
| 631 | kobject_put(b->kobj); | 632 | kobject_put(b->kobj); |
| 632 | kfree(b); | 633 | kfree(b); |
| 633 | per_cpu(threshold_banks, cpu)[bank] = NULL; | 634 | per_cpu(threshold_banks, cpu)[bank] = NULL; |
| @@ -645,14 +646,11 @@ static void threshold_remove_device(unsigned int cpu) | |||
| 645 | } | 646 | } |
| 646 | 647 | ||
| 647 | /* get notified when a cpu comes on/off */ | 648 | /* get notified when a cpu comes on/off */ |
| 648 | static int __cpuinit threshold_cpu_callback(struct notifier_block *nfb, | 649 | static void __cpuinit amd_64_threshold_cpu_callback(unsigned long action, |
| 649 | unsigned long action, void *hcpu) | 650 | unsigned int cpu) |
| 650 | { | 651 | { |
| 651 | /* cpu was unsigned int to begin with */ | ||
| 652 | unsigned int cpu = (unsigned long)hcpu; | ||
| 653 | |||
| 654 | if (cpu >= NR_CPUS) | 652 | if (cpu >= NR_CPUS) |
| 655 | goto out; | 653 | return; |
| 656 | 654 | ||
| 657 | switch (action) { | 655 | switch (action) { |
| 658 | case CPU_ONLINE: | 656 | case CPU_ONLINE: |
| @@ -666,14 +664,8 @@ static int __cpuinit threshold_cpu_callback(struct notifier_block *nfb, | |||
| 666 | default: | 664 | default: |
| 667 | break; | 665 | break; |
| 668 | } | 666 | } |
| 669 | out: | ||
| 670 | return NOTIFY_OK; | ||
| 671 | } | 667 | } |
| 672 | 668 | ||
| 673 | static struct notifier_block threshold_cpu_notifier __cpuinitdata = { | ||
| 674 | .notifier_call = threshold_cpu_callback, | ||
| 675 | }; | ||
| 676 | |||
| 677 | static __init int threshold_init_device(void) | 669 | static __init int threshold_init_device(void) |
| 678 | { | 670 | { |
| 679 | unsigned lcpu = 0; | 671 | unsigned lcpu = 0; |
| @@ -684,7 +676,7 @@ static __init int threshold_init_device(void) | |||
| 684 | if (err) | 676 | if (err) |
| 685 | return err; | 677 | return err; |
| 686 | } | 678 | } |
| 687 | register_hotcpu_notifier(&threshold_cpu_notifier); | 679 | threshold_cpu_callback = amd_64_threshold_cpu_callback; |
| 688 | return 0; | 680 | return 0; |
| 689 | } | 681 | } |
| 690 | 682 | ||
diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c index 46af71676738..8e786b0d665a 100644 --- a/arch/x86/kernel/tsc.c +++ b/arch/x86/kernel/tsc.c | |||
| @@ -314,7 +314,7 @@ static int time_cpufreq_notifier(struct notifier_block *nb, unsigned long val, | |||
| 314 | mark_tsc_unstable("cpufreq changes"); | 314 | mark_tsc_unstable("cpufreq changes"); |
| 315 | } | 315 | } |
| 316 | 316 | ||
| 317 | set_cyc2ns_scale(tsc_khz_ref, freq->cpu); | 317 | set_cyc2ns_scale(tsc_khz, freq->cpu); |
| 318 | 318 | ||
| 319 | return 0; | 319 | return 0; |
| 320 | } | 320 | } |
| @@ -325,6 +325,10 @@ static struct notifier_block time_cpufreq_notifier_block = { | |||
| 325 | 325 | ||
| 326 | static int __init cpufreq_tsc(void) | 326 | static int __init cpufreq_tsc(void) |
| 327 | { | 327 | { |
| 328 | if (!cpu_has_tsc) | ||
| 329 | return 0; | ||
| 330 | if (boot_cpu_has(X86_FEATURE_CONSTANT_TSC)) | ||
| 331 | return 0; | ||
| 328 | cpufreq_register_notifier(&time_cpufreq_notifier_block, | 332 | cpufreq_register_notifier(&time_cpufreq_notifier_block, |
| 329 | CPUFREQ_TRANSITION_NOTIFIER); | 333 | CPUFREQ_TRANSITION_NOTIFIER); |
| 330 | return 0; | 334 | return 0; |
diff --git a/arch/x86/pci/amd_bus.c b/arch/x86/pci/amd_bus.c index dbf532369711..6a0fca78c362 100644 --- a/arch/x86/pci/amd_bus.c +++ b/arch/x86/pci/amd_bus.c | |||
| @@ -1,6 +1,7 @@ | |||
| 1 | #include <linux/init.h> | 1 | #include <linux/init.h> |
| 2 | #include <linux/pci.h> | 2 | #include <linux/pci.h> |
| 3 | #include <linux/topology.h> | 3 | #include <linux/topology.h> |
| 4 | #include <linux/cpu.h> | ||
| 4 | #include "pci.h" | 5 | #include "pci.h" |
| 5 | 6 | ||
| 6 | #ifdef CONFIG_X86_64 | 7 | #ifdef CONFIG_X86_64 |
| @@ -555,15 +556,17 @@ static int __init early_fill_mp_bus_info(void) | |||
| 555 | return 0; | 556 | return 0; |
| 556 | } | 557 | } |
| 557 | 558 | ||
| 558 | postcore_initcall(early_fill_mp_bus_info); | 559 | #else /* !CONFIG_X86_64 */ |
| 559 | 560 | ||
| 560 | #endif | 561 | static int __init early_fill_mp_bus_info(void) { return 0; } |
| 562 | |||
| 563 | #endif /* !CONFIG_X86_64 */ | ||
| 561 | 564 | ||
| 562 | /* common 32/64 bit code */ | 565 | /* common 32/64 bit code */ |
| 563 | 566 | ||
| 564 | #define ENABLE_CF8_EXT_CFG (1ULL << 46) | 567 | #define ENABLE_CF8_EXT_CFG (1ULL << 46) |
| 565 | 568 | ||
| 566 | static void enable_pci_io_ecs_per_cpu(void *unused) | 569 | static void enable_pci_io_ecs(void *unused) |
| 567 | { | 570 | { |
| 568 | u64 reg; | 571 | u64 reg; |
| 569 | rdmsrl(MSR_AMD64_NB_CFG, reg); | 572 | rdmsrl(MSR_AMD64_NB_CFG, reg); |
| @@ -573,14 +576,51 @@ static void enable_pci_io_ecs_per_cpu(void *unused) | |||
| 573 | } | 576 | } |
| 574 | } | 577 | } |
| 575 | 578 | ||
| 576 | static int __init enable_pci_io_ecs(void) | 579 | static int __cpuinit amd_cpu_notify(struct notifier_block *self, |
| 580 | unsigned long action, void *hcpu) | ||
| 577 | { | 581 | { |
| 582 | int cpu = (long)hcpu; | ||
| 583 | switch(action) { | ||
| 584 | case CPU_ONLINE: | ||
| 585 | case CPU_ONLINE_FROZEN: | ||
| 586 | smp_call_function_single(cpu, enable_pci_io_ecs, NULL, 0); | ||
| 587 | break; | ||
| 588 | default: | ||
| 589 | break; | ||
| 590 | } | ||
| 591 | return NOTIFY_OK; | ||
| 592 | } | ||
| 593 | |||
| 594 | static struct notifier_block __cpuinitdata amd_cpu_notifier = { | ||
| 595 | .notifier_call = amd_cpu_notify, | ||
| 596 | }; | ||
| 597 | |||
| 598 | static int __init pci_io_ecs_init(void) | ||
| 599 | { | ||
| 600 | int cpu; | ||
| 601 | |||
| 578 | /* assume all cpus from fam10h have IO ECS */ | 602 | /* assume all cpus from fam10h have IO ECS */ |
| 579 | if (boot_cpu_data.x86 < 0x10) | 603 | if (boot_cpu_data.x86 < 0x10) |
| 580 | return 0; | 604 | return 0; |
| 581 | on_each_cpu(enable_pci_io_ecs_per_cpu, NULL, 1); | 605 | |
| 606 | register_cpu_notifier(&amd_cpu_notifier); | ||
| 607 | for_each_online_cpu(cpu) | ||
| 608 | amd_cpu_notify(&amd_cpu_notifier, (unsigned long)CPU_ONLINE, | ||
| 609 | (void *)(long)cpu); | ||
| 582 | pci_probe |= PCI_HAS_IO_ECS; | 610 | pci_probe |= PCI_HAS_IO_ECS; |
| 611 | |||
| 612 | return 0; | ||
| 613 | } | ||
| 614 | |||
| 615 | static int __init amd_postcore_init(void) | ||
| 616 | { | ||
| 617 | if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD) | ||
| 618 | return 0; | ||
| 619 | |||
| 620 | early_fill_mp_bus_info(); | ||
| 621 | pci_io_ecs_init(); | ||
| 622 | |||
| 583 | return 0; | 623 | return 0; |
| 584 | } | 624 | } |
| 585 | 625 | ||
| 586 | postcore_initcall(enable_pci_io_ecs); | 626 | postcore_initcall(amd_postcore_init); |
diff --git a/arch/x86/pci/i386.c b/arch/x86/pci/i386.c index 5807d1bc73f7..d765da913842 100644 --- a/arch/x86/pci/i386.c +++ b/arch/x86/pci/i386.c | |||
| @@ -31,8 +31,11 @@ | |||
| 31 | #include <linux/ioport.h> | 31 | #include <linux/ioport.h> |
| 32 | #include <linux/errno.h> | 32 | #include <linux/errno.h> |
| 33 | #include <linux/bootmem.h> | 33 | #include <linux/bootmem.h> |
| 34 | #include <linux/acpi.h> | ||
| 34 | 35 | ||
| 35 | #include <asm/pat.h> | 36 | #include <asm/pat.h> |
| 37 | #include <asm/hpet.h> | ||
| 38 | #include <asm/io_apic.h> | ||
| 36 | 39 | ||
| 37 | #include "pci.h" | 40 | #include "pci.h" |
| 38 | 41 | ||
| @@ -77,6 +80,77 @@ pcibios_align_resource(void *data, struct resource *res, | |||
| 77 | } | 80 | } |
| 78 | EXPORT_SYMBOL(pcibios_align_resource); | 81 | EXPORT_SYMBOL(pcibios_align_resource); |
| 79 | 82 | ||
| 83 | static int check_res_with_valid(struct pci_dev *dev, struct resource *res) | ||
| 84 | { | ||
| 85 | unsigned long base; | ||
| 86 | unsigned long size; | ||
| 87 | int i; | ||
| 88 | |||
| 89 | base = res->start; | ||
| 90 | size = (res->start == 0 && res->end == res->start) ? 0 : | ||
| 91 | (res->end - res->start + 1); | ||
| 92 | |||
| 93 | if (!base || !size) | ||
| 94 | return 0; | ||
| 95 | |||
| 96 | #ifdef CONFIG_HPET_TIMER | ||
| 97 | /* for hpet */ | ||
| 98 | if (base == hpet_address && (res->flags & IORESOURCE_MEM)) { | ||
| 99 | dev_info(&dev->dev, "BAR has HPET at %08lx-%08lx\n", | ||
| 100 | base, base + size - 1); | ||
| 101 | return 1; | ||
| 102 | } | ||
| 103 | #endif | ||
| 104 | |||
| 105 | #ifdef CONFIG_X86_IO_APIC | ||
| 106 | for (i = 0; i < nr_ioapics; i++) { | ||
| 107 | unsigned long ioapic_phys = mp_ioapics[i].mp_apicaddr; | ||
| 108 | |||
| 109 | if (base == ioapic_phys && (res->flags & IORESOURCE_MEM)) { | ||
| 110 | dev_info(&dev->dev, "BAR has ioapic at %08lx-%08lx\n", | ||
| 111 | base, base + size - 1); | ||
| 112 | return 1; | ||
| 113 | } | ||
| 114 | } | ||
| 115 | #endif | ||
| 116 | |||
| 117 | #ifdef CONFIG_PCI_MMCONFIG | ||
| 118 | for (i = 0; i < pci_mmcfg_config_num; i++) { | ||
| 119 | unsigned long addr; | ||
| 120 | |||
| 121 | addr = pci_mmcfg_config[i].address; | ||
| 122 | if (base == addr && (res->flags & IORESOURCE_MEM)) { | ||
| 123 | dev_info(&dev->dev, "BAR has MMCONFIG at %08lx-%08lx\n", | ||
| 124 | base, base + size - 1); | ||
| 125 | return 1; | ||
| 126 | } | ||
| 127 | } | ||
| 128 | #endif | ||
| 129 | |||
| 130 | return 0; | ||
| 131 | } | ||
| 132 | |||
| 133 | static int check_platform(struct pci_dev *dev, struct resource *res) | ||
| 134 | { | ||
| 135 | struct resource *root = NULL; | ||
| 136 | |||
| 137 | /* | ||
| 138 | * forcibly insert it into the | ||
| 139 | * resource tree | ||
| 140 | */ | ||
| 141 | if (res->flags & IORESOURCE_MEM) | ||
| 142 | root = &iomem_resource; | ||
| 143 | else if (res->flags & IORESOURCE_IO) | ||
| 144 | root = &ioport_resource; | ||
| 145 | |||
| 146 | if (root && check_res_with_valid(dev, res)) { | ||
| 147 | insert_resource(root, res); | ||
| 148 | |||
| 149 | return 1; | ||
| 150 | } | ||
| 151 | |||
| 152 | return 0; | ||
| 153 | } | ||
| 80 | /* | 154 | /* |
| 81 | * Handle resources of PCI devices. If the world were perfect, we could | 155 | * Handle resources of PCI devices. If the world were perfect, we could |
| 82 | * just allocate all the resource regions and do nothing more. It isn't. | 156 | * just allocate all the resource regions and do nothing more. It isn't. |
| @@ -128,6 +202,8 @@ static void __init pcibios_allocate_bus_resources(struct list_head *bus_list) | |||
| 128 | pr = pci_find_parent_resource(dev, r); | 202 | pr = pci_find_parent_resource(dev, r); |
| 129 | if (!r->start || !pr || | 203 | if (!r->start || !pr || |
| 130 | request_resource(pr, r) < 0) { | 204 | request_resource(pr, r) < 0) { |
| 205 | if (check_platform(dev, r)) | ||
| 206 | continue; | ||
| 131 | dev_err(&dev->dev, "BAR %d: can't " | 207 | dev_err(&dev->dev, "BAR %d: can't " |
| 132 | "allocate resource\n", idx); | 208 | "allocate resource\n", idx); |
| 133 | /* | 209 | /* |
| @@ -171,6 +247,8 @@ static void __init pcibios_allocate_resources(int pass) | |||
| 171 | r->flags, disabled, pass); | 247 | r->flags, disabled, pass); |
| 172 | pr = pci_find_parent_resource(dev, r); | 248 | pr = pci_find_parent_resource(dev, r); |
| 173 | if (!pr || request_resource(pr, r) < 0) { | 249 | if (!pr || request_resource(pr, r) < 0) { |
| 250 | if (check_platform(dev, r)) | ||
| 251 | continue; | ||
| 174 | dev_err(&dev->dev, "BAR %d: can't " | 252 | dev_err(&dev->dev, "BAR %d: can't " |
| 175 | "allocate resource\n", idx); | 253 | "allocate resource\n", idx); |
| 176 | /* We'll assign a new address later */ | 254 | /* We'll assign a new address later */ |
diff --git a/include/asm-x86/cpufeature.h b/include/asm-x86/cpufeature.h index 2f5a792b0acc..762f6a6bc707 100644 --- a/include/asm-x86/cpufeature.h +++ b/include/asm-x86/cpufeature.h | |||
| @@ -91,6 +91,7 @@ | |||
| 91 | #define X86_FEATURE_CX16 (4*32+13) /* CMPXCHG16B */ | 91 | #define X86_FEATURE_CX16 (4*32+13) /* CMPXCHG16B */ |
| 92 | #define X86_FEATURE_XTPR (4*32+14) /* Send Task Priority Messages */ | 92 | #define X86_FEATURE_XTPR (4*32+14) /* Send Task Priority Messages */ |
| 93 | #define X86_FEATURE_DCA (4*32+18) /* Direct Cache Access */ | 93 | #define X86_FEATURE_DCA (4*32+18) /* Direct Cache Access */ |
| 94 | #define X86_FEATURE_XMM4_2 (4*32+20) /* Streaming SIMD Extensions-4.2 */ | ||
| 94 | 95 | ||
| 95 | /* VIA/Cyrix/Centaur-defined CPU features, CPUID level 0xC0000001, word 5 */ | 96 | /* VIA/Cyrix/Centaur-defined CPU features, CPUID level 0xC0000001, word 5 */ |
| 96 | #define X86_FEATURE_XSTORE (5*32+ 2) /* on-CPU RNG present (xstore insn) */ | 97 | #define X86_FEATURE_XSTORE (5*32+ 2) /* on-CPU RNG present (xstore insn) */ |
| @@ -189,6 +190,7 @@ extern const char * const x86_power_flags[32]; | |||
| 189 | #define cpu_has_gbpages boot_cpu_has(X86_FEATURE_GBPAGES) | 190 | #define cpu_has_gbpages boot_cpu_has(X86_FEATURE_GBPAGES) |
| 190 | #define cpu_has_arch_perfmon boot_cpu_has(X86_FEATURE_ARCH_PERFMON) | 191 | #define cpu_has_arch_perfmon boot_cpu_has(X86_FEATURE_ARCH_PERFMON) |
| 191 | #define cpu_has_pat boot_cpu_has(X86_FEATURE_PAT) | 192 | #define cpu_has_pat boot_cpu_has(X86_FEATURE_PAT) |
| 193 | #define cpu_has_xmm4_2 boot_cpu_has(X86_FEATURE_XMM4_2) | ||
| 192 | 194 | ||
| 193 | #if defined(CONFIG_X86_INVLPG) || defined(CONFIG_X86_64) | 195 | #if defined(CONFIG_X86_INVLPG) || defined(CONFIG_X86_64) |
| 194 | # define cpu_has_invlpg 1 | 196 | # define cpu_has_invlpg 1 |
diff --git a/include/asm-x86/mce.h b/include/asm-x86/mce.h index 94f1fd79e22a..531eaa587455 100644 --- a/include/asm-x86/mce.h +++ b/include/asm-x86/mce.h | |||
| @@ -92,6 +92,7 @@ extern int mce_disabled; | |||
| 92 | 92 | ||
| 93 | void mce_log(struct mce *m); | 93 | void mce_log(struct mce *m); |
| 94 | DECLARE_PER_CPU(struct sys_device, device_mce); | 94 | DECLARE_PER_CPU(struct sys_device, device_mce); |
| 95 | extern void (*threshold_cpu_callback)(unsigned long action, unsigned int cpu); | ||
| 95 | 96 | ||
| 96 | #ifdef CONFIG_X86_MCE_INTEL | 97 | #ifdef CONFIG_X86_MCE_INTEL |
| 97 | void mce_intel_feature_init(struct cpuinfo_x86 *c); | 98 | void mce_intel_feature_init(struct cpuinfo_x86 *c); |
