# 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.564   -> 1.565  
#	drivers/usb/host/ohci-hub.c	1.6     -> 1.7    
#	drivers/usb/host/ohci-q.c	1.6     -> 1.7    
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 02/04/30	david-b@pacbell.net	1.565
# [PATCH] Re: ohci-hcd and that NCR implementation ...
# 
# The attached patch makes the one SiS controller behave
# like the other... the key fix being wmb() to make sure that
# no writes are still in CPU caches before telling the HC it's
# OK to fetch the data.  (And a minor tweak to access PCI
# less often through the hub driver.)
# 
# But the OPTi problem seems to be different.  Could you
# try this patch to see if it affects the problem your seeing
# with that NCR implementation?  And in any case, please
# integrate it to Linus' latest.  (Against 2.5.10, might be
# some fuzz on the pci tweak due to that warning fix.)
# 
# Those missing wmb() statements have likely been the root
# cause of various usb-ohci flakes reported over time, too.
# The drivers are still almost identical in those areas.  (Though
# something made ohci-hcd consistently lose that cache flush
# race; maybe it's a bit faster.)
# --------------------------------------------
#
diff -Nru a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c
--- a/drivers/usb/host/ohci-hub.c	Thu May  2 16:48:29 2002
+++ b/drivers/usb/host/ohci-hub.c	Thu May  2 16:48:29 2002
@@ -154,12 +154,10 @@
 	u16		wLength
 ) {
 	struct ohci_hcd	*ohci = hcd_to_ohci (hcd);
-	int		ports;
+	int		ports = hcd->self.root_hub->maxchild;
 	u32		temp;
 	int		retval = 0;
 
-	// if (port request)
-		ports = roothub_a (ohci) & RH_A_NDP; 
 	switch (typeReq) {
 	case ClearHubFeature:
 		switch (wValue) {
diff -Nru a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c
--- a/drivers/usb/host/ohci-q.c	Thu May  2 16:48:29 2002
+++ b/drivers/usb/host/ohci-q.c	Thu May  2 16:48:29 2002
@@ -569,6 +569,9 @@
 	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 ();
+
 	/* append to queue */
 	td->ed->hwTailP = td->hwNextTD;
 }
@@ -641,8 +644,10 @@
 				cnt++;
 			}
 			/* start bulk list */
-			if (!ohci->sleeping)
+			if (!ohci->sleeping) {
+				wmb ();
 				writel (OHCI_BLF, &ohci->regs->cmdstatus);
+			}
 			break;
 
 		case PIPE_INTERRUPT:
@@ -654,6 +659,7 @@
 			break;
 
 		case PIPE_CONTROL:
+			/* control requests don't use toggle state  */
 			info = TD_CC | TD_DP_SETUP | TD_T_DATA0;
 			td_fill (ohci, info,
 #ifdef CONFIG_PCI
@@ -678,8 +684,10 @@
 				: TD_CC | TD_DP_OUT | TD_T_DATA1;
 			td_fill (ohci, info, data, 0, urb, cnt++);
 			/* start control list */
-			if (!ohci->sleeping)
+			if (!ohci->sleeping) {
+				wmb ();
 				writel (OHCI_CLF, &ohci->regs->cmdstatus);
+			}
 			break;
 
 		case PIPE_ISOCHRONOUS:
