aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/usb/host/uhci-q.c16
1 files changed, 15 insertions, 1 deletions
diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c
index 2be84b3b40fe..76b0a9e95a7a 100644
--- a/drivers/usb/host/uhci-q.c
+++ b/drivers/usb/host/uhci-q.c
@@ -13,7 +13,7 @@
13 * (C) Copyright 2000 Yggdrasil Computing, Inc. (port of new PCI interface 13 * (C) Copyright 2000 Yggdrasil Computing, Inc. (port of new PCI interface
14 * support from usb-ohci.c by Adam Richter, adam@yggdrasil.com). 14 * support from usb-ohci.c by Adam Richter, adam@yggdrasil.com).
15 * (C) Copyright 1999 Gregory P. Smith (from usb-ohci.c) 15 * (C) Copyright 1999 Gregory P. Smith (from usb-ohci.c)
16 * (C) Copyright 2004-2005 Alan Stern, stern@rowland.harvard.edu 16 * (C) Copyright 2004-2006 Alan Stern, stern@rowland.harvard.edu
17 */ 17 */
18 18
19 19
@@ -1287,6 +1287,11 @@ restart:
1287 * Check for queues that have made some forward progress. 1287 * Check for queues that have made some forward progress.
1288 * Returns 0 if the queue is not Isochronous, is ACTIVE, and 1288 * Returns 0 if the queue is not Isochronous, is ACTIVE, and
1289 * has not advanced since last examined; 1 otherwise. 1289 * has not advanced since last examined; 1 otherwise.
1290 *
1291 * Early Intel controllers have a bug which causes qh->element sometimes
1292 * not to advance when a TD completes successfully. The queue remains
1293 * stuck on the inactive completed TD. We detect such cases and advance
1294 * the element pointer by hand.
1290 */ 1295 */
1291static int uhci_advance_check(struct uhci_hcd *uhci, struct uhci_qh *qh) 1296static int uhci_advance_check(struct uhci_hcd *uhci, struct uhci_qh *qh)
1292{ 1297{
@@ -1327,6 +1332,15 @@ static int uhci_advance_check(struct uhci_hcd *uhci, struct uhci_qh *qh)
1327 /* The queue hasn't advanced; check for timeout */ 1332 /* The queue hasn't advanced; check for timeout */
1328 if (!qh->wait_expired && time_after(jiffies, 1333 if (!qh->wait_expired && time_after(jiffies,
1329 qh->advance_jiffies + QH_WAIT_TIMEOUT)) { 1334 qh->advance_jiffies + QH_WAIT_TIMEOUT)) {
1335
1336 /* Detect the Intel bug and work around it */
1337 if (qh->post_td && qh_element(qh) ==
1338 cpu_to_le32(qh->post_td->dma_handle)) {
1339 qh->element = qh->post_td->link;
1340 qh->advance_jiffies = jiffies;
1341 return 1;
1342 }
1343
1330 qh->wait_expired = 1; 1344 qh->wait_expired = 1;
1331 1345
1332 /* If the current URB wants FSBR, unlink it temporarily 1346 /* If the current URB wants FSBR, unlink it temporarily