diff options
author | Will Deacon <will.deacon@arm.com> | 2012-07-29 13:09:14 +0100 |
---|---|---|
committer | Will Deacon <will.deacon@arm.com> | 2012-08-23 11:35:52 +0100 |
commit | 5505b206ca006d0506d1d3b3c494aa86234f66e2 (patch) | |
tree | c9fa078345110c7eeab9df768aba3120c98038da /arch/arm/kernel/perf_event.c | |
parent | 6dbc00297095122ea89e016ce6affad0b7c0ddac (diff) |
ARM: perf: move CPU-specific PMU handling code into separate file
This patch moves the CPU-specific PMU handling code out of perf_event.c
and into perf_event_cpu.c.
Signed-off-by: Will Deacon <will.deacon@arm.com>
Diffstat (limited to 'arch/arm/kernel/perf_event.c')
-rw-r--r-- | arch/arm/kernel/perf_event.c | 211 |
1 files changed, 1 insertions, 210 deletions
diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c index 9e3afd1994d9..86fd39937171 100644 --- a/arch/arm/kernel/perf_event.c +++ b/arch/arm/kernel/perf_event.c @@ -12,54 +12,15 @@ */ #define pr_fmt(fmt) "hw perfevents: " fmt -#include <linux/bitmap.h> -#include <linux/interrupt.h> #include <linux/kernel.h> -#include <linux/export.h> -#include <linux/of.h> -#include <linux/perf_event.h> #include <linux/platform_device.h> -#include <linux/spinlock.h> -#include <linux/uaccess.h> #include <linux/pm_runtime.h> +#include <linux/uaccess.h> -#include <asm/cputype.h> -#include <asm/irq.h> #include <asm/irq_regs.h> #include <asm/pmu.h> #include <asm/stacktrace.h> -/* Set at runtime when we know what CPU type we are. */ -static struct arm_pmu *cpu_pmu; - -static DEFINE_PER_CPU(struct perf_event * [ARMPMU_MAX_HWEVENTS], hw_events); -static DEFINE_PER_CPU(unsigned long [BITS_TO_LONGS(ARMPMU_MAX_HWEVENTS)], used_mask); -static DEFINE_PER_CPU(struct pmu_hw_events, cpu_hw_events); - -/* - * Despite the names, these two functions are CPU-specific and are used - * by the OProfile/perf code. - */ -const char *perf_pmu_name(void) -{ - if (!cpu_pmu) - return NULL; - - return cpu_pmu->pmu.name; -} -EXPORT_SYMBOL_GPL(perf_pmu_name); - -int perf_num_counters(void) -{ - int max_events = 0; - - if (cpu_pmu != NULL) - max_events = cpu_pmu->num_events; - - return max_events; -} -EXPORT_SYMBOL_GPL(perf_num_counters); - static int armpmu_map_cache_event(const unsigned (*cache_map) [PERF_COUNT_HW_CACHE_MAX] @@ -608,176 +569,6 @@ int armpmu_register(struct arm_pmu *armpmu, char *name, int type) return perf_pmu_register(&armpmu->pmu, name, type); } -/* Include the PMU-specific implementations. */ -#include "perf_event_xscale.c" -#include "perf_event_v6.c" -#include "perf_event_v7.c" - -static struct pmu_hw_events *cpu_pmu_get_cpu_events(void) -{ - return &__get_cpu_var(cpu_hw_events); -} - -static void __devinit cpu_pmu_init(struct arm_pmu *cpu_pmu) -{ - int cpu; - for_each_possible_cpu(cpu) { - struct pmu_hw_events *events = &per_cpu(cpu_hw_events, cpu); - events->events = per_cpu(hw_events, cpu); - events->used_mask = per_cpu(used_mask, cpu); - raw_spin_lock_init(&events->pmu_lock); - } - cpu_pmu->get_hw_events = cpu_pmu_get_cpu_events; - - /* Ensure the PMU has sane values out of reset. */ - if (cpu_pmu && cpu_pmu->reset) - on_each_cpu(cpu_pmu->reset, NULL, 1); -} - -/* - * PMU hardware loses all context when a CPU goes offline. - * When a CPU is hotplugged back in, since some hardware registers are - * UNKNOWN at reset, the PMU must be explicitly reset to avoid reading - * junk values out of them. - */ -static int __cpuinit cpu_pmu_notify(struct notifier_block *b, - unsigned long action, void *hcpu) -{ - if ((action & ~CPU_TASKS_FROZEN) != CPU_STARTING) - return NOTIFY_DONE; - - if (cpu_pmu && cpu_pmu->reset) - cpu_pmu->reset(NULL); - - return NOTIFY_OK; -} - -static struct notifier_block __cpuinitdata cpu_pmu_hotplug_notifier = { - .notifier_call = cpu_pmu_notify, -}; - -/* - * PMU platform driver and devicetree bindings. - */ -static struct of_device_id __devinitdata cpu_pmu_of_device_ids[] = { - {.compatible = "arm,cortex-a15-pmu", .data = armv7_a15_pmu_init}, - {.compatible = "arm,cortex-a9-pmu", .data = armv7_a9_pmu_init}, - {.compatible = "arm,cortex-a8-pmu", .data = armv7_a8_pmu_init}, - {.compatible = "arm,cortex-a7-pmu", .data = armv7_a7_pmu_init}, - {.compatible = "arm,cortex-a5-pmu", .data = armv7_a5_pmu_init}, - {.compatible = "arm,arm11mpcore-pmu", .data = armv6mpcore_pmu_init}, - {.compatible = "arm,arm1176-pmu", .data = armv6pmu_init}, - {.compatible = "arm,arm1136-pmu", .data = armv6pmu_init}, - {}, -}; - -static struct platform_device_id __devinitdata cpu_pmu_plat_device_ids[] = { - {.name = "arm-pmu"}, - {}, -}; - -/* - * CPU PMU identification and probing. - */ -static struct arm_pmu *__devinit probe_current_pmu(void) -{ - struct arm_pmu *pmu = NULL; - int cpu = get_cpu(); - unsigned long cpuid = read_cpuid_id(); - unsigned long implementor = (cpuid & 0xFF000000) >> 24; - unsigned long part_number = (cpuid & 0xFFF0); - - pr_info("probing PMU on CPU %d\n", cpu); - - /* ARM Ltd CPUs. */ - if (0x41 == implementor) { - switch (part_number) { - case 0xB360: /* ARM1136 */ - case 0xB560: /* ARM1156 */ - case 0xB760: /* ARM1176 */ - pmu = armv6pmu_init(); - break; - case 0xB020: /* ARM11mpcore */ - pmu = armv6mpcore_pmu_init(); - break; - case 0xC080: /* Cortex-A8 */ - pmu = armv7_a8_pmu_init(); - break; - case 0xC090: /* Cortex-A9 */ - pmu = armv7_a9_pmu_init(); - break; - case 0xC050: /* Cortex-A5 */ - pmu = armv7_a5_pmu_init(); - break; - case 0xC0F0: /* Cortex-A15 */ - pmu = armv7_a15_pmu_init(); - break; - case 0xC070: /* Cortex-A7 */ - pmu = armv7_a7_pmu_init(); - break; - } - /* Intel CPUs [xscale]. */ - } else if (0x69 == implementor) { - part_number = (cpuid >> 13) & 0x7; - switch (part_number) { - case 1: - pmu = xscale1pmu_init(); - break; - case 2: - pmu = xscale2pmu_init(); - break; - } - } - - put_cpu(); - return pmu; -} - -static int __devinit cpu_pmu_device_probe(struct platform_device *pdev) -{ - const struct of_device_id *of_id; - struct arm_pmu *(*init_fn)(void); - struct device_node *node = pdev->dev.of_node; - - if (cpu_pmu) { - pr_info("attempt to register multiple PMU devices!"); - return -ENOSPC; - } - - if (node && (of_id = of_match_node(cpu_pmu_of_device_ids, pdev->dev.of_node))) { - init_fn = of_id->data; - cpu_pmu = init_fn(); - } else { - cpu_pmu = probe_current_pmu(); - } - - if (!cpu_pmu) - return -ENODEV; - - cpu_pmu->plat_device = pdev; - cpu_pmu_init(cpu_pmu); - register_cpu_notifier(&cpu_pmu_hotplug_notifier); - armpmu_register(cpu_pmu, cpu_pmu->name, PERF_TYPE_RAW); - - return 0; -} - -static struct platform_driver cpu_pmu_driver = { - .driver = { - .name = "arm-pmu", - .pm = &armpmu_dev_pm_ops, - .of_match_table = cpu_pmu_of_device_ids, - }, - .probe = cpu_pmu_device_probe, - .id_table = cpu_pmu_plat_device_ids, -}; - -static int __init register_pmu_driver(void) -{ - return platform_driver_register(&cpu_pmu_driver); -} -device_initcall(register_pmu_driver); - /* * Callchain handling code. */ |