diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-04-30 11:42:45 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-04-30 11:42:45 -0400 |
commit | 5a5a1bf099d6942399ea0b34a62e5f0bc4c5c36e (patch) | |
tree | df094aa1544281ec0894eee48ad60c9d000a18ba /arch/x86/kernel/cpu | |
parent | 74c7d2f5200a340ae6655e9adcf990381e387937 (diff) | |
parent | 5379f8c0d72cab43bbe6d974ceb3ad84dddc2b8e (diff) |
Merge branch 'x86-ras-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86 RAS changes from Ingo Molnar:
- Add an Intel CMCI hotplug fix
- Add AMD family 16h EDAC support
- Make the AMD MCE banks code more flexible for virtual environments
* 'x86-ras-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
amd64_edac: Add Family 16h support
x86/mce: Rework cmci_rediscover() to play well with CPU hotplug
x86, MCE, AMD: Use MCG_CAP MSR to find out number of banks on AMD
x86, MCE, AMD: Replace shared_bank array with is_shared_bank() helper
Diffstat (limited to 'arch/x86/kernel/cpu')
-rw-r--r-- | arch/x86/kernel/cpu/mcheck/mce.c | 2 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/mcheck/mce_amd.c | 39 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/mcheck/mce_intel.c | 25 |
3 files changed, 30 insertions, 36 deletions
diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c index 7bc126346ace..9239504b41cb 100644 --- a/arch/x86/kernel/cpu/mcheck/mce.c +++ b/arch/x86/kernel/cpu/mcheck/mce.c | |||
@@ -2358,7 +2358,7 @@ mce_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) | |||
2358 | 2358 | ||
2359 | if (action == CPU_POST_DEAD) { | 2359 | if (action == CPU_POST_DEAD) { |
2360 | /* intentionally ignoring frozen here */ | 2360 | /* intentionally ignoring frozen here */ |
2361 | cmci_rediscover(cpu); | 2361 | cmci_rediscover(); |
2362 | } | 2362 | } |
2363 | 2363 | ||
2364 | return NOTIFY_OK; | 2364 | return NOTIFY_OK; |
diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd.c b/arch/x86/kernel/cpu/mcheck/mce_amd.c index 1ac581f38dfa..9cb52767999a 100644 --- a/arch/x86/kernel/cpu/mcheck/mce_amd.c +++ b/arch/x86/kernel/cpu/mcheck/mce_amd.c | |||
@@ -33,7 +33,6 @@ | |||
33 | #include <asm/mce.h> | 33 | #include <asm/mce.h> |
34 | #include <asm/msr.h> | 34 | #include <asm/msr.h> |
35 | 35 | ||
36 | #define NR_BANKS 6 | ||
37 | #define NR_BLOCKS 9 | 36 | #define NR_BLOCKS 9 |
38 | #define THRESHOLD_MAX 0xFFF | 37 | #define THRESHOLD_MAX 0xFFF |
39 | #define INT_TYPE_APIC 0x00020000 | 38 | #define INT_TYPE_APIC 0x00020000 |
@@ -57,12 +56,7 @@ static const char * const th_names[] = { | |||
57 | "execution_unit", | 56 | "execution_unit", |
58 | }; | 57 | }; |
59 | 58 | ||
60 | static DEFINE_PER_CPU(struct threshold_bank * [NR_BANKS], threshold_banks); | 59 | static DEFINE_PER_CPU(struct threshold_bank **, threshold_banks); |
61 | |||
62 | static unsigned char shared_bank[NR_BANKS] = { | ||
63 | 0, 0, 0, 0, 1 | ||
64 | }; | ||
65 | |||
66 | static DEFINE_PER_CPU(unsigned char, bank_map); /* see which banks are on */ | 60 | static DEFINE_PER_CPU(unsigned char, bank_map); /* see which banks are on */ |
67 | 61 | ||
68 | static void amd_threshold_interrupt(void); | 62 | static void amd_threshold_interrupt(void); |
@@ -79,6 +73,12 @@ struct thresh_restart { | |||
79 | u16 old_limit; | 73 | u16 old_limit; |
80 | }; | 74 | }; |
81 | 75 | ||
76 | static inline bool is_shared_bank(int bank) | ||
77 | { | ||
78 | /* Bank 4 is for northbridge reporting and is thus shared */ | ||
79 | return (bank == 4); | ||
80 | } | ||
81 | |||
82 | static const char * const bank4_names(struct threshold_block *b) | 82 | static const char * const bank4_names(struct threshold_block *b) |
83 | { | 83 | { |
84 | switch (b->address) { | 84 | switch (b->address) { |
@@ -214,7 +214,7 @@ void mce_amd_feature_init(struct cpuinfo_x86 *c) | |||
214 | unsigned int bank, block; | 214 | unsigned int bank, block; |
215 | int offset = -1; | 215 | int offset = -1; |
216 | 216 | ||
217 | for (bank = 0; bank < NR_BANKS; ++bank) { | 217 | for (bank = 0; bank < mca_cfg.banks; ++bank) { |
218 | for (block = 0; block < NR_BLOCKS; ++block) { | 218 | for (block = 0; block < NR_BLOCKS; ++block) { |
219 | if (block == 0) | 219 | if (block == 0) |
220 | address = MSR_IA32_MC0_MISC + bank * 4; | 220 | address = MSR_IA32_MC0_MISC + bank * 4; |
@@ -276,7 +276,7 @@ static void amd_threshold_interrupt(void) | |||
276 | mce_setup(&m); | 276 | mce_setup(&m); |
277 | 277 | ||
278 | /* assume first bank caused it */ | 278 | /* assume first bank caused it */ |
279 | for (bank = 0; bank < NR_BANKS; ++bank) { | 279 | for (bank = 0; bank < mca_cfg.banks; ++bank) { |
280 | if (!(per_cpu(bank_map, m.cpu) & (1 << bank))) | 280 | if (!(per_cpu(bank_map, m.cpu) & (1 << bank))) |
281 | continue; | 281 | continue; |
282 | for (block = 0; block < NR_BLOCKS; ++block) { | 282 | for (block = 0; block < NR_BLOCKS; ++block) { |
@@ -467,7 +467,7 @@ static __cpuinit int allocate_threshold_blocks(unsigned int cpu, | |||
467 | u32 low, high; | 467 | u32 low, high; |
468 | int err; | 468 | int err; |
469 | 469 | ||
470 | if ((bank >= NR_BANKS) || (block >= NR_BLOCKS)) | 470 | if ((bank >= mca_cfg.banks) || (block >= NR_BLOCKS)) |
471 | return 0; | 471 | return 0; |
472 | 472 | ||
473 | if (rdmsr_safe_on_cpu(cpu, address, &low, &high)) | 473 | if (rdmsr_safe_on_cpu(cpu, address, &low, &high)) |
@@ -575,7 +575,7 @@ static __cpuinit int threshold_create_bank(unsigned int cpu, unsigned int bank) | |||
575 | const char *name = th_names[bank]; | 575 | const char *name = th_names[bank]; |
576 | int err = 0; | 576 | int err = 0; |
577 | 577 | ||
578 | if (shared_bank[bank]) { | 578 | if (is_shared_bank(bank)) { |
579 | nb = node_to_amd_nb(amd_get_nb_id(cpu)); | 579 | nb = node_to_amd_nb(amd_get_nb_id(cpu)); |
580 | 580 | ||
581 | /* threshold descriptor already initialized on this node? */ | 581 | /* threshold descriptor already initialized on this node? */ |
@@ -609,7 +609,7 @@ static __cpuinit int threshold_create_bank(unsigned int cpu, unsigned int bank) | |||
609 | 609 | ||
610 | per_cpu(threshold_banks, cpu)[bank] = b; | 610 | per_cpu(threshold_banks, cpu)[bank] = b; |
611 | 611 | ||
612 | if (shared_bank[bank]) { | 612 | if (is_shared_bank(bank)) { |
613 | atomic_set(&b->cpus, 1); | 613 | atomic_set(&b->cpus, 1); |
614 | 614 | ||
615 | /* nb is already initialized, see above */ | 615 | /* nb is already initialized, see above */ |
@@ -635,9 +635,17 @@ static __cpuinit int threshold_create_bank(unsigned int cpu, unsigned int bank) | |||
635 | static __cpuinit int threshold_create_device(unsigned int cpu) | 635 | static __cpuinit int threshold_create_device(unsigned int cpu) |
636 | { | 636 | { |
637 | unsigned int bank; | 637 | unsigned int bank; |
638 | struct threshold_bank **bp; | ||
638 | int err = 0; | 639 | int err = 0; |
639 | 640 | ||
640 | for (bank = 0; bank < NR_BANKS; ++bank) { | 641 | bp = kzalloc(sizeof(struct threshold_bank *) * mca_cfg.banks, |
642 | GFP_KERNEL); | ||
643 | if (!bp) | ||
644 | return -ENOMEM; | ||
645 | |||
646 | per_cpu(threshold_banks, cpu) = bp; | ||
647 | |||
648 | for (bank = 0; bank < mca_cfg.banks; ++bank) { | ||
641 | if (!(per_cpu(bank_map, cpu) & (1 << bank))) | 649 | if (!(per_cpu(bank_map, cpu) & (1 << bank))) |
642 | continue; | 650 | continue; |
643 | err = threshold_create_bank(cpu, bank); | 651 | err = threshold_create_bank(cpu, bank); |
@@ -691,7 +699,7 @@ static void threshold_remove_bank(unsigned int cpu, int bank) | |||
691 | if (!b->blocks) | 699 | if (!b->blocks) |
692 | goto free_out; | 700 | goto free_out; |
693 | 701 | ||
694 | if (shared_bank[bank]) { | 702 | if (is_shared_bank(bank)) { |
695 | if (!atomic_dec_and_test(&b->cpus)) { | 703 | if (!atomic_dec_and_test(&b->cpus)) { |
696 | __threshold_remove_blocks(b); | 704 | __threshold_remove_blocks(b); |
697 | per_cpu(threshold_banks, cpu)[bank] = NULL; | 705 | per_cpu(threshold_banks, cpu)[bank] = NULL; |
@@ -719,11 +727,12 @@ static void threshold_remove_device(unsigned int cpu) | |||
719 | { | 727 | { |
720 | unsigned int bank; | 728 | unsigned int bank; |
721 | 729 | ||
722 | for (bank = 0; bank < NR_BANKS; ++bank) { | 730 | for (bank = 0; bank < mca_cfg.banks; ++bank) { |
723 | if (!(per_cpu(bank_map, cpu) & (1 << bank))) | 731 | if (!(per_cpu(bank_map, cpu) & (1 << bank))) |
724 | continue; | 732 | continue; |
725 | threshold_remove_bank(cpu, bank); | 733 | threshold_remove_bank(cpu, bank); |
726 | } | 734 | } |
735 | kfree(per_cpu(threshold_banks, cpu)); | ||
727 | } | 736 | } |
728 | 737 | ||
729 | /* get notified when a cpu comes on/off */ | 738 | /* get notified when a cpu comes on/off */ |
diff --git a/arch/x86/kernel/cpu/mcheck/mce_intel.c b/arch/x86/kernel/cpu/mcheck/mce_intel.c index 402c454fbff0..ae1697c2afe3 100644 --- a/arch/x86/kernel/cpu/mcheck/mce_intel.c +++ b/arch/x86/kernel/cpu/mcheck/mce_intel.c | |||
@@ -285,39 +285,24 @@ void cmci_clear(void) | |||
285 | raw_spin_unlock_irqrestore(&cmci_discover_lock, flags); | 285 | raw_spin_unlock_irqrestore(&cmci_discover_lock, flags); |
286 | } | 286 | } |
287 | 287 | ||
288 | static long cmci_rediscover_work_func(void *arg) | 288 | static void cmci_rediscover_work_func(void *arg) |
289 | { | 289 | { |
290 | int banks; | 290 | int banks; |
291 | 291 | ||
292 | /* Recheck banks in case CPUs don't all have the same */ | 292 | /* Recheck banks in case CPUs don't all have the same */ |
293 | if (cmci_supported(&banks)) | 293 | if (cmci_supported(&banks)) |
294 | cmci_discover(banks); | 294 | cmci_discover(banks); |
295 | |||
296 | return 0; | ||
297 | } | 295 | } |
298 | 296 | ||
299 | /* | 297 | /* After a CPU went down cycle through all the others and rediscover */ |
300 | * After a CPU went down cycle through all the others and rediscover | 298 | void cmci_rediscover(void) |
301 | * Must run in process context. | ||
302 | */ | ||
303 | void cmci_rediscover(int dying) | ||
304 | { | 299 | { |
305 | int cpu, banks; | 300 | int banks; |
306 | 301 | ||
307 | if (!cmci_supported(&banks)) | 302 | if (!cmci_supported(&banks)) |
308 | return; | 303 | return; |
309 | 304 | ||
310 | for_each_online_cpu(cpu) { | 305 | on_each_cpu(cmci_rediscover_work_func, NULL, 1); |
311 | if (cpu == dying) | ||
312 | continue; | ||
313 | |||
314 | if (cpu == smp_processor_id()) { | ||
315 | cmci_rediscover_work_func(NULL); | ||
316 | continue; | ||
317 | } | ||
318 | |||
319 | work_on_cpu(cpu, cmci_rediscover_work_func, NULL); | ||
320 | } | ||
321 | } | 306 | } |
322 | 307 | ||
323 | /* | 308 | /* |