aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorAlan Stern <stern@rowland.harvard.edu>2013-02-26 13:43:41 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-02-26 16:22:38 -0500
commit221f8dfca89276d8aec54c6d07fbe20c281668f0 (patch)
tree0db77e4d75072bb28d30a7e9296fa9f633d206bf /drivers
parent74e1a2a39355b2d3ae8c60c78d8add162c6d7183 (diff)
USB: EHCI: revert "remove ASS/PSS polling timeout"
This patch (as1649) reverts commit 55bcdce8a8228223ec4d17d8ded8134ed265d2c5 (USB: EHCI: remove ASS/PSS polling timeout). That commit was written under the assumption that some controllers may take a very long time to turn off their async and periodic schedules. It now appears that in fact the schedules do get turned off reasonably quickly, but some controllers occasionally leave the schedules' status bits turned on and consequently ehci-hcd can't tell that the schedules are off. VIA controllers in particular have this problem. ehci-hcd tells the hardware to turn off the async schedule, the schedule does get turned off, but the status bit remains on. Since the EHCI spec requires that the schedules not be re-enabled until the previous disable has taken effect, with an unlimited timeout the async schedule never gets turned back on. The resulting symptom is that the system is unable to communicate with USB devices. Signed-off-by: Alan Stern <stern@rowland.harvard.edu> Reported-and-tested-by: Ronald <ronald645@gmail.com> Reported-and-tested-by: Paul Hartman <paul.hartman@gmail.com> Reported-and-tested-by: Dieter Nützel <dieter@nuetzel-hh.de> Reported-and-tested-by: Jean Delvare <khali@linux-fr.org> Cc: stable <stable@vger.kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/usb/host/ehci-timer.c29
1 files changed, 14 insertions, 15 deletions
diff --git a/drivers/usb/host/ehci-timer.c b/drivers/usb/host/ehci-timer.c
index f904071d70df..20dbdcbe9b0f 100644
--- a/drivers/usb/host/ehci-timer.c
+++ b/drivers/usb/host/ehci-timer.c
@@ -113,15 +113,14 @@ static void ehci_poll_ASS(struct ehci_hcd *ehci)
113 113
114 if (want != actual) { 114 if (want != actual) {
115 115
116 /* Poll again later */ 116 /* Poll again later, but give up after about 20 ms */
117 ehci_enable_event(ehci, EHCI_HRTIMER_POLL_ASS, true); 117 if (ehci->ASS_poll_count++ < 20) {
118 ++ehci->ASS_poll_count; 118 ehci_enable_event(ehci, EHCI_HRTIMER_POLL_ASS, true);
119 return; 119 return;
120 }
121 ehci_dbg(ehci, "Waited too long for the async schedule status (%x/%x), giving up\n",
122 want, actual);
120 } 123 }
121
122 if (ehci->ASS_poll_count > 20)
123 ehci_dbg(ehci, "ASS poll count reached %d\n",
124 ehci->ASS_poll_count);
125 ehci->ASS_poll_count = 0; 124 ehci->ASS_poll_count = 0;
126 125
127 /* The status is up-to-date; restart or stop the schedule as needed */ 126 /* The status is up-to-date; restart or stop the schedule as needed */
@@ -160,14 +159,14 @@ static void ehci_poll_PSS(struct ehci_hcd *ehci)
160 159
161 if (want != actual) { 160 if (want != actual) {
162 161
163 /* Poll again later */ 162 /* Poll again later, but give up after about 20 ms */
164 ehci_enable_event(ehci, EHCI_HRTIMER_POLL_PSS, true); 163 if (ehci->PSS_poll_count++ < 20) {
165 return; 164 ehci_enable_event(ehci, EHCI_HRTIMER_POLL_PSS, true);
165 return;
166 }
167 ehci_dbg(ehci, "Waited too long for the periodic schedule status (%x/%x), giving up\n",
168 want, actual);
166 } 169 }
167
168 if (ehci->PSS_poll_count > 20)
169 ehci_dbg(ehci, "PSS poll count reached %d\n",
170 ehci->PSS_poll_count);
171 ehci->PSS_poll_count = 0; 170 ehci->PSS_poll_count = 0;
172 171
173 /* The status is up-to-date; restart or stop the schedule as needed */ 172 /* The status is up-to-date; restart or stop the schedule as needed */