Commit d1df71f8 authored by Alan Stern's avatar Alan Stern Committed by Greg Kroah-Hartman

[PATCH] USB: Fix irq problem in hcd_endpoint_disable()

The recent change made to the irq handling in hcd_endpoint_disable()
caused a problem.  The statement

	local_irq_save (flags);

needs to be outside the rescan loop.  Otherwise, on loop iterations after
the first, flags is always set to indicate that interrupts are disabled.

In fact, since the routine ends with might_sleep() anyway, I don't see any
reason to save the interrupt state at all.  My patch just disables
interrupts at the start and enables them at the end.  I'm not sure that's
how you intended it to work, so you may want to change it a little.
parent 04b4a7d9
......@@ -1273,7 +1273,6 @@ static int hcd_unlink_urb (struct urb *urb)
*/
static void hcd_endpoint_disable (struct usb_device *udev, int endpoint)
{
unsigned long flags;
struct hcd_dev *dev;
struct usb_hcd *hcd;
struct urb *urb;
......@@ -1282,6 +1281,8 @@ static void hcd_endpoint_disable (struct usb_device *udev, int endpoint)
dev = udev->hcpriv;
hcd = udev->bus->hcpriv;
local_irq_disable ();
rescan:
/* (re)block new requests, as best we can */
if (endpoint & USB_DIR_IN) {
......@@ -1293,7 +1294,6 @@ static void hcd_endpoint_disable (struct usb_device *udev, int endpoint)
}
/* then kill any current requests */
local_irq_save (flags);
spin_lock (&hcd_data_lock);
list_for_each_entry (urb, &dev->urb_list, urb_list) {
int tmp = urb->pipe;
......@@ -1342,7 +1342,7 @@ static void hcd_endpoint_disable (struct usb_device *udev, int endpoint)
goto rescan;
}
spin_unlock (&hcd_data_lock);
local_irq_restore (flags);
local_irq_enable ();
/* synchronize with the hardware, so old configuration state
* clears out immediately (and will be freed).
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment