# This is a BitKeeper generated patch for the following project:
# Project Name: Linux kernel tree
# This patch format is intended for GNU patch command version 2.5 or higher.
# This patch includes the following deltas:
#	           ChangeSet	1.660.1.8 -> 1.660.1.9
#	drivers/usb/host/ehci-q.c	1.27    -> 1.28   
#	drivers/usb/host/ehci-hcd.c	1.29    -> 1.30   
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 02/09/30	david-b@pacbell.net	1.660.1.9
# [PATCH] ehci-hcd, urb queuing
# 
# In doing some more extensive testing of the urb queueing behavior,
# I noticed that (a) IOC wasn't always being set for each urb, while
# for now it needs to be set; (b) a qh patchup wasn't done quite
# where it should be.  This resolves those two issues, as well
# as making it a bit less noisy to unlink lots of urbs at the once.
# --------------------------------------------
#
diff -Nru a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
--- a/drivers/usb/host/ehci-hcd.c	Mon Sep 30 17:24:38 2002
+++ b/drivers/usb/host/ehci-hcd.c	Mon Sep 30 17:24:38 2002
@@ -749,7 +749,7 @@
 	default:
 		spin_lock_irqsave (&ehci->lock, flags);
 		if (ehci->reclaim) {
-			dbg ("dq %p: reclaim = %p, %s",
+			vdbg ("dq %p: reclaim = %p, %s",
 				qh, ehci->reclaim, RUN_CONTEXT);
 			if (qh == ehci->reclaim) {
 				/* unlinking qh for another queued urb? */
diff -Nru a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
--- a/drivers/usb/host/ehci-q.c	Mon Sep 30 17:24:38 2002
+++ b/drivers/usb/host/ehci-q.c	Mon Sep 30 17:24:38 2002
@@ -255,23 +255,23 @@
 		struct urb	*urb = qtd->urb;
 		u32		token = 0;
 
+		/* hc's on-chip qh overlay cache can overwrite our idea of
+		 * next qtd ptrs, if we appended a qtd while the queue was
+		 * advancing.  (because we don't use dummy qtds.)
+		 */
+		if (cpu_to_le32 (qtd->qtd_dma) == qh->hw_current
+				&& qtd->hw_next != qh->hw_qtd_next) {
+			qh->hw_alt_next = qtd->hw_alt_next;
+			qh->hw_qtd_next = qtd->hw_next;
+			COUNT (ehci->stats.qpatch);
+		}
+
 		/* clean up any state from previous QTD ...*/
 		if (last) {
 			if (likely (last->urb != urb)) {
 				ehci_urb_done (ehci, last->urb);
 				count++;
 			}
-
-			/* qh overlays can have HC's old cached copies of
-			 * next qtd ptrs, if an URB was queued afterwards.
-			 */
-			if (cpu_to_le32 (last->qtd_dma) == qh->hw_current
-					&& last->hw_next != qh->hw_qtd_next) {
-				qh->hw_alt_next = last->hw_alt_next;
-				qh->hw_qtd_next = last->hw_next;
-				COUNT (ehci->stats.qpatch);
-			}
-
 			ehci_qtd_free (ehci, last);
 			last = 0;
 		}
@@ -529,7 +529,8 @@
 	}
 
 	/* by default, enable interrupt on urb completion */
-	if (likely (!(urb->transfer_flags & URB_NO_INTERRUPT)))
+// ... do it always, unless we switch over to dummy qtds
+//	if (likely (!(urb->transfer_flags & URB_NO_INTERRUPT)))
 		qtd->hw_token |= __constant_cpu_to_le32 (QTD_IOC);
 	return head;
 
@@ -785,7 +786,6 @@
 		/* append to tds already queued to this qh? */
 		if (unlikely (!list_empty (&qh->qtd_list) && qtd)) {
 			struct ehci_qtd		*last_qtd;
-			int			short_rx = 0;
 			u32			hw_next;
 
 			/* update the last qtd's "next" pointer */
@@ -800,23 +800,16 @@
 					&& (epnum & 0x10)) {
 				// only the last QTD for now
 				last_qtd->hw_alt_next = hw_next;
-				short_rx = 1;
 			}
 
-			/* Adjust any old copies in qh overlay too.
-			 * Interrupt code must cope with case of HC having it
-			 * cached, and clobbering these updates.
-			 * ... complicates getting rid of extra interrupts!
-			 * (Or:  use dummy td, so cache always stays valid.)
+			/* qh_completions() may need to patch the qh overlay if
+			 * the hc was advancing this queue while we appended.
+			 * we know it can: last_qtd->hw_token has IOC set.
+			 *
+			 * or:  use a dummy td (so the overlay gets the next td
+			 * only when we set its active bit); fewer irqs.
 			 */
-			if (qh->hw_current == cpu_to_le32 (last_qtd->qtd_dma)) {
-				wmb ();
-				qh->hw_qtd_next = hw_next;
-				if (short_rx)
-					qh->hw_alt_next = hw_next
-				    		| (qh->hw_alt_next & 0x1e);
-				vdbg ("queue to qh %p, patch", qh);
-			}
+			wmb ();
 
 		/* no URB queued */
 		} else {
