Skip to content

Commit c6317bc

Browse files
committed
ARCv2: perf: Ensure perf intr gets enabled on all cores
This was the second perf intr issue perf sampling on multicore requires intr to be enabled on all cores. ARC perf probe code used helper arc_request_percpu_irq() which calls - request_percpu_irq() on core0 - enable_percpu_irq() on all all cores (including core0) genirq requires that request be made ahead of enable call. However if perf probe happened on non core0 (observed on a 3.18 kernel), enable would get called ahead of request, failing obviously and rendering perf intr disabled on all such cores [ 11.120000] 1 ARC perf : 8 counters (48 bits), 113 conditions, [overflow IRQ support] [ 11.130000] 1 -----> enable_percpu_irq() IRQ 20 failed [ 11.140000] 3 -----> enable_percpu_irq() IRQ 20 failed [ 11.140000] 2 -----> enable_percpu_irq() IRQ 20 failed [ 11.140000] 0 =====> request_percpu_irq() IRQ 20 [ 11.140000] 0 -----> enable_percpu_irq() IRQ 20 Fix this fragility, by calling request_percpu_irq() on whatever core calls probe (there is no requirement on which core calls this anyways) and then calling enable on each cores. Interestingly this started as invesigation of STAR 9000838902: "sporadically IRQs enabled on perf prob" which was about occassional boot spew as request_percpu_irq got called non-locally (from an IPI), and re-enabled interrupts in following path proc_mkdir -> spin_unlock_irq() which the irq work code didn't like. | ARC perf : 8 counters (48 bits), 113 conditions, [overflow IRQ support] | | BUG: failure at ../kernel/irq_work.c:135/irq_work_run_list()! | CPU: 0 PID: 0 Comm: swapper/0 Not tainted 3.18.10-01127-g285efb8e66d1 #2 | | Stack Trace: | arc_unwind_core.constprop.1+0x94/0x104 | dump_stack+0x62/0x98 | irq_work_run_list+0xb0/0xb4 | irq_work_run+0x22/0x3c | do_IPI+0x74/0x9c | handle_irq_event_percpu+0x34/0x164 | handle_percpu_irq+0x58/0x78 | generic_handle_irq+0x1e/0x2c | arch_do_IRQ+0x3c/0x60 | ret_from_exception+0x0/0x8 Cc: Marc Zyngier <[email protected]> Cc: Peter Zijlstra <[email protected]> Cc: Thomas Gleixner <[email protected]> Cc: [email protected] Cc: [email protected] Cc: Alexey Brodkin <[email protected]> Cc: <[email protected]> #4.2+ Signed-off-by: Vineet Gupta <[email protected]>
1 parent 5bf704c commit c6317bc

File tree

1 file changed

+9
-23
lines changed

1 file changed

+9
-23
lines changed

arch/arc/kernel/perf_event.c

Lines changed: 9 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -428,12 +428,11 @@ static irqreturn_t arc_pmu_intr(int irq, void *dev)
428428

429429
#endif /* CONFIG_ISA_ARCV2 */
430430

431-
void arc_cpu_pmu_irq_init(void)
431+
static void arc_cpu_pmu_irq_init(void *data)
432432
{
433-
struct arc_pmu_cpu *pmu_cpu = this_cpu_ptr(&arc_pmu_cpu);
433+
int irq = *(int *)data;
434434

435-
arc_request_percpu_irq(arc_pmu->irq, smp_processor_id(), arc_pmu_intr,
436-
"ARC perf counters", pmu_cpu);
435+
enable_percpu_irq(irq, IRQ_TYPE_NONE);
437436

438437
/* Clear all pending interrupt flags */
439438
write_aux_reg(ARC_REG_PCT_INT_ACT, 0xffffffff);
@@ -515,7 +514,6 @@ static int arc_pmu_device_probe(struct platform_device *pdev)
515514

516515
if (has_interrupts) {
517516
int irq = platform_get_irq(pdev, 0);
518-
unsigned long flags;
519517

520518
if (irq < 0) {
521519
pr_err("Cannot get IRQ number for the platform\n");
@@ -524,24 +522,12 @@ static int arc_pmu_device_probe(struct platform_device *pdev)
524522

525523
arc_pmu->irq = irq;
526524

527-
/*
528-
* arc_cpu_pmu_irq_init() needs to be called on all cores for
529-
* their respective local PMU.
530-
* However we use opencoded on_each_cpu() to ensure it is called
531-
* on core0 first, so that arc_request_percpu_irq() sets up
532-
* AUTOEN etc. Otherwise enable_percpu_irq() fails to enable
533-
* perf IRQ on non master cores.
534-
* see arc_request_percpu_irq()
535-
*/
536-
preempt_disable();
537-
local_irq_save(flags);
538-
arc_cpu_pmu_irq_init();
539-
local_irq_restore(flags);
540-
smp_call_function((smp_call_func_t)arc_cpu_pmu_irq_init, 0, 1);
541-
preempt_enable();
542-
543-
/* Clean all pending interrupt flags */
544-
write_aux_reg(ARC_REG_PCT_INT_ACT, 0xffffffff);
525+
/* intc map function ensures irq_set_percpu_devid() called */
526+
request_percpu_irq(irq, arc_pmu_intr, "ARC perf counters",
527+
this_cpu_ptr(&arc_pmu_cpu));
528+
529+
on_each_cpu(arc_cpu_pmu_irq_init, &irq, 1);
530+
545531
} else
546532
arc_pmu->pmu.capabilities |= PERF_PMU_CAP_NO_INTERRUPT;
547533

0 commit comments

Comments
 (0)