diff options
author | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-11-13 22:52:52 +0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-11-13 22:52:52 +0400 |
commit | e592c5d0b7db94b485b4a2342db041a1882b7f75 (patch) | |
tree | 8fee2c21c46b6e9c7ebf79612425cdb0a8b8f35f /drivers/usb/core | |
parent | c0bc3098871dd9b964f6b45ec1e4d70d87811744 (diff) | |
download | linux-e592c5d0b7db94b485b4a2342db041a1882b7f75.tar.xz |
Revert "USB/host: Cleanup unneccessary irq disable code"
This reverts commit 73d4066055e0e2830533041f4b91df8e6e5976ff.
Martin Steigerwald reported that this change caused a hard lockup when
using USB if threadirqs are enabled. Thomas pointed out that this patch
is incorrect, and can cause problems. So revert it to get the
previously working functionality back.
Reported-by: Martin Steigerwald <Martin@lichtvoll.de>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Chuansheng Liu <chuansheng.liu@intel.com>
Cc: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb/core')
-rw-r--r-- | drivers/usb/core/hcd.c | 16 |
1 files changed, 16 insertions, 0 deletions
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 1e741bca0265..f034716190ff 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -2151,8 +2151,15 @@ EXPORT_SYMBOL_GPL(usb_bus_start_enum); irqreturn_t usb_hcd_irq (int irq, void *__hcd) { struct usb_hcd *hcd = __hcd; + unsigned long flags; irqreturn_t rc; + /* IRQF_DISABLED doesn't work correctly with shared IRQs + * when the first handler doesn't use it. So let's just + * assume it's never used. + */ + local_irq_save(flags); + if (unlikely(HCD_DEAD(hcd) || !HCD_HW_ACCESSIBLE(hcd))) rc = IRQ_NONE; else if (hcd->driver->irq(hcd) == IRQ_NONE) @@ -2160,6 +2167,7 @@ irqreturn_t usb_hcd_irq (int irq, void *__hcd) else rc = IRQ_HANDLED; + local_irq_restore(flags); return rc; } EXPORT_SYMBOL_GPL(usb_hcd_irq); @@ -2347,6 +2355,14 @@ static int usb_hcd_request_irqs(struct usb_hcd *hcd, int retval; if (hcd->driver->irq) { + + /* IRQF_DISABLED doesn't work as advertised when used together + * with IRQF_SHARED. As usb_hcd_irq() will always disable + * interrupts we can remove it here. + */ + if (irqflags & IRQF_SHARED) + irqflags &= ~IRQF_DISABLED; + snprintf(hcd->irq_descr, sizeof(hcd->irq_descr), "%s:usb%d", hcd->driver->description, hcd->self.busnum); retval = request_irq(irqnum, &usb_hcd_irq, irqflags, |