# 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.643   -> 1.644  
#	drivers/usb/host/ohci-hcd.c	1.18    -> 1.19   
#	drivers/usb/host/ohci-sa1111.c	1.1     -> 1.2    
#	drivers/usb/host/ohci-dbg.c	1.7     -> 1.8    
#	drivers/usb/host/ohci-q.c	1.12    -> 1.13   
#	drivers/usb/host/ohci.h	1.8     -> 1.9    
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 02/07/15	david-b@pacbell.net	1.644
# [PATCH] ohci misc
# 
# This patch  includes the innocuous bits from a larger one that
# I'm still working on (mostly unlink fixes):
# 
# - updates comments
# - flags TDs that were seen in the donelist
# - removes some bogus whitespace (at EOL etc) and tabs
# - checks for an enumeration issue that might cause trouble
# - delays IRQs a bit more aggressively
# - shortens TD submit paths a smidgeon (smaller ".o")
# - updates some of the debug output
# - sanitizes usb_make_path() output on the SA-1111
# --------------------------------------------
#
diff -Nru a/drivers/usb/host/ohci-dbg.c b/drivers/usb/host/ohci-dbg.c
--- a/drivers/usb/host/ohci-dbg.c	Mon Jul 15 18:05:00 2002
+++ b/drivers/usb/host/ohci-dbg.c	Mon Jul 15 18:05:00 2002
@@ -12,13 +12,14 @@
  
 #ifdef DEBUG
 
-#define pipestring(pipe) ({ char *temp; \
-	switch (usb_pipetype (pipe)) { \
+#define edstring(ed_type) ({ char *temp; \
+	switch (ed_type) { \
 	case PIPE_CONTROL:	temp = "CTRL"; break; \
 	case PIPE_BULK:		temp = "BULK"; break; \
 	case PIPE_INTERRUPT:	temp = "INTR"; break; \
 	default: 		temp = "ISOC"; break; \
 	}; temp;})
+#define pipestring(pipe) edstring(usb_pipetype(pipe))
 
 /* debug| print the main components of an URB     
  * small: 0) header + data packets 1) just header
@@ -35,9 +36,9 @@
 #ifndef	OHCI_VERBOSE_DEBUG
 	if (urb->status != 0)
 #endif
-	dbg("%s:[%4x] dev:%d,ep=%d-%c,%s,flags:%4x,len:%d/%d,stat:%d", 
+	dbg("%s %p dev:%d,ep=%d-%c,%s,flags:%x,len:%d/%d,stat:%d", 
 		    str,
-		    usb_get_current_frame_number (urb->dev), 
+		    urb,
 		    usb_pipedevice (pipe),
 		    usb_pipeendpoint (pipe), 
 		    usb_pipeout (pipe)? 'O': 'I',
@@ -242,21 +243,25 @@
 	ohci_dump_roothub (controller, 1);
 }
 
+static const char data0 [] = "DATA0";
+static const char data1 [] = "DATA1";
+
 static void ohci_dump_td (char *label, struct td *td)
 {
 	u32	tmp = le32_to_cpup (&td->hwINFO);
 
-	dbg ("%s td %p; urb %p index %d; hw next td %08x",
+	dbg ("%s td %p%s; urb %p index %d; hw next td %08x",
 		label, td,
+		(tmp & TD_DONE) ? " (DONE)" : "",
 		td->urb, td->index,
 		le32_to_cpup (&td->hwNextTD));
 	if ((tmp & TD_ISO) == 0) {
-		char	*toggle, *pid;
+		const char	*toggle, *pid;
 		u32	cbp, be;
 
 		switch (tmp & TD_T) {
-		case TD_T_DATA0: toggle = "DATA0"; break;
-		case TD_T_DATA1: toggle = "DATA1"; break;
+		case TD_T_DATA0: toggle = data0; break;
+		case TD_T_DATA1: toggle = data1; break;
 		case TD_T_TOGGLE: toggle = "(CARRY)"; break;
 		default: toggle = "(?)"; break;
 		}
@@ -297,9 +302,9 @@
 	u32	tmp = ed->hwINFO;
 	char	*type = "";
 
-	dbg ("%s: %s, ed %p state 0x%x type %d; next ed %08x",
+	dbg ("%s: %s, ed %p state 0x%x type %s; next ed %08x",
 		ohci->hcd.self.bus_name, label,
-		ed, ed->state, ed->type,
+		ed, ed->state, edstring (ed->type),
 		le32_to_cpup (&ed->hwNextED));
 	switch (tmp & (ED_IN|ED_OUT)) {
 	case ED_OUT: type = "-OUT"; break;
@@ -314,10 +319,10 @@
 		0x000f & (le32_to_cpu (tmp) >> 7),
 		type,
 		0x007f & le32_to_cpu (tmp));
-	dbg ("  tds: head %08x%s%s tail %08x%s",
+	dbg ("  tds: head %08x %s%s tail %08x%s",
 		tmp = le32_to_cpup (&ed->hwHeadP),
+		(ed->hwHeadP & ED_C) ? data1 : data0,
 		(ed->hwHeadP & ED_H) ? " HALT" : "",
-		(ed->hwHeadP & ED_C) ? " CARRY" : "",
 		le32_to_cpup (&ed->hwTailP),
 		verbose ? "" : " (not listing)");
 	if (verbose) {
diff -Nru a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
--- a/drivers/usb/host/ohci-hcd.c	Mon Jul 15 18:05:00 2002
+++ b/drivers/usb/host/ohci-hcd.c	Mon Jul 15 18:05:00 2002
@@ -197,7 +197,7 @@
 
 	/* allocate the TDs (updating hash chains) */
 	spin_lock_irqsave (&ohci->lock, flags);
-	for (i = 0; i < size; i++) { 
+	for (i = 0; i < size; i++) {
 		urb_priv->td [i] = td_alloc (ohci, SLAB_ATOMIC);
 		if (!urb_priv->td [i]) {
 			urb_priv->length = i;
@@ -208,6 +208,8 @@
 	}	
 
 // FIXME:  much of this switch should be generic, move to hcd code ...
+// ... and what's not generic can't really be handled this way.
+// need to consider periodicity for both types!
 
 	/* allocate and claim bandwidth if needed; ISO
 	 * needs start frame index if it was't provided.
@@ -247,14 +249,14 @@
 
 	spin_unlock_irqrestore (&ohci->lock, flags);
 
-	return 0;	
+	return 0;
 }
 
 /*
  * decouple the URB from the HC queues (TDs, urb_priv); it's
- * already marked for deletion.  reporting is always done
+ * already marked using urb->status.  reporting is always done
  * asynchronously, and we might be dealing with an urb that's
- * almost completed anyway...
+ * partially transferred, or an ED with other urbs being unlinked.
  */
 static int ohci_urb_dequeue (struct usb_hcd *hcd, struct urb *urb)
 {
diff -Nru a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c
--- a/drivers/usb/host/ohci-q.c	Mon Jul 15 18:05:00 2002
+++ b/drivers/usb/host/ohci-q.c	Mon Jul 15 18:05:00 2002
@@ -465,6 +465,25 @@
 		 * we know it's already a power of 2
 		 */
 		ed->interval = interval;
+#ifdef DEBUG
+	/*
+	 * There are two other cases we ought to change hwINFO, both during
+	 * enumeration.  There, the control request completes, unlinks, and
+	 * the next request gets queued before the unlink completes, so it
+	 * uses old/wrong hwINFO.  How much of a problem is this?  khubd is
+	 * already retrying after such failures...
+	 */
+	} else if (type == PIPE_CONTROL) {
+		u32	info = le32_to_cpup (&ed->hwINFO);
+
+		if (!(info & 0x7f))
+			dbg ("RETRY ctrl: address != 0");
+		info >>= 16;
+		if (info != udev->epmaxpacketin [0])
+			dbg ("RETRY ctrl: maxpacket %d != 8",
+				udev->epmaxpacketin [0]);
+
+#endif /* DEBUG */
 	}
 
 done:
@@ -539,12 +558,15 @@
 
 	/* aim for only one interrupt per urb.  mostly applies to control
 	 * and iso; other urbs rarely need more than one TD per urb.
+	 * this way, only final tds (or ones with an error) cause IRQs.
 	 *
 	 * NOTE: could delay interrupts even for the last TD, and get fewer
 	 * interrupts ... increasing per-urb latency by sharing interrupts.
+	 * Drivers that queue bulk urbs may request that behavior.
 	 */
-	if (index != (urb_priv->length - 1))
-		info |= is_iso ? TD_DI_SET (7) : TD_DI_SET (1);
+	if (index != (urb_priv->length - 1)
+			|| (urb->transfer_flags & URB_NO_INTERRUPT))
+		info |= TD_DI_SET (7);
 
 	/* use this td as the next dummy */
 	td_pt = urb_priv->td [index];
@@ -565,6 +587,7 @@
 	td->hwINFO = cpu_to_le32 (info);
 	if (is_iso) {
 		td->hwCBP = cpu_to_le32 (data & 0xFFFFF000);
+		td->hwPSW [0] = cpu_to_le16 ((data & 0x0FFF) | 0xE000);
 		td->ed->intriso.last_iso = info & 0xffff;
 	} else {
 		td->hwCBP = cpu_to_le32 (data); 
@@ -574,7 +597,6 @@
 	else
 		td->hwBE = 0;
 	td->hwNextTD = cpu_to_le32 (td_pt->td_dma);
-	td->hwPSW [0] = cpu_to_le16 ((data & 0x0FFF) | 0xE000);
 
 	/* HC might read the TD right after we link it ... */
 	wmb ();
@@ -596,17 +618,17 @@
 	int		cnt = 0; 
 	__u32		info = 0;
   	unsigned int	toggle = 0;
+	int		is_out = usb_pipeout (urb->pipe);
 
 	/* OHCI handles the DATA-toggles itself, we just use the
 	 * USB-toggle bits for resetting
 	 */
-  	if (usb_gettoggle (urb->dev, usb_pipeendpoint (urb->pipe),
-			usb_pipeout (urb->pipe))) {
+  	if (usb_gettoggle (urb->dev, usb_pipeendpoint (urb->pipe), is_out)) {
   		toggle = TD_T_TOGGLE;
 	} else {
   		toggle = TD_T_DATA0;
 		usb_settoggle (urb->dev, usb_pipeendpoint (urb->pipe),
-			usb_pipeout (urb->pipe), 1);
+			is_out, 1);
 	}
 
 	urb_priv->td_cnt = 0;
@@ -614,9 +636,9 @@
 	if (data_len) {
 		data = pci_map_single (ohci->hcd.pdev,
 				       urb->transfer_buffer, data_len,
-				       usb_pipeout (urb->pipe)
-				       ? PCI_DMA_TODEVICE
-				       : PCI_DMA_FROMDEVICE);
+				       is_out
+					       ? PCI_DMA_TODEVICE
+					       : PCI_DMA_FROMDEVICE);
 	} else
 		data = 0;
 
@@ -625,18 +647,20 @@
 	 */
 	switch (usb_pipetype (urb->pipe)) {
 		case PIPE_BULK:
-			info = usb_pipeout (urb->pipe)
+			info = is_out
 				? TD_CC | TD_DP_OUT
 				: TD_CC | TD_DP_IN ;
+			/* TDs _could_ transfer up to 8K each */
 			while (data_len > 4096) {		
 				td_fill (ohci,
 					info | (cnt? TD_T_TOGGLE:toggle),
 					data, 4096, urb, cnt);
 				data += 4096; data_len -= 4096; cnt++;
 			}
-			info = usb_pipeout (urb->pipe)?
-				TD_CC | TD_DP_OUT : TD_CC | TD_R | TD_DP_IN ;
-			td_fill (ohci, info | (cnt? TD_T_TOGGLE:toggle),
+			/* maybe avoid ED halt on final TD short read */
+			if (!(urb->transfer_flags & USB_DISABLE_SPD))
+				info |= TD_R;
+			td_fill (ohci, info | (cnt ? TD_T_TOGGLE : toggle),
 				data, data_len, urb, cnt);
 			cnt++;
 			if ((urb->transfer_flags & USB_ZERO_PACKET)
@@ -653,8 +677,11 @@
 			break;
 
 		case PIPE_INTERRUPT:
+			/* current policy:  only one TD per request.
+			 * otherwise identical to bulk, except for BLF
+			 */
 			info = TD_CC | toggle;
-			info |= usb_pipeout (urb->pipe) 
+			info |= is_out
 				?  TD_DP_OUT
 				:  TD_R | TD_DP_IN;
 			td_fill (ohci, info, data, data_len, urb, cnt++);
@@ -670,14 +697,12 @@
 				 8, urb, cnt++); 
 			if (data_len > 0) {  
 				info = TD_CC | TD_R | TD_T_DATA1;
-				info |= usb_pipeout (urb->pipe)
-				    ? TD_DP_OUT
-				    : TD_DP_IN;
+				info |= is_out ? TD_DP_OUT : TD_DP_IN;
 				/* NOTE:  mishandles transfers >8K, some >4K */
 				td_fill (ohci, info, data, data_len,
 						urb, cnt++);  
 			} 
-			info = usb_pipeout (urb->pipe)
+			info = is_out
 				? TD_CC | TD_DP_IN | TD_T_DATA1
 				: TD_CC | TD_DP_OUT | TD_T_DATA1;
 			td_fill (ohci, info, data, 0, urb, cnt++);
@@ -806,10 +831,13 @@
 	while (td_list_hc) {		
 		td_list = dma_to_td (ohci, td_list_hc);
 
+		td_list->hwINFO |= cpu_to_le32 (TD_DONE);
+
 		if (TD_CC_GET (le32_to_cpup (&td_list->hwINFO))) {
 			urb_priv = (urb_priv_t *) td_list->urb->hcpriv;
-			/* typically the endpoint halts on error; un-halt,
-			 * and maybe dequeue other TDs from this urb
+			/* Non-iso endpoints can halt on error; un-halt,
+			 * and dequeue any other TDs from this urb.
+			 * No other TD could have caused the halt.
 			 */
 			if (td_list->ed->hwHeadP & ED_H) {
 				if (urb_priv && ((td_list->index + 1)
diff -Nru a/drivers/usb/host/ohci-sa1111.c b/drivers/usb/host/ohci-sa1111.c
--- a/drivers/usb/host/ohci-sa1111.c	Mon Jul 15 18:05:00 2002
+++ b/drivers/usb/host/ohci-sa1111.c	Mon Jul 15 18:05:00 2002
@@ -175,7 +175,7 @@
 	usb_bus_init (&hcd->self);
 	hcd->self.op = &usb_hcd_operations;
 	hcd->self.hcpriv = (void *) hcd;
-	hcd->self.bus_name = "SA-1111";
+	hcd->self.bus_name = "sa1111";
 	hcd->product_desc = "SA-1111 OHCI";
 
 	INIT_LIST_HEAD (&hcd->dev_list);
diff -Nru a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h
--- a/drivers/usb/host/ohci.h	Mon Jul 15 18:05:00 2002
+++ b/drivers/usb/host/ohci.h	Mon Jul 15 18:05:00 2002
@@ -11,6 +11,9 @@
 /*
  * OHCI Endpoint Descriptor (ED) ... holds TD queue
  * See OHCI spec, section 4.2
+ *
+ * This is a "Queue Head" for those transfers, which is why
+ * both EHCI and UHCI call similar structures a "QH".
  */
 struct ed {
 	/* first fields are hardware-specified, le32 */
@@ -74,8 +77,8 @@
 	/* these two bits are available for definition/use by HCDs in both
 	 * general and iso tds ... others are available for only one type
 	 */
-//#define TD____	    0x00020000
-#define TD_ISO	    0x00010000			/* copy of ED_ISO */
+#define TD_DONE     0x00020000			/* retired to donelist */
+#define TD_ISO      0x00010000			/* copy of ED_ISO */
 
 	/* hwINFO bits for general tds: */
 #define TD_EC       0x0C000000			/* error count */
@@ -349,12 +352,14 @@
         struct device		*parent_dev;
 
 	/*
-	 * I/O memory used to communicate with the HC (uncached);
+	 * I/O memory used to communicate with the HC (dma-consistent)
 	 */
 	struct ohci_regs	*regs;
 
 	/*
-	 * main memory used to communicate with the HC (uncached)
+	 * main memory used to communicate with the HC (dma-consistent).
+	 * hcd adds to schedule for a live hc any time, but removals finish
+	 * only at the start of the next frame.
 	 */
 	struct ohci_hcca	*hcca;
 	dma_addr_t		hcca_dma;
@@ -365,6 +370,9 @@
 	struct ed		*ed_controltail;	/* last in ctrl list */
  	struct ed		*ed_isotail;		/* last in iso list */
 
+	/*
+	 * memory management for queue data structures
+	 */
 	struct pci_pool		*td_cache;
 	struct pci_pool		*ed_cache;
 	struct hash_list_t	td_hash [TD_HASH_SIZE];
@@ -380,6 +388,7 @@
 
 	unsigned long		flags;		/* for HC bugs */
 #define	OHCI_QUIRK_AMD756	0x01			/* erratum #4 */
+	// there are also chip quirks/bugs in init logic
 
 	/*
 	 * framework state
