summaryrefslogtreecommitdiff
path: root/drivers/usb/host/ehci-hcd.c
diff options
context:
space:
mode:
authorAlan Stern <stern@rowland.harvard.edu>2013-03-22 21:31:11 +0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-03-26 00:35:05 +0400
commit7bc782d73c7db042ecc965866b8c1c2b7d6e93d6 (patch)
treefa5fcfb05da245b4b611585b36a9271c8144fd6b /drivers/usb/host/ehci-hcd.c
parent79bcf7b02ba3d45bafe81a2753cedb8ef49548e3 (diff)
downloadlinux-7bc782d73c7db042ecc965866b8c1c2b7d6e93d6.tar.xz
USB: EHCI: split needs_rescan into two flags
This patch (as1662) does some more QH-related cleanup in ehci-hcd. The qh->needs_rescan flag is currently used for two different purposes; the patch replaces it with two separate flags for greater clarity: qh->dequeue_during_giveback indicates that a completion handler dequeued an URB (implying that a rescan is needed), and qh->exception indicates that the QH is in an exceptional state requiring an unlink (either it encountered an I/O error or an unlink was requested). The new flags get set where the dequeue, exception, or unlink request occurred, rather than where the unlink is started. This is so that in the future, if we need to, we will be able to tell apart unlinks that truly were required from those that were carried out merely because the QH wasn't being used. Signed-off-by: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
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 0c3314c41363..93f4cd75845e 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