diff options
author | Ingo Molnar <mingo@elte.hu> | 2008-09-30 06:16:26 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-09-30 06:16:26 -0400 |
commit | 59293c8ad54726150cf6178164311b004d615ce4 (patch) | |
tree | 6fcf8e59a2c9ac08a4ff092544c34d2254ac0d74 /arch/x86/oprofile | |
parent | 45f197ade73ba95681b9803680c75352fc0a1c0a (diff) | |
parent | 94aca1dac6f6d21f4b07e4864baf7768cabcc6e7 (diff) |
Merge commit 'v2.6.27-rc8' into oprofile
Conflicts:
arch/x86/oprofile/nmi_int.c
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/x86/oprofile')
-rw-r--r-- | arch/x86/oprofile/nmi_int.c | 45 |
1 files changed, 39 insertions, 6 deletions
diff --git a/arch/x86/oprofile/nmi_int.c b/arch/x86/oprofile/nmi_int.c index 4108d02c5292..114df508b407 100644 --- a/arch/x86/oprofile/nmi_int.c +++ b/arch/x86/oprofile/nmi_int.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/slab.h> | 16 | #include <linux/slab.h> |
17 | #include <linux/moduleparam.h> | 17 | #include <linux/moduleparam.h> |
18 | #include <linux/kdebug.h> | 18 | #include <linux/kdebug.h> |
19 | #include <linux/cpu.h> | ||
19 | #include <asm/nmi.h> | 20 | #include <asm/nmi.h> |
20 | #include <asm/msr.h> | 21 | #include <asm/msr.h> |
21 | #include <asm/apic.h> | 22 | #include <asm/apic.h> |
@@ -31,27 +32,50 @@ static DEFINE_PER_CPU(unsigned long, saved_lvtpc); | |||
31 | 32 | ||
32 | static int nmi_start(void); | 33 | static int nmi_start(void); |
33 | static void nmi_stop(void); | 34 | static void nmi_stop(void); |
35 | static void nmi_cpu_start(void *dummy); | ||
36 | static void nmi_cpu_stop(void *dummy); | ||
34 | static void nmi_cpu_save_mpx_registers(struct op_msrs *msrs); | 37 | static void nmi_cpu_save_mpx_registers(struct op_msrs *msrs); |
35 | static void nmi_cpu_restore_mpx_registers(struct op_msrs *msrs); | 38 | static void nmi_cpu_restore_mpx_registers(struct op_msrs *msrs); |
36 | static void nmi_cpu_stop(void *dummy); | ||
37 | static void nmi_cpu_start(void *dummy); | ||
38 | 39 | ||
39 | /* 0 == registered but off, 1 == registered and on */ | 40 | /* 0 == registered but off, 1 == registered and on */ |
40 | static int nmi_enabled = 0; | 41 | static int nmi_enabled = 0; |
41 | 42 | ||
43 | #ifdef CONFIG_SMP | ||
44 | static int oprofile_cpu_notifier(struct notifier_block *b, unsigned long action, | ||
45 | void *data) | ||
46 | { | ||
47 | int cpu = (unsigned long)data; | ||
48 | switch (action) { | ||
49 | case CPU_DOWN_FAILED: | ||
50 | case CPU_ONLINE: | ||
51 | smp_call_function_single(cpu, nmi_cpu_start, NULL, 0); | ||
52 | break; | ||
53 | case CPU_DOWN_PREPARE: | ||
54 | smp_call_function_single(cpu, nmi_cpu_stop, NULL, 1); | ||
55 | break; | ||
56 | } | ||
57 | return NOTIFY_DONE; | ||
58 | } | ||
59 | |||
60 | static struct notifier_block oprofile_cpu_nb = { | ||
61 | .notifier_call = oprofile_cpu_notifier | ||
62 | }; | ||
63 | #endif | ||
64 | |||
42 | #ifdef CONFIG_PM | 65 | #ifdef CONFIG_PM |
43 | 66 | ||
44 | static int nmi_suspend(struct sys_device *dev, pm_message_t state) | 67 | static int nmi_suspend(struct sys_device *dev, pm_message_t state) |
45 | { | 68 | { |
69 | /* Only one CPU left, just stop that one */ | ||
46 | if (nmi_enabled == 1) | 70 | if (nmi_enabled == 1) |
47 | nmi_stop(); | 71 | nmi_cpu_stop(NULL); |
48 | return 0; | 72 | return 0; |
49 | } | 73 | } |
50 | 74 | ||
51 | static int nmi_resume(struct sys_device *dev) | 75 | static int nmi_resume(struct sys_device *dev) |
52 | { | 76 | { |
53 | if (nmi_enabled == 1) | 77 | if (nmi_enabled == 1) |
54 | nmi_start(); | 78 | nmi_cpu_start(NULL); |
55 | return 0; | 79 | return 0; |
56 | } | 80 | } |
57 | 81 | ||
@@ -351,10 +375,12 @@ static void nmi_cpu_shutdown(void *dummy) | |||
351 | 375 | ||
352 | static void nmi_shutdown(void) | 376 | static void nmi_shutdown(void) |
353 | { | 377 | { |
354 | struct op_msrs *msrs = &get_cpu_var(cpu_msrs); | 378 | struct op_msrs *msrs; |
379 | |||
355 | nmi_enabled = 0; | 380 | nmi_enabled = 0; |
356 | on_each_cpu(nmi_cpu_shutdown, NULL, 1); | 381 | on_each_cpu(nmi_cpu_shutdown, NULL, 1); |
357 | unregister_die_notifier(&profile_exceptions_nb); | 382 | unregister_die_notifier(&profile_exceptions_nb); |
383 | msrs = &get_cpu_var(cpu_msrs); | ||
358 | model->shutdown(msrs); | 384 | model->shutdown(msrs); |
359 | free_msrs(); | 385 | free_msrs(); |
360 | put_cpu_var(cpu_msrs); | 386 | put_cpu_var(cpu_msrs); |
@@ -550,6 +576,9 @@ int __init op_nmi_init(struct oprofile_operations *ops) | |||
550 | return -ENODEV; | 576 | return -ENODEV; |
551 | } | 577 | } |
552 | 578 | ||
579 | #ifdef CONFIG_SMP | ||
580 | register_cpu_notifier(&oprofile_cpu_nb); | ||
581 | #endif | ||
553 | /* default values, can be overwritten by model */ | 582 | /* default values, can be overwritten by model */ |
554 | __raw_get_cpu_var(switch_index) = 0; | 583 | __raw_get_cpu_var(switch_index) = 0; |
555 | ops->create_files = nmi_create_files; | 584 | ops->create_files = nmi_create_files; |
@@ -573,8 +602,12 @@ int __init op_nmi_init(struct oprofile_operations *ops) | |||
573 | 602 | ||
574 | void op_nmi_exit(void) | 603 | void op_nmi_exit(void) |
575 | { | 604 | { |
576 | if (using_nmi) | 605 | if (using_nmi) { |
577 | exit_sysfs(); | 606 | exit_sysfs(); |
607 | #ifdef CONFIG_SMP | ||
608 | unregister_cpu_notifier(&oprofile_cpu_nb); | ||
609 | #endif | ||
578 | if (model->exit) | 610 | if (model->exit) |
579 | model->exit(); | 611 | model->exit(); |
612 | } | ||
580 | } | 613 | } |