aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/kernel/perf_event_cpu.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/kernel/perf_event_cpu.c')
-rw-r--r--arch/arm/kernel/perf_event_cpu.c74
1 files changed, 49 insertions, 25 deletions
diff --git a/arch/arm/kernel/perf_event_cpu.c b/arch/arm/kernel/perf_event_cpu.c
index 8d7d8d4de9d6..9a4f6307a016 100644
--- a/arch/arm/kernel/perf_event_cpu.c
+++ b/arch/arm/kernel/perf_event_cpu.c
@@ -23,6 +23,7 @@
23#include <linux/kernel.h> 23#include <linux/kernel.h>
24#include <linux/of.h> 24#include <linux/of.h>
25#include <linux/platform_device.h> 25#include <linux/platform_device.h>
26#include <linux/slab.h>
26#include <linux/spinlock.h> 27#include <linux/spinlock.h>
27 28
28#include <asm/cputype.h> 29#include <asm/cputype.h>
@@ -45,7 +46,7 @@ const char *perf_pmu_name(void)
45 if (!cpu_pmu) 46 if (!cpu_pmu)
46 return NULL; 47 return NULL;
47 48
48 return cpu_pmu->pmu.name; 49 return cpu_pmu->name;
49} 50}
50EXPORT_SYMBOL_GPL(perf_pmu_name); 51EXPORT_SYMBOL_GPL(perf_pmu_name);
51 52
@@ -70,7 +71,7 @@ static struct pmu_hw_events *cpu_pmu_get_cpu_events(void)
70 return &__get_cpu_var(cpu_hw_events); 71 return &__get_cpu_var(cpu_hw_events);
71} 72}
72 73
73static void cpu_pmu_free_irq(void) 74static void cpu_pmu_free_irq(struct arm_pmu *cpu_pmu)
74{ 75{
75 int i, irq, irqs; 76 int i, irq, irqs;
76 struct platform_device *pmu_device = cpu_pmu->plat_device; 77 struct platform_device *pmu_device = cpu_pmu->plat_device;
@@ -86,7 +87,7 @@ static void cpu_pmu_free_irq(void)
86 } 87 }
87} 88}
88 89
89static int cpu_pmu_request_irq(irq_handler_t handler) 90static int cpu_pmu_request_irq(struct arm_pmu *cpu_pmu, irq_handler_t handler)
90{ 91{
91 int i, err, irq, irqs; 92 int i, err, irq, irqs;
92 struct platform_device *pmu_device = cpu_pmu->plat_device; 93 struct platform_device *pmu_device = cpu_pmu->plat_device;
@@ -147,7 +148,7 @@ static void __devinit cpu_pmu_init(struct arm_pmu *cpu_pmu)
147 148
148 /* Ensure the PMU has sane values out of reset. */ 149 /* Ensure the PMU has sane values out of reset. */
149 if (cpu_pmu && cpu_pmu->reset) 150 if (cpu_pmu && cpu_pmu->reset)
150 on_each_cpu(cpu_pmu->reset, NULL, 1); 151 on_each_cpu(cpu_pmu->reset, cpu_pmu, 1);
151} 152}
152 153
153/* 154/*
@@ -163,7 +164,9 @@ static int __cpuinit cpu_pmu_notify(struct notifier_block *b,
163 return NOTIFY_DONE; 164 return NOTIFY_DONE;
164 165
165 if (cpu_pmu && cpu_pmu->reset) 166 if (cpu_pmu && cpu_pmu->reset)
166 cpu_pmu->reset(NULL); 167 cpu_pmu->reset(cpu_pmu);
168 else
169 return NOTIFY_DONE;
167 170
168 return NOTIFY_OK; 171 return NOTIFY_OK;
169} 172}
@@ -195,13 +198,13 @@ static struct platform_device_id __devinitdata cpu_pmu_plat_device_ids[] = {
195/* 198/*
196 * CPU PMU identification and probing. 199 * CPU PMU identification and probing.
197 */ 200 */
198static struct arm_pmu *__devinit probe_current_pmu(void) 201static int __devinit probe_current_pmu(struct arm_pmu *pmu)
199{ 202{
200 struct arm_pmu *pmu = NULL;
201 int cpu = get_cpu(); 203 int cpu = get_cpu();
202 unsigned long cpuid = read_cpuid_id(); 204 unsigned long cpuid = read_cpuid_id();
203 unsigned long implementor = (cpuid & 0xFF000000) >> 24; 205 unsigned long implementor = (cpuid & 0xFF000000) >> 24;
204 unsigned long part_number = (cpuid & 0xFFF0); 206 unsigned long part_number = (cpuid & 0xFFF0);
207 int ret = -ENODEV;
205 208
206 pr_info("probing PMU on CPU %d\n", cpu); 209 pr_info("probing PMU on CPU %d\n", cpu);
207 210
@@ -211,25 +214,25 @@ static struct arm_pmu *__devinit probe_current_pmu(void)
211 case 0xB360: /* ARM1136 */ 214 case 0xB360: /* ARM1136 */
212 case 0xB560: /* ARM1156 */ 215 case 0xB560: /* ARM1156 */
213 case 0xB760: /* ARM1176 */ 216 case 0xB760: /* ARM1176 */
214 pmu = armv6pmu_init(); 217 ret = armv6pmu_init(pmu);
215 break; 218 break;
216 case 0xB020: /* ARM11mpcore */ 219 case 0xB020: /* ARM11mpcore */
217 pmu = armv6mpcore_pmu_init(); 220 ret = armv6mpcore_pmu_init(pmu);
218 break; 221 break;
219 case 0xC080: /* Cortex-A8 */ 222 case 0xC080: /* Cortex-A8 */
220 pmu = armv7_a8_pmu_init(); 223 ret = armv7_a8_pmu_init(pmu);
221 break; 224 break;
222 case 0xC090: /* Cortex-A9 */ 225 case 0xC090: /* Cortex-A9 */
223 pmu = armv7_a9_pmu_init(); 226 ret = armv7_a9_pmu_init(pmu);
224 break; 227 break;
225 case 0xC050: /* Cortex-A5 */ 228 case 0xC050: /* Cortex-A5 */
226 pmu = armv7_a5_pmu_init(); 229 ret = armv7_a5_pmu_init(pmu);
227 break; 230 break;
228 case 0xC0F0: /* Cortex-A15 */ 231 case 0xC0F0: /* Cortex-A15 */
229 pmu = armv7_a15_pmu_init(); 232 ret = armv7_a15_pmu_init(pmu);
230 break; 233 break;
231 case 0xC070: /* Cortex-A7 */ 234 case 0xC070: /* Cortex-A7 */
232 pmu = armv7_a7_pmu_init(); 235 ret = armv7_a7_pmu_init(pmu);
233 break; 236 break;
234 } 237 }
235 /* Intel CPUs [xscale]. */ 238 /* Intel CPUs [xscale]. */
@@ -237,43 +240,54 @@ static struct arm_pmu *__devinit probe_current_pmu(void)
237 part_number = (cpuid >> 13) & 0x7; 240 part_number = (cpuid >> 13) & 0x7;
238 switch (part_number) { 241 switch (part_number) {
239 case 1: 242 case 1:
240 pmu = xscale1pmu_init(); 243 ret = xscale1pmu_init(pmu);
241 break; 244 break;
242 case 2: 245 case 2:
243 pmu = xscale2pmu_init(); 246 ret = xscale2pmu_init(pmu);
244 break; 247 break;
245 } 248 }
246 } 249 }
247 250
248 put_cpu(); 251 put_cpu();
249 return pmu; 252 return ret;
250} 253}
251 254
252static int __devinit cpu_pmu_device_probe(struct platform_device *pdev) 255static int __devinit cpu_pmu_device_probe(struct platform_device *pdev)
253{ 256{
254 const struct of_device_id *of_id; 257 const struct of_device_id *of_id;
255 struct arm_pmu *(*init_fn)(void); 258 int (*init_fn)(struct arm_pmu *);
256 struct device_node *node = pdev->dev.of_node; 259 struct device_node *node = pdev->dev.of_node;
260 struct arm_pmu *pmu;
261 int ret = -ENODEV;
257 262
258 if (cpu_pmu) { 263 if (cpu_pmu) {
259 pr_info("attempt to register multiple PMU devices!"); 264 pr_info("attempt to register multiple PMU devices!");
260 return -ENOSPC; 265 return -ENOSPC;
261 } 266 }
262 267
268 pmu = kzalloc(sizeof(struct arm_pmu), GFP_KERNEL);
269 if (!pmu) {
270 pr_info("failed to allocate PMU device!");
271 return -ENOMEM;
272 }
273
263 if (node && (of_id = of_match_node(cpu_pmu_of_device_ids, pdev->dev.of_node))) { 274 if (node && (of_id = of_match_node(cpu_pmu_of_device_ids, pdev->dev.of_node))) {
264 init_fn = of_id->data; 275 init_fn = of_id->data;
265 cpu_pmu = init_fn(); 276 ret = init_fn(pmu);
266 } else { 277 } else {
267 cpu_pmu = probe_current_pmu(); 278 ret = probe_current_pmu(pmu);
268 } 279 }
269 280
270 if (!cpu_pmu) 281 if (ret) {
271 return -ENODEV; 282 pr_info("failed to register PMU devices!");
283 kfree(pmu);
284 return ret;
285 }
272 286
287 cpu_pmu = pmu;
273 cpu_pmu->plat_device = pdev; 288 cpu_pmu->plat_device = pdev;
274 cpu_pmu_init(cpu_pmu); 289 cpu_pmu_init(cpu_pmu);
275 register_cpu_notifier(&cpu_pmu_hotplug_notifier); 290 armpmu_register(cpu_pmu, PERF_TYPE_RAW);
276 armpmu_register(cpu_pmu, cpu_pmu->name, PERF_TYPE_RAW);
277 291
278 return 0; 292 return 0;
279} 293}
@@ -290,6 +304,16 @@ static struct platform_driver cpu_pmu_driver = {
290 304
291static int __init register_pmu_driver(void) 305static int __init register_pmu_driver(void)
292{ 306{
293 return platform_driver_register(&cpu_pmu_driver); 307 int err;
308
309 err = register_cpu_notifier(&cpu_pmu_hotplug_notifier);
310 if (err)
311 return err;
312
313 err = platform_driver_register(&cpu_pmu_driver);
314 if (err)
315 unregister_cpu_notifier(&cpu_pmu_hotplug_notifier);
316
317 return err;
294} 318}
295device_initcall(register_pmu_driver); 319device_initcall(register_pmu_driver);