Commit 1987625226a918cd20c334ffce5e2a224cba0718
Committed by
Greg Kroah-Hartman
1 parent
c0f082c536
Exists in
master
and in
7 other branches
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); |
include/linux/usb.h
... | ... | @@ -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 |