summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <greg@kroah.com>2002-12-01 06:59:25 -0800
committerGreg Kroah-Hartman <greg@kroah.com>2002-12-01 06:59:25 -0800
commit46eb8948b4852e893f8fcfb1a751d23b7b5ea3ac (patch)
treeec4f2cd92abdf17ff508278150790ff42eea43b0
parent114d2a8e848612ae717ab70d2834f35c812f13d1 (diff)
parent414ca09cee26239c5fd423f676d7dfcb823adbe4 (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.c59
-rw-r--r--drivers/usb/core/hcd-pci.c31
-rw-r--r--drivers/usb/core/hcd.c11
-rw-r--r--drivers/usb/core/usb.c31
-rw-r--r--drivers/usb/host/ehci-dbg.c46
-rw-r--r--drivers/usb/host/ehci-hcd.c76
-rw-r--r--drivers/usb/host/ehci-hub.c19
-rw-r--r--drivers/usb/host/ehci-mem.c45
-rw-r--r--drivers/usb/host/ehci-q.c111
-rw-r--r--drivers/usb/host/uhci-hcd.c4
-rw-r--r--drivers/usb/serial/usb-serial.c45
-rw-r--r--drivers/usb/storage/transport.c2
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));