@@ -149,6 +149,16 @@ void usb_anchor_urb(struct urb *urb, struct usb_anchor *anchor)
}
EXPORT_SYMBOL_GPL(usb_anchor_urb);
/* Callers must hold anchor->lock */
static void __usb_unanchor_urb(struct urb *urb, struct usb_anchor *anchor)
{
urb->anchor = NULL;
list_del(&urb->anchor_list);
usb_put_urb(urb);
if (list_empty(&anchor->urb_list))
wake_up(&anchor->wait);
/**
* usb_unanchor_urb - unanchors an URB
* @urb: pointer to the urb to anchor
@@ -168,17 +178,13 @@ void usb_unanchor_urb(struct urb *urb)
return;
spin_lock_irqsave(&anchor->lock, flags);
if (unlikely(anchor != urb->anchor)) {
/* we've lost the race to another thread */
spin_unlock_irqrestore(&anchor->lock, flags);
/* At this point, we could be competing with another thread which
* has the same intention. To protect the urb from being unanchored
* twice, only the winner of the race gets the job.
*/
if (likely(anchor == urb->anchor))
__usb_unanchor_urb(urb, anchor);
EXPORT_SYMBOL_GPL(usb_unanchor_urb);
@@ -828,20 +834,11 @@ EXPORT_SYMBOL_GPL(usb_unpoison_anchored_urbs);
void usb_unlink_anchored_urbs(struct usb_anchor *anchor)
struct urb *victim;
unsigned long flags;
while (!list_empty(&anchor->urb_list)) {
victim = list_entry(anchor->urb_list.prev, struct urb,
anchor_list);
usb_get_urb(victim);
/* this will unanchor the URB */
while ((victim = usb_get_from_anchor(anchor)) != NULL) {
usb_unlink_urb(victim);
usb_put_urb(victim);
EXPORT_SYMBOL_GPL(usb_unlink_anchored_urbs);
@@ -878,13 +875,13 @@ struct urb *usb_get_from_anchor(struct usb_anchor *anchor)
victim = list_entry(anchor->urb_list.next, struct urb,
usb_unanchor_urb(victim);
__usb_unanchor_urb(victim, anchor);
} else {
victim = NULL;
return victim;
@@ -905,12 +902,7 @@ void usb_scuttle_anchored_urbs(struct usb_anchor *anchor)
/* this may free the URB */