| From 55bcdce8a8228223ec4d17d8ded8134ed265d2c5 Mon Sep 17 00:00:00 2001 |
| From: Alan Stern <stern@rowland.harvard.edu> |
| Date: Fri, 25 Jan 2013 16:52:45 -0500 |
| Subject: USB: EHCI: remove ASS/PSS polling timeout |
| |
| From: Alan Stern <stern@rowland.harvard.edu> |
| |
| commit 55bcdce8a8228223ec4d17d8ded8134ed265d2c5 upstream. |
| |
| This patch (as1647) attempts to work around a problem that seems to |
| affect some nVidia EHCI controllers. They sometimes take a very long |
| time to turn off their async or periodic schedules. I don't know if |
| this is a result of other problems, but in any case it seems wise not |
| to depend on schedule enables or disables taking effect in any |
| specific length of time. |
| |
| The patch removes the existing 20-ms timeout for enabling and |
| disabling the schedules. The driver will now continue to poll the |
| schedule state at 1-ms intervals until the controller finally decides |
| to obey the most recent command issued by the driver. Just in case |
| this hides a problem, a debugging message will be logged if the |
| controller takes longer than 20 polls. |
| |
| I don't know if this will actually fix anything, but it can't hurt. |
| |
| Signed-off-by: Alan Stern <stern@rowland.harvard.edu> |
| Tested-by: Piergiorgio Sartor <piergiorgio.sartor@nexgo.de> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/usb/host/ehci-timer.c | 29 +++++++++++++++-------------- |
| 1 file changed, 15 insertions(+), 14 deletions(-) |
| |
| --- a/drivers/usb/host/ehci-timer.c |
| +++ b/drivers/usb/host/ehci-timer.c |
| @@ -113,14 +113,15 @@ static void ehci_poll_ASS(struct ehci_hc |
| |
| if (want != actual) { |
| |
| - /* 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); |
| - return; |
| - } |
| - ehci_dbg(ehci, "Waited too long for the async schedule status (%x/%x), giving up\n", |
| - want, actual); |
| + /* Poll again later */ |
| + ehci_enable_event(ehci, EHCI_HRTIMER_POLL_ASS, true); |
| + ++ehci->ASS_poll_count; |
| + return; |
| } |
| + |
| + if (ehci->ASS_poll_count > 20) |
| + ehci_dbg(ehci, "ASS poll count reached %d\n", |
| + ehci->ASS_poll_count); |
| ehci->ASS_poll_count = 0; |
| |
| /* The status is up-to-date; restart or stop the schedule as needed */ |
| @@ -159,14 +160,14 @@ static void ehci_poll_PSS(struct ehci_hc |
| |
| if (want != actual) { |
| |
| - /* 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); |
| - return; |
| - } |
| - ehci_dbg(ehci, "Waited too long for the periodic schedule status (%x/%x), giving up\n", |
| - want, actual); |
| + /* Poll again later */ |
| + ehci_enable_event(ehci, EHCI_HRTIMER_POLL_PSS, true); |
| + return; |
| } |
| + |
| + if (ehci->PSS_poll_count > 20) |
| + ehci_dbg(ehci, "PSS poll count reached %d\n", |
| + ehci->PSS_poll_count); |
| ehci->PSS_poll_count = 0; |
| |
| /* The status is up-to-date; restart or stop the schedule as needed */ |