ChangeSet 1.1002.3.1, 2003/02/20 10:17:07-08:00, david-b@pacbell.net

[PATCH] USB: sync with some 2.4 ohci fixes, prepare for backport

The 2.5 version branched from 2.4.5 or so, and since then
a couple hardware-specific tweaks were merged to 2.4; this
teaches 2.5 about NatSemi SUPERIO and PA-RISC quirks.

This also uses os/version neutral HCD calls to register the root
hub and find the HCD's bus.  It also adds os/version neutral
macros for its diagnostic macros.  Most of those changes have
been split out separately, but the macros and a few uses of them
weren't naturally splittable.

Also a couple minor cleanups, like removing CVS ids, having
only one copy of a routine used with the debug files, and
getting rid of some inline #ifdefs.


 drivers/usb/host/ohci-dbg.c    |   26 +++++++++++---------
 drivers/usb/host/ohci-hcd.c    |   53 +++++++++++++++++++++++++++--------------
 drivers/usb/host/ohci-hub.c    |    3 --
 drivers/usb/host/ohci-pci.c    |   44 ++++++++++++++++++++--------------
 drivers/usb/host/ohci-q.c      |   27 ++++++++------------
 drivers/usb/host/ohci-sa1111.c |   10 -------
 drivers/usb/host/ohci.h        |   23 +++++++++++++++++
 7 files changed, 112 insertions(+), 74 deletions(-)


diff -Nru a/drivers/usb/host/ohci-dbg.c b/drivers/usb/host/ohci-dbg.c
--- a/drivers/usb/host/ohci-dbg.c	Fri Feb 28 14:52:14 2003
+++ b/drivers/usb/host/ohci-dbg.c	Fri Feb 28 14:52:14 2003
@@ -5,7 +5,6 @@
  * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
  * 
  * This file is licenced under the GPL.
- * $Id: ohci-dbg.c,v 1.4 2002/03/27 20:40:40 dbrownell Exp $
  */
  
 /*-------------------------------------------------------------------------*/
@@ -318,8 +317,6 @@
 	}
 }
 
-#define DRIVERFS_DEBUG_FILES 		/* only on 2.5 versions */
-
 #else
 static inline void ohci_dump (struct ohci_hcd *controller, int verbose) {}
 
@@ -327,7 +324,19 @@
 
 /*-------------------------------------------------------------------------*/
 
-#ifdef DRIVERFS_DEBUG_FILES
+#ifdef STUB_DEBUG_FILES
+
+static inline void create_debug_files (struct ohci_hcd *bus) { }
+static inline void remove_debug_files (struct ohci_hcd *bus) { }
+
+#else
+
+static inline struct ohci_hcd *dev_to_ohci (struct device *dev)
+{
+	struct usb_hcd	*hcd = dev_get_drvdata (dev);
+
+	return hcd_to_ohci (hcd);
+}
 
 static ssize_t
 show_list (struct ohci_hcd *ohci, char *buf, size_t count, struct ed *ed)
@@ -513,7 +522,7 @@
 	device_create_file (bus->hcd.controller, &dev_attr_async);
 	device_create_file (bus->hcd.controller, &dev_attr_periodic);
 	// registers
-	dev_dbg (bus->hcd.controller, "created debug files\n");
+	ohci_dbg (bus, "created debug files\n");
 }
 
 static inline void remove_debug_files (struct ohci_hcd *bus)
@@ -522,12 +531,7 @@
 	device_remove_file (bus->hcd.controller, &dev_attr_periodic);
 }
 
-#else /* empty stubs for creating those files */
-
-static inline void create_debug_files (struct ohci_hcd *bus) { }
-static inline void remove_debug_files (struct ohci_hcd *bus) { }
-
-#endif /* DRIVERFS_DEBUG_FILES */
+#endif
 
 /*-------------------------------------------------------------------------*/
 
diff -Nru a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
--- a/drivers/usb/host/ohci-hcd.c	Fri Feb 28 14:52:14 2003
+++ b/drivers/usb/host/ohci-hcd.c	Fri Feb 28 14:52:14 2003
@@ -125,6 +125,8 @@
 
 /*-------------------------------------------------------------------------*/
 
+static const char	hcd_name [] = "ohci-hcd";
+
 #include "ohci.h"
 
 static inline void disable (struct ohci_hcd *ohci)
@@ -381,9 +383,12 @@
 {
 	u32 temp;
 
-	/* SMM owns the HC?  not for long! */
+	/* SMM owns the HC?  not for long!
+	 * On PA-RISC, PDC can leave IR set incorrectly; ignore it there.
+	 */
+#ifndef __hppa__
 	if (readl (&ohci->regs->control) & OHCI_CTRL_IR) {
-		dev_dbg (ohci->hcd.controller, "USB HC TakeOver from BIOS/SMM\n");
+		ohci_dbg (ohci, "USB HC TakeOver from BIOS/SMM\n");
 
 		/* this timeout is arbitrary.  we make it long, so systems
 		 * depending on usb keyboards may be usable even if the
@@ -396,17 +401,18 @@
 		while (readl (&ohci->regs->control) & OHCI_CTRL_IR) {
 			wait_ms (10);
 			if (--temp == 0) {
-				dev_err (ohci->hcd.controller, "USB HC TakeOver failed!\n");
+				ohci_err (ohci, "USB HC TakeOver failed!\n");
 				return -1;
 			}
 		}
 	}
+#endif
 
 	/* Disable HC interrupts */
 	writel (OHCI_INTR_MIE, &ohci->regs->intrdisable);
 
-	dev_dbg (ohci->hcd.controller, "USB HC reset_hc %s: ctrl = 0x%x ;\n",
-		ohci->hcd.self.bus_name,
+	ohci_dbg (ohci, "USB HC reset_hc %s: ctrl = 0x%x ;\n",
+		hcd_to_bus (&ohci->hcd)->bus_name,
 		readl (&ohci->regs->control));
 
   	/* Reset USB (needed by some controllers); RemoteWakeupConnected
@@ -451,8 +457,9 @@
  */
 static int hc_start (struct ohci_hcd *ohci)
 {
-  	u32			mask;
+  	u32			mask, tmp;
   	struct usb_device	*udev;
+  	struct usb_bus		*bus;
 
 	spin_lock_init (&ohci->lock);
 	ohci->disabled = 1;
@@ -493,9 +500,20 @@
 	writel (mask, &ohci->regs->intrstatus);
 	writel (mask, &ohci->regs->intrenable);
 
-	/* hub power always on: required for AMD-756 and some Mac platforms */
-	writel ((roothub_a (ohci) | RH_A_NPS) & ~(RH_A_PSM | RH_A_OCPM),
-		&ohci->regs->roothub.a);
+	/* handle root hub init quirks ... */
+	tmp = roothub_a (ohci);
+	tmp &= ~(RH_A_PSM | RH_A_OCPM);
+	if (ohci->flags & OHCI_QUIRK_SUPERIO) {
+		/* NSC 87560 and maybe others */
+		tmp |= RH_A_NOCP;
+		tmp &= ~(RH_A_POTPGT | RH_A_NPS);
+	} else {
+		/* hub power always on; required for AMD-756 and some
+		 * Mac platforms, use this mode everywhere by default
+		 */
+		tmp |= RH_A_NPS;
+	}
+	writel (tmp, &ohci->regs->roothub.a);
 	writel (RH_HS_LPSC, &ohci->regs->roothub.status);
 	writel (0, &ohci->regs->roothub.b);
 
@@ -503,7 +521,8 @@
 	mdelay ((roothub_a (ohci) >> 23) & 0x1fe);
  
 	/* connect the virtual root hub */
-	ohci->hcd.self.root_hub = udev = usb_alloc_dev (NULL, &ohci->hcd.self);
+	bus = hcd_to_bus (&ohci->hcd);
+	bus->root_hub = udev = usb_alloc_dev (NULL, bus);
 	ohci->hcd.state = USB_STATE_READY;
 	if (!udev) {
 		disable (ohci);
@@ -514,9 +533,9 @@
 
 	usb_connect (udev);
 	udev->speed = USB_SPEED_FULL;
-	if (usb_register_root_hub (udev, ohci->hcd.controller) != 0) {
+	if (hcd_register_root (&ohci->hcd) != 0) {
 		usb_put_dev (udev);
-		ohci->hcd.self.root_hub = NULL;
+		bus->root_hub = NULL;
 		disable (ohci);
 		ohci->hc_control &= ~OHCI_CTRL_HCFS;
 		writel (ohci->hc_control, &ohci->regs->control);
@@ -629,8 +648,8 @@
 
 	ohci->disabled = 1;
 	ohci->sleeping = 0;
-	if (ohci->hcd.self.root_hub)
-		usb_disconnect (&ohci->hcd.self.root_hub);
+	if (hcd_to_bus (&ohci->hcd)->root_hub)
+		usb_disconnect (&hcd_to_bus (&ohci->hcd)->root_hub);
 	
 	/* empty the interrupt branches */
 	for (i = 0; i < NUM_INTS; i++) ohci->load [i] = 0;
@@ -644,17 +663,15 @@
 	ohci->ed_bulktail    = NULL;
 
 	if ((temp = hc_reset (ohci)) < 0 || (temp = hc_start (ohci)) < 0) {
-		err ("can't restart %s, %d", ohci->hcd.self.bus_name, temp);
+		ohci_err (ohci, "can't restart, %d\n", temp);
 		return temp;
 	} else
-		dbg ("restart %s completed", ohci->hcd.self.bus_name);
+		ohci_dbg (ohci, "restart complete\n");
 	return 0;
 }
 #endif
 
 /*-------------------------------------------------------------------------*/
-
-static const char	hcd_name [] = "ohci-hcd";
 
 #define DRIVER_INFO DRIVER_VERSION " " DRIVER_DESC
 
diff -Nru a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c
--- a/drivers/usb/host/ohci-hub.c	Fri Feb 28 14:52:14 2003
+++ b/drivers/usb/host/ohci-hub.c	Fri Feb 28 14:52:14 2003
@@ -5,7 +5,6 @@
  * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
  * 
  * This file is licenced under GPL
- * $Id: ohci-hub.c,v 1.3 2002/03/22 16:04:54 dbrownell Exp $
  */
 
 /*-------------------------------------------------------------------------*/
@@ -159,7 +158,7 @@
 	u16		wLength
 ) {
 	struct ohci_hcd	*ohci = hcd_to_ohci (hcd);
-	int		ports = hcd->self.root_hub->maxchild;
+	int		ports = hcd_to_bus (hcd)->root_hub->maxchild;
 	u32		temp;
 	int		retval = 0;
 
diff -Nru a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c
--- a/drivers/usb/host/ohci-pci.c	Fri Feb 28 14:52:14 2003
+++ b/drivers/usb/host/ohci-pci.c	Fri Feb 28 14:52:14 2003
@@ -29,17 +29,6 @@
 
 /*-------------------------------------------------------------------------*/
 
-struct ohci_hcd *dev_to_ohci(struct device *dev) {
-	struct pci_dev *pdev = 
-		container_of (dev, struct pci_dev, dev);
-	struct ohci_hcd	*ohci = 
-		container_of (pci_get_drvdata (pdev), struct ohci_hcd, hcd);
-
-	return ohci;
-}
-
-/*-------------------------------------------------------------------------*/
-
 static int __devinit
 ohci_pci_start (struct usb_hcd *hcd)
 {
@@ -55,22 +44,43 @@
 		/* AMD 756, for most chips (early revs), corrupts register
 		 * values on read ... so enable the vendor workaround.
 		 */
-		if (hcd->pdev->vendor == 0x1022
+		if (hcd->pdev->vendor == PCI_VENDOR_ID_AMD
 				&& hcd->pdev->device == 0x740c) {
 			ohci->flags = OHCI_QUIRK_AMD756;
-			info ("%s: AMD756 erratum 4 workaround",
-				hcd->self.bus_name);
+			ohci_info (ohci, "AMD756 erratum 4 workaround\n");
 		}
 
+		/* FIXME for some of the early AMD 760 southbridges, OHCI
+		 * won't work at all.  blacklist them.
+		 */
+
 		/* Apple's OHCI driver has a lot of bizarre workarounds
 		 * for this chip.  Evidently control and bulk lists
 		 * can get confused.  (B&W G3 models, and ...)
 		 */
-		else if (hcd->pdev->vendor == 0x1045
+		else if (hcd->pdev->vendor == PCI_VENDOR_ID_OPTI
 				&& hcd->pdev->device == 0xc861) {
-			info ("%s: WARNING: OPTi workarounds unavailable",
-				hcd->self.bus_name);
+			ohci_info (ohci,
+				"WARNING: OPTi workarounds unavailable\n");
+		}
+
+		/* Check for NSC87560. We have to look at the bridge (fn1) to
+		 * identify the USB (fn2). This quirk might apply to more or
+		 * even all NSC stuff.
+		 */
+		else if (hcd->pdev->vendor == PCI_VENDOR_ID_NS) {
+			struct pci_dev	*b, *hc;
+
+			hc = hcd->pdev;
+			b  = pci_find_slot (hc->bus->number,
+					PCI_DEVFN (PCI_SLOT (hc->devfn), 1));
+			if (b && b->device == PCI_DEVICE_ID_NS_87560_LIO
+					&& b->vendor == PCI_VENDOR_ID_NS) {
+				ohci->flags |= OHCI_QUIRK_SUPERIO;
+				ohci_info (ohci, "Using NSC SuperIO setup\n");
+			}
 		}
+	
 	}
 
         memset (ohci->hcca, 0, sizeof (struct ohci_hcca));
diff -Nru a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c
--- a/drivers/usb/host/ohci-q.c	Fri Feb 28 14:52:14 2003
+++ b/drivers/usb/host/ohci-q.c	Fri Feb 28 14:52:14 2003
@@ -49,10 +49,10 @@
 	// what lock protects these?
 	switch (usb_pipetype (urb->pipe)) {
 	case PIPE_ISOCHRONOUS:
-		ohci->hcd.self.bandwidth_isoc_reqs--;
+		hcd_to_bus (&ohci->hcd)->bandwidth_isoc_reqs--;
 		break;
 	case PIPE_INTERRUPT:
-		ohci->hcd.self.bandwidth_int_reqs--;
+		hcd_to_bus (&ohci->hcd)->bandwidth_int_reqs--;
 		break;
 	}
 
@@ -143,7 +143,7 @@
 		}
 		ohci->load [i] += ed->load;
 	}
-	ohci->hcd.self.bandwidth_allocated += ed->load / ed->interval;
+	hcd_to_bus (&ohci->hcd)->bandwidth_allocated += ed->load / ed->interval;
 }
 
 /* link an ed into one of the HC chains */
@@ -244,14 +244,11 @@
 		}
 		ohci->load [i] -= ed->load;
 	}	
-	ohci->hcd.self.bandwidth_allocated -= ed->load / ed->interval;
+	hcd_to_bus (&ohci->hcd)->bandwidth_allocated -= ed->load / ed->interval;
 
-#ifdef OHCI_VERBOSE_DEBUG
-	dbg ("%s: unlink %sed %p branch %d [%dus.], interval %d",
-		ohci->hcd.self.bus_name,
+	ohci_vdbg (ohci, "unlink %sed %p branch %d [%dus.], interval %d\n",
 		(ed->hwINFO & ED_ISO) ? "iso " : "",
 		ed, ed->branch, ed->load, ed->interval);
-#endif
 }
 
 /* unlink an ed from one of the HC chains. 
@@ -576,7 +573,7 @@
 	 */
 	case PIPE_INTERRUPT:
 		/* ... and periodic urbs have extra accounting */
-		ohci->hcd.self.bandwidth_int_reqs++;
+		hcd_to_bus (&ohci->hcd)->bandwidth_int_reqs++;
 		/* FALLTHROUGH */
 	case PIPE_BULK:
 		info = is_out
@@ -644,7 +641,7 @@
 				data + urb->iso_frame_desc [cnt].offset,
 				urb->iso_frame_desc [cnt].length, urb, cnt);
 		}
-		ohci->hcd.self.bandwidth_isoc_reqs++;
+		hcd_to_bus (&ohci->hcd)->bandwidth_isoc_reqs++;
 		break;
 	}
 	// ASSERT (urb_priv->length == cnt);
@@ -687,11 +684,10 @@
 		urb->iso_frame_desc [td->index].actual_length = dlen;
 		urb->iso_frame_desc [td->index].status = cc_to_error [cc];
 
-#ifdef VERBOSE_DEBUG
 		if (cc != TD_CC_NOERROR)
-			dbg ("  urb %p iso TD %p (%d) len %d CC %d",
+			ohci_vdbg (ohci,
+				"urb %p iso td %p (%d) len %d cc %d\n",
 				urb, td, 1 + td->index, dlen, cc);
-#endif
 
 	/* BULK, INT, CONTROL ... drivers see aggregate length/status,
 	 * except that "setup" bytes aren't counted and "short" transfers
@@ -730,13 +726,12 @@
 					- td->data_dma;
 		}
 
-#ifdef VERBOSE_DEBUG
 		if (cc != TD_CC_NOERROR && cc < 0x0E)
-			dbg ("  urb %p TD %p (%d) CC %d, len=%d/%d",
+			ohci_vdbg (ohci,
+				"urb %p td %p (%d) cc %d, len=%d/%d\n",
 				urb, td, 1 + td->index, cc,
 				urb->actual_length,
 				urb->transfer_buffer_length);
-#endif
   	}
 }
 
diff -Nru a/drivers/usb/host/ohci-sa1111.c b/drivers/usb/host/ohci-sa1111.c
--- a/drivers/usb/host/ohci-sa1111.c	Fri Feb 28 14:52:14 2003
+++ b/drivers/usb/host/ohci-sa1111.c	Fri Feb 28 14:52:14 2003
@@ -3,7 +3,7 @@
  *
  * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
  * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
- * (C) Hewlett-Packard Company
+ * (C) Copyright 2002 Hewlett-Packard Company
  * 
  * SA1111 Bus Glue
  *
@@ -24,14 +24,6 @@
 #endif
 
 extern int usb_disabled(void);
-
-/*-------------------------------------------------------------------------*/
-
-struct ohci_hcd *dev_to_ohci(struct device *dev) {
-	struct usb_hcd *hcd = dev->driver_data;
-
-	return hcd_to_ohci(hcd);
-}
 
 /*-------------------------------------------------------------------------*/
 
diff -Nru a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h
--- a/drivers/usb/host/ohci.h	Fri Feb 28 14:52:14 2003
+++ b/drivers/usb/host/ohci.h	Fri Feb 28 14:52:14 2003
@@ -372,6 +372,7 @@
 
 	unsigned long		flags;		/* for HC bugs */
 #define	OHCI_QUIRK_AMD756	0x01			/* erratum #4 */
+#define	OHCI_QUIRK_SUPERIO	0x02			/* natsemi */
 	// there are also chip quirks/bugs in init logic
 
 	/*
@@ -382,4 +383,24 @@
 
 #define hcd_to_ohci(hcd_ptr) container_of(hcd_ptr, struct ohci_hcd, hcd)
 
-struct ohci_hcd *dev_to_ohci(struct device *);
+/*-------------------------------------------------------------------------*/
+
+#ifndef DEBUG
+#define STUB_DEBUG_FILES
+#endif	/* DEBUG */
+
+#define ohci_dbg(ohci, fmt, args...) \
+	dev_dbg ((ohci)->hcd.controller , fmt , ## args )
+#define ohci_err(ohci, fmt, args...) \
+	dev_err ((ohci)->hcd.controller , fmt , ## args )
+#define ohci_info(ohci, fmt, args...) \
+	dev_info ((ohci)->hcd.controller , fmt , ## args )
+#define ohci_warn(ohci, fmt, args...) \
+	dev_warn ((ohci)->hcd.controller , fmt , ## args )
+
+#ifdef OHCI_VERBOSE_DEBUG
+#	define ohci_vdbg ohci_dbg
+#else
+#	define ohci_vdbg(ohci, fmt, args...) do { } while (0)
+#endif
+
