X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fusb%2Fcore%2Fhcd.c;h=10064af65d178523a91f37d93b8309a1d9e024c6;hb=97bf2856c6014879bd04983a3e9dfcdac1e7fe85;hp=266e9e06a9f50a7d5e33ca2f95137708c93ed24c;hpb=f7f1b0f1e2fbadeab12d24236000e778aa9b1ead;p=linux-2.6.git diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 266e9e06a..10064af65 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -22,12 +22,6 @@ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include - -#ifdef CONFIG_USB_DEBUG -#define DEBUG -#endif - #include #include #include @@ -39,8 +33,10 @@ #include #include #include +#include #include #include +#include #include @@ -98,7 +94,7 @@ struct usb_busmap { static struct usb_busmap busmap; /* used when updating list of hcds */ -DECLARE_MUTEX (usb_bus_list_lock); /* exported only for usbfs */ +DEFINE_MUTEX(usb_bus_list_lock); /* exported only for usbfs */ EXPORT_SYMBOL_GPL (usb_bus_list_lock); /* used for controlling access to virtual root hubs */ @@ -130,7 +126,7 @@ static const u8 usb2_rh_dev_descriptor [18] = { 0x09, /* __u8 bDeviceClass; HUB_CLASSCODE */ 0x00, /* __u8 bDeviceSubClass; */ 0x01, /* __u8 bDeviceProtocol; [ usb 2.0 single TT ]*/ - 0x08, /* __u8 bMaxPacketSize0; 8 Bytes */ + 0x40, /* __u8 bMaxPacketSize0; 64 Bytes */ 0x00, 0x00, /* __le16 idVendor; */ 0x00, 0x00, /* __le16 idProduct; */ @@ -153,7 +149,7 @@ static const u8 usb11_rh_dev_descriptor [18] = { 0x09, /* __u8 bDeviceClass; HUB_CLASSCODE */ 0x00, /* __u8 bDeviceSubClass; */ 0x00, /* __u8 bDeviceProtocol; [ low/full speeds only ] */ - 0x08, /* __u8 bMaxPacketSize0; 8 Bytes */ + 0x40, /* __u8 bMaxPacketSize0; 64 Bytes */ 0x00, 0x00, /* __le16 idVendor; */ 0x00, 0x00, /* __le16 idProduct; */ @@ -260,7 +256,9 @@ static const u8 hs_rh_config_descriptor [] = { 0x05, /* __u8 ep_bDescriptorType; Endpoint */ 0x81, /* __u8 ep_bEndpointAddress; IN Endpoint 1 */ 0x03, /* __u8 ep_bmAttributes; Interrupt */ - 0x02, 0x00, /* __le16 ep_wMaxPacketSize; 1 + (MAX_ROOT_PORTS / 8) */ + /* __le16 ep_wMaxPacketSize; 1 + (MAX_ROOT_PORTS / 8) + * see hub.c:hub_configure() for details. */ + (USB_MAXCHILDREN + 1 + 7) / 8, 0x00, 0x0c /* __u8 ep_bInterval; (256ms -- usb 2.0 spec) */ }; @@ -322,8 +320,8 @@ static int rh_string ( // id 3 == vendor description } else if (id == 3) { - snprintf (buf, sizeof buf, "%s %s %s", system_utsname.sysname, - system_utsname.release, hcd->driver->description); + snprintf (buf, sizeof buf, "%s %s %s", init_utsname()->sysname, + init_utsname()->release, hcd->driver->description); // unsupported IDs --> "protocol stall" } else @@ -349,7 +347,8 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb) struct usb_ctrlrequest *cmd; u16 typeReq, wValue, wIndex, wLength; u8 *ubuf = urb->transfer_buffer; - u8 tbuf [sizeof (struct usb_hub_descriptor)]; + u8 tbuf [sizeof (struct usb_hub_descriptor)] + __attribute__((aligned(4))); const u8 *bufp = tbuf; int len = 0; int patch_wakeup = 0; @@ -371,21 +370,39 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb) /* DEVICE REQUESTS */ + /* The root hub's remote wakeup enable bit is implemented using + * driver model wakeup flags. If this system supports wakeup + * through USB, userspace may change the default "allow wakeup" + * policy through sysfs or these calls. + * + * Most root hubs support wakeup from downstream devices, for + * runtime power management (disabling USB clocks and reducing + * VBUS power usage). However, not all of them do so; silicon, + * board, and BIOS bugs here are not uncommon, so these can't + * be treated quite like external hubs. + * + * Likewise, not all root hubs will pass wakeup events upstream, + * to wake up the whole system. So don't assume root hub and + * controller capabilities are identical. + */ + case DeviceRequest | USB_REQ_GET_STATUS: - tbuf [0] = (hcd->remote_wakeup << USB_DEVICE_REMOTE_WAKEUP) + tbuf [0] = (device_may_wakeup(&hcd->self.root_hub->dev) + << USB_DEVICE_REMOTE_WAKEUP) | (1 << USB_DEVICE_SELF_POWERED); tbuf [1] = 0; len = 2; break; case DeviceOutRequest | USB_REQ_CLEAR_FEATURE: if (wValue == USB_DEVICE_REMOTE_WAKEUP) - hcd->remote_wakeup = 0; + device_set_wakeup_enable(&hcd->self.root_hub->dev, 0); else goto error; break; case DeviceOutRequest | USB_REQ_SET_FEATURE: - if (hcd->can_wakeup && wValue == USB_DEVICE_REMOTE_WAKEUP) - hcd->remote_wakeup = 1; + if (device_can_wakeup(&hcd->self.root_hub->dev) + && wValue == USB_DEVICE_REMOTE_WAKEUP) + device_set_wakeup_enable(&hcd->self.root_hub->dev, 1); else goto error; break; @@ -414,7 +431,7 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb) bufp = fs_rh_config_descriptor; len = sizeof fs_rh_config_descriptor; } - if (hcd->can_wakeup) + if (device_can_wakeup(&hcd->self.root_hub->dev)) patch_wakeup = 1; break; case USB_DT_STRING << 8: @@ -458,22 +475,18 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb) default: /* non-generic request */ - if (HC_IS_SUSPENDED (hcd->state)) - status = -EAGAIN; - else { - switch (typeReq) { - case GetHubStatus: - case GetPortStatus: - len = 4; - break; - case GetHubDescriptor: - len = sizeof (struct usb_hub_descriptor); - break; - } - status = hcd->driver->hub_control (hcd, - typeReq, wValue, wIndex, - tbuf, wLength); + switch (typeReq) { + case GetHubStatus: + case GetPortStatus: + len = 4; + break; + case GetHubDescriptor: + len = sizeof (struct usb_hub_descriptor); + break; } + status = hcd->driver->hub_control (hcd, + typeReq, wValue, wIndex, + tbuf, wLength); break; error: /* "protocol stall" on error */ @@ -487,7 +500,7 @@ error: "CTRL: TypeReq=0x%x val=0x%x " "idx=0x%x len=%d ==> %d\n", typeReq, wValue, wIndex, - wLength, urb->status); + wLength, status); } } if (len) { @@ -511,7 +524,7 @@ error: if (urb->status == -EINPROGRESS) urb->status = status; spin_unlock (&urb->lock); - usb_hcd_giveback_urb (hcd, urb, NULL); + usb_hcd_giveback_urb (hcd, urb); local_irq_restore (flags); return 0; } @@ -519,182 +532,156 @@ error: /*-------------------------------------------------------------------------*/ /* - * Root Hub interrupt transfers are synthesized with a timer. - * Completions are called in_interrupt() but not in_irq(). + * Root Hub interrupt transfers are polled using a timer if the + * driver requests it; otherwise the driver is responsible for + * calling usb_hcd_poll_rh_status() when an event occurs. * - * Note: some root hubs (including common UHCI based designs) can't - * correctly issue port change IRQs. They're the ones that _need_ a - * timer; most other root hubs don't. Some systems could save a - * lot of battery power by eliminating these root hub timer IRQs. + * Completions are called in_interrupt(), but they may or may not + * be in_irq(). */ +void usb_hcd_poll_rh_status(struct usb_hcd *hcd) +{ + struct urb *urb; + int length; + unsigned long flags; + char buffer[4]; /* Any root hubs with > 31 ports? */ -static void rh_report_status (unsigned long ptr); + if (!hcd->uses_new_polling && !hcd->status_urb) + return; -static int rh_status_urb (struct usb_hcd *hcd, struct urb *urb) -{ - int len = 1 + (urb->dev->maxchild / 8); + length = hcd->driver->hub_status_data(hcd, buffer); + if (length > 0) { - /* rh_timer protected by hcd_data_lock */ - if (hcd->rh_timer.data || urb->transfer_buffer_length < len) { - dev_dbg (hcd->self.controller, - "not queuing rh status urb, stat %d\n", - urb->status); - return -EINVAL; + /* try to complete the status urb */ + local_irq_save (flags); + spin_lock(&hcd_root_hub_lock); + urb = hcd->status_urb; + if (urb) { + spin_lock(&urb->lock); + if (urb->status == -EINPROGRESS) { + hcd->poll_pending = 0; + hcd->status_urb = NULL; + urb->status = 0; + urb->hcpriv = NULL; + urb->actual_length = length; + memcpy(urb->transfer_buffer, buffer, length); + } else /* urb has been unlinked */ + length = 0; + spin_unlock(&urb->lock); + } else + length = 0; + spin_unlock(&hcd_root_hub_lock); + + /* local irqs are always blocked in completions */ + if (length > 0) + usb_hcd_giveback_urb (hcd, urb); + else + hcd->poll_pending = 1; + local_irq_restore (flags); } - init_timer (&hcd->rh_timer); - hcd->rh_timer.function = rh_report_status; - hcd->rh_timer.data = (unsigned long) urb; - /* USB 2.0 spec says 256msec; this is close enough */ - hcd->rh_timer.expires = jiffies + HZ/4; - add_timer (&hcd->rh_timer); - urb->hcpriv = hcd; /* nonzero to indicate it's queued */ - return 0; + /* The USB 2.0 spec says 256 ms. This is close enough and won't + * exceed that limit if HZ is 100. */ + if (hcd->uses_new_polling ? hcd->poll_rh : + (length == 0 && hcd->status_urb != NULL)) + mod_timer (&hcd->rh_timer, jiffies + msecs_to_jiffies(250)); } +EXPORT_SYMBOL_GPL(usb_hcd_poll_rh_status); /* timer callback */ +static void rh_timer_func (unsigned long _hcd) +{ + usb_hcd_poll_rh_status((struct usb_hcd *) _hcd); +} -static void rh_report_status (unsigned long ptr) +/*-------------------------------------------------------------------------*/ + +static int rh_queue_status (struct usb_hcd *hcd, struct urb *urb) { - struct urb *urb; - struct usb_hcd *hcd; - int length = 0; + int retval; unsigned long flags; + int len = 1 + (urb->dev->maxchild / 8); - urb = (struct urb *) ptr; - local_irq_save (flags); - spin_lock (&urb->lock); + spin_lock_irqsave (&hcd_root_hub_lock, flags); + if (urb->status != -EINPROGRESS) /* already unlinked */ + retval = urb->status; + else if (hcd->status_urb || urb->transfer_buffer_length < len) { + dev_dbg (hcd->self.controller, "not queuing rh status urb\n"); + retval = -EINVAL; + } else { + hcd->status_urb = urb; + urb->hcpriv = hcd; /* indicate it's queued */ - /* do nothing if the urb's been unlinked */ - if (!urb->dev - || urb->status != -EINPROGRESS - || (hcd = urb->dev->bus->hcpriv) == NULL) { - spin_unlock (&urb->lock); - local_irq_restore (flags); - return; - } + if (!hcd->uses_new_polling) + mod_timer (&hcd->rh_timer, jiffies + + msecs_to_jiffies(250)); - /* complete the status urb, or retrigger the timer */ - spin_lock (&hcd_data_lock); - if (urb->dev->state == USB_STATE_CONFIGURED) { - length = hcd->driver->hub_status_data ( - hcd, urb->transfer_buffer); - if (length > 0) { - hcd->rh_timer.data = 0; - urb->actual_length = length; - urb->status = 0; - urb->hcpriv = NULL; - } else - mod_timer (&hcd->rh_timer, jiffies + HZ/4); + /* If a status change has already occurred, report it ASAP */ + else if (hcd->poll_pending) + mod_timer (&hcd->rh_timer, jiffies); + retval = 0; } - spin_unlock (&hcd_data_lock); - spin_unlock (&urb->lock); - - /* local irqs are always blocked in completions */ - if (length > 0) - usb_hcd_giveback_urb (hcd, urb, NULL); - local_irq_restore (flags); + spin_unlock_irqrestore (&hcd_root_hub_lock, flags); + return retval; } -/*-------------------------------------------------------------------------*/ - static int rh_urb_enqueue (struct usb_hcd *hcd, struct urb *urb) { - if (usb_pipeint (urb->pipe)) { - int retval; - unsigned long flags; - - spin_lock_irqsave (&hcd_data_lock, flags); - retval = rh_status_urb (hcd, urb); - spin_unlock_irqrestore (&hcd_data_lock, flags); - return retval; - } + if (usb_pipeint (urb->pipe)) + return rh_queue_status (hcd, urb); if (usb_pipecontrol (urb->pipe)) return rh_call_control (hcd, urb); - else - return -EINVAL; + return -EINVAL; } /*-------------------------------------------------------------------------*/ +/* Unlinks of root-hub control URBs are legal, but they don't do anything + * since these URBs always execute synchronously. + */ static int usb_rh_urb_dequeue (struct usb_hcd *hcd, struct urb *urb) { unsigned long flags; - /* note: always a synchronous unlink */ - if ((unsigned long) urb == hcd->rh_timer.data) { - del_timer_sync (&hcd->rh_timer); - hcd->rh_timer.data = 0; + if (usb_pipeendpoint(urb->pipe) == 0) { /* Control URB */ + ; /* Do nothing */ + } else { /* Status URB */ + if (!hcd->uses_new_polling) + del_timer (&hcd->rh_timer); local_irq_save (flags); - urb->hcpriv = NULL; - usb_hcd_giveback_urb (hcd, urb, NULL); + spin_lock (&hcd_root_hub_lock); + if (urb == hcd->status_urb) { + hcd->status_urb = NULL; + urb->hcpriv = NULL; + } else + urb = NULL; /* wasn't fully queued */ + spin_unlock (&hcd_root_hub_lock); + if (urb) + usb_hcd_giveback_urb (hcd, urb); local_irq_restore (flags); - - } else if (usb_pipeendpoint(urb->pipe) == 0) { - spin_lock_irq(&urb->lock); /* from usb_kill_urb */ - ++urb->reject; - spin_unlock_irq(&urb->lock); - - wait_event(usb_kill_urb_queue, - atomic_read(&urb->use_count) == 0); - - spin_lock_irq(&urb->lock); - --urb->reject; - spin_unlock_irq(&urb->lock); - } else - return -EINVAL; + } return 0; } /*-------------------------------------------------------------------------*/ -/* exported only within usbcore */ -struct usb_bus *usb_bus_get (struct usb_bus *bus) -{ - struct class_device *tmp; - - if (!bus) - return NULL; - - tmp = class_device_get(&bus->class_dev); - if (tmp) - return to_usb_bus(tmp); - else - return NULL; -} - -/* exported only within usbcore */ -void usb_bus_put (struct usb_bus *bus) -{ - if (bus) - class_device_put(&bus->class_dev); -} - -/*-------------------------------------------------------------------------*/ - -static void usb_host_release(struct class_device *class_dev) -{ - struct usb_bus *bus = to_usb_bus(class_dev); - - if (bus->release) - bus->release(bus); -} - -static struct class usb_host_class = { - .name = "usb_host", - .release = &usb_host_release, -}; +static struct class *usb_host_class; int usb_host_init(void) { - return class_register(&usb_host_class); + int retval = 0; + + usb_host_class = class_create(THIS_MODULE, "usb_host"); + if (IS_ERR(usb_host_class)) + retval = PTR_ERR(usb_host_class); + return retval; } void usb_host_cleanup(void) { - class_unregister(&usb_host_class); + class_destroy(usb_host_class); } /** @@ -711,41 +698,12 @@ static void usb_bus_init (struct usb_bus *bus) bus->devnum_next = 1; bus->root_hub = NULL; - bus->hcpriv = NULL; bus->busnum = -1; bus->bandwidth_allocated = 0; bus->bandwidth_int_reqs = 0; bus->bandwidth_isoc_reqs = 0; INIT_LIST_HEAD (&bus->bus_list); - - class_device_initialize(&bus->class_dev); - bus->class_dev.class = &usb_host_class; -} - -/** - * usb_alloc_bus - creates a new USB host controller structure - * @op: pointer to a struct usb_operations that this bus structure should use - * Context: !in_interrupt() - * - * Creates a USB host controller bus structure with the specified - * usb_operations and initializes all the necessary internal objects. - * - * If no memory is available, NULL is returned. - * - * The caller should call usb_put_bus() when it is finished with the structure. - */ -struct usb_bus *usb_alloc_bus (struct usb_operations *op) -{ - struct usb_bus *bus; - - bus = kmalloc (sizeof *bus, GFP_KERNEL); - if (!bus) - return NULL; - memset(bus, 0, sizeof(struct usb_bus)); - usb_bus_init (bus); - bus->op = op; - return bus; } /*-------------------------------------------------------------------------*/ @@ -761,34 +719,33 @@ struct usb_bus *usb_alloc_bus (struct usb_operations *op) static int usb_register_bus(struct usb_bus *bus) { int busnum; - int retval; - down (&usb_bus_list_lock); + mutex_lock(&usb_bus_list_lock); busnum = find_next_zero_bit (busmap.busmap, USB_MAXBUS, 1); if (busnum < USB_MAXBUS) { set_bit (busnum, busmap.busmap); bus->busnum = busnum; } else { printk (KERN_ERR "%s: too many buses\n", usbcore_name); - up(&usb_bus_list_lock); + mutex_unlock(&usb_bus_list_lock); return -E2BIG; } - snprintf(bus->class_dev.class_id, BUS_ID_SIZE, "usb%d", busnum); - bus->class_dev.dev = bus->controller; - retval = class_device_add(&bus->class_dev); - if (retval) { + bus->class_dev = class_device_create(usb_host_class, NULL, MKDEV(0,0), + bus->controller, "usb_host%d", busnum); + if (IS_ERR(bus->class_dev)) { clear_bit(busnum, busmap.busmap); - up(&usb_bus_list_lock); - return retval; + mutex_unlock(&usb_bus_list_lock); + return PTR_ERR(bus->class_dev); } + class_set_devdata(bus->class_dev, bus); + /* Add it to the local list of buses */ list_add (&bus->bus_list, &usb_bus_list); - up (&usb_bus_list_lock); + mutex_unlock(&usb_bus_list_lock); - usbfs_add_bus (bus); - usbmon_notify_bus_add (bus); + usb_notify_add_bus(bus); dev_info (bus->controller, "new USB bus registered, assigned bus number %d\n", bus->busnum); return 0; @@ -811,43 +768,33 @@ static void usb_deregister_bus (struct usb_bus *bus) * controller code, as well as having it call this when cleaning * itself up */ - down (&usb_bus_list_lock); + mutex_lock(&usb_bus_list_lock); list_del (&bus->bus_list); - up (&usb_bus_list_lock); + mutex_unlock(&usb_bus_list_lock); - usbmon_notify_bus_remove (bus); - usbfs_remove_bus (bus); + usb_notify_remove_bus(bus); clear_bit (bus->busnum, busmap.busmap); - class_device_del(&bus->class_dev); + class_device_unregister(bus->class_dev); } /** - * usb_hcd_register_root_hub - called by HCD to register its root hub - * @usb_dev: the usb root hub device to be registered. + * register_root_hub - called by usb_add_hcd() to register a root hub * @hcd: host controller for this root hub * - * The USB host controller calls this function to register the root hub - * properly with the USB subsystem. It sets up the device properly in - * the device tree and stores the root_hub pointer in the bus structure, - * then calls usb_new_device() to register the usb device. It also - * assigns the root hub's USB address (always 1). + * This function registers the root hub with the USB subsystem. It sets up + * the device properly in the device tree and then calls usb_new_device() + * to register the usb device. It also assigns the root hub's USB address + * (always 1). */ -int usb_hcd_register_root_hub (struct usb_device *usb_dev, struct usb_hcd *hcd) +static int register_root_hub(struct usb_hcd *hcd) { struct device *parent_dev = hcd->self.controller; + struct usb_device *usb_dev = hcd->self.root_hub; const int devnum = 1; int retval; - /* hcd->driver->start() reported can_wakeup, probably with - * assistance from board's boot firmware. - * NOTE: normal devices won't enable wakeup by default. - */ - if (hcd->can_wakeup) - dev_dbg (parent_dev, "supports USB remote wakeup\n"); - hcd->remote_wakeup = hcd->can_wakeup; - usb_dev->devnum = devnum; usb_dev->bus->devnum_next = devnum + 1; memset (&usb_dev->bus->devmap.devicemap, 0, @@ -855,28 +802,23 @@ int usb_hcd_register_root_hub (struct usb_device *usb_dev, struct usb_hcd *hcd) set_bit (devnum, usb_dev->bus->devmap.devicemap); usb_set_device_state(usb_dev, USB_STATE_ADDRESS); - down (&usb_bus_list_lock); - usb_dev->bus->root_hub = usb_dev; + mutex_lock(&usb_bus_list_lock); usb_dev->ep0.desc.wMaxPacketSize = __constant_cpu_to_le16(64); retval = usb_get_device_descriptor(usb_dev, USB_DT_DEVICE_SIZE); if (retval != sizeof usb_dev->descriptor) { - usb_dev->bus->root_hub = NULL; - up (&usb_bus_list_lock); + mutex_unlock(&usb_bus_list_lock); dev_dbg (parent_dev, "can't read %s device descriptor %d\n", usb_dev->dev.bus_id, retval); return (retval < 0) ? retval : -EMSGSIZE; } - usb_lock_device (usb_dev); retval = usb_new_device (usb_dev); - usb_unlock_device (usb_dev); if (retval) { - usb_dev->bus->root_hub = NULL; dev_err (parent_dev, "can't register root hub for %s, %d\n", usb_dev->dev.bus_id, retval); } - up (&usb_bus_list_lock); + mutex_unlock(&usb_bus_list_lock); if (retval == 0) { spin_lock_irq (&hcd_root_hub_lock); @@ -890,7 +832,15 @@ int usb_hcd_register_root_hub (struct usb_device *usb_dev, struct usb_hcd *hcd) return retval; } -EXPORT_SYMBOL_GPL(usb_hcd_register_root_hub); + +void usb_enable_root_hub_irq (struct usb_bus *bus) +{ + struct usb_hcd *hcd; + + hcd = container_of (bus, struct usb_hcd, self); + if (hcd->driver->hub_irq_enable && hcd->state != HC_STATE_HALT) + hcd->driver->hub_irq_enable (hcd); +} /*-------------------------------------------------------------------------*/ @@ -930,9 +880,9 @@ long usb_calc_bus_time (int speed, int is_input, int isoc, int bytecount) case USB_SPEED_HIGH: /* ISOC or INTR */ // FIXME adjust for input vs output if (isoc) - tmp = HS_USECS (bytecount); + tmp = HS_NSECS_ISO (bytecount); else - tmp = HS_USECS_ISO (bytecount); + tmp = HS_NSECS (bytecount); return tmp; default: pr_debug ("%s: bogus device speed!\n", usbcore_name); @@ -1094,7 +1044,6 @@ static void urb_unlink (struct urb *urb) spin_lock_irqsave (&hcd_data_lock, flags); list_del_init (&urb->urb_list); spin_unlock_irqrestore (&hcd_data_lock, flags); - usb_put_dev (urb->dev); } @@ -1103,10 +1052,10 @@ static void urb_unlink (struct urb *urb) * expects usb_submit_urb() to have sanity checked and conditioned all * inputs in the urb */ -static int hcd_submit_urb (struct urb *urb, int mem_flags) +int usb_hcd_submit_urb (struct urb *urb, gfp_t mem_flags) { int status; - struct usb_hcd *hcd = urb->dev->bus->hcpriv; + struct usb_hcd *hcd = bus_to_hcd(urb->dev->bus); struct usb_host_endpoint *ep; unsigned long flags; @@ -1133,10 +1082,19 @@ static int hcd_submit_urb (struct urb *urb, int mem_flags) else switch (hcd->state) { case HC_STATE_RUNNING: case HC_STATE_RESUMING: - usb_get_dev (urb->dev); +doit: list_add_tail (&urb->urb_list, &ep->urb_list); status = 0; break; + case HC_STATE_SUSPENDED: + /* HC upstream links (register access, wakeup signaling) can work + * even when the downstream links (and DMA etc) are quiesced; let + * usbcore talk to the root hub. + */ + if (hcd->self.controller->power.power_state.event == PM_EVENT_ON + && urb->dev->parent == NULL) + goto doit; + /* FALL THROUGH */ default: status = -ESHUTDOWN; break; @@ -1168,7 +1126,7 @@ static int hcd_submit_urb (struct urb *urb, int mem_flags) /* lower level hcd code should use *_dma exclusively, * unless it uses pio or talks to another transport. */ - if (hcd->self.controller->dma_mask) { + if (hcd->self.uses_dma) { if (usb_pipecontrol (urb->pipe) && !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP)) urb->setup_dma = dma_map_single ( @@ -1203,9 +1161,10 @@ done: /*-------------------------------------------------------------------------*/ /* called in any context */ -static int hcd_get_frame_number (struct usb_device *udev) +int usb_hcd_get_frame_number (struct usb_device *udev) { - struct usb_hcd *hcd = (struct usb_hcd *)udev->bus->hcpriv; + struct usb_hcd *hcd = bus_to_hcd(udev->bus); + if (!HC_IS_RUNNING (hcd->state)) return -ESHUTDOWN; return hcd->driver->get_frame_number (hcd); @@ -1245,7 +1204,7 @@ unlink1 (struct usb_hcd *hcd, struct urb *urb) * caller guarantees urb won't be recycled till both unlink() * and the urb's completion function return */ -static int hcd_unlink_urb (struct urb *urb, int status) +int usb_hcd_unlink_urb (struct urb *urb, int status) { struct usb_host_endpoint *ep; struct usb_hcd *hcd = NULL; @@ -1278,18 +1237,12 @@ static int hcd_unlink_urb (struct urb *urb, int status) spin_lock (&hcd_data_lock); sys = &urb->dev->dev; - hcd = urb->dev->bus->hcpriv; + hcd = bus_to_hcd(urb->dev->bus); if (hcd == NULL) { retval = -ENODEV; goto done; } - /* running ~= hc unlink handshake works (irq, timer, etc) - * halted ~= no unlink handshake is needed - * suspended, resuming == should never happen - */ - WARN_ON (!HC_IS_RUNNING (hcd->state) && hcd->state != HC_STATE_HALT); - /* insist the urb is still queued */ list_for_each(tmp, &ep->urb_list) { if (tmp == &urb->urb_list) @@ -1313,11 +1266,12 @@ static int hcd_unlink_urb (struct urb *urb, int status) * finish unlinking the initial failed usb_set_address() * or device descriptor fetch. */ - if (!hcd->saw_irq && hcd->self.root_hub != urb->dev) { + if (!test_bit(HCD_FLAG_SAW_IRQ, &hcd->flags) + && hcd->self.root_hub != urb->dev) { dev_warn (hcd->self.controller, "Unlink after no-IRQ? " "Controller is probably using the wrong IRQ." "\n"); - hcd->saw_irq = 1; + set_bit(HCD_FLAG_SAW_IRQ, &hcd->flags); } urb->status = status; @@ -1341,40 +1295,33 @@ done: /*-------------------------------------------------------------------------*/ /* disables the endpoint: cancels any pending urbs, then synchronizes with - * the hcd to make sure all endpoint state is gone from hardware. use for + * the hcd to make sure all endpoint state is gone from hardware, and then + * waits until the endpoint's queue is completely drained. use for * set_configuration, set_interface, driver removal, physical disconnect. * * example: a qh stored in ep->hcpriv, holding state related to endpoint * type, maxpacket size, toggle, halt status, and scheduling. */ -static void -hcd_endpoint_disable (struct usb_device *udev, struct usb_host_endpoint *ep) +void usb_hcd_endpoint_disable (struct usb_device *udev, + struct usb_host_endpoint *ep) { struct usb_hcd *hcd; struct urb *urb; - hcd = udev->bus->hcpriv; + hcd = bus_to_hcd(udev->bus); - WARN_ON (!HC_IS_RUNNING (hcd->state) && hcd->state != HC_STATE_HALT); + WARN_ON (!HC_IS_RUNNING (hcd->state) && hcd->state != HC_STATE_HALT && + udev->state != USB_STATE_NOTATTACHED); local_irq_disable (); - /* FIXME move most of this into message.c as part of its - * endpoint disable logic - */ - /* ep is already gone from udev->ep_{in,out}[]; no more submits */ rescan: spin_lock (&hcd_data_lock); list_for_each_entry (urb, &ep->urb_list, urb_list) { int tmp; - /* another cpu may be in hcd, spinning on hcd_data_lock - * to giveback() this urb. the races here should be - * small, but a full fix needs a new "can't submit" - * urb state. - * FIXME urb->reject should allow that... - */ + /* the urb may already have been unlinked */ if (urb->status != -EINPROGRESS) continue; usb_get_urb (urb); @@ -1416,30 +1363,74 @@ rescan: might_sleep (); if (hcd->driver->endpoint_disable) hcd->driver->endpoint_disable (hcd, ep); + + /* Wait until the endpoint queue is completely empty. Most HCDs + * will have done this already in their endpoint_disable method, + * but some might not. And there could be root-hub control URBs + * still pending since they aren't affected by the HCDs' + * endpoint_disable methods. + */ + while (!list_empty (&ep->urb_list)) { + spin_lock_irq (&hcd_data_lock); + + /* The list may have changed while we acquired the spinlock */ + urb = NULL; + if (!list_empty (&ep->urb_list)) { + urb = list_entry (ep->urb_list.prev, struct urb, + urb_list); + usb_get_urb (urb); + } + spin_unlock_irq (&hcd_data_lock); + + if (urb) { + usb_kill_urb (urb); + usb_put_urb (urb); + } + } } /*-------------------------------------------------------------------------*/ -#ifdef CONFIG_USB_SUSPEND +#ifdef CONFIG_PM -static int hcd_hub_suspend (struct usb_bus *bus) +int hcd_bus_suspend (struct usb_bus *bus) { struct usb_hcd *hcd; + int status; hcd = container_of (bus, struct usb_hcd, self); - if (hcd->driver->hub_suspend) - return hcd->driver->hub_suspend (hcd); - return 0; + if (!hcd->driver->bus_suspend) + return -ENOENT; + hcd->state = HC_STATE_QUIESCING; + status = hcd->driver->bus_suspend (hcd); + if (status == 0) + hcd->state = HC_STATE_SUSPENDED; + else + dev_dbg(&bus->root_hub->dev, "%s fail, err %d\n", + "suspend", status); + return status; } -static int hcd_hub_resume (struct usb_bus *bus) +int hcd_bus_resume (struct usb_bus *bus) { struct usb_hcd *hcd; + int status; hcd = container_of (bus, struct usb_hcd, self); - if (hcd->driver->hub_resume) - return hcd->driver->hub_resume (hcd); - return 0; + if (!hcd->driver->bus_resume) + return -ENOENT; + if (hcd->state == HC_STATE_RUNNING) + return 0; + hcd->state = HC_STATE_RESUMING; + status = hcd->driver->bus_resume (hcd); + if (status == 0) + hcd->state = HC_STATE_RUNNING; + else { + dev_dbg(&bus->root_hub->dev, "%s fail, err %d\n", + "resume", status); + usb_hc_died(hcd); + } + return status; } /** @@ -1449,7 +1440,7 @@ static int hcd_hub_resume (struct usb_bus *bus) * The USB host controller calls this function when its root hub is * suspended (with the remote wakeup feature enabled) and a remote * wakeup request is received. It queues a request for khubd to - * resume the root hub. + * resume the root hub (that is, manage its downstream ports again). */ void usb_hcd_resume_root_hub (struct usb_hcd *hcd) { @@ -1460,13 +1451,9 @@ void usb_hcd_resume_root_hub (struct usb_hcd *hcd) usb_resume_root_hub (hcd->self.root_hub); spin_unlock_irqrestore (&hcd_root_hub_lock, flags); } +EXPORT_SYMBOL_GPL(usb_hcd_resume_root_hub); -#else -void usb_hcd_resume_root_hub (struct usb_hcd *hcd) -{ -} #endif -EXPORT_SYMBOL_GPL(usb_hcd_resume_root_hub); /*-------------------------------------------------------------------------*/ @@ -1509,29 +1496,10 @@ EXPORT_SYMBOL (usb_bus_start_enum); /*-------------------------------------------------------------------------*/ -/* - * usb_hcd_operations - adapts usb_bus framework to HCD framework (bus glue) - */ -static struct usb_operations usb_hcd_operations = { - .get_frame_number = hcd_get_frame_number, - .submit_urb = hcd_submit_urb, - .unlink_urb = hcd_unlink_urb, - .buffer_alloc = hcd_buffer_alloc, - .buffer_free = hcd_buffer_free, - .disable = hcd_endpoint_disable, -#ifdef CONFIG_USB_SUSPEND - .hub_suspend = hcd_hub_suspend, - .hub_resume = hcd_hub_resume, -#endif -}; - -/*-------------------------------------------------------------------------*/ - /** * usb_hcd_giveback_urb - return URB from HCD to device driver * @hcd: host controller returning the URB * @urb: urb being returned to the USB device driver. - * @regs: pt_regs, passed down to the URB completion handler * Context: in_interrupt() * * This hands the URB from HCD to its USB device driver, using its @@ -1540,15 +1508,16 @@ static struct usb_operations usb_hcd_operations = { * the device driver won't cause problems if it frees, modifies, * or resubmits this URB. */ -void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb, struct pt_regs *regs) +void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb) { int at_root_hub; at_root_hub = (urb->dev == hcd->self.root_hub); urb_unlink (urb); - /* lower level hcd code should use *_dma exclusively */ - if (hcd->self.controller->dma_mask && !at_root_hub) { + /* lower level hcd code should use *_dma exclusively if the + * host controller does DMA */ + if (hcd->self.uses_dma && !at_root_hub) { if (usb_pipecontrol (urb->pipe) && !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP)) dma_unmap_single (hcd->self.controller, urb->setup_dma, @@ -1566,7 +1535,7 @@ void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb, struct pt_regs usbmon_urb_complete (&hcd->self, urb); /* pass ownership to the completion handler */ - urb->complete (urb, regs); + urb->complete (urb); atomic_dec (&urb->use_count); if (unlikely (urb->reject)) wake_up (&usb_kill_urb_queue); @@ -1585,18 +1554,20 @@ EXPORT_SYMBOL (usb_hcd_giveback_urb); * If the controller isn't HALTed, calls the driver's irq handler. * Checks whether the controller is now dead. */ -irqreturn_t usb_hcd_irq (int irq, void *__hcd, struct pt_regs * r) +irqreturn_t usb_hcd_irq (int irq, void *__hcd) { struct usb_hcd *hcd = __hcd; int start = hcd->state; - if (start == HC_STATE_HALT) + if (unlikely(start == HC_STATE_HALT || + !test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))) return IRQ_NONE; - if (hcd->driver->irq (hcd, r) == IRQ_NONE) + if (hcd->driver->irq (hcd) == IRQ_NONE) return IRQ_NONE; - hcd->saw_irq = 1; - if (hcd->state != start && hcd->state == HC_STATE_HALT) + set_bit(HCD_FLAG_SAW_IRQ, &hcd->flags); + + if (unlikely(hcd->state == HC_STATE_HALT)) usb_hc_died (hcd); return IRQ_HANDLED; } @@ -1619,6 +1590,7 @@ void usb_hc_died (struct usb_hcd *hcd) spin_lock_irqsave (&hcd_root_hub_lock, flags); if (hcd->rh_registered) { + hcd->poll_rh = 0; /* make khubd clean up old urbs and devices */ usb_set_device_state (hcd->self.root_hub, @@ -1631,14 +1603,6 @@ EXPORT_SYMBOL_GPL (usb_hc_died); /*-------------------------------------------------------------------------*/ -static void hcd_release (struct usb_bus *bus) -{ - struct usb_hcd *hcd; - - hcd = container_of(bus, struct usb_hcd, self); - kfree(hcd); -} - /** * usb_create_hcd - create and initialize an HCD structure * @driver: HC driver that will use this hcd @@ -1657,21 +1621,22 @@ struct usb_hcd *usb_create_hcd (const struct hc_driver *driver, { struct usb_hcd *hcd; - hcd = kcalloc(1, sizeof(*hcd) + driver->hcd_priv_size, GFP_KERNEL); + hcd = kzalloc(sizeof(*hcd) + driver->hcd_priv_size, GFP_KERNEL); if (!hcd) { dev_dbg (dev, "hcd alloc failed\n"); return NULL; } dev_set_drvdata(dev, hcd); + kref_init(&hcd->kref); usb_bus_init(&hcd->self); - hcd->self.op = &usb_hcd_operations; - hcd->self.hcpriv = hcd; - hcd->self.release = &hcd_release; hcd->self.controller = dev; hcd->self.bus_name = bus_name; + hcd->self.uses_dma = (dev->dma_mask != NULL); init_timer(&hcd->rh_timer); + hcd->rh_timer.function = rh_timer_func; + hcd->rh_timer.data = (unsigned long) hcd; hcd->driver = driver; hcd->product_desc = (driver->product_desc) ? driver->product_desc : @@ -1681,10 +1646,25 @@ struct usb_hcd *usb_create_hcd (const struct hc_driver *driver, } EXPORT_SYMBOL (usb_create_hcd); +static void hcd_release (struct kref *kref) +{ + struct usb_hcd *hcd = container_of (kref, struct usb_hcd, kref); + + kfree(hcd); +} + +struct usb_hcd *usb_get_hcd (struct usb_hcd *hcd) +{ + if (hcd) + kref_get (&hcd->kref); + return hcd; +} +EXPORT_SYMBOL (usb_get_hcd); + void usb_put_hcd (struct usb_hcd *hcd) { - dev_set_drvdata(hcd->self.controller, NULL); - usb_bus_put(&hcd->self); + if (hcd) + kref_put (&hcd->kref, hcd_release); } EXPORT_SYMBOL (usb_put_hcd); @@ -1701,43 +1681,65 @@ EXPORT_SYMBOL (usb_put_hcd); int usb_add_hcd(struct usb_hcd *hcd, unsigned int irqnum, unsigned long irqflags) { - int retval; + int retval; + struct usb_device *rhdev; dev_info(hcd->self.controller, "%s\n", hcd->product_desc); - /* till now HC has been in an indeterminate state ... */ - if (hcd->driver->reset && (retval = hcd->driver->reset(hcd)) < 0) { - dev_err(hcd->self.controller, "can't reset\n"); - return retval; - } + set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); + /* HC is in reset state, but accessible. Now do the one-time init, + * bottom up so that hcds can customize the root hubs before khubd + * starts talking to them. (Note, bus id is assigned early too.) + */ if ((retval = hcd_buffer_create(hcd)) != 0) { dev_dbg(hcd->self.controller, "pool alloc failed\n"); return retval; } if ((retval = usb_register_bus(&hcd->self)) < 0) - goto err1; + goto err_register_bus; - if (hcd->driver->irq) { - char buf[8], *bufp = buf; + if ((rhdev = usb_alloc_dev(NULL, &hcd->self, 0)) == NULL) { + dev_err(hcd->self.controller, "unable to allocate root hub\n"); + retval = -ENOMEM; + goto err_allocate_root_hub; + } + rhdev->speed = (hcd->driver->flags & HCD_USB2) ? USB_SPEED_HIGH : + USB_SPEED_FULL; + hcd->self.root_hub = rhdev; -#ifdef __sparc__ - bufp = __irq_itoa(irqnum); -#else - sprintf(buf, "%d", irqnum); -#endif + /* wakeup flag init defaults to "everything works" for root hubs, + * but drivers can override it in reset() if needed, along with + * recording the overall controller's system wakeup capability. + */ + device_init_wakeup(&rhdev->dev, 1); + + /* "reset" is misnamed; its role is now one-time init. the controller + * should already have been reset (and boot firmware kicked off etc). + */ + if (hcd->driver->reset && (retval = hcd->driver->reset(hcd)) < 0) { + dev_err(hcd->self.controller, "can't setup\n"); + goto err_hcd_driver_setup; + } + + /* NOTE: root hub and controller capabilities may not be the same */ + if (device_can_wakeup(hcd->self.controller) + && device_can_wakeup(&hcd->self.root_hub->dev)) + dev_dbg(hcd->self.controller, "supports USB remote wakeup\n"); + /* enable irqs just before we start the controller */ + if (hcd->driver->irq) { snprintf(hcd->irq_descr, sizeof(hcd->irq_descr), "%s:usb%d", hcd->driver->description, hcd->self.busnum); if ((retval = request_irq(irqnum, &usb_hcd_irq, irqflags, hcd->irq_descr, hcd)) != 0) { dev_err(hcd->self.controller, - "request interrupt %s failed\n", bufp); - goto err2; + "request interrupt %d failed\n", irqnum); + goto err_request_irq; } hcd->irq = irqnum; - dev_info(hcd->self.controller, "irq %s, %s 0x%08llx\n", bufp, + dev_info(hcd->self.controller, "irq %d, %s 0x%08llx\n", irqnum, (hcd->driver->flags & HCD_MEMORY) ? "io mem" : "io base", (unsigned long long)hcd->rsrc_start); @@ -1752,17 +1754,30 @@ int usb_add_hcd(struct usb_hcd *hcd, if ((retval = hcd->driver->start(hcd)) < 0) { dev_err(hcd->self.controller, "startup error %d\n", retval); - goto err3; + goto err_hcd_driver_start; } + /* starting here, usbcore will pay attention to this root hub */ + rhdev->bus_mA = min(500u, hcd->power_budget); + if ((retval = register_root_hub(hcd)) != 0) + goto err_register_root_hub; + + if (hcd->uses_new_polling && hcd->poll_rh) + usb_hcd_poll_rh_status(hcd); return retval; - err3: +err_register_root_hub: + hcd->driver->stop(hcd); +err_hcd_driver_start: if (hcd->irq >= 0) free_irq(irqnum, hcd); - err2: +err_request_irq: +err_hcd_driver_setup: + hcd->self.root_hub = NULL; + usb_put_dev(rhdev); +err_allocate_root_hub: usb_deregister_bus(&hcd->self); - err1: +err_register_bus: hcd_buffer_destroy(hcd); return retval; } @@ -1787,7 +1802,13 @@ void usb_remove_hcd(struct usb_hcd *hcd) spin_lock_irq (&hcd_root_hub_lock); hcd->rh_registered = 0; spin_unlock_irq (&hcd_root_hub_lock); + + mutex_lock(&usb_bus_list_lock); usb_disconnect(&hcd->self.root_hub); + mutex_unlock(&usb_bus_list_lock); + + hcd->poll_rh = 0; + del_timer_sync(&hcd->rh_timer); hcd->driver->stop(hcd); hcd->state = HC_STATE_HALT; @@ -1799,9 +1820,19 @@ void usb_remove_hcd(struct usb_hcd *hcd) } EXPORT_SYMBOL (usb_remove_hcd); +void +usb_hcd_platform_shutdown(struct platform_device* dev) +{ + struct usb_hcd *hcd = platform_get_drvdata(dev); + + if (hcd->driver->shutdown) + hcd->driver->shutdown(hcd); +} +EXPORT_SYMBOL (usb_hcd_platform_shutdown); + /*-------------------------------------------------------------------------*/ -#if defined(CONFIG_USB_MON) || defined(CONFIG_USB_MON_MODULE) +#if defined(CONFIG_USB_MON) struct usb_mon_operations *mon_ops;