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

[PATCH] USB: Fix a bug in the UHCI dequeueing code

On Mon, 23 Feb 2004, Stephen Hemminger wrote:

> Great, the kernel with this patch ran successfully all weekend.  Looks like no
> more races in the unlink path.

Wonderful.  Thanks a lot for all your SMP testing, it's been a big help.


This patch corrects an error in the dequeueing code for UHCI.  Improper
locking caused it to hang in the oddball case where an URB was unlinked
even before it had been queued.
parent c03edb1b
...@@ -1508,11 +1508,8 @@ static int uhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, int mem_flags) ...@@ -1508,11 +1508,8 @@ static int uhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, int mem_flags)
struct urb_priv *urbp = urb->hcpriv; struct urb_priv *urbp = urb->hcpriv;
list_del_init(&urbp->urb_list); list_del_init(&urbp->urb_list);
spin_unlock_irqrestore(&uhci->urb_list_lock, flags); uhci_destroy_urb_priv(uhci, urb);
uhci_destroy_urb_priv (uhci, urb); } else
return ret;
}
ret = 0; ret = 0;
out: out:
...@@ -1649,10 +1646,12 @@ static int uhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb) ...@@ -1649,10 +1646,12 @@ static int uhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb)
{ {
struct uhci_hcd *uhci = hcd_to_uhci(hcd); struct uhci_hcd *uhci = hcd_to_uhci(hcd);
unsigned long flags; unsigned long flags;
struct urb_priv *urbp = urb->hcpriv; struct urb_priv *urbp;
spin_lock_irqsave(&uhci->urb_list_lock, flags); spin_lock_irqsave(&uhci->urb_list_lock, flags);
urbp = urb->hcpriv;
if (!urbp) /* URB was never linked! */
goto done;
list_del_init(&urbp->urb_list); list_del_init(&urbp->urb_list);
uhci_unlink_generic(uhci, urb); uhci_unlink_generic(uhci, urb);
...@@ -1665,6 +1664,7 @@ static int uhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb) ...@@ -1665,6 +1664,7 @@ static int uhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb)
list_add_tail(&urbp->urb_list, &uhci->urb_remove_list); list_add_tail(&urbp->urb_list, &uhci->urb_remove_list);
spin_unlock(&uhci->urb_remove_list_lock); spin_unlock(&uhci->urb_remove_list_lock);
done:
spin_unlock_irqrestore(&uhci->urb_list_lock, flags); spin_unlock_irqrestore(&uhci->urb_list_lock, flags);
return 0; return 0;
} }
......
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