[4.2.y-ckt stable] Patch "genirq: Prevent chip buslock deadlock" has been added to the 4.2.y-ckt tree

Kamal Mostafa kamal at canonical.com
Fri Jan 15 23:58:18 UTC 2016


This is a note to let you know that I have just added a patch titled

    genirq: Prevent chip buslock deadlock

to the linux-4.2.y-queue branch of the 4.2.y-ckt extended stable tree 
which can be found at:

    http://kernel.ubuntu.com/git/ubuntu/linux.git/log/?h=linux-4.2.y-queue

This patch is scheduled to be released in version 4.2.8-ckt2.

If you, or anyone else, feels it should not be added to this tree, please 
reply to this email.

For more information about the 4.2.y-ckt tree, see
https://wiki.ubuntu.com/Kernel/Dev/ExtendedStable

Thanks.
-Kamal

---8<------------------------------------------------------------

>From 763b76d289cad3b68991285495d2e4b46a28b9de Mon Sep 17 00:00:00 2001
From: Thomas Gleixner <tglx at linutronix.de>
Date: Sun, 13 Dec 2015 18:12:30 +0100
Subject: genirq: Prevent chip buslock deadlock
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

commit abc7e40c81d113ef4bacb556f0a77ca63ac81d85 upstream.

If a interrupt chip utilizes chip->buslock then free_irq() can
deadlock in the following way:

CPU0				CPU1
				interrupt(X) (Shared or spurious)
free_irq(X)			interrupt_thread(X)
chip_bus_lock(X)
				   irq_finalize_oneshot(X)
				     chip_bus_lock(X)
synchronize_irq(X)

synchronize_irq() waits for the interrupt thread to complete,
i.e. forever.

Solution is simple: Drop chip_bus_lock() before calling
synchronize_irq() as we do with the irq_desc lock. There is nothing to
be protected after the point where irq_desc lock has been released.

This adds chip_bus_lock/unlock() to the remove_irq() code path, but
that's actually correct in the case where remove_irq() is called on
such an interrupt. The current users of remove_irq() are not affected
as none of those interrupts is on a chip which requires buslock.

Reported-by: Fredrik Markström <fredrik.markstrom at gmail.com>
Signed-off-by: Thomas Gleixner <tglx at linutronix.de>
Signed-off-by: Kamal Mostafa <kamal at canonical.com>
---
 kernel/irq/manage.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index f974485..aaec958 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -1363,6 +1363,7 @@ static struct irqaction *__free_irq(unsigned int irq, void *dev_id)
 	if (!desc)
 		return NULL;

+	chip_bus_lock(desc);
 	raw_spin_lock_irqsave(&desc->lock, flags);

 	/*
@@ -1376,7 +1377,7 @@ static struct irqaction *__free_irq(unsigned int irq, void *dev_id)
 		if (!action) {
 			WARN(1, "Trying to free already-free IRQ %d\n", irq);
 			raw_spin_unlock_irqrestore(&desc->lock, flags);
-
+			chip_bus_sync_unlock(desc);
 			return NULL;
 		}

@@ -1403,6 +1404,7 @@ static struct irqaction *__free_irq(unsigned int irq, void *dev_id)
 #endif

 	raw_spin_unlock_irqrestore(&desc->lock, flags);
+	chip_bus_sync_unlock(desc);

 	unregister_handler_proc(irq, action);

@@ -1476,9 +1478,7 @@ void free_irq(unsigned int irq, void *dev_id)
 		desc->affinity_notify = NULL;
 #endif

-	chip_bus_lock(desc);
 	kfree(__free_irq(irq, dev_id));
-	chip_bus_sync_unlock(desc);
 }
 EXPORT_SYMBOL(free_irq);

--
1.9.1





More information about the kernel-team mailing list