summaryrefslogtreecommitdiffstats
path: root/drivers/ieee1394/ohci1394.c
diff options
context:
space:
mode:
authorAndy Wingo <wingo@pobox.com>2005-10-19 21:23:46 -0700
committerLinus Torvalds <torvalds@g5.osdl.org>2005-10-19 23:04:30 -0700
commit4a9949d7ac9e2bc51939f27b184be6e1bd99004e (patch)
tree85f67b527d3ff5a550ada8e08600f1400ddc5960 /drivers/ieee1394/ohci1394.c
parentc367c21c93ccdaf7e1e124891633d89f9ae77f54 (diff)
downloadlinux-4a9949d7ac9e2bc51939f27b184be6e1bd99004e.tar.bz2
[PATCH] raw1394: fix locking in the presence of SMP and interrupts
Changes all spinlocks that can be held during an irq handler to disable interrupts while the lock is held. Changes spin_[un]lock_irq to use the irqsave/irqrestore variants for robustness and readability. In raw1394.c:handle_iso_listen(), don't grab host_info_lock at all -- we're not accessing host_info_list or host_count, and holding this lock while trying to tasklet_kill the iso tasklet this can cause an ABBA deadlock if ohci:dma_rcv_tasklet is running and tries to grab host_info_lock in raw1394.c:receive_iso. Test program attached reliably deadlocks all SMP machines I have been able to test without this patch. Signed-off-by: Andy Wingo <wingo@pobox.com> Acked-by: Ben Collins <bcollins@ubuntu.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers/ieee1394/ohci1394.c')
-rw-r--r--drivers/ieee1394/ohci1394.c6
1 files changed, 3 insertions, 3 deletions
diff --git a/drivers/ieee1394/ohci1394.c b/drivers/ieee1394/ohci1394.c
index 6a6acbd80af4..4cf9b8f3e336 100644
--- a/drivers/ieee1394/ohci1394.c
+++ b/drivers/ieee1394/ohci1394.c
@@ -2283,8 +2283,9 @@ static void ohci_schedule_iso_tasklets(struct ti_ohci *ohci,
{
struct ohci1394_iso_tasklet *t;
unsigned long mask;
+ unsigned long flags;
- spin_lock(&ohci->iso_tasklet_list_lock);
+ spin_lock_irqsave(&ohci->iso_tasklet_list_lock, flags);
list_for_each_entry(t, &ohci->iso_tasklet_list, link) {
mask = 1 << t->context;
@@ -2295,8 +2296,7 @@ static void ohci_schedule_iso_tasklets(struct ti_ohci *ohci,
tasklet_schedule(&t->tasklet);
}
- spin_unlock(&ohci->iso_tasklet_list_lock);
-
+ spin_unlock_irqrestore(&ohci->iso_tasklet_list_lock, flags);
}
static irqreturn_t ohci_irq_handler(int irq, void *dev_id,