[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <1372694659-30176-5-git-send-email-james.hogan@imgtec.com>
Date: Mon, 1 Jul 2013 17:04:18 +0100
From: James Hogan <james.hogan@...tec.com>
To: <linux-kernel@...r.kernel.org>
CC: Thomas Gleixner <tglx@...utronix.de>,
James Hogan <james.hogan@...tec.com>
Subject: [PATCH 4/5] metag: kick: prevent nested kick handlers
The main kick trigger handler iterates a list of kick handlers and calls
each one. This is done with the kick_handlers_lock spin lock held, but
this causes a problem on SMP where IPIs are implemented with kicks. A
reschedule IPI calls scheduler_ipi() which uses irq_enter() and
irq_exit(). This results in the scheduler being invoked with
kick_handlers_lock held which can result in a nested kick trigger
attempting to acquire the lock, resulting in deadlock.
irq_enter() and irq_exit() can nest, so call them from the main kick
interrupt handler so that softirqs are only handled after
kick_handlers_lock is released.
Signed-off-by: James Hogan <james.hogan@...tec.com>
---
arch/metag/kernel/kick.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/arch/metag/kernel/kick.c b/arch/metag/kernel/kick.c
index 50fcbec..beb3776 100644
--- a/arch/metag/kernel/kick.c
+++ b/arch/metag/kernel/kick.c
@@ -26,6 +26,8 @@
* pass it as an argument.
*/
#include <linux/export.h>
+#include <linux/hardirq.h>
+#include <linux/irq.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/types.h>
@@ -66,6 +68,7 @@ EXPORT_SYMBOL(kick_unregister_func);
TBIRES
kick_handler(TBIRES State, int SigNum, int Triggers, int Inst, PTBI pTBI)
{
+ struct pt_regs *old_regs;
struct kick_irq_handler *kh;
struct list_head *lh;
int handled = 0;
@@ -79,6 +82,9 @@ kick_handler(TBIRES State, int SigNum, int Triggers, int Inst, PTBI pTBI)
trace_hardirqs_off();
+ old_regs = set_irq_regs((struct pt_regs *)State.Sig.pCtx);
+ irq_enter();
+
/*
* There is no need to disable interrupts here because we
* can't nest KICK interrupts in a KICK interrupt handler.
@@ -97,5 +103,8 @@ kick_handler(TBIRES State, int SigNum, int Triggers, int Inst, PTBI pTBI)
WARN_ON(!handled);
+ irq_exit();
+ set_irq_regs(old_regs);
+
return tail_end(ret);
}
--
1.8.1.2
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Powered by blists - more mailing lists