Commit 221f8dfc authored by Alan Stern's avatar Alan Stern Committed by Greg Kroah-Hartman

USB: EHCI: revert "remove ASS/PSS polling timeout"

This patch (as1649) reverts commit
55bcdce8 (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: default avatarAlan Stern <stern@rowland.harvard.edu>
Reported-and-tested-by: default avatarRonald <ronald645@gmail.com>
Reported-and-tested-by: default avatarPaul Hartman <paul.hartman@gmail.com>
Reported-and-tested-by: default avatarDieter Nützel <dieter@nuetzel-hh.de>
Reported-and-tested-by: default avatarJean Delvare <khali@linux-fr.org>
Cc: stable <stable@vger.kernel.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 74e1a2a3
...@@ -113,15 +113,14 @@ static void ehci_poll_ASS(struct ehci_hcd *ehci) ...@@ -113,15 +113,14 @@ static void ehci_poll_ASS(struct ehci_hcd *ehci)
if (want != actual) { if (want != actual) {
/* Poll again later */ /* Poll again later, but give up after about 20 ms */
if (ehci->ASS_poll_count++ < 20) {
ehci_enable_event(ehci, EHCI_HRTIMER_POLL_ASS, true); ehci_enable_event(ehci, EHCI_HRTIMER_POLL_ASS, true);
++ehci->ASS_poll_count;
return; return;
} }
ehci_dbg(ehci, "Waited too long for the async schedule status (%x/%x), giving up\n",
if (ehci->ASS_poll_count > 20) want, actual);
ehci_dbg(ehci, "ASS poll count reached %d\n", }
ehci->ASS_poll_count);
ehci->ASS_poll_count = 0; ehci->ASS_poll_count = 0;
/* The status is up-to-date; restart or stop the schedule as needed */ /* 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,14 +159,14 @@ static void ehci_poll_PSS(struct ehci_hcd *ehci)
if (want != actual) { if (want != actual) {
/* Poll again later */ /* Poll again later, but give up after about 20 ms */
if (ehci->PSS_poll_count++ < 20) {
ehci_enable_event(ehci, EHCI_HRTIMER_POLL_PSS, true); ehci_enable_event(ehci, EHCI_HRTIMER_POLL_PSS, true);
return; return;
} }
ehci_dbg(ehci, "Waited too long for the periodic schedule status (%x/%x), giving up\n",
if (ehci->PSS_poll_count > 20) want, actual);
ehci_dbg(ehci, "PSS poll count reached %d\n", }
ehci->PSS_poll_count);
ehci->PSS_poll_count = 0; ehci->PSS_poll_count = 0;
/* The status is up-to-date; restart or stop the schedule as needed */ /* The status is up-to-date; restart or stop the schedule as needed */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment