diff options
Diffstat (limited to 'arch/x86/kernel/cpu/mcheck/mce_amd_64.c')
-rw-r--r-- | arch/x86/kernel/cpu/mcheck/mce_amd_64.c | 43 |
1 files changed, 23 insertions, 20 deletions
diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd_64.c b/arch/x86/kernel/cpu/mcheck/mce_amd_64.c index f2ee0ae29bd..c5a32f92d07 100644 --- a/arch/x86/kernel/cpu/mcheck/mce_amd_64.c +++ b/arch/x86/kernel/cpu/mcheck/mce_amd_64.c | |||
@@ -67,7 +67,7 @@ static struct threshold_block threshold_defaults = { | |||
67 | struct threshold_bank { | 67 | struct threshold_bank { |
68 | struct kobject *kobj; | 68 | struct kobject *kobj; |
69 | struct threshold_block *blocks; | 69 | struct threshold_block *blocks; |
70 | cpumask_t cpus; | 70 | cpumask_var_t cpus; |
71 | }; | 71 | }; |
72 | static DEFINE_PER_CPU(struct threshold_bank *, threshold_banks[NR_BANKS]); | 72 | static DEFINE_PER_CPU(struct threshold_bank *, threshold_banks[NR_BANKS]); |
73 | 73 | ||
@@ -79,6 +79,8 @@ static unsigned char shared_bank[NR_BANKS] = { | |||
79 | 79 | ||
80 | static DEFINE_PER_CPU(unsigned char, bank_map); /* see which banks are on */ | 80 | static DEFINE_PER_CPU(unsigned char, bank_map); /* see which banks are on */ |
81 | 81 | ||
82 | static void amd_threshold_interrupt(void); | ||
83 | |||
82 | /* | 84 | /* |
83 | * CPU Initialization | 85 | * CPU Initialization |
84 | */ | 86 | */ |
@@ -174,6 +176,8 @@ void mce_amd_feature_init(struct cpuinfo_x86 *c) | |||
174 | tr.reset = 0; | 176 | tr.reset = 0; |
175 | tr.old_limit = 0; | 177 | tr.old_limit = 0; |
176 | threshold_restart_bank(&tr); | 178 | threshold_restart_bank(&tr); |
179 | |||
180 | mce_threshold_vector = amd_threshold_interrupt; | ||
177 | } | 181 | } |
178 | } | 182 | } |
179 | } | 183 | } |
@@ -187,19 +191,13 @@ void mce_amd_feature_init(struct cpuinfo_x86 *c) | |||
187 | * the interrupt goes off when error_count reaches threshold_limit. | 191 | * the interrupt goes off when error_count reaches threshold_limit. |
188 | * the handler will simply log mcelog w/ software defined bank number. | 192 | * the handler will simply log mcelog w/ software defined bank number. |
189 | */ | 193 | */ |
190 | asmlinkage void mce_threshold_interrupt(void) | 194 | static void amd_threshold_interrupt(void) |
191 | { | 195 | { |
192 | unsigned int bank, block; | 196 | unsigned int bank, block; |
193 | struct mce m; | 197 | struct mce m; |
194 | u32 low = 0, high = 0, address = 0; | 198 | u32 low = 0, high = 0, address = 0; |
195 | 199 | ||
196 | ack_APIC_irq(); | 200 | mce_setup(&m); |
197 | exit_idle(); | ||
198 | irq_enter(); | ||
199 | |||
200 | memset(&m, 0, sizeof(m)); | ||
201 | rdtscll(m.tsc); | ||
202 | m.cpu = smp_processor_id(); | ||
203 | 201 | ||
204 | /* assume first bank caused it */ | 202 | /* assume first bank caused it */ |
205 | for (bank = 0; bank < NR_BANKS; ++bank) { | 203 | for (bank = 0; bank < NR_BANKS; ++bank) { |
@@ -233,7 +231,8 @@ asmlinkage void mce_threshold_interrupt(void) | |||
233 | 231 | ||
234 | /* Log the machine check that caused the threshold | 232 | /* Log the machine check that caused the threshold |
235 | event. */ | 233 | event. */ |
236 | do_machine_check(NULL, 0); | 234 | machine_check_poll(MCP_TIMESTAMP, |
235 | &__get_cpu_var(mce_poll_banks)); | ||
237 | 236 | ||
238 | if (high & MASK_OVERFLOW_HI) { | 237 | if (high & MASK_OVERFLOW_HI) { |
239 | rdmsrl(address, m.misc); | 238 | rdmsrl(address, m.misc); |
@@ -243,13 +242,10 @@ asmlinkage void mce_threshold_interrupt(void) | |||
243 | + bank * NR_BLOCKS | 242 | + bank * NR_BLOCKS |
244 | + block; | 243 | + block; |
245 | mce_log(&m); | 244 | mce_log(&m); |
246 | goto out; | 245 | return; |
247 | } | 246 | } |
248 | } | 247 | } |
249 | } | 248 | } |
250 | out: | ||
251 | inc_irq_stat(irq_threshold_count); | ||
252 | irq_exit(); | ||
253 | } | 249 | } |
254 | 250 | ||
255 | /* | 251 | /* |
@@ -481,7 +477,7 @@ static __cpuinit int threshold_create_bank(unsigned int cpu, unsigned int bank) | |||
481 | 477 | ||
482 | #ifdef CONFIG_SMP | 478 | #ifdef CONFIG_SMP |
483 | if (cpu_data(cpu).cpu_core_id && shared_bank[bank]) { /* symlink */ | 479 | if (cpu_data(cpu).cpu_core_id && shared_bank[bank]) { /* symlink */ |
484 | i = first_cpu(per_cpu(cpu_core_map, cpu)); | 480 | i = cpumask_first(&per_cpu(cpu_core_map, cpu)); |
485 | 481 | ||
486 | /* first core not up yet */ | 482 | /* first core not up yet */ |
487 | if (cpu_data(i).cpu_core_id) | 483 | if (cpu_data(i).cpu_core_id) |
@@ -501,7 +497,7 @@ static __cpuinit int threshold_create_bank(unsigned int cpu, unsigned int bank) | |||
501 | if (err) | 497 | if (err) |
502 | goto out; | 498 | goto out; |
503 | 499 | ||
504 | b->cpus = per_cpu(cpu_core_map, cpu); | 500 | cpumask_copy(b->cpus, &per_cpu(cpu_core_map, cpu)); |
505 | per_cpu(threshold_banks, cpu)[bank] = b; | 501 | per_cpu(threshold_banks, cpu)[bank] = b; |
506 | goto out; | 502 | goto out; |
507 | } | 503 | } |
@@ -512,15 +508,20 @@ static __cpuinit int threshold_create_bank(unsigned int cpu, unsigned int bank) | |||
512 | err = -ENOMEM; | 508 | err = -ENOMEM; |
513 | goto out; | 509 | goto out; |
514 | } | 510 | } |
511 | if (!alloc_cpumask_var(&b->cpus, GFP_KERNEL)) { | ||
512 | kfree(b); | ||
513 | err = -ENOMEM; | ||
514 | goto out; | ||
515 | } | ||
515 | 516 | ||
516 | b->kobj = kobject_create_and_add(name, &per_cpu(device_mce, cpu).kobj); | 517 | b->kobj = kobject_create_and_add(name, &per_cpu(device_mce, cpu).kobj); |
517 | if (!b->kobj) | 518 | if (!b->kobj) |
518 | goto out_free; | 519 | goto out_free; |
519 | 520 | ||
520 | #ifndef CONFIG_SMP | 521 | #ifndef CONFIG_SMP |
521 | b->cpus = CPU_MASK_ALL; | 522 | cpumask_setall(b->cpus); |
522 | #else | 523 | #else |
523 | b->cpus = per_cpu(cpu_core_map, cpu); | 524 | cpumask_copy(b->cpus, &per_cpu(cpu_core_map, cpu)); |
524 | #endif | 525 | #endif |
525 | 526 | ||
526 | per_cpu(threshold_banks, cpu)[bank] = b; | 527 | per_cpu(threshold_banks, cpu)[bank] = b; |
@@ -529,7 +530,7 @@ static __cpuinit int threshold_create_bank(unsigned int cpu, unsigned int bank) | |||
529 | if (err) | 530 | if (err) |
530 | goto out_free; | 531 | goto out_free; |
531 | 532 | ||
532 | for_each_cpu_mask_nr(i, b->cpus) { | 533 | for_each_cpu(i, b->cpus) { |
533 | if (i == cpu) | 534 | if (i == cpu) |
534 | continue; | 535 | continue; |
535 | 536 | ||
@@ -545,6 +546,7 @@ static __cpuinit int threshold_create_bank(unsigned int cpu, unsigned int bank) | |||
545 | 546 | ||
546 | out_free: | 547 | out_free: |
547 | per_cpu(threshold_banks, cpu)[bank] = NULL; | 548 | per_cpu(threshold_banks, cpu)[bank] = NULL; |
549 | free_cpumask_var(b->cpus); | ||
548 | kfree(b); | 550 | kfree(b); |
549 | out: | 551 | out: |
550 | return err; | 552 | return err; |
@@ -619,7 +621,7 @@ static void threshold_remove_bank(unsigned int cpu, int bank) | |||
619 | #endif | 621 | #endif |
620 | 622 | ||
621 | /* remove all sibling symlinks before unregistering */ | 623 | /* remove all sibling symlinks before unregistering */ |
622 | for_each_cpu_mask_nr(i, b->cpus) { | 624 | for_each_cpu(i, b->cpus) { |
623 | if (i == cpu) | 625 | if (i == cpu) |
624 | continue; | 626 | continue; |
625 | 627 | ||
@@ -632,6 +634,7 @@ static void threshold_remove_bank(unsigned int cpu, int bank) | |||
632 | free_out: | 634 | free_out: |
633 | kobject_del(b->kobj); | 635 | kobject_del(b->kobj); |
634 | kobject_put(b->kobj); | 636 | kobject_put(b->kobj); |
637 | free_cpumask_var(b->cpus); | ||
635 | kfree(b); | 638 | kfree(b); |
636 | per_cpu(threshold_banks, cpu)[bank] = NULL; | 639 | per_cpu(threshold_banks, cpu)[bank] = NULL; |
637 | } | 640 | } |