diff options
author | Andy Wingo <wingo@pobox.com> | 2005-10-20 00:23:46 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-10-20 02:04:30 -0400 |
commit | 4a9949d7ac9e2bc51939f27b184be6e1bd99004e (patch) | |
tree | 85f67b527d3ff5a550ada8e08600f1400ddc5960 /drivers/ieee1394/ohci1394.c | |
parent | c367c21c93ccdaf7e1e124891633d89f9ae77f54 (diff) |
[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.c | 6 |
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, | |||
2283 | { | 2283 | { |
2284 | struct ohci1394_iso_tasklet *t; | 2284 | struct ohci1394_iso_tasklet *t; |
2285 | unsigned long mask; | 2285 | unsigned long mask; |
2286 | unsigned long flags; | ||
2286 | 2287 | ||
2287 | spin_lock(&ohci->iso_tasklet_list_lock); | 2288 | spin_lock_irqsave(&ohci->iso_tasklet_list_lock, flags); |
2288 | 2289 | ||
2289 | list_for_each_entry(t, &ohci->iso_tasklet_list, link) { | 2290 | list_for_each_entry(t, &ohci->iso_tasklet_list, link) { |
2290 | mask = 1 << t->context; | 2291 | mask = 1 << t->context; |
@@ -2295,8 +2296,7 @@ static void ohci_schedule_iso_tasklets(struct ti_ohci *ohci, | |||
2295 | tasklet_schedule(&t->tasklet); | 2296 | tasklet_schedule(&t->tasklet); |
2296 | } | 2297 | } |
2297 | 2298 | ||
2298 | spin_unlock(&ohci->iso_tasklet_list_lock); | 2299 | spin_unlock_irqrestore(&ohci->iso_tasklet_list_lock, flags); |
2299 | |||
2300 | } | 2300 | } |
2301 | 2301 | ||
2302 | static irqreturn_t ohci_irq_handler(int irq, void *dev_id, | 2302 | static irqreturn_t ohci_irq_handler(int irq, void *dev_id, |