aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/oprofile/nmi_int.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/oprofile/nmi_int.c')
-rw-r--r--arch/x86/oprofile/nmi_int.c75
1 files changed, 61 insertions, 14 deletions
diff --git a/arch/x86/oprofile/nmi_int.c b/arch/x86/oprofile/nmi_int.c
index 7f3329b55d2e..0227694f7dab 100644
--- a/arch/x86/oprofile/nmi_int.c
+++ b/arch/x86/oprofile/nmi_int.c
@@ -15,6 +15,7 @@
15#include <linux/slab.h> 15#include <linux/slab.h>
16#include <linux/moduleparam.h> 16#include <linux/moduleparam.h>
17#include <linux/kdebug.h> 17#include <linux/kdebug.h>
18#include <linux/cpu.h>
18#include <asm/nmi.h> 19#include <asm/nmi.h>
19#include <asm/msr.h> 20#include <asm/msr.h>
20#include <asm/apic.h> 21#include <asm/apic.h>
@@ -28,23 +29,48 @@ static DEFINE_PER_CPU(unsigned long, saved_lvtpc);
28 29
29static int nmi_start(void); 30static int nmi_start(void);
30static void nmi_stop(void); 31static void nmi_stop(void);
32static void nmi_cpu_start(void *dummy);
33static void nmi_cpu_stop(void *dummy);
31 34
32/* 0 == registered but off, 1 == registered and on */ 35/* 0 == registered but off, 1 == registered and on */
33static int nmi_enabled = 0; 36static int nmi_enabled = 0;
34 37
38#ifdef CONFIG_SMP
39static int oprofile_cpu_notifier(struct notifier_block *b, unsigned long action,
40 void *data)
41{
42 int cpu = (unsigned long)data;
43 switch (action) {
44 case CPU_DOWN_FAILED:
45 case CPU_ONLINE:
46 smp_call_function_single(cpu, nmi_cpu_start, NULL, 0);
47 break;
48 case CPU_DOWN_PREPARE:
49 smp_call_function_single(cpu, nmi_cpu_stop, NULL, 1);
50 break;
51 }
52 return NOTIFY_DONE;
53}
54
55static struct notifier_block oprofile_cpu_nb = {
56 .notifier_call = oprofile_cpu_notifier
57};
58#endif
59
35#ifdef CONFIG_PM 60#ifdef CONFIG_PM
36 61
37static int nmi_suspend(struct sys_device *dev, pm_message_t state) 62static int nmi_suspend(struct sys_device *dev, pm_message_t state)
38{ 63{
64 /* Only one CPU left, just stop that one */
39 if (nmi_enabled == 1) 65 if (nmi_enabled == 1)
40 nmi_stop(); 66 nmi_cpu_stop(NULL);
41 return 0; 67 return 0;
42} 68}
43 69
44static int nmi_resume(struct sys_device *dev) 70static int nmi_resume(struct sys_device *dev)
45{ 71{
46 if (nmi_enabled == 1) 72 if (nmi_enabled == 1)
47 nmi_start(); 73 nmi_cpu_start(NULL);
48 return 0; 74 return 0;
49} 75}
50 76
@@ -369,20 +395,34 @@ static int __init ppro_init(char **cpu_type)
369{ 395{
370 __u8 cpu_model = boot_cpu_data.x86_model; 396 __u8 cpu_model = boot_cpu_data.x86_model;
371 397
372 if (cpu_model == 14) 398 switch (cpu_model) {
399 case 0 ... 2:
400 *cpu_type = "i386/ppro";
401 break;
402 case 3 ... 5:
403 *cpu_type = "i386/pii";
404 break;
405 case 6 ... 8:
406 *cpu_type = "i386/piii";
407 break;
408 case 9:
409 *cpu_type = "i386/p6_mobile";
410 break;
411 case 10 ... 13:
412 *cpu_type = "i386/p6";
413 break;
414 case 14:
373 *cpu_type = "i386/core"; 415 *cpu_type = "i386/core";
374 else if (cpu_model == 15 || cpu_model == 23) 416 break;
417 case 15: case 23:
375 *cpu_type = "i386/core_2"; 418 *cpu_type = "i386/core_2";
376 else if (cpu_model > 0xd) 419 break;
420 case 26:
421 *cpu_type = "i386/core_2";
422 break;
423 default:
424 /* Unknown */
377 return 0; 425 return 0;
378 else if (cpu_model == 9) {
379 *cpu_type = "i386/p6_mobile";
380 } else if (cpu_model > 5) {
381 *cpu_type = "i386/piii";
382 } else if (cpu_model > 2) {
383 *cpu_type = "i386/pii";
384 } else {
385 *cpu_type = "i386/ppro";
386 } 426 }
387 427
388 model = &op_ppro_spec; 428 model = &op_ppro_spec;
@@ -449,6 +489,9 @@ int __init op_nmi_init(struct oprofile_operations *ops)
449 } 489 }
450 490
451 init_sysfs(); 491 init_sysfs();
492#ifdef CONFIG_SMP
493 register_cpu_notifier(&oprofile_cpu_nb);
494#endif
452 using_nmi = 1; 495 using_nmi = 1;
453 ops->create_files = nmi_create_files; 496 ops->create_files = nmi_create_files;
454 ops->setup = nmi_setup; 497 ops->setup = nmi_setup;
@@ -462,6 +505,10 @@ int __init op_nmi_init(struct oprofile_operations *ops)
462 505
463void op_nmi_exit(void) 506void op_nmi_exit(void)
464{ 507{
465 if (using_nmi) 508 if (using_nmi) {
466 exit_sysfs(); 509 exit_sysfs();
510#ifdef CONFIG_SMP
511 unregister_cpu_notifier(&oprofile_cpu_nb);
512#endif
513 }
467} 514}