diff options
author | Nicolas Pitre <nicolas.pitre@linaro.org> | 2014-07-25 16:05:31 -0400 |
---|---|---|
committer | Steven Rostedt <rostedt@goodmis.org> | 2014-08-07 20:40:41 -0400 |
commit | 365ec7b17327329efc71276722ca8db3f21f2edd (patch) | |
tree | 620a7260ca6cd55032a79d22e99d9a83cd62d439 /arch/arm/kernel/smp.c | |
parent | f6d9804d145b9c42dbbabefdda208a6a492b2236 (diff) |
ARM: add IPI tracepoints
The strings used to list IPIs in /proc/interrupts are reused for tracing
purposes.
While at it, prevent a negative ipinr from escaping the range check
in handle_IPI().
Link: http://lkml.kernel.org/p/1406318733-26754-4-git-send-email-nicolas.pitre@linaro.org
Acked-by: Daniel Lezcano <daniel.lezcano@linaro.org>
Signed-off-by: Nicolas Pitre <nico@linaro.org>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Diffstat (limited to 'arch/arm/kernel/smp.c')
-rw-r--r-- | arch/arm/kernel/smp.c | 70 |
1 files changed, 42 insertions, 28 deletions
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index 7c4fada440f0..9388a3d479e1 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c | |||
@@ -47,6 +47,9 @@ | |||
47 | #include <asm/mach/arch.h> | 47 | #include <asm/mach/arch.h> |
48 | #include <asm/mpu.h> | 48 | #include <asm/mpu.h> |
49 | 49 | ||
50 | #define CREATE_TRACE_POINTS | ||
51 | #include <trace/events/ipi.h> | ||
52 | |||
50 | /* | 53 | /* |
51 | * as from 2.5, kernels no longer have an init_tasks structure | 54 | * as from 2.5, kernels no longer have an init_tasks structure |
52 | * so we need some other way of telling a new secondary core | 55 | * so we need some other way of telling a new secondary core |
@@ -430,38 +433,15 @@ void __init smp_prepare_cpus(unsigned int max_cpus) | |||
430 | } | 433 | } |
431 | } | 434 | } |
432 | 435 | ||
433 | static void (*smp_cross_call)(const struct cpumask *, unsigned int); | 436 | static void (*__smp_cross_call)(const struct cpumask *, unsigned int); |
434 | 437 | ||
435 | void __init set_smp_cross_call(void (*fn)(const struct cpumask *, unsigned int)) | 438 | void __init set_smp_cross_call(void (*fn)(const struct cpumask *, unsigned int)) |
436 | { | 439 | { |
437 | if (!smp_cross_call) | 440 | if (!__smp_cross_call) |
438 | smp_cross_call = fn; | 441 | __smp_cross_call = fn; |
439 | } | ||
440 | |||
441 | void arch_send_call_function_ipi_mask(const struct cpumask *mask) | ||
442 | { | ||
443 | smp_cross_call(mask, IPI_CALL_FUNC); | ||
444 | } | ||
445 | |||
446 | void arch_send_wakeup_ipi_mask(const struct cpumask *mask) | ||
447 | { | ||
448 | smp_cross_call(mask, IPI_WAKEUP); | ||
449 | } | ||
450 | |||
451 | void arch_send_call_function_single_ipi(int cpu) | ||
452 | { | ||
453 | smp_cross_call(cpumask_of(cpu), IPI_CALL_FUNC_SINGLE); | ||
454 | } | 442 | } |
455 | 443 | ||
456 | #ifdef CONFIG_IRQ_WORK | 444 | static const char *ipi_types[NR_IPI] __tracepoint_string = { |
457 | void arch_irq_work_raise(void) | ||
458 | { | ||
459 | if (is_smp()) | ||
460 | smp_cross_call(cpumask_of(smp_processor_id()), IPI_IRQ_WORK); | ||
461 | } | ||
462 | #endif | ||
463 | |||
464 | static const char *ipi_types[NR_IPI] = { | ||
465 | #define S(x,s) [x] = s | 445 | #define S(x,s) [x] = s |
466 | S(IPI_WAKEUP, "CPU wakeup interrupts"), | 446 | S(IPI_WAKEUP, "CPU wakeup interrupts"), |
467 | S(IPI_TIMER, "Timer broadcast interrupts"), | 447 | S(IPI_TIMER, "Timer broadcast interrupts"), |
@@ -473,6 +453,12 @@ static const char *ipi_types[NR_IPI] = { | |||
473 | S(IPI_COMPLETION, "completion interrupts"), | 453 | S(IPI_COMPLETION, "completion interrupts"), |
474 | }; | 454 | }; |
475 | 455 | ||
456 | static void smp_cross_call(const struct cpumask *target, unsigned int ipinr) | ||
457 | { | ||
458 | trace_ipi_raise(target, ipi_types[ipinr]); | ||
459 | __smp_cross_call(target, ipinr); | ||
460 | } | ||
461 | |||
476 | void show_ipi_list(struct seq_file *p, int prec) | 462 | void show_ipi_list(struct seq_file *p, int prec) |
477 | { | 463 | { |
478 | unsigned int cpu, i; | 464 | unsigned int cpu, i; |
@@ -499,6 +485,29 @@ u64 smp_irq_stat_cpu(unsigned int cpu) | |||
499 | return sum; | 485 | return sum; |
500 | } | 486 | } |
501 | 487 | ||
488 | void arch_send_call_function_ipi_mask(const struct cpumask *mask) | ||
489 | { | ||
490 | smp_cross_call(mask, IPI_CALL_FUNC); | ||
491 | } | ||
492 | |||
493 | void arch_send_wakeup_ipi_mask(const struct cpumask *mask) | ||
494 | { | ||
495 | smp_cross_call(mask, IPI_WAKEUP); | ||
496 | } | ||
497 | |||
498 | void arch_send_call_function_single_ipi(int cpu) | ||
499 | { | ||
500 | smp_cross_call(cpumask_of(cpu), IPI_CALL_FUNC_SINGLE); | ||
501 | } | ||
502 | |||
503 | #ifdef CONFIG_IRQ_WORK | ||
504 | void arch_irq_work_raise(void) | ||
505 | { | ||
506 | if (is_smp()) | ||
507 | smp_cross_call(cpumask_of(smp_processor_id()), IPI_IRQ_WORK); | ||
508 | } | ||
509 | #endif | ||
510 | |||
502 | #ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST | 511 | #ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST |
503 | void tick_broadcast(const struct cpumask *mask) | 512 | void tick_broadcast(const struct cpumask *mask) |
504 | { | 513 | { |
@@ -556,8 +565,10 @@ void handle_IPI(int ipinr, struct pt_regs *regs) | |||
556 | unsigned int cpu = smp_processor_id(); | 565 | unsigned int cpu = smp_processor_id(); |
557 | struct pt_regs *old_regs = set_irq_regs(regs); | 566 | struct pt_regs *old_regs = set_irq_regs(regs); |
558 | 567 | ||
559 | if (ipinr < NR_IPI) | 568 | if ((unsigned)ipinr < NR_IPI) { |
569 | trace_ipi_entry(ipi_types[ipinr]); | ||
560 | __inc_irq_stat(cpu, ipi_irqs[ipinr]); | 570 | __inc_irq_stat(cpu, ipi_irqs[ipinr]); |
571 | } | ||
561 | 572 | ||
562 | switch (ipinr) { | 573 | switch (ipinr) { |
563 | case IPI_WAKEUP: | 574 | case IPI_WAKEUP: |
@@ -612,6 +623,9 @@ void handle_IPI(int ipinr, struct pt_regs *regs) | |||
612 | cpu, ipinr); | 623 | cpu, ipinr); |
613 | break; | 624 | break; |
614 | } | 625 | } |
626 | |||
627 | if ((unsigned)ipinr < NR_IPI) | ||
628 | trace_ipi_exit(ipi_types[ipinr]); | ||
615 | set_irq_regs(old_regs); | 629 | set_irq_regs(old_regs); |
616 | } | 630 | } |
617 | 631 | ||