aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/kernel')
-rw-r--r--arch/arm/kernel/Makefile3
-rw-r--r--arch/arm/kernel/perf_event.c347
-rw-r--r--arch/arm/kernel/perf_event_cpu.c295
-rw-r--r--arch/arm/kernel/perf_event_v6.c12
-rw-r--r--arch/arm/kernel/perf_event_v7.c32
-rw-r--r--arch/arm/kernel/perf_event_xscale.c10
-rw-r--r--arch/arm/kernel/pmu.c36
7 files changed, 374 insertions, 361 deletions
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
index 7ad2d5cf7008..1c4321430737 100644
--- a/arch/arm/kernel/Makefile
+++ b/arch/arm/kernel/Makefile
@@ -69,8 +69,7 @@ obj-$(CONFIG_CPU_XSC3) += xscale-cp0.o
69obj-$(CONFIG_CPU_MOHAWK) += xscale-cp0.o 69obj-$(CONFIG_CPU_MOHAWK) += xscale-cp0.o
70obj-$(CONFIG_CPU_PJ4) += pj4-cp0.o 70obj-$(CONFIG_CPU_PJ4) += pj4-cp0.o
71obj-$(CONFIG_IWMMXT) += iwmmxt.o 71obj-$(CONFIG_IWMMXT) += iwmmxt.o
72obj-$(CONFIG_CPU_HAS_PMU) += pmu.o 72obj-$(CONFIG_HW_PERF_EVENTS) += perf_event.o perf_event_cpu.o
73obj-$(CONFIG_HW_PERF_EVENTS) += perf_event.o
74AFLAGS_iwmmxt.o := -Wa,-mcpu=iwmmxt 73AFLAGS_iwmmxt.o := -Wa,-mcpu=iwmmxt
75obj-$(CONFIG_ARM_CPU_TOPOLOGY) += topology.o 74obj-$(CONFIG_ARM_CPU_TOPOLOGY) += topology.o
76 75
diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c
index ab243b87118d..93971b1a4f0b 100644
--- a/arch/arm/kernel/perf_event.c
+++ b/arch/arm/kernel/perf_event.c
@@ -12,68 +12,15 @@
12 */ 12 */
13#define pr_fmt(fmt) "hw perfevents: " fmt 13#define pr_fmt(fmt) "hw perfevents: " fmt
14 14
15#include <linux/bitmap.h>
16#include <linux/interrupt.h>
17#include <linux/kernel.h> 15#include <linux/kernel.h>
18#include <linux/export.h>
19#include <linux/perf_event.h>
20#include <linux/platform_device.h> 16#include <linux/platform_device.h>
21#include <linux/spinlock.h> 17#include <linux/pm_runtime.h>
22#include <linux/uaccess.h> 18#include <linux/uaccess.h>
23 19
24#include <asm/cputype.h>
25#include <asm/irq.h>
26#include <asm/irq_regs.h> 20#include <asm/irq_regs.h>
27#include <asm/pmu.h> 21#include <asm/pmu.h>
28#include <asm/stacktrace.h> 22#include <asm/stacktrace.h>
29 23
30/*
31 * ARMv6 supports a maximum of 3 events, starting from index 0. If we add
32 * another platform that supports more, we need to increase this to be the
33 * largest of all platforms.
34 *
35 * ARMv7 supports up to 32 events:
36 * cycle counter CCNT + 31 events counters CNT0..30.
37 * Cortex-A8 has 1+4 counters, Cortex-A9 has 1+6 counters.
38 */
39#define ARMPMU_MAX_HWEVENTS 32
40
41static DEFINE_PER_CPU(struct perf_event * [ARMPMU_MAX_HWEVENTS], hw_events);
42static DEFINE_PER_CPU(unsigned long [BITS_TO_LONGS(ARMPMU_MAX_HWEVENTS)], used_mask);
43static DEFINE_PER_CPU(struct pmu_hw_events, cpu_hw_events);
44
45#define to_arm_pmu(p) (container_of(p, struct arm_pmu, pmu))
46
47/* Set at runtime when we know what CPU type we are. */
48static struct arm_pmu *cpu_pmu;
49
50const char *perf_pmu_name(void)
51{
52 if (!cpu_pmu)
53 return NULL;
54
55 return cpu_pmu->pmu.name;
56}
57EXPORT_SYMBOL_GPL(perf_pmu_name);
58
59int perf_num_counters(void)
60{
61 int max_events = 0;
62
63 if (cpu_pmu != NULL)
64 max_events = cpu_pmu->num_events;
65
66 return max_events;
67}
68EXPORT_SYMBOL_GPL(perf_num_counters);
69
70#define HW_OP_UNSUPPORTED 0xFFFF
71
72#define C(_x) \
73 PERF_COUNT_HW_CACHE_##_x
74
75#define CACHE_OP_UNSUPPORTED 0xFFFF
76
77static int 24static int
78armpmu_map_cache_event(const unsigned (*cache_map) 25armpmu_map_cache_event(const unsigned (*cache_map)
79 [PERF_COUNT_HW_CACHE_MAX] 26 [PERF_COUNT_HW_CACHE_MAX]
@@ -104,7 +51,7 @@ armpmu_map_cache_event(const unsigned (*cache_map)
104} 51}
105 52
106static int 53static int
107armpmu_map_event(const unsigned (*event_map)[PERF_COUNT_HW_MAX], u64 config) 54armpmu_map_hw_event(const unsigned (*event_map)[PERF_COUNT_HW_MAX], u64 config)
108{ 55{
109 int mapping = (*event_map)[config]; 56 int mapping = (*event_map)[config];
110 return mapping == HW_OP_UNSUPPORTED ? -ENOENT : mapping; 57 return mapping == HW_OP_UNSUPPORTED ? -ENOENT : mapping;
@@ -116,19 +63,20 @@ armpmu_map_raw_event(u32 raw_event_mask, u64 config)
116 return (int)(config & raw_event_mask); 63 return (int)(config & raw_event_mask);
117} 64}
118 65
119static int map_cpu_event(struct perf_event *event, 66int
120 const unsigned (*event_map)[PERF_COUNT_HW_MAX], 67armpmu_map_event(struct perf_event *event,
121 const unsigned (*cache_map) 68 const unsigned (*event_map)[PERF_COUNT_HW_MAX],
122 [PERF_COUNT_HW_CACHE_MAX] 69 const unsigned (*cache_map)
123 [PERF_COUNT_HW_CACHE_OP_MAX] 70 [PERF_COUNT_HW_CACHE_MAX]
124 [PERF_COUNT_HW_CACHE_RESULT_MAX], 71 [PERF_COUNT_HW_CACHE_OP_MAX]
125 u32 raw_event_mask) 72 [PERF_COUNT_HW_CACHE_RESULT_MAX],
73 u32 raw_event_mask)
126{ 74{
127 u64 config = event->attr.config; 75 u64 config = event->attr.config;
128 76
129 switch (event->attr.type) { 77 switch (event->attr.type) {
130 case PERF_TYPE_HARDWARE: 78 case PERF_TYPE_HARDWARE:
131 return armpmu_map_event(event_map, config); 79 return armpmu_map_hw_event(event_map, config);
132 case PERF_TYPE_HW_CACHE: 80 case PERF_TYPE_HW_CACHE:
133 return armpmu_map_cache_event(cache_map, config); 81 return armpmu_map_cache_event(cache_map, config);
134 case PERF_TYPE_RAW: 82 case PERF_TYPE_RAW:
@@ -222,7 +170,6 @@ armpmu_stop(struct perf_event *event, int flags)
222 */ 170 */
223 if (!(hwc->state & PERF_HES_STOPPED)) { 171 if (!(hwc->state & PERF_HES_STOPPED)) {
224 armpmu->disable(hwc, hwc->idx); 172 armpmu->disable(hwc, hwc->idx);
225 barrier(); /* why? */
226 armpmu_event_update(event, hwc, hwc->idx); 173 armpmu_event_update(event, hwc, hwc->idx);
227 hwc->state |= PERF_HES_STOPPED | PERF_HES_UPTODATE; 174 hwc->state |= PERF_HES_STOPPED | PERF_HES_UPTODATE;
228 } 175 }
@@ -350,99 +297,41 @@ validate_group(struct perf_event *event)
350 return 0; 297 return 0;
351} 298}
352 299
353static irqreturn_t armpmu_platform_irq(int irq, void *dev) 300static irqreturn_t armpmu_dispatch_irq(int irq, void *dev)
354{ 301{
355 struct arm_pmu *armpmu = (struct arm_pmu *) dev; 302 struct arm_pmu *armpmu = (struct arm_pmu *) dev;
356 struct platform_device *plat_device = armpmu->plat_device; 303 struct platform_device *plat_device = armpmu->plat_device;
357 struct arm_pmu_platdata *plat = dev_get_platdata(&plat_device->dev); 304 struct arm_pmu_platdata *plat = dev_get_platdata(&plat_device->dev);
358 305
359 return plat->handle_irq(irq, dev, armpmu->handle_irq); 306 if (plat && plat->handle_irq)
307 return plat->handle_irq(irq, dev, armpmu->handle_irq);
308 else
309 return armpmu->handle_irq(irq, dev);
360} 310}
361 311
362static void 312static void
363armpmu_release_hardware(struct arm_pmu *armpmu) 313armpmu_release_hardware(struct arm_pmu *armpmu)
364{ 314{
365 int i, irq, irqs; 315 armpmu->free_irq();
366 struct platform_device *pmu_device = armpmu->plat_device; 316 pm_runtime_put_sync(&armpmu->plat_device->dev);
367 struct arm_pmu_platdata *plat =
368 dev_get_platdata(&pmu_device->dev);
369
370 irqs = min(pmu_device->num_resources, num_possible_cpus());
371
372 for (i = 0; i < irqs; ++i) {
373 if (!cpumask_test_and_clear_cpu(i, &armpmu->active_irqs))
374 continue;
375 irq = platform_get_irq(pmu_device, i);
376 if (irq >= 0) {
377 if (plat && plat->disable_irq)
378 plat->disable_irq(irq);
379 free_irq(irq, armpmu);
380 }
381 }
382
383 release_pmu(armpmu->type);
384} 317}
385 318
386static int 319static int
387armpmu_reserve_hardware(struct arm_pmu *armpmu) 320armpmu_reserve_hardware(struct arm_pmu *armpmu)
388{ 321{
389 struct arm_pmu_platdata *plat; 322 int err;
390 irq_handler_t handle_irq;
391 int i, err, irq, irqs;
392 struct platform_device *pmu_device = armpmu->plat_device; 323 struct platform_device *pmu_device = armpmu->plat_device;
393 324
394 if (!pmu_device) 325 if (!pmu_device)
395 return -ENODEV; 326 return -ENODEV;
396 327
397 err = reserve_pmu(armpmu->type); 328 pm_runtime_get_sync(&pmu_device->dev);
329 err = armpmu->request_irq(armpmu_dispatch_irq);
398 if (err) { 330 if (err) {
399 pr_warning("unable to reserve pmu\n"); 331 armpmu_release_hardware(armpmu);
400 return err; 332 return err;
401 } 333 }
402 334
403 plat = dev_get_platdata(&pmu_device->dev);
404 if (plat && plat->handle_irq)
405 handle_irq = armpmu_platform_irq;
406 else
407 handle_irq = armpmu->handle_irq;
408
409 irqs = min(pmu_device->num_resources, num_possible_cpus());
410 if (irqs < 1) {
411 pr_err("no irqs for PMUs defined\n");
412 return -ENODEV;
413 }
414
415 for (i = 0; i < irqs; ++i) {
416 err = 0;
417 irq = platform_get_irq(pmu_device, i);
418 if (irq < 0)
419 continue;
420
421 /*
422 * If we have a single PMU interrupt that we can't shift,
423 * assume that we're running on a uniprocessor machine and
424 * continue. Otherwise, continue without this interrupt.
425 */
426 if (irq_set_affinity(irq, cpumask_of(i)) && irqs > 1) {
427 pr_warning("unable to set irq affinity (irq=%d, cpu=%u)\n",
428 irq, i);
429 continue;
430 }
431
432 err = request_irq(irq, handle_irq,
433 IRQF_DISABLED | IRQF_NOBALANCING,
434 "arm-pmu", armpmu);
435 if (err) {
436 pr_err("unable to request IRQ%d for ARM PMU counters\n",
437 irq);
438 armpmu_release_hardware(armpmu);
439 return err;
440 } else if (plat && plat->enable_irq)
441 plat->enable_irq(irq);
442
443 cpumask_set_cpu(i, &armpmu->active_irqs);
444 }
445
446 return 0; 335 return 0;
447} 336}
448 337
@@ -581,6 +470,32 @@ static void armpmu_disable(struct pmu *pmu)
581 armpmu->stop(); 470 armpmu->stop();
582} 471}
583 472
473#ifdef CONFIG_PM_RUNTIME
474static int armpmu_runtime_resume(struct device *dev)
475{
476 struct arm_pmu_platdata *plat = dev_get_platdata(dev);
477
478 if (plat && plat->runtime_resume)
479 return plat->runtime_resume(dev);
480
481 return 0;
482}
483
484static int armpmu_runtime_suspend(struct device *dev)
485{
486 struct arm_pmu_platdata *plat = dev_get_platdata(dev);
487
488 if (plat && plat->runtime_suspend)
489 return plat->runtime_suspend(dev);
490
491 return 0;
492}
493#endif
494
495const struct dev_pm_ops armpmu_dev_pm_ops = {
496 SET_RUNTIME_PM_OPS(armpmu_runtime_suspend, armpmu_runtime_resume, NULL)
497};
498
584static void __init armpmu_init(struct arm_pmu *armpmu) 499static void __init armpmu_init(struct arm_pmu *armpmu)
585{ 500{
586 atomic_set(&armpmu->active_events, 0); 501 atomic_set(&armpmu->active_events, 0);
@@ -598,174 +513,14 @@ static void __init armpmu_init(struct arm_pmu *armpmu)
598 }; 513 };
599} 514}
600 515
601int __init armpmu_register(struct arm_pmu *armpmu, char *name, int type) 516int armpmu_register(struct arm_pmu *armpmu, char *name, int type)
602{ 517{
603 armpmu_init(armpmu); 518 armpmu_init(armpmu);
519 pr_info("enabled with %s PMU driver, %d counters available\n",
520 armpmu->name, armpmu->num_events);
604 return perf_pmu_register(&armpmu->pmu, name, type); 521 return perf_pmu_register(&armpmu->pmu, name, type);
605} 522}
606 523
607/* Include the PMU-specific implementations. */
608#include "perf_event_xscale.c"
609#include "perf_event_v6.c"
610#include "perf_event_v7.c"
611
612/*
613 * Ensure the PMU has sane values out of reset.
614 * This requires SMP to be available, so exists as a separate initcall.
615 */
616static int __init
617cpu_pmu_reset(void)
618{
619 if (cpu_pmu && cpu_pmu->reset)
620 return on_each_cpu(cpu_pmu->reset, NULL, 1);
621 return 0;
622}
623arch_initcall(cpu_pmu_reset);
624
625/*
626 * PMU platform driver and devicetree bindings.
627 */
628static struct of_device_id armpmu_of_device_ids[] = {
629 {.compatible = "arm,cortex-a9-pmu"},
630 {.compatible = "arm,cortex-a8-pmu"},
631 {.compatible = "arm,arm1136-pmu"},
632 {.compatible = "arm,arm1176-pmu"},
633 {},
634};
635
636static struct platform_device_id armpmu_plat_device_ids[] = {
637 {.name = "arm-pmu"},
638 {},
639};
640
641static int __devinit armpmu_device_probe(struct platform_device *pdev)
642{
643 if (!cpu_pmu)
644 return -ENODEV;
645
646 cpu_pmu->plat_device = pdev;
647 return 0;
648}
649
650static struct platform_driver armpmu_driver = {
651 .driver = {
652 .name = "arm-pmu",
653 .of_match_table = armpmu_of_device_ids,
654 },
655 .probe = armpmu_device_probe,
656 .id_table = armpmu_plat_device_ids,
657};
658
659static int __init register_pmu_driver(void)
660{
661 return platform_driver_register(&armpmu_driver);
662}
663device_initcall(register_pmu_driver);
664
665static struct pmu_hw_events *armpmu_get_cpu_events(void)
666{
667 return &__get_cpu_var(cpu_hw_events);
668}
669
670static void __init cpu_pmu_init(struct arm_pmu *armpmu)
671{
672 int cpu;
673 for_each_possible_cpu(cpu) {
674 struct pmu_hw_events *events = &per_cpu(cpu_hw_events, cpu);
675 events->events = per_cpu(hw_events, cpu);
676 events->used_mask = per_cpu(used_mask, cpu);
677 raw_spin_lock_init(&events->pmu_lock);
678 }
679 armpmu->get_hw_events = armpmu_get_cpu_events;
680 armpmu->type = ARM_PMU_DEVICE_CPU;
681}
682
683/*
684 * PMU hardware loses all context when a CPU goes offline.
685 * When a CPU is hotplugged back in, since some hardware registers are
686 * UNKNOWN at reset, the PMU must be explicitly reset to avoid reading
687 * junk values out of them.
688 */
689static int __cpuinit pmu_cpu_notify(struct notifier_block *b,
690 unsigned long action, void *hcpu)
691{
692 if ((action & ~CPU_TASKS_FROZEN) != CPU_STARTING)
693 return NOTIFY_DONE;
694
695 if (cpu_pmu && cpu_pmu->reset)
696 cpu_pmu->reset(NULL);
697
698 return NOTIFY_OK;
699}
700
701static struct notifier_block __cpuinitdata pmu_cpu_notifier = {
702 .notifier_call = pmu_cpu_notify,
703};
704
705/*
706 * CPU PMU identification and registration.
707 */
708static int __init
709init_hw_perf_events(void)
710{
711 unsigned long cpuid = read_cpuid_id();
712 unsigned long implementor = (cpuid & 0xFF000000) >> 24;
713 unsigned long part_number = (cpuid & 0xFFF0);
714
715 /* ARM Ltd CPUs. */
716 if (0x41 == implementor) {
717 switch (part_number) {
718 case 0xB360: /* ARM1136 */
719 case 0xB560: /* ARM1156 */
720 case 0xB760: /* ARM1176 */
721 cpu_pmu = armv6pmu_init();
722 break;
723 case 0xB020: /* ARM11mpcore */
724 cpu_pmu = armv6mpcore_pmu_init();
725 break;
726 case 0xC080: /* Cortex-A8 */
727 cpu_pmu = armv7_a8_pmu_init();
728 break;
729 case 0xC090: /* Cortex-A9 */
730 cpu_pmu = armv7_a9_pmu_init();
731 break;
732 case 0xC050: /* Cortex-A5 */
733 cpu_pmu = armv7_a5_pmu_init();
734 break;
735 case 0xC0F0: /* Cortex-A15 */
736 cpu_pmu = armv7_a15_pmu_init();
737 break;
738 case 0xC070: /* Cortex-A7 */
739 cpu_pmu = armv7_a7_pmu_init();
740 break;
741 }
742 /* Intel CPUs [xscale]. */
743 } else if (0x69 == implementor) {
744 part_number = (cpuid >> 13) & 0x7;
745 switch (part_number) {
746 case 1:
747 cpu_pmu = xscale1pmu_init();
748 break;
749 case 2:
750 cpu_pmu = xscale2pmu_init();
751 break;
752 }
753 }
754
755 if (cpu_pmu) {
756 pr_info("enabled with %s PMU driver, %d counters available\n",
757 cpu_pmu->name, cpu_pmu->num_events);
758 cpu_pmu_init(cpu_pmu);
759 register_cpu_notifier(&pmu_cpu_notifier);
760 armpmu_register(cpu_pmu, cpu_pmu->name, PERF_TYPE_RAW);
761 } else {
762 pr_info("no hardware support available\n");
763 }
764
765 return 0;
766}
767early_initcall(init_hw_perf_events);
768
769/* 524/*
770 * Callchain handling code. 525 * Callchain handling code.
771 */ 526 */
diff --git a/arch/arm/kernel/perf_event_cpu.c b/arch/arm/kernel/perf_event_cpu.c
new file mode 100644
index 000000000000..8d7d8d4de9d6
--- /dev/null
+++ b/arch/arm/kernel/perf_event_cpu.c
@@ -0,0 +1,295 @@
1/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License version 2 as
4 * published by the Free Software Foundation.
5 *
6 * This program is distributed in the hope that it will be useful,
7 * but WITHOUT ANY WARRANTY; without even the implied warranty of
8 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 * GNU General Public License for more details.
10 *
11 * You should have received a copy of the GNU General Public License
12 * along with this program; if not, write to the Free Software
13 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
14 *
15 * Copyright (C) 2012 ARM Limited
16 *
17 * Author: Will Deacon <will.deacon@arm.com>
18 */
19#define pr_fmt(fmt) "CPU PMU: " fmt
20
21#include <linux/bitmap.h>
22#include <linux/export.h>
23#include <linux/kernel.h>
24#include <linux/of.h>
25#include <linux/platform_device.h>
26#include <linux/spinlock.h>
27
28#include <asm/cputype.h>
29#include <asm/irq_regs.h>
30#include <asm/pmu.h>
31
32/* Set at runtime when we know what CPU type we are. */
33static struct arm_pmu *cpu_pmu;
34
35static DEFINE_PER_CPU(struct perf_event * [ARMPMU_MAX_HWEVENTS], hw_events);
36static DEFINE_PER_CPU(unsigned long [BITS_TO_LONGS(ARMPMU_MAX_HWEVENTS)], used_mask);
37static DEFINE_PER_CPU(struct pmu_hw_events, cpu_hw_events);
38
39/*
40 * Despite the names, these two functions are CPU-specific and are used
41 * by the OProfile/perf code.
42 */
43const char *perf_pmu_name(void)
44{
45 if (!cpu_pmu)
46 return NULL;
47
48 return cpu_pmu->pmu.name;
49}
50EXPORT_SYMBOL_GPL(perf_pmu_name);
51
52int perf_num_counters(void)
53{
54 int max_events = 0;
55
56 if (cpu_pmu != NULL)
57 max_events = cpu_pmu->num_events;
58
59 return max_events;
60}
61EXPORT_SYMBOL_GPL(perf_num_counters);
62
63/* Include the PMU-specific implementations. */
64#include "perf_event_xscale.c"
65#include "perf_event_v6.c"
66#include "perf_event_v7.c"
67
68static struct pmu_hw_events *cpu_pmu_get_cpu_events(void)
69{
70 return &__get_cpu_var(cpu_hw_events);
71}
72
73static void cpu_pmu_free_irq(void)
74{
75 int i, irq, irqs;
76 struct platform_device *pmu_device = cpu_pmu->plat_device;
77
78 irqs = min(pmu_device->num_resources, num_possible_cpus());
79
80 for (i = 0; i < irqs; ++i) {
81 if (!cpumask_test_and_clear_cpu(i, &cpu_pmu->active_irqs))
82 continue;
83 irq = platform_get_irq(pmu_device, i);
84 if (irq >= 0)
85 free_irq(irq, cpu_pmu);
86 }
87}
88
89static int cpu_pmu_request_irq(irq_handler_t handler)
90{
91 int i, err, irq, irqs;
92 struct platform_device *pmu_device = cpu_pmu->plat_device;
93
94 if (!pmu_device)
95 return -ENODEV;
96
97 irqs = min(pmu_device->num_resources, num_possible_cpus());
98 if (irqs < 1) {
99 pr_err("no irqs for PMUs defined\n");
100 return -ENODEV;
101 }
102
103 for (i = 0; i < irqs; ++i) {
104 err = 0;
105 irq = platform_get_irq(pmu_device, i);
106 if (irq < 0)
107 continue;
108
109 /*
110 * If we have a single PMU interrupt that we can't shift,
111 * assume that we're running on a uniprocessor machine and
112 * continue. Otherwise, continue without this interrupt.
113 */
114 if (irq_set_affinity(irq, cpumask_of(i)) && irqs > 1) {
115 pr_warning("unable to set irq affinity (irq=%d, cpu=%u)\n",
116 irq, i);
117 continue;
118 }
119
120 err = request_irq(irq, handler, IRQF_NOBALANCING, "arm-pmu",
121 cpu_pmu);
122 if (err) {
123 pr_err("unable to request IRQ%d for ARM PMU counters\n",
124 irq);
125 return err;
126 }
127
128 cpumask_set_cpu(i, &cpu_pmu->active_irqs);
129 }
130
131 return 0;
132}
133
134static void __devinit cpu_pmu_init(struct arm_pmu *cpu_pmu)
135{
136 int cpu;
137 for_each_possible_cpu(cpu) {
138 struct pmu_hw_events *events = &per_cpu(cpu_hw_events, cpu);
139 events->events = per_cpu(hw_events, cpu);
140 events->used_mask = per_cpu(used_mask, cpu);
141 raw_spin_lock_init(&events->pmu_lock);
142 }
143
144 cpu_pmu->get_hw_events = cpu_pmu_get_cpu_events;
145 cpu_pmu->request_irq = cpu_pmu_request_irq;
146 cpu_pmu->free_irq = cpu_pmu_free_irq;
147
148 /* Ensure the PMU has sane values out of reset. */
149 if (cpu_pmu && cpu_pmu->reset)
150 on_each_cpu(cpu_pmu->reset, NULL, 1);
151}
152
153/*
154 * PMU hardware loses all context when a CPU goes offline.
155 * When a CPU is hotplugged back in, since some hardware registers are
156 * UNKNOWN at reset, the PMU must be explicitly reset to avoid reading
157 * junk values out of them.
158 */
159static int __cpuinit cpu_pmu_notify(struct notifier_block *b,
160 unsigned long action, void *hcpu)
161{
162 if ((action & ~CPU_TASKS_FROZEN) != CPU_STARTING)
163 return NOTIFY_DONE;
164
165 if (cpu_pmu && cpu_pmu->reset)
166 cpu_pmu->reset(NULL);
167
168 return NOTIFY_OK;
169}
170
171static struct notifier_block __cpuinitdata cpu_pmu_hotplug_notifier = {
172 .notifier_call = cpu_pmu_notify,
173};
174
175/*
176 * PMU platform driver and devicetree bindings.
177 */
178static struct of_device_id __devinitdata cpu_pmu_of_device_ids[] = {
179 {.compatible = "arm,cortex-a15-pmu", .data = armv7_a15_pmu_init},
180 {.compatible = "arm,cortex-a9-pmu", .data = armv7_a9_pmu_init},
181 {.compatible = "arm,cortex-a8-pmu", .data = armv7_a8_pmu_init},
182 {.compatible = "arm,cortex-a7-pmu", .data = armv7_a7_pmu_init},
183 {.compatible = "arm,cortex-a5-pmu", .data = armv7_a5_pmu_init},
184 {.compatible = "arm,arm11mpcore-pmu", .data = armv6mpcore_pmu_init},
185 {.compatible = "arm,arm1176-pmu", .data = armv6pmu_init},
186 {.compatible = "arm,arm1136-pmu", .data = armv6pmu_init},
187 {},
188};
189
190static struct platform_device_id __devinitdata cpu_pmu_plat_device_ids[] = {
191 {.name = "arm-pmu"},
192 {},
193};
194
195/*
196 * CPU PMU identification and probing.
197 */
198static struct arm_pmu *__devinit probe_current_pmu(void)
199{
200 struct arm_pmu *pmu = NULL;
201 int cpu = get_cpu();
202 unsigned long cpuid = read_cpuid_id();
203 unsigned long implementor = (cpuid & 0xFF000000) >> 24;
204 unsigned long part_number = (cpuid & 0xFFF0);
205
206 pr_info("probing PMU on CPU %d\n", cpu);
207
208 /* ARM Ltd CPUs. */
209 if (0x41 == implementor) {
210 switch (part_number) {
211 case 0xB360: /* ARM1136 */
212 case 0xB560: /* ARM1156 */
213 case 0xB760: /* ARM1176 */
214 pmu = armv6pmu_init();
215 break;
216 case 0xB020: /* ARM11mpcore */
217 pmu = armv6mpcore_pmu_init();
218 break;
219 case 0xC080: /* Cortex-A8 */
220 pmu = armv7_a8_pmu_init();
221 break;
222 case 0xC090: /* Cortex-A9 */
223 pmu = armv7_a9_pmu_init();
224 break;
225 case 0xC050: /* Cortex-A5 */
226 pmu = armv7_a5_pmu_init();
227 break;
228 case 0xC0F0: /* Cortex-A15 */
229 pmu = armv7_a15_pmu_init();
230 break;
231 case 0xC070: /* Cortex-A7 */
232 pmu = armv7_a7_pmu_init();
233 break;
234 }
235 /* Intel CPUs [xscale]. */
236 } else if (0x69 == implementor) {
237 part_number = (cpuid >> 13) & 0x7;
238 switch (part_number) {
239 case 1:
240 pmu = xscale1pmu_init();
241 break;
242 case 2:
243 pmu = xscale2pmu_init();
244 break;
245 }
246 }
247
248 put_cpu();
249 return pmu;
250}
251
252static int __devinit cpu_pmu_device_probe(struct platform_device *pdev)
253{
254 const struct of_device_id *of_id;
255 struct arm_pmu *(*init_fn)(void);
256 struct device_node *node = pdev->dev.of_node;
257
258 if (cpu_pmu) {
259 pr_info("attempt to register multiple PMU devices!");
260 return -ENOSPC;
261 }
262
263 if (node && (of_id = of_match_node(cpu_pmu_of_device_ids, pdev->dev.of_node))) {
264 init_fn = of_id->data;
265 cpu_pmu = init_fn();
266 } else {
267 cpu_pmu = probe_current_pmu();
268 }
269
270 if (!cpu_pmu)
271 return -ENODEV;
272
273 cpu_pmu->plat_device = pdev;
274 cpu_pmu_init(cpu_pmu);
275 register_cpu_notifier(&cpu_pmu_hotplug_notifier);
276 armpmu_register(cpu_pmu, cpu_pmu->name, PERF_TYPE_RAW);
277
278 return 0;
279}
280
281static struct platform_driver cpu_pmu_driver = {
282 .driver = {
283 .name = "arm-pmu",
284 .pm = &armpmu_dev_pm_ops,
285 .of_match_table = cpu_pmu_of_device_ids,
286 },
287 .probe = cpu_pmu_device_probe,
288 .id_table = cpu_pmu_plat_device_ids,
289};
290
291static int __init register_pmu_driver(void)
292{
293 return platform_driver_register(&cpu_pmu_driver);
294}
295device_initcall(register_pmu_driver);
diff --git a/arch/arm/kernel/perf_event_v6.c b/arch/arm/kernel/perf_event_v6.c
index c90fcb2b6967..6ccc07971745 100644
--- a/arch/arm/kernel/perf_event_v6.c
+++ b/arch/arm/kernel/perf_event_v6.c
@@ -645,7 +645,7 @@ armv6mpcore_pmu_disable_event(struct hw_perf_event *hwc,
645 645
646static int armv6_map_event(struct perf_event *event) 646static int armv6_map_event(struct perf_event *event)
647{ 647{
648 return map_cpu_event(event, &armv6_perf_map, 648 return armpmu_map_event(event, &armv6_perf_map,
649 &armv6_perf_cache_map, 0xFF); 649 &armv6_perf_cache_map, 0xFF);
650} 650}
651 651
@@ -664,7 +664,7 @@ static struct arm_pmu armv6pmu = {
664 .max_period = (1LLU << 32) - 1, 664 .max_period = (1LLU << 32) - 1,
665}; 665};
666 666
667static struct arm_pmu *__init armv6pmu_init(void) 667static struct arm_pmu *__devinit armv6pmu_init(void)
668{ 668{
669 return &armv6pmu; 669 return &armv6pmu;
670} 670}
@@ -679,7 +679,7 @@ static struct arm_pmu *__init armv6pmu_init(void)
679 679
680static int armv6mpcore_map_event(struct perf_event *event) 680static int armv6mpcore_map_event(struct perf_event *event)
681{ 681{
682 return map_cpu_event(event, &armv6mpcore_perf_map, 682 return armpmu_map_event(event, &armv6mpcore_perf_map,
683 &armv6mpcore_perf_cache_map, 0xFF); 683 &armv6mpcore_perf_cache_map, 0xFF);
684} 684}
685 685
@@ -698,17 +698,17 @@ static struct arm_pmu armv6mpcore_pmu = {
698 .max_period = (1LLU << 32) - 1, 698 .max_period = (1LLU << 32) - 1,
699}; 699};
700 700
701static struct arm_pmu *__init armv6mpcore_pmu_init(void) 701static struct arm_pmu *__devinit armv6mpcore_pmu_init(void)
702{ 702{
703 return &armv6mpcore_pmu; 703 return &armv6mpcore_pmu;
704} 704}
705#else 705#else
706static struct arm_pmu *__init armv6pmu_init(void) 706static struct arm_pmu *__devinit armv6pmu_init(void)
707{ 707{
708 return NULL; 708 return NULL;
709} 709}
710 710
711static struct arm_pmu *__init armv6mpcore_pmu_init(void) 711static struct arm_pmu *__devinit armv6mpcore_pmu_init(void)
712{ 712{
713 return NULL; 713 return NULL;
714} 714}
diff --git a/arch/arm/kernel/perf_event_v7.c b/arch/arm/kernel/perf_event_v7.c
index f04070bd2183..bd4b090ebcfd 100644
--- a/arch/arm/kernel/perf_event_v7.c
+++ b/arch/arm/kernel/perf_event_v7.c
@@ -1204,31 +1204,31 @@ static void armv7pmu_reset(void *info)
1204 1204
1205static int armv7_a8_map_event(struct perf_event *event) 1205static int armv7_a8_map_event(struct perf_event *event)
1206{ 1206{
1207 return map_cpu_event(event, &armv7_a8_perf_map, 1207 return armpmu_map_event(event, &armv7_a8_perf_map,
1208 &armv7_a8_perf_cache_map, 0xFF); 1208 &armv7_a8_perf_cache_map, 0xFF);
1209} 1209}
1210 1210
1211static int armv7_a9_map_event(struct perf_event *event) 1211static int armv7_a9_map_event(struct perf_event *event)
1212{ 1212{
1213 return map_cpu_event(event, &armv7_a9_perf_map, 1213 return armpmu_map_event(event, &armv7_a9_perf_map,
1214 &armv7_a9_perf_cache_map, 0xFF); 1214 &armv7_a9_perf_cache_map, 0xFF);
1215} 1215}
1216 1216
1217static int armv7_a5_map_event(struct perf_event *event) 1217static int armv7_a5_map_event(struct perf_event *event)
1218{ 1218{
1219 return map_cpu_event(event, &armv7_a5_perf_map, 1219 return armpmu_map_event(event, &armv7_a5_perf_map,
1220 &armv7_a5_perf_cache_map, 0xFF); 1220 &armv7_a5_perf_cache_map, 0xFF);
1221} 1221}
1222 1222
1223static int armv7_a15_map_event(struct perf_event *event) 1223static int armv7_a15_map_event(struct perf_event *event)
1224{ 1224{
1225 return map_cpu_event(event, &armv7_a15_perf_map, 1225 return armpmu_map_event(event, &armv7_a15_perf_map,
1226 &armv7_a15_perf_cache_map, 0xFF); 1226 &armv7_a15_perf_cache_map, 0xFF);
1227} 1227}
1228 1228
1229static int armv7_a7_map_event(struct perf_event *event) 1229static int armv7_a7_map_event(struct perf_event *event)
1230{ 1230{
1231 return map_cpu_event(event, &armv7_a7_perf_map, 1231 return armpmu_map_event(event, &armv7_a7_perf_map,
1232 &armv7_a7_perf_cache_map, 0xFF); 1232 &armv7_a7_perf_cache_map, 0xFF);
1233} 1233}
1234 1234
@@ -1245,7 +1245,7 @@ static struct arm_pmu armv7pmu = {
1245 .max_period = (1LLU << 32) - 1, 1245 .max_period = (1LLU << 32) - 1,
1246}; 1246};
1247 1247
1248static u32 __init armv7_read_num_pmnc_events(void) 1248static u32 __devinit armv7_read_num_pmnc_events(void)
1249{ 1249{
1250 u32 nb_cnt; 1250 u32 nb_cnt;
1251 1251
@@ -1256,7 +1256,7 @@ static u32 __init armv7_read_num_pmnc_events(void)
1256 return nb_cnt + 1; 1256 return nb_cnt + 1;
1257} 1257}
1258 1258
1259static struct arm_pmu *__init armv7_a8_pmu_init(void) 1259static struct arm_pmu *__devinit armv7_a8_pmu_init(void)
1260{ 1260{
1261 armv7pmu.name = "ARMv7 Cortex-A8"; 1261 armv7pmu.name = "ARMv7 Cortex-A8";
1262 armv7pmu.map_event = armv7_a8_map_event; 1262 armv7pmu.map_event = armv7_a8_map_event;
@@ -1264,7 +1264,7 @@ static struct arm_pmu *__init armv7_a8_pmu_init(void)
1264 return &armv7pmu; 1264 return &armv7pmu;
1265} 1265}
1266 1266
1267static struct arm_pmu *__init armv7_a9_pmu_init(void) 1267static struct arm_pmu *__devinit armv7_a9_pmu_init(void)
1268{ 1268{
1269 armv7pmu.name = "ARMv7 Cortex-A9"; 1269 armv7pmu.name = "ARMv7 Cortex-A9";
1270 armv7pmu.map_event = armv7_a9_map_event; 1270 armv7pmu.map_event = armv7_a9_map_event;
@@ -1272,7 +1272,7 @@ static struct arm_pmu *__init armv7_a9_pmu_init(void)
1272 return &armv7pmu; 1272 return &armv7pmu;
1273} 1273}
1274 1274
1275static struct arm_pmu *__init armv7_a5_pmu_init(void) 1275static struct arm_pmu *__devinit armv7_a5_pmu_init(void)
1276{ 1276{
1277 armv7pmu.name = "ARMv7 Cortex-A5"; 1277 armv7pmu.name = "ARMv7 Cortex-A5";
1278 armv7pmu.map_event = armv7_a5_map_event; 1278 armv7pmu.map_event = armv7_a5_map_event;
@@ -1280,7 +1280,7 @@ static struct arm_pmu *__init armv7_a5_pmu_init(void)
1280 return &armv7pmu; 1280 return &armv7pmu;
1281} 1281}
1282 1282
1283static struct arm_pmu *__init armv7_a15_pmu_init(void) 1283static struct arm_pmu *__devinit armv7_a15_pmu_init(void)
1284{ 1284{
1285 armv7pmu.name = "ARMv7 Cortex-A15"; 1285 armv7pmu.name = "ARMv7 Cortex-A15";
1286 armv7pmu.map_event = armv7_a15_map_event; 1286 armv7pmu.map_event = armv7_a15_map_event;
@@ -1289,7 +1289,7 @@ static struct arm_pmu *__init armv7_a15_pmu_init(void)
1289 return &armv7pmu; 1289 return &armv7pmu;
1290} 1290}
1291 1291
1292static struct arm_pmu *__init armv7_a7_pmu_init(void) 1292static struct arm_pmu *__devinit armv7_a7_pmu_init(void)
1293{ 1293{
1294 armv7pmu.name = "ARMv7 Cortex-A7"; 1294 armv7pmu.name = "ARMv7 Cortex-A7";
1295 armv7pmu.map_event = armv7_a7_map_event; 1295 armv7pmu.map_event = armv7_a7_map_event;
@@ -1298,27 +1298,27 @@ static struct arm_pmu *__init armv7_a7_pmu_init(void)
1298 return &armv7pmu; 1298 return &armv7pmu;
1299} 1299}
1300#else 1300#else
1301static struct arm_pmu *__init armv7_a8_pmu_init(void) 1301static struct arm_pmu *__devinit armv7_a8_pmu_init(void)
1302{ 1302{
1303 return NULL; 1303 return NULL;
1304} 1304}
1305 1305
1306static struct arm_pmu *__init armv7_a9_pmu_init(void) 1306static struct arm_pmu *__devinit armv7_a9_pmu_init(void)
1307{ 1307{
1308 return NULL; 1308 return NULL;
1309} 1309}
1310 1310
1311static struct arm_pmu *__init armv7_a5_pmu_init(void) 1311static struct arm_pmu *__devinit armv7_a5_pmu_init(void)
1312{ 1312{
1313 return NULL; 1313 return NULL;
1314} 1314}
1315 1315
1316static struct arm_pmu *__init armv7_a15_pmu_init(void) 1316static struct arm_pmu *__devinit armv7_a15_pmu_init(void)
1317{ 1317{
1318 return NULL; 1318 return NULL;
1319} 1319}
1320 1320
1321static struct arm_pmu *__init armv7_a7_pmu_init(void) 1321static struct arm_pmu *__devinit armv7_a7_pmu_init(void)
1322{ 1322{
1323 return NULL; 1323 return NULL;
1324} 1324}
diff --git a/arch/arm/kernel/perf_event_xscale.c b/arch/arm/kernel/perf_event_xscale.c
index f759fe0bab63..426e19f380a2 100644
--- a/arch/arm/kernel/perf_event_xscale.c
+++ b/arch/arm/kernel/perf_event_xscale.c
@@ -430,7 +430,7 @@ xscale1pmu_write_counter(int counter, u32 val)
430 430
431static int xscale_map_event(struct perf_event *event) 431static int xscale_map_event(struct perf_event *event)
432{ 432{
433 return map_cpu_event(event, &xscale_perf_map, 433 return armpmu_map_event(event, &xscale_perf_map,
434 &xscale_perf_cache_map, 0xFF); 434 &xscale_perf_cache_map, 0xFF);
435} 435}
436 436
@@ -449,7 +449,7 @@ static struct arm_pmu xscale1pmu = {
449 .max_period = (1LLU << 32) - 1, 449 .max_period = (1LLU << 32) - 1,
450}; 450};
451 451
452static struct arm_pmu *__init xscale1pmu_init(void) 452static struct arm_pmu *__devinit xscale1pmu_init(void)
453{ 453{
454 return &xscale1pmu; 454 return &xscale1pmu;
455} 455}
@@ -816,17 +816,17 @@ static struct arm_pmu xscale2pmu = {
816 .max_period = (1LLU << 32) - 1, 816 .max_period = (1LLU << 32) - 1,
817}; 817};
818 818
819static struct arm_pmu *__init xscale2pmu_init(void) 819static struct arm_pmu *__devinit xscale2pmu_init(void)
820{ 820{
821 return &xscale2pmu; 821 return &xscale2pmu;
822} 822}
823#else 823#else
824static struct arm_pmu *__init xscale1pmu_init(void) 824static struct arm_pmu *__devinit xscale1pmu_init(void)
825{ 825{
826 return NULL; 826 return NULL;
827} 827}
828 828
829static struct arm_pmu *__init xscale2pmu_init(void) 829static struct arm_pmu *__devinit xscale2pmu_init(void)
830{ 830{
831 return NULL; 831 return NULL;
832} 832}
diff --git a/arch/arm/kernel/pmu.c b/arch/arm/kernel/pmu.c
deleted file mode 100644
index 2334bf8a650a..000000000000
--- a/arch/arm/kernel/pmu.c
+++ /dev/null
@@ -1,36 +0,0 @@
1/*
2 * linux/arch/arm/kernel/pmu.c
3 *
4 * Copyright (C) 2009 picoChip Designs Ltd, Jamie Iles
5 * Copyright (C) 2010 ARM Ltd, Will Deacon
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 *
11 */
12
13#include <linux/err.h>
14#include <linux/kernel.h>
15#include <linux/module.h>
16
17#include <asm/pmu.h>
18
19/*
20 * PMU locking to ensure mutual exclusion between different subsystems.
21 */
22static unsigned long pmu_lock[BITS_TO_LONGS(ARM_NUM_PMU_DEVICES)];
23
24int
25reserve_pmu(enum arm_pmu_type type)
26{
27 return test_and_set_bit_lock(type, pmu_lock) ? -EBUSY : 0;
28}
29EXPORT_SYMBOL_GPL(reserve_pmu);
30
31void
32release_pmu(enum arm_pmu_type type)
33{
34 clear_bit_unlock(type, pmu_lock);
35}
36EXPORT_SYMBOL_GPL(release_pmu);