Commit 46eb8948 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

Merge kroah.com:/home/linux/linux/BK/bleeding-2.5

into kroah.com:/home/linux/linux/BK/gregkh-2.5
parents 114d2a8e 414ca09c
......@@ -239,14 +239,10 @@ 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_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;
......@@ -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);
}
......@@ -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);
}
}
/* cleanup and return */
......
......@@ -146,7 +146,7 @@ int usb_hcd_pci_probe (struct pci_dev *dev, const struct pci_device_id *id)
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 @@ int usb_hcd_pci_probe (struct pci_dev *dev, const struct pci_device_id *id)
#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 @@ int usb_hcd_pci_probe (struct pci_dev *dev, const struct pci_device_id *id)
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 {
......
......@@ -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)) {
......
......@@ -70,22 +70,21 @@ static struct device_driver usb_generic_driver = {
.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)
if (!try_module_get(driver->owner)) {
err ("Can't get a module reference for %s", driver->name);
return error;
}
......@@ -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,15 +117,12 @@ int usb_device_remove(struct device *dev)
return -ENODEV;
}
if (driver->owner) {
m = try_inc_mod_count(driver->owner);
if (m == 0) {
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
* the holder of the lock guards against
......@@ -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;
}
......
......@@ -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 {
for (qh = ehci->async->qh_next.qh; qh; qh = qh->qh_next.qh)
qh_lines (qh, &next, &size);
} while ((qh = qh->qh_next.qh) != ehci->async);
}
if (ehci->reclaim) {
temp = snprintf (next, size, "\nreclaim =\n");
size -= temp;
......
......@@ -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;
......@@ -374,6 +377,21 @@ static int ehci_start (struct usb_hcd *hcd)
writel (INTR_MASK, &ehci->regs->intr_enable);
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.
......@@ -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 @@ static int ehci_start (struct usb_hcd *hcd)
/* 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",
dev_info (*hcd->controller,
"USB %x.%x enabled, EHCI %x.%02x, driver %s\n",
((tempbyte & 0xf0)>>4), (tempbyte & 0x0f),
temp >> 8, temp & 0xff,
hcd_name, DRIVER_VERSION);
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;
......
......@@ -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;
......
......@@ -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;
}
......@@ -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 @@ ehci_qh_make (
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);
if (!(cmd & CMD_ASE)) {
/* 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;
}
}
/* 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 @@ scan_async (struct ehci_hcd *ehci)
/* 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);
}
}
/* keep latencies down: let any irqs in */
......@@ -1021,8 +1006,6 @@ scan_async (struct ehci_hcd *ehci)
}
qh = qh->qh_next.qh;
if (!qh) /* unlinked? */
goto rescan;
} while (qh != ehci->async);
} while (qh);
}
}
......@@ -1051,10 +1051,6 @@ static int uhci_result_control(struct uhci_hcd *uhci, struct urb *urb)
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) {
......
......@@ -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) {
......
......@@ -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));
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment