# 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 + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,32) +#include "../hcd.h" +#else #include "../core/hcd.h" +#endif #include #include @@ -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 */