diff options
Diffstat (limited to 'drivers/usb/host/whci/asl.c')
-rw-r--r-- | drivers/usb/host/whci/asl.c | 23 |
1 files changed, 16 insertions, 7 deletions
diff --git a/drivers/usb/host/whci/asl.c b/drivers/usb/host/whci/asl.c index c632437c7649..562eba108816 100644 --- a/drivers/usb/host/whci/asl.c +++ b/drivers/usb/host/whci/asl.c | |||
@@ -115,6 +115,10 @@ static uint32_t process_qset(struct whc *whc, struct whc_qset *qset) | |||
115 | if (status & QTD_STS_HALTED) { | 115 | if (status & QTD_STS_HALTED) { |
116 | /* Ug, an error. */ | 116 | /* Ug, an error. */ |
117 | process_halted_qtd(whc, qset, td); | 117 | process_halted_qtd(whc, qset, td); |
118 | /* A halted qTD always triggers an update | ||
119 | because the qset was either removed or | ||
120 | reactivated. */ | ||
121 | update |= WHC_UPDATE_UPDATED; | ||
118 | goto done; | 122 | goto done; |
119 | } | 123 | } |
120 | 124 | ||
@@ -305,6 +309,7 @@ int asl_urb_dequeue(struct whc *whc, struct urb *urb, int status) | |||
305 | struct whc_urb *wurb = urb->hcpriv; | 309 | struct whc_urb *wurb = urb->hcpriv; |
306 | struct whc_qset *qset = wurb->qset; | 310 | struct whc_qset *qset = wurb->qset; |
307 | struct whc_std *std, *t; | 311 | struct whc_std *std, *t; |
312 | bool has_qtd = false; | ||
308 | int ret; | 313 | int ret; |
309 | unsigned long flags; | 314 | unsigned long flags; |
310 | 315 | ||
@@ -315,17 +320,21 @@ int asl_urb_dequeue(struct whc *whc, struct urb *urb, int status) | |||
315 | goto out; | 320 | goto out; |
316 | 321 | ||
317 | list_for_each_entry_safe(std, t, &qset->stds, list_node) { | 322 | list_for_each_entry_safe(std, t, &qset->stds, list_node) { |
318 | if (std->urb == urb) | 323 | if (std->urb == urb) { |
324 | if (std->qtd) | ||
325 | has_qtd = true; | ||
319 | qset_free_std(whc, std); | 326 | qset_free_std(whc, std); |
320 | else | 327 | } else |
321 | std->qtd = NULL; /* so this std is re-added when the qset is */ | 328 | std->qtd = NULL; /* so this std is re-added when the qset is */ |
322 | } | 329 | } |
323 | 330 | ||
324 | asl_qset_remove(whc, qset); | 331 | if (has_qtd) { |
325 | wurb->status = status; | 332 | asl_qset_remove(whc, qset); |
326 | wurb->is_async = true; | 333 | wurb->status = status; |
327 | queue_work(whc->workqueue, &wurb->dequeue_work); | 334 | wurb->is_async = true; |
328 | 335 | queue_work(whc->workqueue, &wurb->dequeue_work); | |
336 | } else | ||
337 | qset_remove_urb(whc, qset, urb, status); | ||
329 | out: | 338 | out: |
330 | spin_unlock_irqrestore(&whc->lock, flags); | 339 | spin_unlock_irqrestore(&whc->lock, flags); |
331 | 340 | ||