ChangeSet 1.1305.7.5, 2003/06/16 12:01:45-07:00, david-b@pacbell.net

[PATCH] USB: ehci, fix qh re-activation problem

This resolves a problem that appears when relinking
a bulk or control QH that has a partially completed
multi-packet qTD.  Some I/O could be repeated.

Such cases can happen when an empty QH starts to unlink,
but gets re-activated (by queueing the multi-packet qTD)
before the HC saw the unlink.  It's rarely an issue with
control traffic (transfers are so small) or when bulk
queues are active (the QH won't empty).


 drivers/usb/host/ehci-hcd.c |    2 +-
 drivers/usb/host/ehci-q.c   |   16 +++++++++++-----
 2 files changed, 12 insertions(+), 6 deletions(-)


diff -Nru a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
--- a/drivers/usb/host/ehci-hcd.c	Wed Jun 18 11:15:55 2003
+++ b/drivers/usb/host/ehci-hcd.c	Wed Jun 18 11:15:55 2003
@@ -91,7 +91,7 @@
  * 2001-June	Works with usb-storage and NEC EHCI on 2.4
  */
 
-#define DRIVER_VERSION "2003-Jun-12"
+#define DRIVER_VERSION "2003-Jun-13"
 #define DRIVER_AUTHOR "David Brownell"
 #define DRIVER_DESC "USB 2.0 'Enhanced' Host Controller (EHCI) Driver"
 
diff -Nru a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
--- a/drivers/usb/host/ehci-q.c	Wed Jun 18 11:15:55 2003
+++ b/drivers/usb/host/ehci-q.c	Wed Jun 18 11:15:55 2003
@@ -360,11 +360,17 @@
 	if (unlikely (stopped != 0)
 			/* some EHCI 0.95 impls will overlay dummy qtds */ 
 			|| qh->hw_qtd_next == EHCI_LIST_END) {
-		qh_update (ehci, qh,
-			list_empty (&qh->qtd_list)
-				? qh->dummy
-				: list_entry (qh->qtd_list.next,
-					struct ehci_qtd, qtd_list));
+		if (list_empty (&qh->qtd_list))
+			end = qh->dummy;
+		else {
+			end = list_entry (qh->qtd_list.next,
+					struct ehci_qtd, qtd_list);
+			/* first qtd may already be partially processed */
+			if (cpu_to_le32 (end->qtd_dma) == qh->hw_current)
+				end = 0;
+		}
+		if (end)
+			qh_update (ehci, qh, end);
 	}
 
 	return count;
