diff options
author | David Vrabel <david.vrabel@csr.com> | 2009-06-24 13:26:40 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2009-09-23 09:46:21 -0400 |
commit | 831baa4915de465357b25c471bbb9b36472024df (patch) | |
tree | b28e8365e77defb84ba1437993b64be753274ead /drivers/usb/host/whci/asl.c | |
parent | 586dfc8cafc25cf785332fdfe9530f392e26f30d (diff) |
USB: whci-hcd: make endpoint_reset method async
usb_hcd_endpoint_reset() may be called in atomic context and must not
sleep. So make whci-hcd's endpoint_reset() asynchronous. URBs
submitted while the reset is in progress will be queued (on the std
list) and transfers will resume once the reset is complete.
Signed-off-by: David Vrabel <david.vrabel@csr.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/host/whci/asl.c')
-rw-r--r-- | drivers/usb/host/whci/asl.c | 12 |
1 files changed, 11 insertions, 1 deletions
diff --git a/drivers/usb/host/whci/asl.c b/drivers/usb/host/whci/asl.c index c2050785a819..c632437c7649 100644 --- a/drivers/usb/host/whci/asl.c +++ b/drivers/usb/host/whci/asl.c | |||
@@ -227,11 +227,21 @@ void scan_async_work(struct work_struct *work) | |||
227 | /* | 227 | /* |
228 | * Now that the ASL is updated, complete the removal of any | 228 | * Now that the ASL is updated, complete the removal of any |
229 | * removed qsets. | 229 | * removed qsets. |
230 | * | ||
231 | * If the qset was to be reset, do so and reinsert it into the | ||
232 | * ASL if it has pending transfers. | ||
230 | */ | 233 | */ |
231 | spin_lock_irq(&whc->lock); | 234 | spin_lock_irq(&whc->lock); |
232 | 235 | ||
233 | list_for_each_entry_safe(qset, t, &whc->async_removed_list, list_node) { | 236 | list_for_each_entry_safe(qset, t, &whc->async_removed_list, list_node) { |
234 | qset_remove_complete(whc, qset); | 237 | qset_remove_complete(whc, qset); |
238 | if (qset->reset) { | ||
239 | qset_reset(whc, qset); | ||
240 | if (!list_empty(&qset->stds)) { | ||
241 | asl_qset_insert_begin(whc, qset); | ||
242 | queue_work(whc->workqueue, &whc->async_work); | ||
243 | } | ||
244 | } | ||
235 | } | 245 | } |
236 | 246 | ||
237 | spin_unlock_irq(&whc->lock); | 247 | spin_unlock_irq(&whc->lock); |
@@ -267,7 +277,7 @@ int asl_urb_enqueue(struct whc *whc, struct urb *urb, gfp_t mem_flags) | |||
267 | else | 277 | else |
268 | err = qset_add_urb(whc, qset, urb, GFP_ATOMIC); | 278 | err = qset_add_urb(whc, qset, urb, GFP_ATOMIC); |
269 | if (!err) { | 279 | if (!err) { |
270 | if (!qset->in_sw_list) | 280 | if (!qset->in_sw_list && !qset->remove) |
271 | asl_qset_insert_begin(whc, qset); | 281 | asl_qset_insert_begin(whc, qset); |
272 | } else | 282 | } else |
273 | usb_hcd_unlink_urb_from_ep(&whc->wusbhc.usb_hcd, urb); | 283 | usb_hcd_unlink_urb_from_ep(&whc->wusbhc.usb_hcd, urb); |