diff options
author | Lorenzo Pieralisi <Lorenzo.Pieralisi@arm.com> | 2012-03-06 11:37:45 -0500 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2012-03-07 04:40:50 -0500 |
commit | a0feb6db0fe03326d7d2c7a4615ce3289615c023 (patch) | |
tree | 5252086b8224c588148af6a48618030aa6e4827a /arch/arm | |
parent | 3f31ae121348afd9ed39700ea2a63c17cd7eeed1 (diff) |
ARM: 7358/1: perf: add PMU hotplug notifier
When a CPU is taken out of reset, either cold booted or hotplugged in,
some of its PMU registers can contain UNKNOWN values.
This patch adds a hotplug notifier to ARM core perf code so that upon
CPU restart the PMU unit is reset and becomes ready to use again.
Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm')
-rw-r--r-- | arch/arm/kernel/perf_event.c | 23 |
1 files changed, 23 insertions, 0 deletions
diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c index 56173ae16448..b2abfa18f137 100644 --- a/arch/arm/kernel/perf_event.c +++ b/arch/arm/kernel/perf_event.c | |||
@@ -680,6 +680,28 @@ static void __init cpu_pmu_init(struct arm_pmu *armpmu) | |||
680 | } | 680 | } |
681 | 681 | ||
682 | /* | 682 | /* |
683 | * PMU hardware loses all context when a CPU goes offline. | ||
684 | * When a CPU is hotplugged back in, since some hardware registers are | ||
685 | * UNKNOWN at reset, the PMU must be explicitly reset to avoid reading | ||
686 | * junk values out of them. | ||
687 | */ | ||
688 | static int __cpuinit pmu_cpu_notify(struct notifier_block *b, | ||
689 | unsigned long action, void *hcpu) | ||
690 | { | ||
691 | if ((action & ~CPU_TASKS_FROZEN) != CPU_STARTING) | ||
692 | return NOTIFY_DONE; | ||
693 | |||
694 | if (cpu_pmu && cpu_pmu->reset) | ||
695 | cpu_pmu->reset(NULL); | ||
696 | |||
697 | return NOTIFY_OK; | ||
698 | } | ||
699 | |||
700 | static struct notifier_block __cpuinitdata pmu_cpu_notifier = { | ||
701 | .notifier_call = pmu_cpu_notify, | ||
702 | }; | ||
703 | |||
704 | /* | ||
683 | * CPU PMU identification and registration. | 705 | * CPU PMU identification and registration. |
684 | */ | 706 | */ |
685 | static int __init | 707 | static int __init |
@@ -730,6 +752,7 @@ init_hw_perf_events(void) | |||
730 | pr_info("enabled with %s PMU driver, %d counters available\n", | 752 | pr_info("enabled with %s PMU driver, %d counters available\n", |
731 | cpu_pmu->name, cpu_pmu->num_events); | 753 | cpu_pmu->name, cpu_pmu->num_events); |
732 | cpu_pmu_init(cpu_pmu); | 754 | cpu_pmu_init(cpu_pmu); |
755 | register_cpu_notifier(&pmu_cpu_notifier); | ||
733 | armpmu_register(cpu_pmu, "cpu", PERF_TYPE_RAW); | 756 | armpmu_register(cpu_pmu, "cpu", PERF_TYPE_RAW); |
734 | } else { | 757 | } else { |
735 | pr_info("no hardware support available\n"); | 758 | pr_info("no hardware support available\n"); |