aboutsummaryrefslogtreecommitdiff
path: root/drivers/usb/host/ehci-hcd.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/host/ehci-hcd.c')
-rw-r--r--drivers/usb/host/ehci-hcd.c16
1 files changed, 11 insertions, 5 deletions
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 0c3314c4136..93f4cd75845 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -903,11 +903,14 @@ static int ehci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
qh = (struct ehci_qh *) urb->hcpriv;
if (!qh)
break;
+ qh->exception = 1;
switch (qh->qh_state) {
case QH_STATE_LINKED:
- case QH_STATE_COMPLETING:
start_unlink_async(ehci, qh);
break;
+ case QH_STATE_COMPLETING:
+ qh->dequeue_during_giveback = 1;
+ break;
case QH_STATE_UNLINK:
case QH_STATE_UNLINK_WAIT:
/* already started */
@@ -923,11 +926,14 @@ static int ehci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
qh = (struct ehci_qh *) urb->hcpriv;
if (!qh)
break;
+ qh->exception = 1;
switch (qh->qh_state) {
case QH_STATE_LINKED:
- case QH_STATE_COMPLETING:
start_unlink_intr(ehci, qh);
break;
+ case QH_STATE_COMPLETING:
+ qh->dequeue_during_giveback = 1;
+ break;
case QH_STATE_IDLE:
qh_completions (ehci, qh);
break;
@@ -984,6 +990,7 @@ rescan:
goto done;
}
+ qh->exception = 1;
if (ehci->rh_state < EHCI_RH_RUNNING)
qh->qh_state = QH_STATE_IDLE;
switch (qh->qh_state) {
@@ -1052,13 +1059,12 @@ ehci_endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep)
usb_settoggle(qh->dev, epnum, is_out, 0);
if (!list_empty(&qh->qtd_list)) {
WARN_ONCE(1, "clear_halt for a busy endpoint\n");
- } else if (qh->qh_state == QH_STATE_LINKED ||
- qh->qh_state == QH_STATE_COMPLETING) {
-
+ } else {
/* The toggle value in the QH can't be updated
* while the QH is active. Unlink it now;
* re-linking will call qh_refresh().
*/
+ qh->exception = 1;
if (eptype == USB_ENDPOINT_XFER_BULK)
start_unlink_async(ehci, qh);
else