aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlan Stern <stern@rowland.harvard.edu>2009-05-27 18:21:56 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2009-06-16 00:44:46 -0400
commitb18ffd49e86102a9ed0a1cc83fdafe3891e844e5 (patch)
tree78b60211d13839baaa92128e1b583dc12139392c
parent5effabbe9e6e0089f7afdde35cb51e8c8b4cf6bc (diff)
USB: EHCI: update toggle state for linked QHs
This patch (as1245) fixes a bug in ehci-hcd. When an URB is queued for an endpoint whose QH is already in the LINKED state, the QH doesn't get refreshed. As a result, if usb_clear_halt() was called during the time that the QH was linked but idle, the data toggle value in the QH doesn't get reset. The symptom is that after a clear_halt, data gets lost and transfers time out. This problem is starting to show up now because the "ehci-hcd unlink speedups" patch causes QHs with no queued URBs to remain linked for a suitable time. The patch utilizes the new endpoint_reset mechanism to fix the problem. When an endpoint is reset, the new method forcibly unlinks the QH (if necessary) and safely updates the toggle value. This allows qh_update() to be simplified and avoids using usb_device's toggle bits in a rather unintuitive way. Signed-off-by: Alan Stern <stern@rowland.harvard.edu> CC: David Brownell <david-b@pacbell.net> Tested-by: David <david@unsolicited.net> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r--drivers/usb/host/ehci-au1xxx.c1
-rw-r--r--drivers/usb/host/ehci-fsl.c1
-rw-r--r--drivers/usb/host/ehci-hcd.c45
-rw-r--r--drivers/usb/host/ehci-ixp4xx.c1
-rw-r--r--drivers/usb/host/ehci-orion.c1
-rw-r--r--drivers/usb/host/ehci-pci.c1
-rw-r--r--drivers/usb/host/ehci-ppc-of.c1
-rw-r--r--drivers/usb/host/ehci-ps3.c1
-rw-r--r--drivers/usb/host/ehci-q.c19
9 files changed, 53 insertions, 18 deletions
diff --git a/drivers/usb/host/ehci-au1xxx.c b/drivers/usb/host/ehci-au1xxx.c
index bf69f4739107..c3a778bd359c 100644
--- a/drivers/usb/host/ehci-au1xxx.c
+++ b/drivers/usb/host/ehci-au1xxx.c
@@ -97,6 +97,7 @@ static const struct hc_driver ehci_au1xxx_hc_driver = {
97 .urb_enqueue = ehci_urb_enqueue, 97 .urb_enqueue = ehci_urb_enqueue,
98 .urb_dequeue = ehci_urb_dequeue, 98 .urb_dequeue = ehci_urb_dequeue,
99 .endpoint_disable = ehci_endpoint_disable, 99 .endpoint_disable = ehci_endpoint_disable,
100 .endpoint_reset = ehci_endpoint_reset,
100 101
101 /* 102 /*
102 * scheduling support 103 * scheduling support
diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c
index 01c3da34f678..bf86809c5120 100644
--- a/drivers/usb/host/ehci-fsl.c
+++ b/drivers/usb/host/ehci-fsl.c
@@ -309,6 +309,7 @@ static const struct hc_driver ehci_fsl_hc_driver = {
309 .urb_enqueue = ehci_urb_enqueue, 309 .urb_enqueue = ehci_urb_enqueue,
310 .urb_dequeue = ehci_urb_dequeue, 310 .urb_dequeue = ehci_urb_dequeue,
311 .endpoint_disable = ehci_endpoint_disable, 311 .endpoint_disable = ehci_endpoint_disable,
312 .endpoint_reset = ehci_endpoint_reset,
312 313
313 /* 314 /*
314 * scheduling support 315 * scheduling support
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index a2ca9cbf2809..2b72473544d3 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -1024,6 +1024,51 @@ done:
1024 return; 1024 return;
1025} 1025}
1026 1026
1027static void
1028ehci_endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep)
1029{
1030 struct ehci_hcd *ehci = hcd_to_ehci(hcd);
1031 struct ehci_qh *qh;
1032 int eptype = usb_endpoint_type(&ep->desc);
1033
1034 if (eptype != USB_ENDPOINT_XFER_BULK && eptype != USB_ENDPOINT_XFER_INT)
1035 return;
1036
1037 rescan:
1038 spin_lock_irq(&ehci->lock);
1039 qh = ep->hcpriv;
1040
1041 /* For Bulk and Interrupt endpoints we maintain the toggle state
1042 * in the hardware; the toggle bits in udev aren't used at all.
1043 * When an endpoint is reset by usb_clear_halt() we must reset
1044 * the toggle bit in the QH.
1045 */
1046 if (qh) {
1047 if (!list_empty(&qh->qtd_list)) {
1048 WARN_ONCE(1, "clear_halt for a busy endpoint\n");
1049 } else if (qh->qh_state == QH_STATE_IDLE) {
1050 qh->hw_token &= ~cpu_to_hc32(ehci, QTD_TOGGLE);
1051 } else {
1052 /* It's not safe to write into the overlay area
1053 * while the QH is active. Unlink it first and
1054 * wait for the unlink to complete.
1055 */
1056 if (qh->qh_state == QH_STATE_LINKED) {
1057 if (eptype == USB_ENDPOINT_XFER_BULK) {
1058 unlink_async(ehci, qh);
1059 } else {
1060 intr_deschedule(ehci, qh);
1061 (void) qh_schedule(ehci, qh);
1062 }
1063 }
1064 spin_unlock_irq(&ehci->lock);
1065 schedule_timeout_uninterruptible(1);
1066 goto rescan;
1067 }
1068 }
1069 spin_unlock_irq(&ehci->lock);
1070}
1071
1027static int ehci_get_frame (struct usb_hcd *hcd) 1072static int ehci_get_frame (struct usb_hcd *hcd)
1028{ 1073{
1029 struct ehci_hcd *ehci = hcd_to_ehci (hcd); 1074 struct ehci_hcd *ehci = hcd_to_ehci (hcd);
diff --git a/drivers/usb/host/ehci-ixp4xx.c b/drivers/usb/host/ehci-ixp4xx.c
index 9c32063a0c2f..a44bb4a94954 100644
--- a/drivers/usb/host/ehci-ixp4xx.c
+++ b/drivers/usb/host/ehci-ixp4xx.c
@@ -51,6 +51,7 @@ static const struct hc_driver ixp4xx_ehci_hc_driver = {
51 .urb_enqueue = ehci_urb_enqueue, 51 .urb_enqueue = ehci_urb_enqueue,
52 .urb_dequeue = ehci_urb_dequeue, 52 .urb_dequeue = ehci_urb_dequeue,
53 .endpoint_disable = ehci_endpoint_disable, 53 .endpoint_disable = ehci_endpoint_disable,
54 .endpoint_reset = ehci_endpoint_reset,
54 .get_frame_number = ehci_get_frame, 55 .get_frame_number = ehci_get_frame,
55 .hub_status_data = ehci_hub_status_data, 56 .hub_status_data = ehci_hub_status_data,
56 .hub_control = ehci_hub_control, 57 .hub_control = ehci_hub_control,
diff --git a/drivers/usb/host/ehci-orion.c b/drivers/usb/host/ehci-orion.c
index 17dc15407a07..770dd9aba62a 100644
--- a/drivers/usb/host/ehci-orion.c
+++ b/drivers/usb/host/ehci-orion.c
@@ -149,6 +149,7 @@ static const struct hc_driver ehci_orion_hc_driver = {
149 .urb_enqueue = ehci_urb_enqueue, 149 .urb_enqueue = ehci_urb_enqueue,
150 .urb_dequeue = ehci_urb_dequeue, 150 .urb_dequeue = ehci_urb_dequeue,
151 .endpoint_disable = ehci_endpoint_disable, 151 .endpoint_disable = ehci_endpoint_disable,
152 .endpoint_reset = ehci_endpoint_reset,
152 153
153 /* 154 /*
154 * scheduling support 155 * scheduling support
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
index e74948898f76..f3683e1da161 100644
--- a/drivers/usb/host/ehci-pci.c
+++ b/drivers/usb/host/ehci-pci.c
@@ -388,6 +388,7 @@ static const struct hc_driver ehci_pci_hc_driver = {
388 .urb_enqueue = ehci_urb_enqueue, 388 .urb_enqueue = ehci_urb_enqueue,
389 .urb_dequeue = ehci_urb_dequeue, 389 .urb_dequeue = ehci_urb_dequeue,
390 .endpoint_disable = ehci_endpoint_disable, 390 .endpoint_disable = ehci_endpoint_disable,
391 .endpoint_reset = ehci_endpoint_reset,
391 392
392 /* 393 /*
393 * scheduling support 394 * scheduling support
diff --git a/drivers/usb/host/ehci-ppc-of.c b/drivers/usb/host/ehci-ppc-of.c
index ef732b704f53..fbd272288fc2 100644
--- a/drivers/usb/host/ehci-ppc-of.c
+++ b/drivers/usb/host/ehci-ppc-of.c
@@ -61,6 +61,7 @@ static const struct hc_driver ehci_ppc_of_hc_driver = {
61 .urb_enqueue = ehci_urb_enqueue, 61 .urb_enqueue = ehci_urb_enqueue,
62 .urb_dequeue = ehci_urb_dequeue, 62 .urb_dequeue = ehci_urb_dequeue,
63 .endpoint_disable = ehci_endpoint_disable, 63 .endpoint_disable = ehci_endpoint_disable,
64 .endpoint_reset = ehci_endpoint_reset,
64 65
65 /* 66 /*
66 * scheduling support 67 * scheduling support
diff --git a/drivers/usb/host/ehci-ps3.c b/drivers/usb/host/ehci-ps3.c
index 1ba9f9a8c308..4b4df23efddf 100644
--- a/drivers/usb/host/ehci-ps3.c
+++ b/drivers/usb/host/ehci-ps3.c
@@ -65,6 +65,7 @@ static const struct hc_driver ps3_ehci_hc_driver = {
65 .urb_enqueue = ehci_urb_enqueue, 65 .urb_enqueue = ehci_urb_enqueue,
66 .urb_dequeue = ehci_urb_dequeue, 66 .urb_dequeue = ehci_urb_dequeue,
67 .endpoint_disable = ehci_endpoint_disable, 67 .endpoint_disable = ehci_endpoint_disable,
68 .endpoint_reset = ehci_endpoint_reset,
68 .get_frame_number = ehci_get_frame, 69 .get_frame_number = ehci_get_frame,
69 .hub_status_data = ehci_hub_status_data, 70 .hub_status_data = ehci_hub_status_data,
70 .hub_control = ehci_hub_control, 71 .hub_control = ehci_hub_control,
diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
index 1976b1b3778c..3192f683f807 100644
--- a/drivers/usb/host/ehci-q.c
+++ b/drivers/usb/host/ehci-q.c
@@ -93,22 +93,6 @@ qh_update (struct ehci_hcd *ehci, struct ehci_qh *qh, struct ehci_qtd *qtd)
93 qh->hw_qtd_next = QTD_NEXT(ehci, qtd->qtd_dma); 93 qh->hw_qtd_next = QTD_NEXT(ehci, qtd->qtd_dma);
94 qh->hw_alt_next = EHCI_LIST_END(ehci); 94 qh->hw_alt_next = EHCI_LIST_END(ehci);
95 95
96 /* Except for control endpoints, we make hardware maintain data
97 * toggle (like OHCI) ... here (re)initialize the toggle in the QH,
98 * and set the pseudo-toggle in udev. Only usb_clear_halt() will
99 * ever clear it.
100 */
101 if (!(qh->hw_info1 & cpu_to_hc32(ehci, 1 << 14))) {
102 unsigned is_out, epnum;
103
104 is_out = !(qtd->hw_token & cpu_to_hc32(ehci, 1 << 8));
105 epnum = (hc32_to_cpup(ehci, &qh->hw_info1) >> 8) & 0x0f;
106 if (unlikely (!usb_gettoggle (qh->dev, epnum, is_out))) {
107 qh->hw_token &= ~cpu_to_hc32(ehci, QTD_TOGGLE);
108 usb_settoggle (qh->dev, epnum, is_out, 1);
109 }
110 }
111
112 /* HC must see latest qtd and qh data before we clear ACTIVE+HALT */ 96 /* HC must see latest qtd and qh data before we clear ACTIVE+HALT */
113 wmb (); 97 wmb ();
114 qh->hw_token &= cpu_to_hc32(ehci, QTD_TOGGLE | QTD_STS_PING); 98 qh->hw_token &= cpu_to_hc32(ehci, QTD_TOGGLE | QTD_STS_PING);
@@ -850,7 +834,6 @@ done:
850 qh->qh_state = QH_STATE_IDLE; 834 qh->qh_state = QH_STATE_IDLE;
851 qh->hw_info1 = cpu_to_hc32(ehci, info1); 835 qh->hw_info1 = cpu_to_hc32(ehci, info1);
852 qh->hw_info2 = cpu_to_hc32(ehci, info2); 836 qh->hw_info2 = cpu_to_hc32(ehci, info2);
853 usb_settoggle (urb->dev, usb_pipeendpoint (urb->pipe), !is_input, 1);
854 qh_refresh (ehci, qh); 837 qh_refresh (ehci, qh);
855 return qh; 838 return qh;
856} 839}
@@ -881,7 +864,7 @@ static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
881 } 864 }
882 } 865 }
883 866
884 /* clear halt and/or toggle; and maybe recover from silicon quirk */ 867 /* clear halt and maybe recover from silicon quirk */
885 if (qh->qh_state == QH_STATE_IDLE) 868 if (qh->qh_state == QH_STATE_IDLE)
886 qh_refresh (ehci, qh); 869 qh_refresh (ehci, qh);
887 870