From 13cc2dab097545e5e8bc3f951ab1c06eb8b3ff8f Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Mon, 25 Aug 2008 22:40:25 +0200 Subject: [PATCH] --- yaml --- r: 115788 b: refs/heads/master c: 1987625226a918cd20c334ffce5e2a224cba0718 h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/drivers/usb/core/urb.c | 70 ++++++++++++++++++++++++++++++++++++ trunk/include/linux/usb.h | 3 ++ 3 files changed, 74 insertions(+), 1 deletion(-) diff --git a/[refs] b/[refs] index 02a170315e5c..6a4d8ac76fd8 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: c0f082c5367a02e8493d779e16ad336167e14718 +refs/heads/master: 1987625226a918cd20c334ffce5e2a224cba0718 diff --git a/trunk/drivers/usb/core/urb.c b/trunk/drivers/usb/core/urb.c index eebc070c3cc7..175d528f4029 100644 --- a/trunk/drivers/usb/core/urb.c +++ b/trunk/drivers/usb/core/urb.c @@ -716,3 +716,73 @@ int usb_wait_anchor_empty_timeout(struct usb_anchor *anchor, msecs_to_jiffies(timeout)); } EXPORT_SYMBOL_GPL(usb_wait_anchor_empty_timeout); + +/** + * usb_get_from_anchor - get an anchor's oldest urb + * @anchor: the anchor whose urb you want + * + * this will take the oldest urb from an anchor, + * unanchor and return it + */ +struct urb *usb_get_from_anchor(struct usb_anchor *anchor) +{ + struct urb *victim; + unsigned long flags; + + spin_lock_irqsave(&anchor->lock, flags); + if (!list_empty(&anchor->urb_list)) { + victim = list_entry(anchor->urb_list.next, struct urb, + anchor_list); + usb_get_urb(victim); + spin_unlock_irqrestore(&anchor->lock, flags); + usb_unanchor_urb(victim); + } else { + spin_unlock_irqrestore(&anchor->lock, flags); + victim = NULL; + } + + return victim; +} + +EXPORT_SYMBOL_GPL(usb_get_from_anchor); + +/** + * usb_scuttle_anchored_urbs - unanchor all an anchor's urbs + * @anchor: the anchor whose urbs you want to unanchor + * + * use this to get rid of all an anchor's urbs + */ +void usb_scuttle_anchored_urbs(struct usb_anchor *anchor) +{ + struct urb *victim; + unsigned long flags; + + spin_lock_irqsave(&anchor->lock, flags); + while (!list_empty(&anchor->urb_list)) { + victim = list_entry(anchor->urb_list.prev, struct urb, + anchor_list); + usb_get_urb(victim); + spin_unlock_irqrestore(&anchor->lock, flags); + /* this may free the URB */ + usb_unanchor_urb(victim); + usb_put_urb(victim); + spin_lock_irqsave(&anchor->lock, flags); + } + spin_unlock_irqrestore(&anchor->lock, flags); +} + +EXPORT_SYMBOL_GPL(usb_scuttle_anchored_urbs); + +/** + * usb_anchor_empty - is an anchor empty + * @anchor: the anchor you want to query + * + * returns 1 if the anchor has no urbs associated with it + */ +int usb_anchor_empty(struct usb_anchor *anchor) +{ + return list_empty(&anchor->urb_list); +} + +EXPORT_SYMBOL_GPL(usb_anchor_empty); + diff --git a/trunk/include/linux/usb.h b/trunk/include/linux/usb.h index d97927970f54..8fa973bede5e 100644 --- a/trunk/include/linux/usb.h +++ b/trunk/include/linux/usb.h @@ -1469,6 +1469,9 @@ extern void usb_anchor_urb(struct urb *urb, struct usb_anchor *anchor); extern void usb_unanchor_urb(struct urb *urb); extern int usb_wait_anchor_empty_timeout(struct usb_anchor *anchor, unsigned int timeout); +extern struct urb *usb_get_from_anchor(struct usb_anchor *anchor); +extern void usb_scuttle_anchored_urbs(struct usb_anchor *anchor); +extern int usb_anchor_empty(struct usb_anchor *anchor); /** * usb_urb_dir_in - check if an URB describes an IN transfer