diff options
| author | Greg Kroah-Hartman <greg@kroah.com> | 2002-12-01 06:59:25 -0800 |
|---|---|---|
| committer | Greg Kroah-Hartman <greg@kroah.com> | 2002-12-01 06:59:25 -0800 |
| commit | 46eb8948b4852e893f8fcfb1a751d23b7b5ea3ac (patch) | |
| tree | ec4f2cd92abdf17ff508278150790ff42eea43b0 | |
| parent | 114d2a8e848612ae717ab70d2834f35c812f13d1 (diff) | |
| parent | 414ca09cee26239c5fd423f676d7dfcb823adbe4 (diff) | |
Merge kroah.com:/home/linux/linux/BK/bleeding-2.5
into kroah.com:/home/linux/linux/BK/gregkh-2.5
| -rw-r--r-- | drivers/usb/core/devio.c | 59 | ||||
| -rw-r--r-- | drivers/usb/core/hcd-pci.c | 31 | ||||
| -rw-r--r-- | drivers/usb/core/hcd.c | 11 | ||||
| -rw-r--r-- | drivers/usb/core/usb.c | 31 | ||||
| -rw-r--r-- | drivers/usb/host/ehci-dbg.c | 46 | ||||
| -rw-r--r-- | drivers/usb/host/ehci-hcd.c | 76 | ||||
| -rw-r--r-- | drivers/usb/host/ehci-hub.c | 19 | ||||
| -rw-r--r-- | drivers/usb/host/ehci-mem.c | 45 | ||||
| -rw-r--r-- | drivers/usb/host/ehci-q.c | 111 | ||||
| -rw-r--r-- | drivers/usb/host/uhci-hcd.c | 4 | ||||
| -rw-r--r-- | drivers/usb/serial/usb-serial.c | 45 | ||||
| -rw-r--r-- | drivers/usb/storage/transport.c | 2 |
12 files changed, 231 insertions, 249 deletions
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index 4199b9332979..c1adbac7f205 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -239,18 +239,14 @@ extern __inline__ struct async *async_getpending(struct dev_state *ps, void *use { unsigned long flags; struct async *as; - struct list_head *p; spin_lock_irqsave(&ps->lock, flags); - for (p = ps->async_pending.next; p != &ps->async_pending; ) { - as = list_entry(p, struct async, asynclist); - p = p->next; - if (as->userurb != userurb) - continue; - list_del_init(&as->asynclist); - spin_unlock_irqrestore(&ps->lock, flags); - return as; - } + list_for_each_entry(as, &ps->async_pending, asynclist) + if (as->userurb == userurb) { + list_del_init(&as->asynclist); + spin_unlock_irqrestore(&ps->lock, flags); + return as; + } spin_unlock_irqrestore(&ps->lock, flags); return NULL; } @@ -295,19 +291,14 @@ static void destroy_async (struct dev_state *ps, struct list_head *list) static void destroy_async_on_interface (struct dev_state *ps, unsigned int intf) { - struct async *as; - struct list_head *p, hitlist; + struct list_head *p, *q, hitlist; unsigned long flags; INIT_LIST_HEAD(&hitlist); spin_lock_irqsave(&ps->lock, flags); - for (p = ps->async_pending.next; p != &ps->async_pending; ) { - as = list_entry(p, struct async, asynclist); - p = p->next; - - if (as->intf == intf) - list_move_tail(&as->asynclist, &hitlist); - } + list_for_each_safe(p, q, &ps->async_pending) + if (intf == list_entry(p, struct async, asynclist)->intf) + list_move_tail(p, &hitlist); spin_unlock_irqrestore(&ps->lock, flags); destroy_async(ps, &hitlist); } @@ -869,7 +860,7 @@ static int proc_submiturb(struct dev_state *ps, void *arg) if (uurb.buffer_length > 16384) return -EINVAL; if (!access_ok((uurb.endpoint & USB_DIR_IN) ? VERIFY_WRITE : VERIFY_READ, uurb.buffer, uurb.buffer_length)) - return -EFAULT; + return -EFAULT; break; default: @@ -964,10 +955,10 @@ static int processcompl(struct async *as) if (!(usb_pipeisoc(urb->pipe))) return 0; for (i = 0; i < urb->number_of_packets; i++) { - if (put_user(urb->iso_frame_desc[i].actual_length, + if (put_user(urb->iso_frame_desc[i].actual_length, &((struct usbdevfs_urb *)as->userurb)->iso_frame_desc[i].actual_length)) return -EFAULT; - if (put_user(urb->iso_frame_desc[i].status, + if (put_user(urb->iso_frame_desc[i].status, &((struct usbdevfs_urb *)as->userurb)->iso_frame_desc[i].status)) return -EFAULT; } @@ -1099,12 +1090,10 @@ static int proc_ioctl (struct dev_state *ps, void *arg) else switch (ctrl.ioctl_code) { /* disconnect kernel driver from interface, leaving it unbound. */ + /* maybe unbound - you get no guarantee it stays unbound */ case USBDEVFS_DISCONNECT: - /* this function is voodoo. */ - /* which function ... usb_device_remove()? - * FIXME either the module lock (BKL) should be involved - * here too, or the 'default' case below is broken - */ + /* this function is misdesigned - retained for compatibility */ + lock_kernel(); driver = ifp->driver; if (driver) { dbg ("disconnect '%s' from dev %d interface %d", @@ -1112,11 +1101,14 @@ static int proc_ioctl (struct dev_state *ps, void *arg) usb_device_remove(&ifp->dev); } else retval = -ENODATA; + unlock_kernel(); break; /* let kernel drivers try to (re)bind to the interface */ case USBDEVFS_CONNECT: + lock_kernel(); retval = usb_device_probe (&ifp->dev); + unlock_kernel(); break; /* talk directly to the interface's driver */ @@ -1131,20 +1123,17 @@ static int proc_ioctl (struct dev_state *ps, void *arg) unlock_kernel(); retval = -ENOSYS; } else { - if (driver->owner - && !try_inc_mod_count (driver->owner)) { + if (!try_module_get (driver->owner)) { unlock_kernel(); retval = -ENOSYS; break; } unlock_kernel (); retval = driver->ioctl (ifp, ctrl.ioctl_code, buf); - if (driver->owner) - __MOD_DEC_USE_COUNT (driver->owner); + if (retval == -ENOIOCTLCMD) + retval = -ENOTTY; + module_put (driver->owner); } - - if (retval == -ENOIOCTLCMD) - retval = -ENOTTY; } /* cleanup and return */ @@ -1197,7 +1186,7 @@ static int usbdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd case USBDEVFS_RESET: ret = proc_resetdevice(ps); break; - + case USBDEVFS_CLEAR_HALT: ret = proc_clearhalt(ps, (void *)arg); if (ret >= 0) diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c index dc0ef310d316..e66aaac9fa78 100644 --- a/drivers/usb/core/hcd-pci.c +++ b/drivers/usb/core/hcd-pci.c @@ -146,7 +146,7 @@ clean_3: goto clean_2; } - info ("%s @ %s, %s", hcd->description, dev->slot_name, dev->dev.name); + dev_info (*hcd->controller, "%s\n", hcd->product_desc); #ifndef __sparc__ sprintf (buf, "%d", dev->irq); @@ -155,7 +155,8 @@ clean_3: #endif if (request_irq (dev->irq, usb_hcd_irq, SA_SHIRQ, hcd->description, hcd) != 0) { - err ("request interrupt %s failed", bufp); + dev_err (*hcd->controller, + "request interrupt %s failed\n", bufp); retval = -EBUSY; goto clean_3; } @@ -163,7 +164,7 @@ clean_3: hcd->regs = base; hcd->region = region; - info ("irq %s, %s %p", bufp, + dev_info (*hcd->controller, "irq %s, %s %p\n", bufp, (driver->flags & HCD_MEMORY) ? "pci mem" : "io base", base); @@ -205,19 +206,20 @@ void usb_hcd_pci_remove (struct pci_dev *dev) hcd = pci_get_drvdata(dev); if (!hcd) return; - info ("remove: %s, state %x", hcd->self.bus_name, hcd->state); + dev_info (*hcd->controller, "remove, state %x\n", hcd->state); if (in_interrupt ()) BUG (); hub = hcd->self.root_hub; hcd->state = USB_STATE_QUIESCING; - dbg ("%s: roothub graceful disconnect", hcd->self.bus_name); + dev_dbg (*hcd->controller, "roothub graceful disconnect\n"); usb_disconnect (&hub); hcd->driver->stop (hcd); hcd_buffer_destroy (hcd); hcd->state = USB_STATE_HALT; + pci_set_drvdata (dev, 0); free_irq (hcd->irq, hcd); if (hcd->driver->flags & HCD_MEMORY) { @@ -230,9 +232,12 @@ void usb_hcd_pci_remove (struct pci_dev *dev) } usb_deregister_bus (&hcd->self); - if (atomic_read (&hcd->self.refcnt) != 1) - err ("usb_hcd_pci_remove %s, count != 1", hcd->self.bus_name); - + if (atomic_read (&hcd->self.refcnt) != 1) { + dev_warn (*hcd->controller, + "dangling refs (%d) to bus %d!\n", + atomic_read (&hcd->self.refcnt) - 1, + hcd->self.busnum); + } hcd->driver->hcd_free (hcd); } EXPORT_SYMBOL (usb_hcd_pci_remove); @@ -279,7 +284,7 @@ int usb_hcd_pci_suspend (struct pci_dev *dev, u32 state) int retval; hcd = pci_get_drvdata(dev); - info ("suspend %s to state %d", hcd->self.bus_name, state); + dev_info (*hcd->controller, "suspend to state %d\n", state); pci_save_state (dev, hcd->pci_state); @@ -308,19 +313,19 @@ int usb_hcd_pci_resume (struct pci_dev *dev) int retval; hcd = pci_get_drvdata(dev); - info ("resume %s", hcd->self.bus_name); + dev_info (*hcd->controller, "resume\n"); /* guard against multiple resumes (APM bug?) */ atomic_inc (&hcd->resume_count); if (atomic_read (&hcd->resume_count) != 1) { - err ("concurrent PCI resumes for %s", hcd->self.bus_name); + dev_err (*hcd->controller, "concurrent PCI resumes\n"); retval = 0; goto done; } retval = -EBUSY; if (hcd->state != USB_STATE_SUSPENDED) { - dbg ("can't resume, not suspended!"); + dev_dbg (*hcd->controller, "can't resume, not suspended!\n"); goto done; } hcd->state = USB_STATE_RESUMING; @@ -330,7 +335,7 @@ int usb_hcd_pci_resume (struct pci_dev *dev) retval = hcd->driver->resume (hcd); if (!HCD_IS_RUNNING (hcd->state)) { - dbg ("resume %s failure, retval %d", hcd->self.bus_name, retval); + dev_dbg (*hcd->controller, "resume fail, retval %d\n", retval); usb_hc_died (hcd); // FIXME: recover, reset etc. } else { diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index f8153e7ee704..2318f7893f09 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -715,7 +715,8 @@ int usb_register_root_hub (struct usb_device *usb_dev, struct device *parent_dev sprintf (&usb_dev->dev.bus_id[0], "usb%d", usb_dev->bus->busnum); retval = usb_new_device (usb_dev, parent_dev); if (retval) - err("%s - usb_new_device failed with value %d", __FUNCTION__, retval); + dev_err (*parent_dev, "can't register root hub for %s, %d\n", + usb_dev->dev.bus_id, retval); return retval; } EXPORT_SYMBOL (usb_register_root_hub); @@ -1286,13 +1287,7 @@ void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb) // NOTE: a generic device/urb monitoring hook would go here. // hcd_monitor_hook(MONITOR_URB_FINISH, urb, dev) - // It would catch exit/unlink paths for all urbs, but non-exit - // completions for periodic urbs need hooks inside the HCD. - // hcd_monitor_hook(MONITOR_URB_UPDATE, urb, dev) - - if (urb->status) - dbg ("giveback urb %p status %d len %d", - urb, urb->status, urb->actual_length); + // It would catch exit/unlink paths for all urbs. /* lower level hcd code should use *_dma exclusively */ if (!(urb->transfer_flags & URB_NO_DMA_MAP)) { diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index 4c34d40f3c3f..bef9a14746e5 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c @@ -69,24 +69,23 @@ static struct device_driver usb_generic_driver = { .probe = generic_probe, .remove = generic_remove, }; - + +/* needs to be called with BKL held */ int usb_device_probe(struct device *dev) { struct usb_interface * intf = to_usb_interface(dev); struct usb_driver * driver = to_usb_driver(dev->driver); const struct usb_device_id *id; int error = -ENODEV; - int m; dbg("%s", __FUNCTION__); if (!driver->probe) return error; - if (driver->owner) { - m = try_inc_mod_count(driver->owner); - if (m == 0) - return error; + if (!try_module_get(driver->owner)) { + err ("Can't get a module reference for %s", driver->name); + return error; } id = usb_match_id (intf, driver->id_table); @@ -99,8 +98,7 @@ int usb_device_probe(struct device *dev) if (!error) intf->driver = driver; - if (driver->owner) - __MOD_DEC_USE_COUNT(driver->owner); + module_put(driver->owner); return error; } @@ -109,7 +107,6 @@ int usb_device_remove(struct device *dev) { struct usb_interface *intf; struct usb_driver *driver; - int m; intf = list_entry(dev,struct usb_interface,dev); driver = to_usb_driver(dev->driver); @@ -120,14 +117,11 @@ int usb_device_remove(struct device *dev) return -ENODEV; } - if (driver->owner) { - m = try_inc_mod_count(driver->owner); - if (m == 0) { - // FIXME this happens even when we just rmmod - // drivers that aren't in active use... - err("Dieing driver still bound to device.\n"); - return -EIO; - } + if (!try_module_get(driver->owner)) { + // FIXME this happens even when we just rmmod + // drivers that aren't in active use... + err("Dieing driver still bound to device.\n"); + return -EIO; } /* if we sleep here on an umanaged driver @@ -143,8 +137,7 @@ int usb_device_remove(struct device *dev) usb_driver_release_interface(driver, intf); up(&driver->serialize); - if (driver->owner) - __MOD_DEC_USE_COUNT(driver->owner); + module_put(driver->owner); return 0; } diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c index a06bf78b533c..69d60a2d9a95 100644 --- a/drivers/usb/host/ehci-dbg.c +++ b/drivers/usb/host/ehci-dbg.c @@ -18,6 +18,17 @@ /* this file is part of ehci-hcd.c */ +#define ehci_dbg(ehci, fmt, args...) \ + dev_dbg (*(ehci)->hcd.controller, fmt, ## args ) + +#ifdef EHCI_VERBOSE_DEBUG +#define ehci_vdbg(ehci, fmt, args...) \ + dev_dbg (*(ehci)->hcd.controller, fmt, ## args ) +#else +#define ehci_vdbg(ehci, fmt, args...) do { } while (0) +#endif + + #ifdef EHCI_VERBOSE_DEBUG # define vdbg dbg #else @@ -34,7 +45,8 @@ static void dbg_hcs_params (struct ehci_hcd *ehci, char *label) { u32 params = readl (&ehci->caps->hcs_params); - dbg ("%s hcs_params 0x%x dbg=%d%s cc=%d pcc=%d%s%s ports=%d", + ehci_dbg (ehci, + "%s hcs_params 0x%x dbg=%d%s cc=%d pcc=%d%s%s ports=%d\n", label, params, HCS_DEBUG_PORT (params), HCS_INDICATOR (params) ? " ind" : "", @@ -56,9 +68,8 @@ static void dbg_hcs_params (struct ehci_hcd *ehci, char *label) ((i & 0x1) ? ((byte)&0xf) : ((byte>>4)&0xf))); strcat(buf, tmp); } - dbg ("%s: %s portroute %s", - hcd_to_bus (&ehci->hcd)->bus_name, label, - buf); + ehci_dbg (ehci, "%s portroute %s\n", + label, buf); } } #else @@ -77,19 +88,16 @@ static void dbg_hcc_params (struct ehci_hcd *ehci, char *label) { u32 params = readl (&ehci->caps->hcc_params); - if (HCC_EXT_CAPS (params)) { - // EHCI 0.96 ... could interpret these (legacy?) - dbg ("%s extended capabilities at pci %2x", - label, HCC_EXT_CAPS (params)); - } if (HCC_ISOC_CACHE (params)) { - dbg ("%s hcc_params %04x caching frame %s%s%s", + ehci_dbg (ehci, + "%s hcc_params %04x caching frame %s%s%s\n", label, params, HCC_PGM_FRAMELISTLEN (params) ? "256/512/1024" : "1024", HCC_CANPARK (params) ? " park" : "", HCC_64BIT_ADDR (params) ? " 64 bit addr" : ""); } else { - dbg ("%s hcc_params %04x caching %d uframes %s%s%s", + ehci_dbg (ehci, + "%s hcc_params %04x thresh %d uframes %s%s%s\n", label, params, HCC_ISOC_THRES (params), @@ -235,19 +243,19 @@ dbg_port_buf (char *buf, unsigned len, char *label, int port, u32 status) #define dbg_status(ehci, label, status) { \ char _buf [80]; \ dbg_status_buf (_buf, sizeof _buf, label, status); \ - dbg ("%s", _buf); \ + ehci_dbg (ehci, "%s\n", _buf); \ } #define dbg_cmd(ehci, label, command) { \ char _buf [80]; \ dbg_command_buf (_buf, sizeof _buf, label, command); \ - dbg ("%s", _buf); \ + ehci_dbg (ehci, "%s\n", _buf); \ } -#define dbg_port(hcd, label, port, status) { \ +#define dbg_port(ehci, label, port, status) { \ char _buf [80]; \ dbg_port_buf (_buf, sizeof _buf, label, port, status); \ - dbg ("%s", _buf); \ + ehci_dbg (ehci, "%s\n", _buf); \ } /*-------------------------------------------------------------------------*/ @@ -338,12 +346,8 @@ show_async (struct device *dev, char *buf, size_t count, loff_t off) * one QH per line, and TDs we know about */ spin_lock_irqsave (&ehci->lock, flags); - if (ehci->async) { - qh = ehci->async; - do { - qh_lines (qh, &next, &size); - } while ((qh = qh->qh_next.qh) != ehci->async); - } + for (qh = ehci->async->qh_next.qh; qh; qh = qh->qh_next.qh) + qh_lines (qh, &next, &size); if (ehci->reclaim) { temp = snprintf (next, size, "\nreclaim =\n"); size -= temp; diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index f78c8ad0a808..6a70bc006b6e 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -17,6 +17,13 @@ */ #include <linux/config.h> + +#ifdef CONFIG_USB_DEBUG + #define DEBUG +#else + #undef DEBUG +#endif + #include <linux/module.h> #include <linux/pci.h> #include <linux/kernel.h> @@ -31,12 +38,6 @@ #include <linux/list.h> #include <linux/interrupt.h> -#ifdef CONFIG_USB_DEBUG - #define DEBUG -#else - #undef DEBUG -#endif - #include <linux/usb.h> #include <linux/version.h> @@ -70,6 +71,7 @@ * * HISTORY: * + * 2002-11-29 Correct handling for hw async_next register. * 2002-08-06 Handling for bulk and interrupt transfers is mostly shared; * only scheduling is different, no arbitrary limitations. * 2002-07-25 Sanity check PCI reads, mostly for better cardbus support, @@ -92,7 +94,7 @@ * 2001-June Works with usb-storage and NEC EHCI on 2.4 */ -#define DRIVER_VERSION "2002-Sep-23" +#define DRIVER_VERSION "2002-Nov-29" #define DRIVER_AUTHOR "David Brownell" #define DRIVER_DESC "USB 2.0 'Enhanced' Host Controller (EHCI) Driver" @@ -114,7 +116,7 @@ static const char hcd_name [] = "ehci-hcd"; #define EHCI_TUNE_MULT_TT 1 #define EHCI_WATCHDOG_JIFFIES (HZ/100) /* arbitrary; ~10 msec */ -#define EHCI_ASYNC_JIFFIES (HZ/3) /* async idle timeout */ +#define EHCI_ASYNC_JIFFIES (HZ/20) /* async idle timeout */ /* Initial IRQ latency: lower than default */ static int log2_irq_thresh = 0; // 0 to 6 @@ -215,7 +217,7 @@ static void ehci_ready (struct ehci_hcd *ehci) /* wait for any schedule enables/disables to take effect */ temp = 0; - if (ehci->async) + if (ehci->async->qh_next.qh) temp = STS_ASS; if (ehci->next_uframe != -1) temp |= STS_PSS; @@ -260,7 +262,7 @@ static void ehci_watchdog (unsigned long param) spin_lock_irqsave (&ehci->lock, flags); /* guard against lost IAA, which wedges everything */ ehci_irq (&ehci->hcd); - /* unlink the last qh after it's idled a while */ + /* stop async processing after it's idled a while */ if (ehci->async_idle) { start_unlink_async (ehci, ehci->async); ehci->async_idle = 0; @@ -287,12 +289,13 @@ static int bios_handoff (struct ehci_hcd *ehci, int where, u32 cap) pci_read_config_dword (ehci->hcd.pdev, where, &cap); } while ((cap & (1 << 16)) && msec); if (cap & (1 << 16)) { - info ("BIOS handoff failed (%d, %04x)", where, cap); + dev_info (*ehci->hcd.controller, + "BIOS handoff failed (%d, %04x)\n", + where, cap); return 1; } - dbg ("BIOS handoff succeeded"); - } else - dbg ("BIOS handoff not needed"); + ehci_dbg (ehci, "BIOS handoff succeeded\n"); + } return 0; } @@ -323,14 +326,15 @@ static int ehci_start (struct usb_hcd *hcd) u32 cap; pci_read_config_dword (ehci->hcd.pdev, temp, &cap); - dbg ("capability %04x at %02x", cap, temp); + ehci_dbg (ehci, "capability %04x at %02x\n", cap, temp); switch (cap & 0xff) { case 1: /* BIOS/SMM/... handoff */ if (bios_handoff (ehci, temp, cap) != 0) return -EOPNOTSUPP; break; case 0: /* illegal reserved capability */ - warn ("illegal capability!"); + dev_warn (*ehci->hcd.controller, + "illegal capability!\n"); cap = 0; /* FALLTHROUGH */ default: /* unknown */ @@ -360,7 +364,6 @@ static int ehci_start (struct usb_hcd *hcd) else // N microframes cached ehci->i_thresh = 2 + HCC_ISOC_THRES (hcc_params); - ehci->async = 0; ehci->reclaim = 0; ehci->next_uframe = -1; @@ -375,6 +378,21 @@ static int ehci_start (struct usb_hcd *hcd) writel (ehci->periodic_dma, &ehci->regs->frame_list); /* + * dedicate a qh for the async ring head, since we couldn't unlink + * a 'real' qh without stopping the async schedule [4.8]. use it + * as the 'reclamation list head' too. + */ + ehci->async->qh_next.qh = 0; + ehci->async->hw_next = QH_NEXT (ehci->async->qh_dma); + ehci->async->hw_info1 = cpu_to_le32 (QH_HEAD); + ehci->async->hw_token = cpu_to_le32 (QTD_STS_HALT); + ehci->async->hw_qtd_next = EHCI_LIST_END; + ehci->async->qh_state = QH_STATE_LINKED; + ehci_qtd_free (ehci, ehci->async->dummy); + ehci->async->dummy = 0; + writel ((u32)ehci->async->qh_dma, &ehci->regs->async_next); + + /* * hcc_params controls whether ehci->regs->segment must (!!!) * be used; it constrains QH/ITD/SITD and QTD locations. * pci_pool consistent memory always uses segment zero. @@ -388,7 +406,8 @@ static int ehci_start (struct usb_hcd *hcd) if (HCC_64BIT_ADDR (hcc_params)) { writel (0, &ehci->regs->segment); if (!pci_set_dma_mask (ehci->hcd.pdev, 0xffffffffffffffffULL)) - info ("enabled 64bit PCI DMA (DAC)"); + dev_info (*ehci->hcd.controller, + "enabled 64bit PCI DMA (DAC)\n"); } /* clear interrupt enables, set irq latency */ @@ -435,10 +454,10 @@ done2: /* PCI Serial Bus Release Number is at 0x60 offset */ pci_read_config_byte (hcd->pdev, 0x60, &tempbyte); temp = readw (&ehci->caps->hci_version); - info ("USB %x.%x support enabled, EHCI rev %x.%02x, %s %s", - ((tempbyte & 0xf0)>>4), (tempbyte & 0x0f), - temp >> 8, temp & 0xff, - hcd_name, DRIVER_VERSION); + dev_info (*hcd->controller, + "USB %x.%x enabled, EHCI %x.%02x, driver %s\n", + ((tempbyte & 0xf0)>>4), (tempbyte & 0x0f), + temp >> 8, temp & 0xff, DRIVER_VERSION); /* * From here on, khubd concurrently accesses the root @@ -470,13 +489,13 @@ static void ehci_stop (struct usb_hcd *hcd) { struct ehci_hcd *ehci = hcd_to_ehci (hcd); - dbg ("%s: stop", hcd_to_bus (hcd)->bus_name); + ehci_dbg (ehci, "stop\n"); /* no more interrupts ... */ if (hcd->state == USB_STATE_RUNNING) ehci_ready (ehci); if (in_interrupt ()) /* should not happen!! */ - err ("stopped %s!", RUN_CONTEXT); + dev_err (*hcd->controller, "stopped %s!\n", RUN_CONTEXT); else del_timer_sync (&ehci->watchdog); ehci_reset (ehci); @@ -492,9 +511,9 @@ static void ehci_stop (struct usb_hcd *hcd) ehci_mem_cleanup (ehci); #ifdef EHCI_STATS - dbg ("irq normal %ld err %ld reclaim %ld", + ehci_dbg (ehci, "irq normal %ld err %ld reclaim %ld\n", ehci->stats.normal, ehci->stats.error, ehci->stats.reclaim); - dbg ("complete %ld unlink %ld", + ehci_dbg (ehci, "complete %ld unlink %ld\n", ehci->stats.complete, ehci->stats.unlink); #endif @@ -738,8 +757,8 @@ static int ehci_urb_dequeue (struct usb_hcd *hcd, struct urb *urb) struct ehci_qh *qh = (struct ehci_qh *) urb->hcpriv; unsigned long flags; - dbg ("%s urb_dequeue %p qh %p state %d", - hcd_to_bus (hcd)->bus_name, urb, qh, qh->qh_state); + ehci_vdbg (ehci, "urb_dequeue %p qh %p state %d\n", + urb, qh, qh->qh_state); switch (usb_pipetype (urb->pipe)) { // case PIPE_CONTROL: @@ -982,7 +1001,6 @@ MODULE_LICENSE ("GPL"); static int __init init (void) { - dbg (DRIVER_INFO); if (usb_disabled()) return -ENODEV; diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c index eb8ff9c17627..c0795ddba09f 100644 --- a/drivers/usb/host/ehci-hub.c +++ b/drivers/usb/host/ehci-hub.c @@ -40,18 +40,15 @@ static int check_reset_complete ( /* 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", - hcd_to_bus (&ehci->hcd)->bus_name, - index + 1, port_status); + ehci_dbg (ehci, "port %d full speed --> companion\n", + index + 1); // 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", - hcd_to_bus (&ehci->hcd)->bus_name, - index + 1); + ehci_dbg (ehci, "port %d high speed\n", index + 1); return port_status; } @@ -277,7 +274,7 @@ static int ehci_hub_control ( #ifndef EHCI_VERBOSE_DEBUG if (status & ~0xffff) /* only if wPortChange is interesting */ #endif - dbg_port (hcd, "GetStatus", wIndex + 1, temp); + dbg_port (ehci, "GetStatus", wIndex + 1, temp); // we "know" this alignment is good, caller used kmalloc()... *((u32 *) buf) = cpu_to_le32 (status); break; @@ -313,14 +310,12 @@ static int ehci_hub_control ( /* line status bits may report this as low speed */ if ((temp & (PORT_PE|PORT_CONNECT)) == PORT_CONNECT && PORT_USB11 (temp)) { - dbg ("%s port %d low speed, give to companion", - hcd_to_bus (&ehci->hcd)->bus_name, + ehci_dbg (ehci, + "port %d low speed --> companion\n", wIndex + 1); temp |= PORT_OWNER; } else { - vdbg ("%s port %d reset", - hcd_to_bus (&ehci->hcd)->bus_name, - wIndex + 1); + ehci_vdbg (ehci, "port %d reset", wIndex + 1); temp |= PORT_RESET; temp &= ~PORT_PE; diff --git a/drivers/usb/host/ehci-mem.c b/drivers/usb/host/ehci-mem.c index b55de3f3c995..11e054680fd4 100644 --- a/drivers/usb/host/ehci-mem.c +++ b/drivers/usb/host/ehci-mem.c @@ -103,7 +103,7 @@ static struct ehci_qh *ehci_qh_alloc (struct ehci_hcd *ehci, int flags) /* dummy td enables safe urb queuing */ qh->dummy = ehci_qtd_alloc (ehci, flags); if (qh->dummy == 0) { - dbg ("no dummy td"); + ehci_dbg (ehci, "no dummy td\n"); pci_pool_free (ehci->qh_pool, qh, qh->qh_dma); qh = 0; } @@ -113,19 +113,17 @@ static struct ehci_qh *ehci_qh_alloc (struct ehci_hcd *ehci, int flags) /* to share a qh (cpu threads, or hc) */ static inline struct ehci_qh *qh_get (/* ehci, */ struct ehci_qh *qh) { - // dbg ("get %p (%d++)", qh, qh->refcount.counter); atomic_inc (&qh->refcount); return qh; } static void qh_put (struct ehci_hcd *ehci, struct ehci_qh *qh) { - // dbg ("put %p (--%d)", qh, qh->refcount.counter); if (!atomic_dec_and_test (&qh->refcount)) return; /* clean qtds first, and know this is not linked */ if (!list_empty (&qh->qtd_list) || qh->qh_next.ptr) { - dbg ("unused qh not empty!"); + ehci_dbg (ehci, "unused qh not empty!\n"); BUG (); } if (qh->dummy) @@ -142,6 +140,10 @@ static void qh_put (struct ehci_hcd *ehci, struct ehci_qh *qh) static void ehci_mem_cleanup (struct ehci_hcd *ehci) { + if (ehci->async) + qh_put (ehci, ehci->async); + ehci->async = 0; + /* PCI consistent memory and pools */ if (ehci->qtd_pool) pci_pool_destroy (ehci->qtd_pool); @@ -183,20 +185,20 @@ static int ehci_mem_init (struct ehci_hcd *ehci, int flags) 32 /* byte alignment (for hw parts) */, 4096 /* can't cross 4K */); if (!ehci->qtd_pool) { - dbg ("no qtd pool"); - ehci_mem_cleanup (ehci); - return -ENOMEM; + goto fail; } - /* QH for control/bulk/intr transfers */ + /* QHs for control/bulk/intr transfers */ ehci->qh_pool = pci_pool_create ("ehci_qh", ehci->hcd.pdev, sizeof (struct ehci_qh), 32 /* byte alignment (for hw parts) */, 4096 /* can't cross 4K */); if (!ehci->qh_pool) { - dbg ("no qh pool"); - ehci_mem_cleanup (ehci); - return -ENOMEM; + goto fail; + } + ehci->async = ehci_qh_alloc (ehci, flags); + if (!ehci->async) { + goto fail; } /* ITD for high speed ISO transfers */ @@ -205,9 +207,7 @@ static int ehci_mem_init (struct ehci_hcd *ehci, int flags) 32 /* byte alignment (for hw parts) */, 4096 /* can't cross 4K */); if (!ehci->itd_pool) { - dbg ("no itd pool"); - ehci_mem_cleanup (ehci); - return -ENOMEM; + goto fail; } /* SITD for full/low speed split ISO transfers */ @@ -216,9 +216,7 @@ static int ehci_mem_init (struct ehci_hcd *ehci, int flags) 32 /* byte alignment (for hw parts) */, 4096 /* can't cross 4K */); if (!ehci->sitd_pool) { - dbg ("no sitd pool"); - ehci_mem_cleanup (ehci); - return -ENOMEM; + goto fail; } /* Hardware periodic table */ @@ -227,9 +225,7 @@ static int ehci_mem_init (struct ehci_hcd *ehci, int flags) ehci->periodic_size * sizeof (u32), &ehci->periodic_dma); if (ehci->periodic == 0) { - dbg ("no hw periodic table"); - ehci_mem_cleanup (ehci); - return -ENOMEM; + goto fail; } for (i = 0; i < ehci->periodic_size; i++) ehci->periodic [i] = EHCI_LIST_END; @@ -237,11 +233,14 @@ static int ehci_mem_init (struct ehci_hcd *ehci, int flags) /* software shadow of hardware table */ ehci->pshadow = kmalloc (ehci->periodic_size * sizeof (void *), flags); if (ehci->pshadow == 0) { - dbg ("no shadow periodic table"); - ehci_mem_cleanup (ehci); - return -ENOMEM; + goto fail; } memset (ehci->pshadow, 0, ehci->periodic_size * sizeof (void *)); return 0; + +fail: + ehci_dbg (ehci, "couldn't init memory\n"); + ehci_mem_cleanup (ehci); + return -ENOMEM; } diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index 2bb5995dc220..563f001b327c 100644 --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c @@ -130,8 +130,9 @@ static inline void qtd_copy_status (struct urb *urb, size_t length, u32 token) else /* unknown */ urb->status = -EPROTO; - dbg ("ep %d-%s qtd token %08x --> status %d", - /* devpath */ + ehci_vdbg (ehci, + "dev%d ep%d%s qtd token %08x --> status %d\n", + usb_pipedev (urb->pipe), usb_pipeendpoint (urb->pipe), usb_pipein (urb->pipe) ? "in" : "out", token, urb->status); @@ -678,33 +679,33 @@ done: static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh) { u32 dma = QH_NEXT (qh->qh_dma); - struct ehci_qh *q; + struct ehci_qh *head; - if (unlikely (!(q = ehci->async))) { + /* (re)start the async schedule? */ + head = ehci->async; + if (ehci->async_idle) + del_timer (&ehci->watchdog); + else if (!head->qh_next.qh) { u32 cmd = readl (&ehci->regs->command); - /* in case a clear of CMD_ASE didn't take yet */ - (void) handshake (&ehci->regs->status, STS_ASS, 0, 150); - - qh->hw_info1 |= __constant_cpu_to_le32 (QH_HEAD); /* [4.8] */ - qh->qh_next.qh = qh; - qh->hw_next = dma; - wmb (); - ehci->async = qh; - writel ((u32)qh->qh_dma, &ehci->regs->async_next); - cmd |= CMD_ASE | CMD_RUN; - writel (cmd, &ehci->regs->command); - ehci->hcd.state = USB_STATE_RUNNING; - /* posted write need not be known to HC yet ... */ - } else { - /* splice right after "start" of ring */ - qh->hw_info1 &= ~__constant_cpu_to_le32 (QH_HEAD); /* [4.8] */ - qh->qh_next = q->qh_next; - qh->hw_next = q->hw_next; - wmb (); - q->qh_next.qh = qh; - q->hw_next = dma; + if (!(cmd & CMD_ASE)) { + /* in case a clear of CMD_ASE didn't take yet */ + (void) handshake (&ehci->regs->status, STS_ASS, 0, 150); + cmd |= CMD_ASE | CMD_RUN; + writel (cmd, &ehci->regs->command); + ehci->hcd.state = USB_STATE_RUNNING; + /* posted write need not be known to HC yet ... */ + } } + + /* splice right after start */ + qh->qh_next = head->qh_next; + qh->hw_next = head->hw_next; + wmb (); + + head->qh_next.qh = qh; + head->hw_next = dma; + qh->qh_state = QH_STATE_LINKED; /* qtd completions reported later by interrupt */ @@ -897,6 +898,14 @@ static void end_unlink_async (struct ehci_hcd *ehci) qh_link_async (ehci, qh); else qh_put (ehci, qh); // refcount from async list + + /* it's not free to turn the async schedule on/off, so we leave it + * active but idle for a while once it empties. + */ + if (!ehci->async->qh_next.qh && !timer_pending (&ehci->watchdog)) { + ehci->async_idle = 1; + mod_timer (&ehci->watchdog, jiffies + EHCI_ASYNC_JIFFIES); + } } /* makes sure the async qh will become idle */ @@ -909,7 +918,6 @@ static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh) #ifdef DEBUG if (ehci->reclaim - || !ehci->async || qh->qh_state != QH_STATE_LINKED #ifdef CONFIG_SMP // this macro lies except on SMP compiles @@ -919,31 +927,20 @@ static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh) BUG (); #endif - qh->qh_state = QH_STATE_UNLINK; - ehci->reclaim = qh = qh_get (qh); - - // dbg_qh ("start unlink", ehci, qh); - - /* Remove the last QH (qhead)? Stop async schedule first. */ - if (unlikely (qh == ehci->async && qh->qh_next.qh == qh)) { + /* stop async schedule right now? */ + if (unlikely (qh == ehci->async)) { /* can't get here without STS_ASS set */ if (ehci->hcd.state != USB_STATE_HALT) { writel (cmd & ~CMD_ASE, &ehci->regs->command); - (void) handshake (&ehci->regs->status, STS_ASS, 0, 150); -#if 0 - // one VT8235 system wants to die with STS_FATAL - // unless this qh is leaked here. others seem ok... - qh = qh_get (qh); - dbg_qh ("async/off", ehci, qh); -#endif + wmb (); + // handshake later, if we need to } - qh->qh_next.qh = ehci->async = 0; - - ehci->reclaim_ready = 1; - tasklet_schedule (&ehci->tasklet); return; } + qh->qh_state = QH_STATE_UNLINK; + ehci->reclaim = qh = qh_get (qh); + if (unlikely (ehci->hcd.state == USB_STATE_HALT)) { ehci->reclaim_ready = 1; tasklet_schedule (&ehci->tasklet); @@ -951,13 +948,9 @@ static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh) } prev = ehci->async; - while (prev->qh_next.qh != qh && prev->qh_next.qh != ehci->async) + while (prev->qh_next.qh != qh) prev = prev->qh_next.qh; - if (qh->hw_info1 & __constant_cpu_to_le32 (QH_HEAD)) { - ehci->async = prev; - prev->hw_info1 |= __constant_cpu_to_le32 (QH_HEAD); - } prev->hw_next = qh->hw_next; prev->qh_next = qh->qh_next; wmb (); @@ -979,7 +972,7 @@ scan_async (struct ehci_hcd *ehci) unsigned count; rescan: - qh = ehci->async; + qh = ehci->async->qh_next.qh; count = 0; if (likely (qh != 0)) { do { @@ -991,25 +984,17 @@ rescan: /* concurrent unlink could happen here */ count += qh_completions (ehci, qh); qh_put (ehci, qh); + goto rescan; } /* unlink idle entries, reducing HC PCI usage as - * well as HCD schedule-scanning costs. removing - * the last qh is deferred, since it's costly. + * well as HCD schedule-scanning costs. * * FIXME don't unlink idle entries so quickly; it * can penalize (common) half duplex protocols. */ if (list_empty (&qh->qtd_list) && !ehci->reclaim) { - if (qh->qh_next.qh != qh) { - // dbg ("irq/empty"); - start_unlink_async (ehci, qh); - } else if (!timer_pending (&ehci->watchdog)) { - /* can't use IAA for last entry */ - ehci->async_idle = 1; - mod_timer (&ehci->watchdog, - jiffies + EHCI_ASYNC_JIFFIES); - } + start_unlink_async (ehci, qh); } /* keep latencies down: let any irqs in */ @@ -1021,8 +1006,6 @@ rescan: } qh = qh->qh_next.qh; - if (!qh) /* unlinked? */ - goto rescan; - } while (qh != ehci->async); + } while (qh); } } diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c index c5d574ea947c..eff487471b20 100644 --- a/drivers/usb/host/uhci-hcd.c +++ b/drivers/usb/host/uhci-hcd.c @@ -1051,10 +1051,6 @@ status_phase: td_error: ret = uhci_map_status(status, uhci_packetout(td_token(td))); - if (ret == -EPIPE) - /* endpoint has stalled - mark it halted */ - usb_endpoint_halt(urb->dev, uhci_endpoint(td_token(td)), - uhci_packetout(td_token(td))); err: if ((debug == 1 && ret != -EPIPE) || debug > 1) { diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index cfcf341f4cbb..178cec0e5e1f 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -467,9 +467,12 @@ static int serial_open (struct tty_struct *tty, struct file * filp) down (&port->sem); port->tty = tty; - /* lock this module before we call it */ - if (serial->type->owner) - __MOD_INC_USE_COUNT(serial->type->owner); + /* lock this module before we call it, + this may, which means we must bail out, safe because we are called with BKL held */ + if (!try_module_get(serial->type->owner)) { + retval = -ENODEV; + goto bailout; + } ++port->open_count; if (port->open_count == 1) { @@ -481,10 +484,10 @@ static int serial_open (struct tty_struct *tty, struct file * filp) retval = usb_serial_generic_open(port, filp); if (retval) { port->open_count = 0; - if (serial->type->owner) - __MOD_DEC_USE_COUNT(serial->type->owner); + module_put(serial->type->owner); } } +bailout: up (&port->sem); return retval; @@ -508,8 +511,7 @@ static void __serial_close(struct usb_serial_port *port, struct file *filp) port->open_count = 0; } - if (port->serial->type->owner) - __MOD_DEC_USE_COUNT(port->serial->type->owner); + module_put(port->serial->type->owner); } static void serial_close(struct tty_struct *tty, struct file * filp) @@ -899,11 +901,13 @@ int usb_serial_probe(struct usb_interface *interface, /* if this device type has a probe function, call it */ if (type->probe) { - if (type->owner) - __MOD_INC_USE_COUNT(type->owner); + if (!try_module_get(type->owner)) { + err ("module get failed, exiting"); + kfree (serial); + return -EIO; + } retval = type->probe (serial); - if (type->owner) - __MOD_DEC_USE_COUNT(type->owner); + module_put(type->owner); if (retval < 0) { dbg ("sub driver rejected device"); @@ -996,11 +1000,13 @@ int usb_serial_probe(struct usb_interface *interface, if (!num_ports) { /* if this device type has a calc_num_ports function, call it */ if (type->calc_num_ports) { - if (type->owner) - __MOD_INC_USE_COUNT(type->owner); + if (!try_module_get(type->owner)) { + err ("module get failed, exiting"); + kfree (serial); + return -EIO; + } num_ports = type->calc_num_ports (serial); - if (type->owner) - __MOD_DEC_USE_COUNT(type->owner); + module_put(type->owner); } if (!num_ports) num_ports = type->num_ports; @@ -1110,11 +1116,12 @@ int usb_serial_probe(struct usb_interface *interface, /* if this device type has an attach function, call it */ if (type->attach) { - if (type->owner) - __MOD_INC_USE_COUNT(type->owner); + if (!try_module_get(type->owner)) { + err ("module get failed, exiting"); + goto probe_error; + } retval = type->attach (serial); - if (type->owner) - __MOD_DEC_USE_COUNT(type->owner); + module_put(type->owner); if (retval < 0) goto probe_error; if (retval > 0) { diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c index 378cf03db154..b1e4bdd9ff96 100644 --- a/drivers/usb/storage/transport.c +++ b/drivers/usb/storage/transport.c @@ -532,8 +532,6 @@ int usb_stor_clear_halt(struct us_data *us, unsigned int pipe) if (result < 0) return result; - printk(KERN_ERR "usb_stor_clear_halt() WORKED!\n"); - /* reset the toggles and endpoint flags */ usb_endpoint_running(us->pusb_dev, usb_pipeendpoint(pipe), usb_pipeout(pipe)); |
