Revert "USB/host: Cleanup unneccessary irq disable code"
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 13 Nov 2012 18:52:52 +0000 (10:52 -0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 13 Nov 2012 18:52:52 +0000 (10:52 -0800)
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>
drivers/usb/core/hcd.c
drivers/usb/host/ehci-ls1x.c
drivers/usb/host/ohci-xls.c

index 1e741bca02652e8f4ed2b027654abc3ac9d16a4f..f034716190ff425c89b007e2e10e4cd98ca6cb61 100644 (file)
@@ -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,
index ca759652626bcf5f823a32bf9e6640acda23a02b..aa0f328922dfad88495b919a84d82abd3a494ac9 100644 (file)
@@ -113,7 +113,7 @@ static int ehci_hcd_ls1x_probe(struct platform_device *pdev)
                goto err_put_hcd;
        }
 
-       ret = usb_add_hcd(hcd, irq, IRQF_SHARED);
+       ret = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED);
        if (ret)
                goto err_put_hcd;
 
index 84201cd1a472cd5b00bd959b28bcf35af24137e6..41e378f17c66ac453f2aabfd25640c8e77120224 100644 (file)
@@ -56,7 +56,7 @@ static int ohci_xls_probe_internal(const struct hc_driver *driver,
                goto err3;
        }
 
-       retval = usb_add_hcd(hcd, irq, IRQF_SHARED);
+       retval = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED);
        if (retval != 0)
                goto err4;
        return retval;
This page took 0.028902 seconds and 5 git commands to generate.