Commit 1987625226a918cd20c334ffce5e2a224cba0718

Authored by Oliver Neukum
Committed by Greg Kroah-Hartman
1 parent c0f082c536

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>

Showing 2 changed files with 73 additions and 0 deletions Side-by-side Diff

drivers/usb/core/urb.c
... ... @@ -716,4 +716,73 @@
716 716 msecs_to_jiffies(timeout));
717 717 }
718 718 EXPORT_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 + */
  727 +struct 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 +
  747 +EXPORT_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 + */
  755 +void 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 +
  774 +EXPORT_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 + */
  782 +int usb_anchor_empty(struct usb_anchor *anchor)
  783 +{
  784 + return list_empty(&anchor->urb_list);
  785 +}
  786 +
  787 +EXPORT_SYMBOL_GPL(usb_anchor_empty);
... ... @@ -1469,6 +1469,9 @@
1469 1469 extern void usb_unanchor_urb(struct urb *urb);
1470 1470 extern int usb_wait_anchor_empty_timeout(struct usb_anchor *anchor,
1471 1471 unsigned int timeout);
  1472 +extern struct urb *usb_get_from_anchor(struct usb_anchor *anchor);
  1473 +extern void usb_scuttle_anchored_urbs(struct usb_anchor *anchor);
  1474 +extern int usb_anchor_empty(struct usb_anchor *anchor);
1472 1475  
1473 1476 /**
1474 1477 * usb_urb_dir_in - check if an URB describes an IN transfer