diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-08-10 18:05:02 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-08-10 18:05:02 -0400 |
commit | 9895850b23886e030cd1e7241d5529a57e969c3d (patch) | |
tree | 1061626db450aeb72dcfcd247c24b33e5238c8c4 /drivers/usb/core/urb.c | |
parent | fc385c313275b114bc6ad36e60c5177d63250548 (diff) | |
parent | b58af4066d240b18b43f202e07b9ec7461d90b17 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6: (148 commits)
USB: serial: fix stalled writes
USB: remove fake "address-of" expressions
USB: fix thread-unsafe anchor utiliy routines
USB: usbtest: support test device with only one iso-in or iso-out endpoint
USB: usbtest: avoid to free coherent buffer in atomic context
USB: xhci: Set DMA mask for host.
USB: xhci: Don't flush doorbell writes.
USB: xhci: Reduce reads and writes of interrupter registers.
USB: xhci: Make xhci_set_hc_event_deq() static.
USB: xhci: Minimize HW event ring dequeue pointer writes.
USB: xhci: Make xhci_handle_event() static.
USB: xhci: Remove unnecessary reads of IRQ_PENDING register.
USB: xhci: Performance - move xhci_work() into xhci_irq()
USB: xhci: Performance - move interrupt handlers into xhci-ring.c
USB: xhci: Performance - move functions that find ep ring.
USB:: fix linux/usb.h kernel-doc warnings
USB: add USB serial ssu100 driver
USB: usb-storage: implement autosuspend
USB: ehci: fix remove of ehci debugfs dir
USB: Add USB 2.0 to ssb ohci driver
...
Diffstat (limited to 'drivers/usb/core/urb.c')
-rw-r--r-- | drivers/usb/core/urb.c | 50 |
1 files changed, 21 insertions, 29 deletions
diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c index 7c0555548ac..419e6b34e2f 100644 --- a/drivers/usb/core/urb.c +++ b/drivers/usb/core/urb.c | |||
@@ -137,6 +137,16 @@ void usb_anchor_urb(struct urb *urb, struct usb_anchor *anchor) | |||
137 | } | 137 | } |
138 | EXPORT_SYMBOL_GPL(usb_anchor_urb); | 138 | EXPORT_SYMBOL_GPL(usb_anchor_urb); |
139 | 139 | ||
140 | /* Callers must hold anchor->lock */ | ||
141 | static void __usb_unanchor_urb(struct urb *urb, struct usb_anchor *anchor) | ||
142 | { | ||
143 | urb->anchor = NULL; | ||
144 | list_del(&urb->anchor_list); | ||
145 | usb_put_urb(urb); | ||
146 | if (list_empty(&anchor->urb_list)) | ||
147 | wake_up(&anchor->wait); | ||
148 | } | ||
149 | |||
140 | /** | 150 | /** |
141 | * usb_unanchor_urb - unanchors an URB | 151 | * usb_unanchor_urb - unanchors an URB |
142 | * @urb: pointer to the urb to anchor | 152 | * @urb: pointer to the urb to anchor |
@@ -156,17 +166,14 @@ void usb_unanchor_urb(struct urb *urb) | |||
156 | return; | 166 | return; |
157 | 167 | ||
158 | spin_lock_irqsave(&anchor->lock, flags); | 168 | spin_lock_irqsave(&anchor->lock, flags); |
159 | if (unlikely(anchor != urb->anchor)) { | 169 | /* |
160 | /* we've lost the race to another thread */ | 170 | * At this point, we could be competing with another thread which |
161 | spin_unlock_irqrestore(&anchor->lock, flags); | 171 | * has the same intention. To protect the urb from being unanchored |
162 | return; | 172 | * twice, only the winner of the race gets the job. |
163 | } | 173 | */ |
164 | urb->anchor = NULL; | 174 | if (likely(anchor == urb->anchor)) |
165 | list_del(&urb->anchor_list); | 175 | __usb_unanchor_urb(urb, anchor); |
166 | spin_unlock_irqrestore(&anchor->lock, flags); | 176 | spin_unlock_irqrestore(&anchor->lock, flags); |
167 | usb_put_urb(urb); | ||
168 | if (list_empty(&anchor->urb_list)) | ||
169 | wake_up(&anchor->wait); | ||
170 | } | 177 | } |
171 | EXPORT_SYMBOL_GPL(usb_unanchor_urb); | 178 | EXPORT_SYMBOL_GPL(usb_unanchor_urb); |
172 | 179 | ||
@@ -749,20 +756,11 @@ EXPORT_SYMBOL_GPL(usb_unpoison_anchored_urbs); | |||
749 | void usb_unlink_anchored_urbs(struct usb_anchor *anchor) | 756 | void usb_unlink_anchored_urbs(struct usb_anchor *anchor) |
750 | { | 757 | { |
751 | struct urb *victim; | 758 | struct urb *victim; |
752 | unsigned long flags; | ||
753 | 759 | ||
754 | spin_lock_irqsave(&anchor->lock, flags); | 760 | while ((victim = usb_get_from_anchor(anchor)) != NULL) { |
755 | while (!list_empty(&anchor->urb_list)) { | ||
756 | victim = list_entry(anchor->urb_list.prev, struct urb, | ||
757 | anchor_list); | ||
758 | usb_get_urb(victim); | ||
759 | spin_unlock_irqrestore(&anchor->lock, flags); | ||
760 | /* this will unanchor the URB */ | ||
761 | usb_unlink_urb(victim); | 761 | usb_unlink_urb(victim); |
762 | usb_put_urb(victim); | 762 | usb_put_urb(victim); |
763 | spin_lock_irqsave(&anchor->lock, flags); | ||
764 | } | 763 | } |
765 | spin_unlock_irqrestore(&anchor->lock, flags); | ||
766 | } | 764 | } |
767 | EXPORT_SYMBOL_GPL(usb_unlink_anchored_urbs); | 765 | EXPORT_SYMBOL_GPL(usb_unlink_anchored_urbs); |
768 | 766 | ||
@@ -799,12 +797,11 @@ struct urb *usb_get_from_anchor(struct usb_anchor *anchor) | |||
799 | victim = list_entry(anchor->urb_list.next, struct urb, | 797 | victim = list_entry(anchor->urb_list.next, struct urb, |
800 | anchor_list); | 798 | anchor_list); |
801 | usb_get_urb(victim); | 799 | usb_get_urb(victim); |
802 | spin_unlock_irqrestore(&anchor->lock, flags); | 800 | __usb_unanchor_urb(victim, anchor); |
803 | usb_unanchor_urb(victim); | ||
804 | } else { | 801 | } else { |
805 | spin_unlock_irqrestore(&anchor->lock, flags); | ||
806 | victim = NULL; | 802 | victim = NULL; |
807 | } | 803 | } |
804 | spin_unlock_irqrestore(&anchor->lock, flags); | ||
808 | 805 | ||
809 | return victim; | 806 | return victim; |
810 | } | 807 | } |
@@ -826,12 +823,7 @@ void usb_scuttle_anchored_urbs(struct usb_anchor *anchor) | |||
826 | while (!list_empty(&anchor->urb_list)) { | 823 | while (!list_empty(&anchor->urb_list)) { |
827 | victim = list_entry(anchor->urb_list.prev, struct urb, | 824 | victim = list_entry(anchor->urb_list.prev, struct urb, |
828 | anchor_list); | 825 | anchor_list); |
829 | usb_get_urb(victim); | 826 | __usb_unanchor_urb(victim, anchor); |
830 | spin_unlock_irqrestore(&anchor->lock, flags); | ||
831 | /* this may free the URB */ | ||
832 | usb_unanchor_urb(victim); | ||
833 | usb_put_urb(victim); | ||
834 | spin_lock_irqsave(&anchor->lock, flags); | ||
835 | } | 827 | } |
836 | spin_unlock_irqrestore(&anchor->lock, flags); | 828 | spin_unlock_irqrestore(&anchor->lock, flags); |
837 | } | 829 | } |