aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/oprofile
diff options
context:
space:
mode:
authorWill Deacon <will.deacon@arm.com>2010-08-29 14:52:00 -0400
committerRobert Richter <robert.richter@amd.com>2010-08-31 05:49:07 -0400
commitc7fd239a647ead1c336a051012d6bb96465ea8c6 (patch)
tree0ea0d2f251c1979a05d5e10bae1a0296187b95ac /arch/arm/oprofile
parent979048e1f26190d16b5aea87166177f37e614439 (diff)
ARM: oprofile: fix and simplify init/exit functions
Now that oprofile_arch_exit is only called when the OProfile module is unloaded, it can assume that init completed successfully and not have to worry about double frees or releasing NULL perf events. This patch ensures that oprofile_arch_init fails gracefully on ARM and simplifies the exit code based on the above. Cc: Robert Richter <robert.richter@amd.com> Cc: Matt Fleming <matt@console-pimps.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Ingo Molnar <mingo@elte.hu> Signed-off-by: Will Deacon <will.deacon@arm.com> Signed-off-by: Robert Richter <robert.richter@amd.com>
Diffstat (limited to 'arch/arm/oprofile')
-rw-r--r--arch/arm/oprofile/common.c47
1 files changed, 25 insertions, 22 deletions
diff --git a/arch/arm/oprofile/common.c b/arch/arm/oprofile/common.c
index 0691176899ff..c3652f73fed4 100644
--- a/arch/arm/oprofile/common.c
+++ b/arch/arm/oprofile/common.c
@@ -275,7 +275,7 @@ out:
275 return ret; 275 return ret;
276} 276}
277 277
278static void exit_driverfs(void) 278static void __exit exit_driverfs(void)
279{ 279{
280 platform_device_unregister(oprofile_pdev); 280 platform_device_unregister(oprofile_pdev);
281 platform_driver_unregister(&oprofile_driver); 281 platform_driver_unregister(&oprofile_driver);
@@ -359,14 +359,13 @@ int __init oprofile_arch_init(struct oprofile_operations *ops)
359 if (!counter_config) { 359 if (!counter_config) {
360 pr_info("oprofile: failed to allocate %d " 360 pr_info("oprofile: failed to allocate %d "
361 "counters\n", perf_num_counters); 361 "counters\n", perf_num_counters);
362 return -ENOMEM; 362 ret = -ENOMEM;
363 goto out;
363 } 364 }
364 365
365 ret = init_driverfs(); 366 ret = init_driverfs();
366 if (ret) { 367 if (ret)
367 kfree(counter_config); 368 goto out;
368 return ret;
369 }
370 369
371 for_each_possible_cpu(cpu) { 370 for_each_possible_cpu(cpu) {
372 perf_events[cpu] = kcalloc(perf_num_counters, 371 perf_events[cpu] = kcalloc(perf_num_counters,
@@ -374,9 +373,8 @@ int __init oprofile_arch_init(struct oprofile_operations *ops)
374 if (!perf_events[cpu]) { 373 if (!perf_events[cpu]) {
375 pr_info("oprofile: failed to allocate %d perf events " 374 pr_info("oprofile: failed to allocate %d perf events "
376 "for cpu %d\n", perf_num_counters, cpu); 375 "for cpu %d\n", perf_num_counters, cpu);
377 while (--cpu >= 0) 376 ret = -ENOMEM;
378 kfree(perf_events[cpu]); 377 goto out;
379 return -ENOMEM;
380 } 378 }
381 } 379 }
382 380
@@ -393,28 +391,33 @@ int __init oprofile_arch_init(struct oprofile_operations *ops)
393 else 391 else
394 pr_info("oprofile: using %s\n", ops->cpu_type); 392 pr_info("oprofile: using %s\n", ops->cpu_type);
395 393
394out:
395 if (ret) {
396 for_each_possible_cpu(cpu)
397 kfree(perf_events[cpu]);
398 kfree(counter_config);
399 }
400
396 return ret; 401 return ret;
397} 402}
398 403
399void oprofile_arch_exit(void) 404void __exit oprofile_arch_exit(void)
400{ 405{
401 int cpu, id; 406 int cpu, id;
402 struct perf_event *event; 407 struct perf_event *event;
403 408
404 if (*perf_events) { 409 for_each_possible_cpu(cpu) {
405 exit_driverfs(); 410 for (id = 0; id < perf_num_counters; ++id) {
406 for_each_possible_cpu(cpu) { 411 event = perf_events[cpu][id];
407 for (id = 0; id < perf_num_counters; ++id) { 412 if (event)
408 event = perf_events[cpu][id]; 413 perf_event_release_kernel(event);
409 if (event != NULL)
410 perf_event_release_kernel(event);
411 }
412 kfree(perf_events[cpu]);
413 } 414 }
415
416 kfree(perf_events[cpu]);
414 } 417 }
415 418
416 if (counter_config) 419 kfree(counter_config);
417 kfree(counter_config); 420 exit_driverfs();
418} 421}
419#else 422#else
420int __init oprofile_arch_init(struct oprofile_operations *ops) 423int __init oprofile_arch_init(struct oprofile_operations *ops)
@@ -422,5 +425,5 @@ int __init oprofile_arch_init(struct oprofile_operations *ops)
422 pr_info("oprofile: hardware counters not available\n"); 425 pr_info("oprofile: hardware counters not available\n");
423 return -ENODEV; 426 return -ENODEV;
424} 427}
425void oprofile_arch_exit(void) {} 428void __exit oprofile_arch_exit(void) {}
426#endif /* CONFIG_HW_PERF_EVENTS */ 429#endif /* CONFIG_HW_PERF_EVENTS */