ARM PMU interrupt is not threaded and we run all handlers with interrupts
disabled, but irq_work_run() would be called at the end of the interrupt
handler, so below warning would be triggered by the sleeppable spin_lock
when run 'perf top' command:
BUG: sleeping function called from invalid context at linux/kernel/rtmutex.c:658
in_atomic(): 1, irqs_disabled(): 128, pid: 1731, name: perf
[<80017d6c>] (unwind_backtrace+0x0/0x104) from [<806416c4>] 
(dump_stack+0x20/0x24)
[<806416c4>] (dump_stack+0x20/0x24) from [<80061208>] (__might_sleep+0xf4/0x108)
[<80061208>] (__might_sleep+0xf4/0x108) from [<8064a74c>] 
(rt_spin_lock+0x2c/0x38)
[<8064a74c>] (rt_spin_lock+0x2c/0x38) from [<800642e8>] (__wake_up+0x34/0x60)
[<800642e8>] (__wake_up+0x34/0x60) from [<800e2610>] 
(perf_event_wakeup+0x40/0x84)
[<800e2610>] (perf_event_wakeup+0x40/0x84) from [<800e2690>] 
(perf_pending_event+0x3c/0x60)
[<800e2690>] (perf_pending_event+0x3c/0x60) from [<800dd36c>] 
(irq_work_run+0x74/0xa4)
[<800dd36c>] (irq_work_run+0x74/0xa4) from [<8001b018>] 
(armv7pmu_handle_irq+0x12c/0x19c)
[<8001b018>] (armv7pmu_handle_irq+0x12c/0x19c) from [<800a87b0>] 
(handle_irq_event_percpu+0xf0/0x438)
[<800a87b0>] (handle_irq_event_percpu+0xf0/0x438) from [<800a8b70>] 
(handle_irq_event+0x78/0xa0)
[<800a8b70>] (handle_irq_event+0x78/0xa0) from [<800abdac>] 
(handle_fasteoi_irq+0xd4/0x18c)
[<800abdac>] (handle_fasteoi_irq+0xd4/0x18c) from [<800a7e70>] 
(generic_handle_irq+0x40/0x50)
[<800a7e70>] (generic_handle_irq+0x40/0x50) from [<8000f7a4>] 
(handle_IRQ+0x68/0xbc)
[<8000f7a4>] (handle_IRQ+0x68/0xbc) from [<800084e8>] (gic_handle_irq+0x38/0x68)
[<800084e8>] (gic_handle_irq+0x38/0x68) from [<8064b100>] (__irq_svc+0x40/0x70)

Inspired by 
upstream(git://git.kernel.org/pub/scm/linux/kernel/git/rt/linux-stable-rt.git)
commit 8baf86762 "x86-no-perf-irq-work-rt.patch", we can run the irq-work under 
softirq
context in rt kernel to resolve this problem.

Signed-off-by: Xufeng Zhang <[email protected]>
---
 arch/arm/kernel/perf_event_v6.c     |    2 ++
 arch/arm/kernel/perf_event_v7.c     |    2 ++
 arch/arm/kernel/perf_event_xscale.c |    4 ++++
 3 files changed, 8 insertions(+), 0 deletions(-)

diff --git a/arch/arm/kernel/perf_event_v6.c b/arch/arm/kernel/perf_event_v6.c
index b78af0c..b432a65 100644
--- a/arch/arm/kernel/perf_event_v6.c
+++ b/arch/arm/kernel/perf_event_v6.c
@@ -524,7 +524,9 @@ armv6pmu_handle_irq(int irq_num,
         * platforms that can have the PMU interrupts raised as an NMI, this
         * will not work.
         */
+#ifndef CONFIG_PREEMPT_RT_FULL
        irq_work_run();
+#endif
 
        return IRQ_HANDLED;
 }
diff --git a/arch/arm/kernel/perf_event_v7.c b/arch/arm/kernel/perf_event_v7.c
index 00755d8..4331eab 100644
--- a/arch/arm/kernel/perf_event_v7.c
+++ b/arch/arm/kernel/perf_event_v7.c
@@ -1112,7 +1112,9 @@ static irqreturn_t armv7pmu_handle_irq(int irq_num, void 
*dev)
         * platforms that can have the PMU interrupts raised as an NMI, this
         * will not work.
         */
+#ifndef CONFIG_PREEMPT_RT_FULL
        irq_work_run();
+#endif
 
        return IRQ_HANDLED;
 }
diff --git a/arch/arm/kernel/perf_event_xscale.c 
b/arch/arm/kernel/perf_event_xscale.c
index 71a21e6..9bb9a0f 100644
--- a/arch/arm/kernel/perf_event_xscale.c
+++ b/arch/arm/kernel/perf_event_xscale.c
@@ -271,7 +271,9 @@ xscale1pmu_handle_irq(int irq_num, void *dev)
                        cpu_pmu->disable(hwc, idx);
        }
 
+#ifndef CONFIG_PREEMPT_RT_FULL
        irq_work_run();
+#endif
 
        /*
         * Re-enable the PMU.
@@ -611,7 +613,9 @@ xscale2pmu_handle_irq(int irq_num, void *dev)
                        cpu_pmu->disable(hwc, idx);
        }
 
+#ifndef CONFIG_PREEMPT_RT_FULL
        irq_work_run();
+#endif
 
        /*
         * Re-enable the PMU.
-- 
1.7.1

_______________________________________________
linux-yocto mailing list
[email protected]
https://lists.yoctoproject.org/listinfo/linux-yocto

Reply via email to