aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/cpu
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-04-30 11:42:45 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-04-30 11:42:45 -0400
commit5a5a1bf099d6942399ea0b34a62e5f0bc4c5c36e (patch)
treedf094aa1544281ec0894eee48ad60c9d000a18ba /arch/x86/kernel/cpu
parent74c7d2f5200a340ae6655e9adcf990381e387937 (diff)
parent5379f8c0d72cab43bbe6d974ceb3ad84dddc2b8e (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.c2
-rw-r--r--arch/x86/kernel/cpu/mcheck/mce_amd.c39
-rw-r--r--arch/x86/kernel/cpu/mcheck/mce_intel.c25
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
60static DEFINE_PER_CPU(struct threshold_bank * [NR_BANKS], threshold_banks); 59static DEFINE_PER_CPU(struct threshold_bank **, threshold_banks);
61
62static unsigned char shared_bank[NR_BANKS] = {
63 0, 0, 0, 0, 1
64};
65
66static DEFINE_PER_CPU(unsigned char, bank_map); /* see which banks are on */ 60static DEFINE_PER_CPU(unsigned char, bank_map); /* see which banks are on */
67 61
68static void amd_threshold_interrupt(void); 62static void amd_threshold_interrupt(void);
@@ -79,6 +73,12 @@ struct thresh_restart {
79 u16 old_limit; 73 u16 old_limit;
80}; 74};
81 75
76static 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
82static const char * const bank4_names(struct threshold_block *b) 82static 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)
635static __cpuinit int threshold_create_device(unsigned int cpu) 635static __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
288static long cmci_rediscover_work_func(void *arg) 288static 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 298void cmci_rediscover(void)
301 * Must run in process context.
302 */
303void 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/*