# 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.600.1.5 -> 1.600.1.6
#	drivers/usb/host/ehci-q.c	1.23    -> 1.24   
#	drivers/usb/host/ehci-dbg.c	1.7     -> 1.8    
#	drivers/usb/host/ehci-sched.c	1.18    -> 1.19   
#	drivers/usb/host/ehci-hub.c	1.9     -> 1.10   
#	drivers/usb/host/ehci-hcd.c	1.24    -> 1.25   
#	drivers/usb/host/ehci.h	1.8     -> 1.9    
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 02/09/04	david-b@pacbell.net	1.600.1.6
# [PATCH] Re: updated ehci patch ...
# 
#  * keep watchdog on shorter leash, and just do
#    standard irq processing when it barks.  this
#    means I can use a somewhat iffy vt8235 mobo.
# 
#  * updates to the driverfs debug output, including
#    using S_IRUGO so anyone can gawk.
# 
#  * some updates, mostly to use a new hcd_to_bus(),
#    so this version also compiles on a (slightly
#    patched) 2.4.20-pre5 kernel.  (*)
# --------------------------------------------
#
diff -Nru a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c
--- a/drivers/usb/host/ehci-dbg.c	Thu Sep  5 08:51:32 2002
+++ b/drivers/usb/host/ehci-dbg.c	Thu Sep  5 08:51:32 2002
@@ -57,7 +57,7 @@
 			strcat(buf, tmp);
 		}
 		dbg ("%s: %s portroute %s", 
-			ehci->hcd.self.bus_name, label,
+			hcd_to_bus (&ehci->hcd)->bus_name, label,
 			buf);
 	}
 }
@@ -122,7 +122,8 @@
 	}
 }
 
-static int dbg_status_buf (char *buf, unsigned len, char *label, u32 status)
+static int __attribute__((__unused__))
+dbg_status_buf (char *buf, unsigned len, char *label, u32 status)
 {
 	return snprintf (buf, len,
 		"%s%sstatus %04x%s%s%s%s%s%s%s%s%s%s",
@@ -140,7 +141,8 @@
 		);
 }
 
-static int dbg_intr_buf (char *buf, unsigned len, char *label, u32 enable)
+static int __attribute__((__unused__))
+dbg_intr_buf (char *buf, unsigned len, char *label, u32 enable)
 {
 	return snprintf (buf, len,
 		"%s%sintrenable %02x%s%s%s%s%s%s",
@@ -213,19 +215,19 @@
 
 static inline int __attribute__((__unused__))
 dbg_status_buf (char *buf, unsigned len, char *label, u32 status)
-{}
+{ return 0; }
 
 static inline int __attribute__((__unused__))
 dbg_command_buf (char *buf, unsigned len, char *label, u32 command)
-{}
+{ return 0; }
 
 static inline int __attribute__((__unused__))
 dbg_intr_buf (char *buf, unsigned len, char *label, u32 enable)
-{}
+{ return 0; }
 
 static inline int __attribute__((__unused__))
 dbg_port_buf (char *buf, unsigned len, char *label, int port, u32 status)
-{}
+{ return 0; }
 
 #endif	/* DEBUG */
 
@@ -248,7 +250,16 @@
 	dbg ("%s", _buf); \
 }
 
-#ifdef DEBUG
+/*-------------------------------------------------------------------------*/
+
+#ifdef STUB_DEBUG_FILES
+
+static inline void create_debug_files (struct ehci_hcd *bus) { }
+static inline void remove_debug_files (struct ehci_hcd *bus) { }
+
+#else
+
+/* troubleshooting help: expose state in driverfs */
 
 #define speed_char(info1) ({ char tmp; \
 		switch (info1 & (3 << 12)) { \
@@ -258,6 +269,49 @@
 		default: tmp = '?'; break; \
 		}; tmp; })
 
+static void qh_lines (struct ehci_qh *qh, char **nextp, unsigned *sizep)
+{
+	u32			scratch;
+	struct list_head	*entry;
+	struct ehci_qtd		*td;
+	unsigned		temp;
+	unsigned		size = *sizep;
+	char			*next = *nextp;
+
+	scratch = cpu_to_le32p (&qh->hw_info1);
+	temp = snprintf (next, size, "qh/%p dev%d %cs ep%d %08x %08x",
+			qh, scratch & 0x007f,
+			speed_char (scratch),
+			(scratch >> 8) & 0x000f,
+			scratch, cpu_to_le32p (&qh->hw_info2));
+	size -= temp;
+	next += temp;
+
+	list_for_each (entry, &qh->qtd_list) {
+		td = list_entry (entry, struct ehci_qtd,
+				qtd_list);
+		scratch = cpu_to_le32p (&td->hw_token);
+		temp = snprintf (next, size,
+				"\n\ttd/%p %s len=%d %08x urb %p",
+				td, ({ char *tmp;
+				 switch ((scratch>>8)&0x03) {
+				 case 0: tmp = "out"; break;
+				 case 1: tmp = "in"; break;
+				 case 2: tmp = "setup"; break;
+				 default: tmp = "?"; break;
+				 } tmp;}),
+				(scratch >> 16) & 0x7fff,
+				scratch,
+				td->urb);
+		size -= temp;
+		next += temp;
+	}
+
+	temp = snprintf (next, size, "\n");
+	*sizep = size - temp;
+	*nextp = next + temp;
+}
+
 static ssize_t
 show_async (struct device *dev, char *buf, size_t count, loff_t off)
 {
@@ -284,49 +338,21 @@
 	if (ehci->async) {
 		qh = ehci->async;
 		do {
-			u32			scratch;
-			struct list_head	*entry;
-			struct ehci_qtd		*td;
-
-			scratch = cpu_to_le32p (&qh->hw_info1);
-			temp = snprintf (next, size, "qh %p dev%d %cs ep%d",
-					qh, scratch & 0x007f,
-					speed_char (scratch),
-					(scratch >> 8) & 0x000f);
-			size -= temp;
-			next += temp;
-
-			list_for_each (entry, &qh->qtd_list) {
-				td = list_entry (entry, struct ehci_qtd,
-						qtd_list);
-				scratch = cpu_to_le32p (&td->hw_token);
-				temp = snprintf (next, size,
-						", td %p len=%d tok %04x %s",
-						td, scratch >> 16,
-						scratch & 0xffff,
-						({ char *tmp;
-						 switch ((scratch>>8)&0x03) {
-						 case 0: tmp = "out"; break;
-						 case 1: tmp = "in"; break;
-						 case 2: tmp = "setup"; break;
-						 default: tmp = "?"; break;
-						 } tmp;})
-						);
-				size -= temp;
-				next += temp;
-			}
-
-			temp = snprintf (next, size, "\n");
-			size -= temp;
-			next += temp;
-
+			qh_lines (qh, &next, &size);
 		} while ((qh = qh->qh_next.qh) != ehci->async);
 	}
+	if (ehci->reclaim) {
+		temp = snprintf (next, size, "\nreclaim =\n");
+		size -= temp;
+		next += temp;
+
+		qh_lines (ehci->reclaim, &next, &size);
+	}
 	spin_unlock_irqrestore (&ehci->lock, flags);
 
 	return count - size;
 }
-static DEVICE_ATTR (async, S_IRUSR, show_async, NULL);
+static DEVICE_ATTR (async, S_IRUGO, show_async, NULL);
 
 #define DBG_SCHED_LIMIT 64
 
@@ -373,7 +399,7 @@
 		do {
 			switch (tag) {
 			case Q_TYPE_QH:
-				temp = snprintf (next, size, " intr-%d %p",
+				temp = snprintf (next, size, " qh%d/%p",
 						p.qh->period, p.qh);
 				size -= temp;
 				next += temp;
@@ -387,12 +413,14 @@
 							&p.qh->hw_info1);
 
 					temp = snprintf (next, size,
-						" (%cs dev%d ep%d)",
+						" (%cs dev%d ep%d [%d/%d] %d)",
 						speed_char (scratch),
 						scratch & 0x007f,
-						(scratch >> 8) & 0x000f);
+						(scratch >> 8) & 0x000f,
+						p.qh->usecs, p.qh->c_usecs,
+						scratch >> 16);
 
-					/* FIXME TDs too */
+					/* FIXME TD info too */
 
 					if (seen_count < DBG_SCHED_LIMIT)
 						seen [seen_count++].qh = p.qh;
@@ -434,7 +462,7 @@
 
 	return count - size;
 }
-static DEVICE_ATTR (periodic, S_IRUSR, show_periodic, NULL);
+static DEVICE_ATTR (periodic, S_IRUGO, show_periodic, NULL);
 
 #undef DBG_SCHED_LIMIT
 
@@ -522,7 +550,7 @@
 
 	return count - size;
 }
-static DEVICE_ATTR (registers, S_IRUSR, show_registers, NULL);
+static DEVICE_ATTR (registers, S_IRUGO, show_registers, NULL);
 
 static inline void create_debug_files (struct ehci_hcd *bus)
 {
@@ -538,14 +566,5 @@
 	device_remove_file (&bus->hcd.pdev->dev, &dev_attr_registers);
 }
 
-#else /* DEBUG */
-
-static inline void create_debug_files (struct ehci_hcd *bus)
-{
-}
-
-static inline void remove_debug_files (struct ehci_hcd *bus)
-{
-}
+#endif /* STUB_DEBUG_FILES */
 
-#endif /* DEBUG */
diff -Nru a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
--- a/drivers/usb/host/ehci-hcd.c	Thu Sep  5 08:51:32 2002
+++ b/drivers/usb/host/ehci-hcd.c	Thu Sep  5 08:51:32 2002
@@ -38,7 +38,12 @@
 #endif
 
 #include <linux/usb.h>
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,32)
+#include "../hcd.h"
+#else
 #include "../core/hcd.h"
+#endif
 
 #include <asm/byteorder.h>
 #include <asm/io.h>
@@ -104,7 +109,7 @@
 #define	EHCI_TUNE_MULT_HS	1	/* 1-3 transactions/uframe; 4.10.3 */
 #define	EHCI_TUNE_MULT_TT	1
 
-#define EHCI_WATCHDOG_JIFFIES	(HZ/10)		/* arbitrary; ~100 msec */
+#define EHCI_WATCHDOG_JIFFIES	(HZ/100)	/* arbitrary; ~10 msec */
 
 /* Initial IRQ latency:  lower than default */
 static int log2_irq_thresh = 0;		// 0 to 6
@@ -234,6 +239,8 @@
 
 static void ehci_tasklet (unsigned long param);
 
+static void ehci_irq (struct usb_hcd *hcd);
+
 static void ehci_watchdog (unsigned long param)
 {
 	struct ehci_hcd		*ehci = (struct ehci_hcd *) param;
@@ -241,14 +248,8 @@
 
 	/* guard against lost IAA, which wedges everything */
 	spin_lock_irqsave (&ehci->lock, flags);
-	if (ehci->reclaim) {
-		err ("%s watchdog, reclaim qh %p%s", ehci->hcd.self.bus_name,
-			ehci->reclaim, ehci->reclaim_ready ? " ready" : "");
-//		ehci->reclaim_ready = 1;
-		tasklet_schedule (&ehci->tasklet);
-	}
+	ehci_irq (&ehci->hcd);
 	spin_unlock_irqrestore (&ehci->lock, flags);
-
 }
 
 /* EHCI 0.96 (and later) section 5.1 says how to kick BIOS/SMM/...
@@ -286,6 +287,7 @@
 	struct ehci_hcd		*ehci = hcd_to_ehci (hcd);
 	u32			temp;
 	struct usb_device	*udev;
+	struct usb_bus		*bus;
 	int			retval;
 	u32			hcc_params;
 	u8                      tempbyte;
@@ -396,15 +398,14 @@
 	ehci->watchdog.data = (unsigned long) ehci;
 
 	/* wire up the root hub */
-	hcd->self.root_hub = udev = usb_alloc_dev (NULL, &hcd->self);
+	bus = hcd_to_bus (hcd);
+	bus->root_hub = udev = usb_alloc_dev (NULL, bus);
 	if (!udev) {
 done2:
 		ehci_mem_cleanup (ehci);
 		return -ENOMEM;
 	}
 
-	create_debug_files (ehci);
-
 	/*
 	 * Start, enabling full USB 2.0 functionality ... usb 1.1 devices
 	 * are explicitly handed to companion controller(s), so no TT is
@@ -432,16 +433,22 @@
 	 */
 	usb_connect (udev);
 	udev->speed = USB_SPEED_HIGH;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,32)
+	if (usb_new_device (udev) != 0) {
+#else
 	if (usb_register_root_hub (udev, &ehci->hcd.pdev->dev) != 0) {
+#endif
 		if (hcd->state == USB_STATE_RUNNING)
 			ehci_ready (ehci);
 		ehci_reset (ehci);
-		hcd->self.root_hub = 0;
+		bus->root_hub = 0;
 		usb_free_dev (udev); 
 		retval = -ENODEV;
 		goto done2;
 	}
 
+	create_debug_files (ehci);
+
 	return 0;
 }
 
@@ -451,7 +458,7 @@
 {
 	struct ehci_hcd		*ehci = hcd_to_ehci (hcd);
 
-	dbg ("%s: stop", hcd->self.bus_name);
+	dbg ("%s: stop", hcd_to_bus (hcd)->bus_name);
 
 	/* no more interrupts ... */
 	if (hcd->state == USB_STATE_RUNNING)
@@ -493,7 +500,7 @@
 	int			ports;
 	int			i;
 
-	dbg ("%s: suspend to %d", hcd->self.bus_name, state);
+	dbg ("%s: suspend to %d", hcd_to_bus (hcd)->bus_name, state);
 
 	ports = HCS_N_PORTS (ehci->hcs_params);
 
@@ -510,7 +517,7 @@
 		if ((temp & PORT_PE) == 0
 				|| (temp & PORT_OWNER) != 0)
 			continue;
-dbg ("%s: suspend port %d", hcd->self.bus_name, i);
+dbg ("%s: suspend port %d", hcd_to_bus (hcd)->bus_name, i);
 		temp |= PORT_SUSPEND;
 		writel (temp, &ehci->regs->port_status [i]);
 	}
@@ -532,7 +539,7 @@
 	int			ports;
 	int			i;
 
-	dbg ("%s: resume", hcd->self.bus_name);
+	dbg ("%s: resume", hcd_to_bus (hcd)->bus_name);
 
 	ports = HCS_N_PORTS (ehci->hcs_params);
 
@@ -552,7 +559,7 @@
 		if ((temp & PORT_PE) == 0
 				|| (temp & PORT_SUSPEND) != 0)
 			continue;
-dbg ("%s: resume port %d", hcd->self.bus_name, i);
+dbg ("%s: resume port %d", hcd_to_bus (hcd)->bus_name, i);
 		temp |= PORT_RESUME;
 		writel (temp, &ehci->regs->port_status [i]);
 		readl (&ehci->regs->command);	/* unblock posted writes */
@@ -599,7 +606,7 @@
 
 	/* e.g. cardbus physical eject */
 	if (status == ~(u32) 0) {
-		dbg ("%s: device removed!", hcd->self.bus_name);
+		dbg ("%s: device removed!", hcd_to_bus (hcd)->bus_name);
 		goto dead;
 	}
 
@@ -632,7 +639,7 @@
 	/* PCI errors [4.15.2.4] */
 	if (unlikely ((status & STS_FATAL) != 0)) {
 		err ("%s: fatal error, state %x",
-			hcd->self.bus_name, hcd->state);
+			hcd_to_bus (hcd)->bus_name, hcd->state);
 dead:
 		ehci_reset (ehci);
 		/* generic layer kills/unlinks all urbs, then
@@ -708,7 +715,7 @@
 	unsigned long		flags;
 
 	dbg ("%s urb_dequeue %p qh %p state %d",
-		hcd->self.bus_name, urb, qh, qh->qh_state);
+		hcd_to_bus (hcd)->bus_name, urb, qh, qh->qh_state);
 
 	switch (usb_pipetype (urb->pipe)) {
 	// case PIPE_CONTROL:
@@ -795,7 +802,8 @@
 	/* ASSERT:  no requests/urbs are still linked (so no TDs) */
 	/* ASSERT:  nobody can be submitting urbs for this any more */
 
-	dbg ("%s: free_config devnum %d", hcd->self.bus_name, udev->devnum);
+	dbg ("%s: free_config devnum %d",
+		hcd_to_bus (hcd)->bus_name, udev->devnum);
 
 	spin_lock_irqsave (&ehci->lock, flags);
 	for (i = 0; i < 32; i++) {
@@ -816,7 +824,8 @@
 				why = 0;
 			if (why) {
 				err ("dev %s-%s ep %d-%s error: %s",
-					hcd->self.bus_name, udev->devpath,
+					hcd_to_bus (hcd)->bus_name,
+					udev->devpath,
 					i & 0xf, (i & 0x10) ? "IN" : "OUT",
 					why);
 				BUG ();
diff -Nru a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
--- a/drivers/usb/host/ehci-hub.c	Thu Sep  5 08:51:32 2002
+++ b/drivers/usb/host/ehci-hub.c	Thu Sep  5 08:51:32 2002
@@ -41,14 +41,17 @@
 	/* if reset finished and it's still not enabled -- handoff */
 	if (!(port_status & PORT_PE)) {
 		dbg ("%s port %d full speed, give to companion, 0x%x",
-			ehci->hcd.self.bus_name, index + 1, port_status);
+			hcd_to_bus (&ehci->hcd)->bus_name,
+			index + 1, port_status);
 
 		// what happens if HCS_N_CC(params) == 0 ?
 		port_status |= PORT_OWNER;
 		writel (port_status, &ehci->regs->port_status [index]);
 
 	} else
-		dbg ("%s port %d high speed", ehci->hcd.self.bus_name, index + 1);
+		dbg ("%s port %d high speed",
+			hcd_to_bus (&ehci->hcd)->bus_name,
+			index + 1);
 
 	return port_status;
 }
@@ -310,11 +313,13 @@
 			if ((temp & (PORT_PE|PORT_CONNECT)) == PORT_CONNECT
 					&& PORT_USB11 (temp)) {
 				dbg ("%s port %d low speed, give to companion",
-					hcd->self.bus_name, wIndex + 1);
+					hcd_to_bus (&ehci->hcd)->bus_name,
+					wIndex + 1);
 				temp |= PORT_OWNER;
 			} else {
 				vdbg ("%s port %d reset",
-					hcd->self.bus_name, wIndex + 1);
+					hcd_to_bus (&ehci->hcd)->bus_name,
+					wIndex + 1);
 				temp |= PORT_RESET;
 				temp &= ~PORT_PE;
 
diff -Nru a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
--- a/drivers/usb/host/ehci-q.c	Thu Sep  5 08:51:32 2002
+++ b/drivers/usb/host/ehci-q.c	Thu Sep  5 08:51:32 2002
@@ -178,7 +178,7 @@
 		if ((qh->hw_info2 & cpu_to_le32 (0x00ff)) != 0) {
 
 			/* ... update hc-wide periodic stats (for usbfs) */
-			ehci->hcd.self.bandwidth_int_reqs--;
+			hcd_to_bus (&ehci->hcd)->bandwidth_int_reqs--;
 
 #ifdef	INTR_AUTOMAGIC
 			if (!((urb->status == -ENOENT)
@@ -215,7 +215,7 @@
 		int	status;
 
 		resubmit->dev = dev;
-		status = usb_submit_urb (resubmit, SLAB_KERNEL);
+		status = SUBMIT_URB (resubmit, SLAB_KERNEL);
 		if (status != 0)
 			err ("can't resubmit interrupt urb %p: status %d",
 					resubmit, status);
@@ -652,8 +652,8 @@
 			info2 |= hb_mult (maxp) << 30;
 		}
 		break;
-#ifdef DEBUG
 	default:
+#ifdef DEBUG
 		BUG ();
 #endif
 	}
@@ -841,7 +841,8 @@
 		epnum |= 0x10;
 
 	vdbg ("%s: submit_async urb %p len %d ep %d-%s qtd %p [qh %p]",
-		ehci->hcd.self.bus_name, urb, urb->transfer_buffer_length,
+		hcd_to_bus (&ehci->hcd)->bus_name,
+		urb, urb->transfer_buffer_length,
 		epnum & 0x0f, (epnum & 0x10) ? "in" : "out",
 		qtd, dev ? dev->ep [epnum] : (void *)~0);
 
diff -Nru a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
--- a/drivers/usb/host/ehci-sched.c	Thu Sep  5 08:51:32 2002
+++ b/drivers/usb/host/ehci-sched.c	Thu Sep  5 08:51:32 2002
@@ -273,7 +273,7 @@
 	qh->qh_state = QH_STATE_IDLE;
 
 	/* update per-qh bandwidth utilization (for usbfs) */
-	ehci->hcd.self.bandwidth_allocated -= 
+	hcd_to_bus (&ehci->hcd)->bandwidth_allocated -= 
 		(qh->usecs + qh->c_usecs) / qh->period;
 
 	vdbg ("descheduled qh %p, per = %d frame = %d count = %d, urbs = %d",
@@ -435,7 +435,7 @@
 	} while (frame < ehci->periodic_size);
 
 	/* update per-qh bandwidth for usbfs */
-	ehci->hcd.self.bandwidth_allocated += 
+	hcd_to_bus (&ehci->hcd)->bandwidth_allocated += 
 		(qh->usecs + qh->c_usecs) / qh->period;
 
 	/* maybe enable periodic schedule processing */
@@ -485,7 +485,7 @@
 	BUG_ON (qh == 0);
 
 	/* ... update usbfs periodic stats */
-	ehci->hcd.self.bandwidth_int_reqs++;
+	hcd_to_bus (&ehci->hcd)->bandwidth_int_reqs++;
 
 done:
 	spin_unlock_irqrestore (&ehci->lock, flags);
diff -Nru a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
--- a/drivers/usb/host/ehci.h	Thu Sep  5 08:51:32 2002
+++ b/drivers/usb/host/ehci.h	Thu Sep  5 08:51:32 2002
@@ -391,4 +391,26 @@
 	union ehci_shadow	fstn_next;	/* ptr to periodic q entry */
 } __attribute__ ((aligned (32)));
 
+/*-------------------------------------------------------------------------*/
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,32)
+
+#define SUBMIT_URB(urb,mem_flags) usb_submit_urb(urb)
+#define STUB_DEBUG_FILES
+
+#else	/* LINUX_VERSION_CODE */
+
+static inline struct usb_bus *hcd_to_bus (struct usb_hcd *hcd)
+	{ return &hcd->self; }
+
+#define SUBMIT_URB(urb,mem_flags) usb_submit_urb(urb,mem_flags)
+
+#ifndef DEBUG
+#define STUB_DEBUG_FILES
+#endif	/* DEBUG */
+
+#endif	/* LINUX_VERSION_CODE */
+
+/*-------------------------------------------------------------------------*/
+
 #endif /* __LINUX_EHCI_HCD_H */
