aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOliver Neukum <oliver@neukum.org>2008-08-25 16:40:25 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2008-10-17 17:41:02 -0400
commit1987625226a918cd20c334ffce5e2a224cba0718 (patch)
tree4502ac6292f22c72f1d15fb649d99565e83b7e0a
parentc0f082c5367a02e8493d779e16ad336167e14718 (diff)
USB: anchor API changes needed for btusb
This extends the anchor API as btusb needs for autosuspend. Signed-off-by: Oliver Neukum <oneukum@suse.de> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r--drivers/usb/core/urb.c70
-rw-r--r--include/linux/usb.h3
2 files changed, 73 insertions, 0 deletions
diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c
index eebc070c3cc7..175d528f4029 100644
--- a/drivers/usb/core/urb.c
+++ b/drivers/usb/core/urb.c
@@ -716,3 +716,73 @@ int usb_wait_anchor_empty_timeout(struct usb_anchor *anchor,
716 msecs_to_jiffies(timeout)); 716 msecs_to_jiffies(timeout));
717} 717}
718EXPORT_SYMBOL_GPL(usb_wait_anchor_empty_timeout); 718EXPORT_SYMBOL_GPL(usb_wait_anchor_empty_timeout);
719
720/**
721 * usb_get_from_anchor - get an anchor's oldest urb
722 * @anchor: the anchor whose urb you want
723 *
724 * this will take the oldest urb from an anchor,
725 * unanchor and return it
726 */
727struct urb *usb_get_from_anchor(struct usb_anchor *anchor)
728{
729 struct urb *victim;
730 unsigned long flags;
731
732 spin_lock_irqsave(&anchor->lock, flags);
733 if (!list_empty(&anchor->urb_list)) {
734 victim = list_entry(anchor->urb_list.next, struct urb,
735 anchor_list);
736 usb_get_urb(victim);
737 spin_unlock_irqrestore(&anchor->lock, flags);
738 usb_unanchor_urb(victim);
739 } else {
740 spin_unlock_irqrestore(&anchor->lock, flags);
741 victim = NULL;
742 }
743
744 return victim;
745}
746
747EXPORT_SYMBOL_GPL(usb_get_from_anchor);
748
749/**
750 * usb_scuttle_anchored_urbs - unanchor all an anchor's urbs
751 * @anchor: the anchor whose urbs you want to unanchor
752 *
753 * use this to get rid of all an anchor's urbs
754 */
755void usb_scuttle_anchored_urbs(struct usb_anchor *anchor)
756{
757 struct urb *victim;
758 unsigned long flags;
759
760 spin_lock_irqsave(&anchor->lock, flags);
761 while (!list_empty(&anchor->urb_list)) {
762 victim = list_entry(anchor->urb_list.prev, struct urb,
763 anchor_list);
764 usb_get_urb(victim);
765 spin_unlock_irqrestore(&anchor->lock, flags);
766 /* this may free the URB */
767 usb_unanchor_urb(victim);
768 usb_put_urb(victim);
769 spin_lock_irqsave(&anchor->lock, flags);
770 }
771 spin_unlock_irqrestore(&anchor->lock, flags);
772}
773
774EXPORT_SYMBOL_GPL(usb_scuttle_anchored_urbs);
775
776/**
777 * usb_anchor_empty - is an anchor empty
778 * @anchor: the anchor you want to query
779 *
780 * returns 1 if the anchor has no urbs associated with it
781 */
782int usb_anchor_empty(struct usb_anchor *anchor)
783{
784 return list_empty(&anchor->urb_list);
785}
786
787EXPORT_SYMBOL_GPL(usb_anchor_empty);
788
diff --git a/include/linux/usb.h b/include/linux/usb.h
index d97927970f54..8fa973bede5e 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -1469,6 +1469,9 @@ extern void usb_anchor_urb(struct urb *urb, struct usb_anchor *anchor);
1469extern void usb_unanchor_urb(struct urb *urb); 1469extern void usb_unanchor_urb(struct urb *urb);
1470extern int usb_wait_anchor_empty_timeout(struct usb_anchor *anchor, 1470extern int usb_wait_anchor_empty_timeout(struct usb_anchor *anchor,
1471 unsigned int timeout); 1471 unsigned int timeout);
1472extern struct urb *usb_get_from_anchor(struct usb_anchor *anchor);
1473extern void usb_scuttle_anchored_urbs(struct usb_anchor *anchor);
1474extern int usb_anchor_empty(struct usb_anchor *anchor);
1472 1475
1473/** 1476/**
1474 * usb_urb_dir_in - check if an URB describes an IN transfer 1477 * usb_urb_dir_in - check if an URB describes an IN transfer