aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--kernel/events/hw_breakpoint.c34
1 files changed, 11 insertions, 23 deletions
diff --git a/kernel/events/hw_breakpoint.c b/kernel/events/hw_breakpoint.c
index 9c71445328af..38418f786f36 100644
--- a/kernel/events/hw_breakpoint.c
+++ b/kernel/events/hw_breakpoint.c
@@ -497,8 +497,8 @@ register_wide_hw_breakpoint(struct perf_event_attr *attr,
497 perf_overflow_handler_t triggered, 497 perf_overflow_handler_t triggered,
498 void *context) 498 void *context)
499{ 499{
500 struct perf_event * __percpu *cpu_events, **pevent, *bp; 500 struct perf_event * __percpu *cpu_events, *bp;
501 long err; 501 long err = 0;
502 int cpu; 502 int cpu;
503 503
504 cpu_events = alloc_percpu(typeof(*cpu_events)); 504 cpu_events = alloc_percpu(typeof(*cpu_events));
@@ -507,31 +507,21 @@ register_wide_hw_breakpoint(struct perf_event_attr *attr,
507 507
508 get_online_cpus(); 508 get_online_cpus();
509 for_each_online_cpu(cpu) { 509 for_each_online_cpu(cpu) {
510 pevent = per_cpu_ptr(cpu_events, cpu);
511 bp = perf_event_create_kernel_counter(attr, cpu, NULL, 510 bp = perf_event_create_kernel_counter(attr, cpu, NULL,
512 triggered, context); 511 triggered, context);
513
514 *pevent = bp;
515
516 if (IS_ERR(bp)) { 512 if (IS_ERR(bp)) {
517 err = PTR_ERR(bp); 513 err = PTR_ERR(bp);
518 goto fail; 514 break;
519 } 515 }
520 }
521 put_online_cpus();
522
523 return cpu_events;
524 516
525fail: 517 per_cpu(*cpu_events, cpu) = bp;
526 for_each_online_cpu(cpu) {
527 pevent = per_cpu_ptr(cpu_events, cpu);
528 if (IS_ERR(*pevent))
529 break;
530 unregister_hw_breakpoint(*pevent);
531 } 518 }
532 put_online_cpus(); 519 put_online_cpus();
533 520
534 free_percpu(cpu_events); 521 if (likely(!err))
522 return cpu_events;
523
524 unregister_wide_hw_breakpoint(cpu_events);
535 return (void __percpu __force *)ERR_PTR(err); 525 return (void __percpu __force *)ERR_PTR(err);
536} 526}
537EXPORT_SYMBOL_GPL(register_wide_hw_breakpoint); 527EXPORT_SYMBOL_GPL(register_wide_hw_breakpoint);
@@ -543,12 +533,10 @@ EXPORT_SYMBOL_GPL(register_wide_hw_breakpoint);
543void unregister_wide_hw_breakpoint(struct perf_event * __percpu *cpu_events) 533void unregister_wide_hw_breakpoint(struct perf_event * __percpu *cpu_events)
544{ 534{
545 int cpu; 535 int cpu;
546 struct perf_event **pevent;
547 536
548 for_each_possible_cpu(cpu) { 537 for_each_possible_cpu(cpu)
549 pevent = per_cpu_ptr(cpu_events, cpu); 538 unregister_hw_breakpoint(per_cpu(*cpu_events, cpu));
550 unregister_hw_breakpoint(*pevent); 539
551 }
552 free_percpu(cpu_events); 540 free_percpu(cpu_events);
553} 541}
554EXPORT_SYMBOL_GPL(unregister_wide_hw_breakpoint); 542EXPORT_SYMBOL_GPL(unregister_wide_hw_breakpoint);