aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/oprofile/oprofile_perf.c
diff options
context:
space:
mode:
authorRobert Richter <robert.richter@amd.com>2010-09-29 09:42:30 -0400
committerRobert Richter <robert.richter@amd.com>2010-10-11 13:34:04 -0400
commite9677b3ce207a07fad5746b6f7ddc70cae79de0a (patch)
treefd94cd24431c1c853372bea47f662e50a7ea4bcf /drivers/oprofile/oprofile_perf.c
parent2bcb2b641a8f1524f7a9801eb9e52a00b8f18c6e (diff)
oprofile, ARM: Use oprofile_arch_exit() to cleanup on failure
There is duplicate cleanup code in the init and exit functions. Now, oprofile_arch_exit() is also used if oprofile_arch_init() fails. Acked-by: Will Deacon <will.deacon@arm.com> Signed-off-by: Robert Richter <robert.richter@amd.com>
Diffstat (limited to 'drivers/oprofile/oprofile_perf.c')
-rw-r--r--drivers/oprofile/oprofile_perf.c54
1 files changed, 26 insertions, 28 deletions
diff --git a/drivers/oprofile/oprofile_perf.c b/drivers/oprofile/oprofile_perf.c
index a34137f2e26c..b17235a24a4d 100644
--- a/drivers/oprofile/oprofile_perf.c
+++ b/drivers/oprofile/oprofile_perf.c
@@ -245,10 +245,33 @@ static int __init init_driverfs(void) { return 0; }
245#define exit_driverfs() do { } while (0) 245#define exit_driverfs() do { } while (0)
246#endif /* CONFIG_PM */ 246#endif /* CONFIG_PM */
247 247
248void oprofile_perf_exit(void)
249{
250 int cpu, id;
251 struct perf_event *event;
252
253 for_each_possible_cpu(cpu) {
254 for (id = 0; id < num_counters; ++id) {
255 event = perf_events[cpu][id];
256 if (event)
257 perf_event_release_kernel(event);
258 }
259
260 kfree(perf_events[cpu]);
261 }
262
263 kfree(counter_config);
264 exit_driverfs();
265}
266
248int __init oprofile_perf_init(struct oprofile_operations *ops) 267int __init oprofile_perf_init(struct oprofile_operations *ops)
249{ 268{
250 int cpu, ret = 0; 269 int cpu, ret = 0;
251 270
271 ret = init_driverfs();
272 if (ret)
273 return ret;
274
252 memset(&perf_events, 0, sizeof(perf_events)); 275 memset(&perf_events, 0, sizeof(perf_events));
253 276
254 num_counters = perf_num_counters(); 277 num_counters = perf_num_counters();
@@ -265,13 +288,10 @@ int __init oprofile_perf_init(struct oprofile_operations *ops)
265 pr_info("oprofile: failed to allocate %d " 288 pr_info("oprofile: failed to allocate %d "
266 "counters\n", num_counters); 289 "counters\n", num_counters);
267 ret = -ENOMEM; 290 ret = -ENOMEM;
291 num_counters = 0;
268 goto out; 292 goto out;
269 } 293 }
270 294
271 ret = init_driverfs();
272 if (ret)
273 goto out;
274
275 for_each_possible_cpu(cpu) { 295 for_each_possible_cpu(cpu) {
276 perf_events[cpu] = kcalloc(num_counters, 296 perf_events[cpu] = kcalloc(num_counters,
277 sizeof(struct perf_event *), GFP_KERNEL); 297 sizeof(struct perf_event *), GFP_KERNEL);
@@ -296,30 +316,8 @@ int __init oprofile_perf_init(struct oprofile_operations *ops)
296 pr_info("oprofile: using %s\n", ops->cpu_type); 316 pr_info("oprofile: using %s\n", ops->cpu_type);
297 317
298out: 318out:
299 if (ret) { 319 if (ret)
300 for_each_possible_cpu(cpu) 320 oprofile_perf_exit();
301 kfree(perf_events[cpu]);
302 kfree(counter_config);
303 }
304 321
305 return ret; 322 return ret;
306} 323}
307
308void __exit oprofile_perf_exit(void)
309{
310 int cpu, id;
311 struct perf_event *event;
312
313 for_each_possible_cpu(cpu) {
314 for (id = 0; id < num_counters; ++id) {
315 event = perf_events[cpu][id];
316 if (event)
317 perf_event_release_kernel(event);
318 }
319
320 kfree(perf_events[cpu]);
321 }
322
323 kfree(counter_config);
324 exit_driverfs();
325}