USB: add urb->unlinked field
[safe/jmp/linux-2.6] / drivers / usb / core / hcd.c
index 8969e42..ec17fc4 100644 (file)
@@ -99,12 +99,17 @@ EXPORT_SYMBOL_GPL (usb_bus_list_lock);
 /* used for controlling access to virtual root hubs */
 static DEFINE_SPINLOCK(hcd_root_hub_lock);
 
-/* used when updating hcd data */
-static DEFINE_SPINLOCK(hcd_data_lock);
+/* used when updating an endpoint's URB list */
+static DEFINE_SPINLOCK(hcd_urb_list_lock);
 
 /* wait queue for synchronous unlinks */
 DECLARE_WAIT_QUEUE_HEAD(usb_kill_urb_queue);
 
+static inline int is_root_hub(struct usb_device *udev)
+{
+       return (udev->parent == NULL);
+}
+
 /*-------------------------------------------------------------------------*/
 
 /*
@@ -351,10 +356,18 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb)
        const u8        *bufp = tbuf;
        int             len = 0;
        int             patch_wakeup = 0;
-       unsigned long   flags;
-       int             status = 0;
+       int             status;
        int             n;
 
+       might_sleep();
+
+       spin_lock_irq(&hcd_root_hub_lock);
+       status = usb_hcd_link_urb_to_ep(hcd, urb);
+       spin_unlock_irq(&hcd_root_hub_lock);
+       if (status)
+               return status;
+       urb->hcpriv = hcd;      /* Indicate it's queued */
+
        cmd = (struct usb_ctrlrequest *) urb->setup_packet;
        typeReq  = (cmd->bRequestType << 8) | cmd->bRequest;
        wValue   = le16_to_cpu (cmd->wValue);
@@ -518,13 +531,19 @@ error:
        }
 
        /* any errors get returned through the urb completion */
-       local_irq_save (flags);
-       spin_lock (&urb->lock);
-       if (urb->status == -EINPROGRESS)
-               urb->status = status;
-       spin_unlock (&urb->lock);
-       usb_hcd_giveback_urb (hcd, urb);
-       local_irq_restore (flags);
+       spin_lock_irq(&hcd_root_hub_lock);
+       urb->status = status;
+       usb_hcd_unlink_urb_from_ep(hcd, urb);
+
+       /* This peculiar use of spinlocks echoes what real HC drivers do.
+        * Avoiding calls to local_irq_disable/enable makes the code
+        * RT-friendly.
+        */
+       spin_unlock(&hcd_root_hub_lock);
+       usb_hcd_giveback_urb(hcd, urb);
+       spin_lock(&hcd_root_hub_lock);
+
+       spin_unlock_irq(&hcd_root_hub_lock);
        return 0;
 }
 
@@ -554,38 +573,33 @@ void usb_hcd_poll_rh_status(struct usb_hcd *hcd)
        if (length > 0) {
 
                /* try to complete the status urb */
-               local_irq_save (flags);
-               spin_lock(&hcd_root_hub_lock);
+               spin_lock_irqsave(&hcd_root_hub_lock, flags);
                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
+                       hcd->poll_pending = 0;
+                       hcd->status_urb = NULL;
+                       urb->status = 0;
+                       urb->actual_length = length;
+                       memcpy(urb->transfer_buffer, buffer, length);
+
+                       usb_hcd_unlink_urb_from_ep(hcd, urb);
+                       spin_unlock(&hcd_root_hub_lock);
+                       usb_hcd_giveback_urb(hcd, urb);
+                       spin_lock(&hcd_root_hub_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);
+               }
+               spin_unlock_irqrestore(&hcd_root_hub_lock, flags);
        }
 
        /* The USB 2.0 spec says 256 ms.  This is close enough and won't
-        * exceed that limit if HZ is 100. */
+        * exceed that limit if HZ is 100. The math is more clunky than
+        * maybe expected, this is to make sure that all timers for USB devices
+        * fire at the same time to give the CPU a break inbetween */
        if (hcd->uses_new_polling ? hcd->poll_rh :
                        (length == 0 && hcd->status_urb != NULL))
-               mod_timer (&hcd->rh_timer, jiffies + msecs_to_jiffies(250));
+               mod_timer (&hcd->rh_timer, (jiffies/(HZ/4) + 1) * (HZ/4));
 }
 EXPORT_SYMBOL_GPL(usb_hcd_poll_rh_status);
 
@@ -604,33 +618,35 @@ static int rh_queue_status (struct usb_hcd *hcd, struct urb *urb)
        int             len = 1 + (urb->dev->maxchild / 8);
 
        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) {
+       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 */
+               goto done;
+       }
 
-               if (!hcd->uses_new_polling)
-                       mod_timer (&hcd->rh_timer, jiffies +
-                                       msecs_to_jiffies(250));
+       retval = usb_hcd_link_urb_to_ep(hcd, urb);
+       if (retval)
+               goto done;
 
-               /* If a status change has already occurred, report it ASAP */
-               else if (hcd->poll_pending)
-                       mod_timer (&hcd->rh_timer, jiffies);
-               retval = 0;
-       }
+       hcd->status_urb = urb;
+       urb->hcpriv = hcd;      /* indicate it's queued */
+       if (!hcd->uses_new_polling)
+               mod_timer(&hcd->rh_timer, (jiffies/(HZ/4) + 1) * (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;
+ done:
        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))
+       if (usb_endpoint_xfer_int(&urb->ep->desc))
                return rh_queue_status (hcd, urb);
-       if (usb_pipecontrol (urb->pipe))
+       if (usb_endpoint_xfer_control(&urb->ep->desc))
                return rh_call_control (hcd, urb);
        return -EINVAL;
 }
@@ -640,32 +656,96 @@ static int rh_urb_enqueue (struct usb_hcd *hcd, struct urb *urb)
 /* 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)
+static int usb_rh_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
 {
        unsigned long   flags;
+       int             rc;
+
+       spin_lock_irqsave(&hcd_root_hub_lock, flags);
+       rc = usb_hcd_check_unlink_urb(hcd, urb, status);
+       if (rc)
+               goto done;
 
-       if (usb_pipeendpoint(urb->pipe) == 0) { /* Control URB */
+       if (usb_endpoint_num(&urb->ep->desc) == 0) {    /* Control URB */
                ;       /* Do nothing */
 
        } else {                                /* Status URB */
                if (!hcd->uses_new_polling)
                        del_timer (&hcd->rh_timer);
-               local_irq_save (flags);
-               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);
+                       usb_hcd_unlink_urb_from_ep(hcd, urb);
+
+                       spin_unlock(&hcd_root_hub_lock);
+                       usb_hcd_giveback_urb(hcd, urb);
+                       spin_lock(&hcd_root_hub_lock);
+               }
        }
+ done:
+       spin_unlock_irqrestore(&hcd_root_hub_lock, flags);
+       return rc;
+}
 
-       return 0;
+
+
+/*
+ * Show & store the current value of authorized_default
+ */
+static ssize_t usb_host_authorized_default_show(struct device *dev,
+                                               struct device_attribute *attr,
+                                               char *buf)
+{
+       struct usb_device *rh_usb_dev = to_usb_device(dev);
+       struct usb_bus *usb_bus = rh_usb_dev->bus;
+       struct usb_hcd *usb_hcd;
+
+       if (usb_bus == NULL)    /* FIXME: not sure if this case is possible */
+               return -ENODEV;
+       usb_hcd = bus_to_hcd(usb_bus);
+       return snprintf(buf, PAGE_SIZE, "%u\n", usb_hcd->authorized_default);
 }
 
+static ssize_t usb_host_authorized_default_store(struct device *dev,
+                                                struct device_attribute *attr,
+                                                const char *buf, size_t size)
+{
+       ssize_t result;
+       unsigned val;
+       struct usb_device *rh_usb_dev = to_usb_device(dev);
+       struct usb_bus *usb_bus = rh_usb_dev->bus;
+       struct usb_hcd *usb_hcd;
+
+       if (usb_bus == NULL)    /* FIXME: not sure if this case is possible */
+               return -ENODEV;
+       usb_hcd = bus_to_hcd(usb_bus);
+       result = sscanf(buf, "%u\n", &val);
+       if (result == 1) {
+               usb_hcd->authorized_default = val? 1 : 0;
+               result = size;
+       }
+       else
+               result = -EINVAL;
+       return result;
+}
+
+static DEVICE_ATTR(authorized_default, 0644,
+           usb_host_authorized_default_show,
+           usb_host_authorized_default_store);
+
+
+/* Group all the USB bus attributes */
+static struct attribute *usb_bus_attrs[] = {
+               &dev_attr_authorized_default.attr,
+               NULL,
+};
+
+static struct attribute_group usb_bus_attr_group = {
+       .name = NULL,   /* we want them in the same directory */
+       .attrs = usb_bus_attrs,
+};
+
+
+
 /*-------------------------------------------------------------------------*/
 
 static struct class *usb_host_class;
@@ -719,27 +799,23 @@ static void usb_bus_init (struct usb_bus *bus)
  */
 static int usb_register_bus(struct usb_bus *bus)
 {
+       int result = -E2BIG;
        int busnum;
 
        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 {
+       if (busnum >= USB_MAXBUS) {
                printk (KERN_ERR "%s: too many buses\n", usbcore_name);
-               mutex_unlock(&usb_bus_list_lock);
-               return -E2BIG;
+               goto error_find_busnum;
        }
-
+       set_bit (busnum, busmap.busmap);
+       bus->busnum = busnum;
        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);
-               mutex_unlock(&usb_bus_list_lock);
-               return PTR_ERR(bus->class_dev);
-       }
-
+                                            bus->controller, "usb_host%d",
+                                            busnum);
+       result = PTR_ERR(bus->class_dev);
+       if (IS_ERR(bus->class_dev))
+               goto error_create_class_dev;
        class_set_devdata(bus->class_dev, bus);
 
        /* Add it to the local list of buses */
@@ -748,8 +824,15 @@ static int usb_register_bus(struct usb_bus *bus)
 
        usb_notify_add_bus(bus);
 
-       dev_info (bus->controller, "new USB bus registered, assigned bus number %d\n", bus->busnum);
+       dev_info (bus->controller, "new USB bus registered, assigned bus "
+                 "number %d\n", bus->busnum);
        return 0;
+
+error_create_class_dev:
+       clear_bit(busnum, busmap.busmap);
+error_find_busnum:
+       mutex_unlock(&usb_bus_list_lock);
+       return result;
 }
 
 /**
@@ -901,99 +984,140 @@ EXPORT_SYMBOL (usb_calc_bus_time);
 
 /*-------------------------------------------------------------------------*/
 
-static void urb_unlink (struct urb *urb)
-{
-       unsigned long           flags;
-
-       /* clear all state linking urb to this dev (and hcd) */
-
-       spin_lock_irqsave (&hcd_data_lock, flags);
-       list_del_init (&urb->urb_list);
-       spin_unlock_irqrestore (&hcd_data_lock, flags);
-}
-
-
-/* may be called in any context with a valid urb->dev usecount
- * caller surrenders "ownership" of urb
- * expects usb_submit_urb() to have sanity checked and conditioned all
- * inputs in the urb
+/**
+ * usb_hcd_link_urb_to_ep - add an URB to its endpoint queue
+ * @hcd: host controller to which @urb was submitted
+ * @urb: URB being submitted
+ *
+ * Host controller drivers should call this routine in their enqueue()
+ * method.  The HCD's private spinlock must be held and interrupts must
+ * be disabled.  The actions carried out here are required for URB
+ * submission, as well as for endpoint shutdown and for usb_kill_urb.
+ *
+ * Returns 0 for no error, otherwise a negative error code (in which case
+ * the enqueue() method must fail).  If no error occurs but enqueue() fails
+ * anyway, it must call usb_hcd_unlink_urb_from_ep() before releasing
+ * the private spinlock and returning.
  */
-int usb_hcd_submit_urb (struct urb *urb, gfp_t mem_flags)
+int usb_hcd_link_urb_to_ep(struct usb_hcd *hcd, struct urb *urb)
 {
-       int                     status;
-       struct usb_hcd          *hcd = bus_to_hcd(urb->dev->bus);
-       struct usb_host_endpoint *ep;
-       unsigned long           flags;
+       int             rc = 0;
 
-       if (!hcd)
-               return -ENODEV;
+       spin_lock(&hcd_urb_list_lock);
 
-       usbmon_urb_submit(&hcd->self, urb);
+       /* Check that the URB isn't being killed */
+       if (unlikely(urb->reject)) {
+               rc = -EPERM;
+               goto done;
+       }
+
+       if (unlikely(!urb->ep->enabled)) {
+               rc = -ENOENT;
+               goto done;
+       }
 
        /*
-        * Atomically queue the urb,  first to our records, then to the HCD.
-        * Access to urb->status is controlled by urb->lock ... changes on
-        * i/o completion (normal or fault) or unlinking.
+        * Check the host controller's state and add the URB to the
+        * endpoint's queue.
         */
-
-       // FIXME:  verify that quiescing hc works right (RH cleans up)
-
-       spin_lock_irqsave (&hcd_data_lock, flags);
-       ep = (usb_pipein(urb->pipe) ? urb->dev->ep_in : urb->dev->ep_out)
-                       [usb_pipeendpoint(urb->pipe)];
-       if (unlikely (!ep))
-               status = -ENOENT;
-       else if (unlikely (urb->reject))
-               status = -EPERM;
-       else switch (hcd->state) {
+       switch (hcd->state) {
        case HC_STATE_RUNNING:
        case HC_STATE_RESUMING:
-doit:
-               list_add_tail (&urb->urb_list, &ep->urb_list);
-               status = 0;
+               urb->unlinked = 0;
+               list_add_tail(&urb->urb_list, &urb->ep->urb_list);
                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;
+               rc = -ESHUTDOWN;
+               goto done;
        }
-       spin_unlock_irqrestore (&hcd_data_lock, flags);
-       if (status) {
-               INIT_LIST_HEAD (&urb->urb_list);
-               usbmon_urb_submit_error(&hcd->self, urb, status);
-               return status;
+ done:
+       spin_unlock(&hcd_urb_list_lock);
+       return rc;
+}
+EXPORT_SYMBOL_GPL(usb_hcd_link_urb_to_ep);
+
+/**
+ * usb_hcd_check_unlink_urb - check whether an URB may be unlinked
+ * @hcd: host controller to which @urb was submitted
+ * @urb: URB being checked for unlinkability
+ * @status: error code to store in @urb if the unlink succeeds
+ *
+ * Host controller drivers should call this routine in their dequeue()
+ * method.  The HCD's private spinlock must be held and interrupts must
+ * be disabled.  The actions carried out here are required for making
+ * sure than an unlink is valid.
+ *
+ * Returns 0 for no error, otherwise a negative error code (in which case
+ * the dequeue() method must fail).  The possible error codes are:
+ *
+ *     -EIDRM: @urb was not submitted or has already completed.
+ *             The completion function may not have been called yet.
+ *
+ *     -EBUSY: @urb has already been unlinked.
+ */
+int usb_hcd_check_unlink_urb(struct usb_hcd *hcd, struct urb *urb,
+               int status)
+{
+       struct list_head        *tmp;
+
+       /* insist the urb is still queued */
+       list_for_each(tmp, &urb->ep->urb_list) {
+               if (tmp == &urb->urb_list)
+                       break;
        }
+       if (tmp != &urb->urb_list)
+               return -EIDRM;
 
-       /* increment urb's reference count as part of giving it to the HCD
-        * (which now controls it).  HCD guarantees that it either returns
-        * an error or calls giveback(), but not both.
+       /* Any status except -EINPROGRESS means something already started to
+        * unlink this URB from the hardware.  So there's no more work to do.
         */
-       urb = usb_get_urb (urb);
-       atomic_inc (&urb->use_count);
-
-       if (urb->dev == hcd->self.root_hub) {
-               /* NOTE:  requirement on hub callers (usbfs and the hub
-                * driver, for now) that URBs' urb->transfer_buffer be
-                * valid and usb_buffer_{sync,unmap}() not be needed, since
-                * they could clobber root hub response data.
-                */
-               status = rh_urb_enqueue (hcd, urb);
-               goto done;
+       if (urb->unlinked)
+               return -EBUSY;
+       urb->unlinked = status;
+
+       /* IRQ setup can easily be broken so that USB controllers
+        * never get completion IRQs ... maybe even the ones we need to
+        * finish unlinking the initial failed usb_set_address()
+        * or device descriptor fetch.
+        */
+       if (!test_bit(HCD_FLAG_SAW_IRQ, &hcd->flags) &&
+                       !is_root_hub(urb->dev)) {
+               dev_warn(hcd->self.controller, "Unlink after no-IRQ?  "
+                       "Controller is probably using the wrong IRQ.\n");
+               set_bit(HCD_FLAG_SAW_IRQ, &hcd->flags);
        }
 
-       /* lower level hcd code should use *_dma exclusively,
+       return 0;
+}
+EXPORT_SYMBOL_GPL(usb_hcd_check_unlink_urb);
+
+/**
+ * usb_hcd_unlink_urb_from_ep - remove an URB from its endpoint queue
+ * @hcd: host controller to which @urb was submitted
+ * @urb: URB being unlinked
+ *
+ * Host controller drivers should call this routine before calling
+ * usb_hcd_giveback_urb().  The HCD's private spinlock must be held and
+ * interrupts must be disabled.  The actions carried out here are required
+ * for URB completion.
+ */
+void usb_hcd_unlink_urb_from_ep(struct usb_hcd *hcd, struct urb *urb)
+{
+       /* clear all state linking urb to this dev (and hcd) */
+       spin_lock(&hcd_urb_list_lock);
+       list_del_init(&urb->urb_list);
+       spin_unlock(&hcd_urb_list_lock);
+}
+EXPORT_SYMBOL_GPL(usb_hcd_unlink_urb_from_ep);
+
+static void map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb)
+{
+       /* Map the URB's buffers for DMA access.
+        * Lower level HCD code should use *_dma exclusively,
         * unless it uses pio or talks to another transport.
         */
-       if (hcd->self.uses_dma) {
-               if (usb_pipecontrol (urb->pipe)
+       if (hcd->self.uses_dma && !is_root_hub(urb->dev)) {
+               if (usb_endpoint_xfer_control(&urb->ep->desc)
                        && !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP))
                        urb->setup_dma = dma_map_single (
                                        hcd->self.controller,
@@ -1006,34 +1130,75 @@ doit:
                                        hcd->self.controller,
                                        urb->transfer_buffer,
                                        urb->transfer_buffer_length,
-                                       usb_pipein (urb->pipe)
+                                       usb_urb_dir_in(urb)
                                            ? DMA_FROM_DEVICE
                                            : DMA_TO_DEVICE);
        }
+}
 
-       status = hcd->driver->urb_enqueue (hcd, ep, urb, mem_flags);
-done:
-       if (unlikely (status)) {
-               urb_unlink (urb);
-               atomic_dec (&urb->use_count);
-               if (urb->reject)
-                       wake_up (&usb_kill_urb_queue);
-               usbmon_urb_submit_error(&hcd->self, urb, status);
-               usb_put_urb (urb);
+static void unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb)
+{
+       if (hcd->self.uses_dma && !is_root_hub(urb->dev)) {
+               if (usb_endpoint_xfer_control(&urb->ep->desc)
+                       && !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP))
+                       dma_unmap_single(hcd->self.controller, urb->setup_dma,
+                                       sizeof(struct usb_ctrlrequest),
+                                       DMA_TO_DEVICE);
+               if (urb->transfer_buffer_length != 0
+                       && !(urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP))
+                       dma_unmap_single(hcd->self.controller,
+                                       urb->transfer_dma,
+                                       urb->transfer_buffer_length,
+                                       usb_urb_dir_in(urb)
+                                           ? DMA_FROM_DEVICE
+                                           : DMA_TO_DEVICE);
        }
-       return status;
 }
 
 /*-------------------------------------------------------------------------*/
 
-/* called in any context */
-int usb_hcd_get_frame_number (struct usb_device *udev)
+/* may be called in any context with a valid urb->dev usecount
+ * caller surrenders "ownership" of urb
+ * expects usb_submit_urb() to have sanity checked and conditioned all
+ * inputs in the urb
+ */
+int usb_hcd_submit_urb (struct urb *urb, gfp_t mem_flags)
 {
-       struct usb_hcd  *hcd = bus_to_hcd(udev->bus);
+       int                     status;
+       struct usb_hcd          *hcd = bus_to_hcd(urb->dev->bus);
 
-       if (!HC_IS_RUNNING (hcd->state))
-               return -ESHUTDOWN;
-       return hcd->driver->get_frame_number (hcd);
+       /* increment urb's reference count as part of giving it to the HCD
+        * (which will control it).  HCD guarantees that it either returns
+        * an error or calls giveback(), but not both.
+        */
+       usb_get_urb(urb);
+       atomic_inc(&urb->use_count);
+       usbmon_urb_submit(&hcd->self, urb);
+
+       /* NOTE requirements on root-hub callers (usbfs and the hub
+        * driver, for now):  URBs' urb->transfer_buffer must be
+        * valid and usb_buffer_{sync,unmap}() not be needed, since
+        * they could clobber root hub response data.  Also, control
+        * URBs must be submitted in process context with interrupts
+        * enabled.
+        */
+       map_urb_for_dma(hcd, urb);
+       if (is_root_hub(urb->dev))
+               status = rh_urb_enqueue(hcd, urb);
+       else
+               status = hcd->driver->urb_enqueue(hcd, urb, mem_flags);
+
+       if (unlikely(status)) {
+               usbmon_urb_submit_error(&hcd->self, urb, status);
+               unmap_urb_for_dma(hcd, urb);
+               urb->hcpriv = NULL;
+               INIT_LIST_HEAD(&urb->urb_list);
+               atomic_dec(&urb->use_count);
+               if (urb->reject)
+                       wake_up(&usb_kill_urb_queue);
+               usb_put_urb(urb);
+       }
+       return status;
 }
 
 /*-------------------------------------------------------------------------*/
@@ -1043,24 +1208,19 @@ int usb_hcd_get_frame_number (struct usb_device *udev)
  * soon as practical.  we've already set up the urb's return status,
  * but we can't know if the callback completed already.
  */
-static int
-unlink1 (struct usb_hcd *hcd, struct urb *urb)
+static int unlink1(struct usb_hcd *hcd, struct urb *urb, int status)
 {
        int             value;
 
-       if (urb->dev == hcd->self.root_hub)
-               value = usb_rh_urb_dequeue (hcd, urb);
+       if (is_root_hub(urb->dev))
+               value = usb_rh_urb_dequeue(hcd, urb, status);
        else {
 
                /* The only reason an HCD might fail this call is if
                 * it has not yet fully queued the urb to begin with.
                 * Such failures should be harmless. */
-               value = hcd->driver->urb_dequeue (hcd, urb);
+               value = hcd->driver->urb_dequeue(hcd, urb, status);
        }
-
-       if (value != 0)
-               dev_dbg (hcd->self.controller, "dequeue %p --> %d\n",
-                               urb, value);
        return value;
 }
 
@@ -1072,91 +1232,59 @@ unlink1 (struct usb_hcd *hcd, struct urb *urb)
  */
 int usb_hcd_unlink_urb (struct urb *urb, int status)
 {
-       struct usb_host_endpoint        *ep;
-       struct usb_hcd                  *hcd = NULL;
-       struct device                   *sys = NULL;
-       unsigned long                   flags;
-       struct list_head                *tmp;
-       int                             retval;
-
-       if (!urb)
-               return -EINVAL;
-       if (!urb->dev || !urb->dev->bus)
-               return -ENODEV;
-       ep = (usb_pipein(urb->pipe) ? urb->dev->ep_in : urb->dev->ep_out)
-                       [usb_pipeendpoint(urb->pipe)];
-       if (!ep)
-               return -ENODEV;
-
-       /*
-        * we contend for urb->status with the hcd core,
-        * which changes it while returning the urb.
-        *
-        * Caller guaranteed that the urb pointer hasn't been freed, and
-        * that it was submitted.  But as a rule it can't know whether or
-        * not it's already been unlinked ... so we respect the reversed
-        * lock sequence needed for the usb_hcd_giveback_urb() code paths
-        * (urb lock, then hcd_data_lock) in case some other CPU is now
-        * unlinking it.
-        */
-       spin_lock_irqsave (&urb->lock, flags);
-       spin_lock (&hcd_data_lock);
+       struct usb_hcd          *hcd;
+       int                     retval;
 
-       sys = &urb->dev->dev;
        hcd = bus_to_hcd(urb->dev->bus);
-       if (hcd == NULL) {
-               retval = -ENODEV;
-               goto done;
-       }
+       retval = unlink1(hcd, urb, status);
 
-       /* insist the urb is still queued */
-       list_for_each(tmp, &ep->urb_list) {
-               if (tmp == &urb->urb_list)
-                       break;
-       }
-       if (tmp != &urb->urb_list) {
-               retval = -EIDRM;
-               goto done;
-       }
-
-       /* Any status except -EINPROGRESS means something already started to
-        * unlink this URB from the hardware.  So there's no more work to do.
-        */
-       if (urb->status != -EINPROGRESS) {
-               retval = -EBUSY;
-               goto done;
-       }
-
-       /* IRQ setup can easily be broken so that USB controllers
-        * never get completion IRQs ... maybe even the ones we need to
-        * finish unlinking the initial failed usb_set_address()
-        * or device descriptor fetch.
-        */
-       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");
-               set_bit(HCD_FLAG_SAW_IRQ, &hcd->flags);
-       }
-
-       urb->status = status;
-
-       spin_unlock (&hcd_data_lock);
-       spin_unlock_irqrestore (&urb->lock, flags);
-
-       retval = unlink1 (hcd, urb);
        if (retval == 0)
                retval = -EINPROGRESS;
+       else if (retval != -EIDRM && retval != -EBUSY)
+               dev_dbg(&urb->dev->dev, "hcd_unlink_urb %p fail %d\n",
+                               urb, retval);
        return retval;
+}
 
-done:
-       spin_unlock (&hcd_data_lock);
-       spin_unlock_irqrestore (&urb->lock, flags);
-       if (retval != -EIDRM && sys && sys->driver)
-               dev_dbg (sys, "hcd_unlink_urb %p fail %d\n", urb, retval);
-       return retval;
+/*-------------------------------------------------------------------------*/
+
+/**
+ * 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.
+ * Context: in_interrupt()
+ *
+ * This hands the URB from HCD to its USB device driver, using its
+ * completion function.  The HCD has freed all per-urb resources
+ * (and is done using urb->hcpriv).  It also released all HCD locks;
+ * the device driver won't cause problems if it frees, modifies,
+ * or resubmits this URB.
+ *
+ * If @urb was unlinked, the value of @urb->status will be overridden by
+ * @urb->unlinked.  Erroneous short transfers are detected in case
+ * the HCD hasn't checked for them.
+ */
+void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb)
+{
+       unmap_urb_for_dma(hcd, urb);
+       usbmon_urb_complete (&hcd->self, urb);
+       usb_unanchor_urb(urb);
+       urb->hcpriv = NULL;
+       if (unlikely(urb->unlinked))
+               urb->status = urb->unlinked;
+       else if (unlikely((urb->transfer_flags & URB_SHORT_NOT_OK) &&
+                       urb->actual_length < urb->transfer_buffer_length &&
+                       !urb->status))
+               urb->status = -EREMOTEIO;
+
+       /* pass ownership to the completion handler */
+       urb->complete (urb);
+       atomic_dec (&urb->use_count);
+       if (unlikely (urb->reject))
+               wake_up (&usb_kill_urb_queue);
+       usb_put_urb (urb);
 }
+EXPORT_SYMBOL (usb_hcd_giveback_urb);
 
 /*-------------------------------------------------------------------------*/
 
@@ -1174,55 +1302,51 @@ void usb_hcd_endpoint_disable (struct usb_device *udev,
        struct usb_hcd          *hcd;
        struct urb              *urb;
 
+       might_sleep();
        hcd = bus_to_hcd(udev->bus);
-       local_irq_disable ();
 
        /* ep is already gone from udev->ep_{in,out}[]; no more submits */
 rescan:
-       spin_lock (&hcd_data_lock);
+       spin_lock_irq(&hcd_urb_list_lock);
        list_for_each_entry (urb, &ep->urb_list, urb_list) {
-               int     tmp;
+               int     is_in;
 
-               /* the urb may already have been unlinked */
-               if (urb->status != -EINPROGRESS)
+               if (urb->unlinked)
                        continue;
                usb_get_urb (urb);
-               spin_unlock (&hcd_data_lock);
-
-               spin_lock (&urb->lock);
-               tmp = urb->status;
-               if (tmp == -EINPROGRESS)
-                       urb->status = -ESHUTDOWN;
-               spin_unlock (&urb->lock);
-
-               /* kick hcd unless it's already returning this */
-               if (tmp == -EINPROGRESS) {
-                       tmp = urb->pipe;
-                       unlink1 (hcd, urb);
-                       dev_dbg (hcd->self.controller,
-                               "shutdown urb %p pipe %08x ep%d%s%s\n",
-                               urb, tmp, usb_pipeendpoint (tmp),
-                               (tmp & USB_DIR_IN) ? "in" : "out",
-                               ({ char *s; \
-                                switch (usb_pipetype (tmp)) { \
-                                case PIPE_CONTROL:     s = ""; break; \
-                                case PIPE_BULK:        s = "-bulk"; break; \
-                                case PIPE_INTERRUPT:   s = "-intr"; break; \
-                                default:               s = "-iso"; break; \
-                               }; s;}));
-               }
+               is_in = usb_urb_dir_in(urb);
+               spin_unlock(&hcd_urb_list_lock);
+
+               /* kick hcd */
+               unlink1(hcd, urb, -ESHUTDOWN);
+               dev_dbg (hcd->self.controller,
+                       "shutdown urb %p ep%d%s%s\n",
+                       urb, usb_endpoint_num(&ep->desc),
+                       is_in ? "in" : "out",
+                       ({      char *s;
+
+                                switch (usb_endpoint_type(&ep->desc)) {
+                                case USB_ENDPOINT_XFER_CONTROL:
+                                       s = ""; break;
+                                case USB_ENDPOINT_XFER_BULK:
+                                       s = "-bulk"; break;
+                                case USB_ENDPOINT_XFER_INT:
+                                       s = "-intr"; break;
+                                default:
+                                       s = "-iso"; break;
+                               };
+                               s;
+                       }));
                usb_put_urb (urb);
 
                /* list contents may have changed */
                goto rescan;
        }
-       spin_unlock (&hcd_data_lock);
-       local_irq_enable ();
+       spin_unlock_irq(&hcd_urb_list_lock);
 
        /* synchronize with the hardware, so old configuration state
         * clears out immediately (and will be freed).
         */
-       might_sleep ();
        if (hcd->driver->endpoint_disable)
                hcd->driver->endpoint_disable (hcd, ep);
 
@@ -1233,7 +1357,7 @@ rescan:
         * endpoint_disable methods.
         */
        while (!list_empty (&ep->urb_list)) {
-               spin_lock_irq (&hcd_data_lock);
+               spin_lock_irq(&hcd_urb_list_lock);
 
                /* The list may have changed while we acquired the spinlock */
                urb = NULL;
@@ -1242,7 +1366,7 @@ rescan:
                                        urb_list);
                        usb_get_urb (urb);
                }
-               spin_unlock_irq (&hcd_data_lock);
+               spin_unlock_irq(&hcd_urb_list_lock);
 
                if (urb) {
                        usb_kill_urb (urb);
@@ -1253,44 +1377,73 @@ rescan:
 
 /*-------------------------------------------------------------------------*/
 
+/* called in any context */
+int usb_hcd_get_frame_number (struct usb_device *udev)
+{
+       struct usb_hcd  *hcd = bus_to_hcd(udev->bus);
+
+       if (!HC_IS_RUNNING (hcd->state))
+               return -ESHUTDOWN;
+       return hcd->driver->get_frame_number (hcd);
+}
+
+/*-------------------------------------------------------------------------*/
+
 #ifdef CONFIG_PM
 
-int hcd_bus_suspend (struct usb_bus *bus)
+int hcd_bus_suspend(struct usb_device *rhdev)
 {
-       struct usb_hcd          *hcd;
-       int                     status;
+       struct usb_hcd  *hcd = container_of(rhdev->bus, struct usb_hcd, self);
+       int             status;
+       int             old_state = hcd->state;
 
-       hcd = container_of (bus, struct usb_hcd, self);
-       if (!hcd->driver->bus_suspend)
-               return -ENOENT;
-       hcd->state = HC_STATE_QUIESCING;
-       status = hcd->driver->bus_suspend (hcd);
-       if (status == 0)
+       dev_dbg(&rhdev->dev, "bus %s%s\n",
+                       rhdev->auto_pm ? "auto-" : "", "suspend");
+       if (!hcd->driver->bus_suspend) {
+               status = -ENOENT;
+       } else {
+               hcd->state = HC_STATE_QUIESCING;
+               status = hcd->driver->bus_suspend(hcd);
+       }
+       if (status == 0) {
+               usb_set_device_state(rhdev, USB_STATE_SUSPENDED);
                hcd->state = HC_STATE_SUSPENDED;
-       else
-               dev_dbg(&bus->root_hub->dev, "%s fail, err %d\n",
+       } else {
+               hcd->state = old_state;
+               dev_dbg(&rhdev->dev, "bus %s fail, err %d\n",
                                "suspend", status);
+       }
        return status;
 }
 
-int hcd_bus_resume (struct usb_bus *bus)
+int hcd_bus_resume(struct usb_device *rhdev)
 {
-       struct usb_hcd          *hcd;
-       int                     status;
+       struct usb_hcd  *hcd = container_of(rhdev->bus, struct usb_hcd, self);
+       int             status;
+       int             old_state = hcd->state;
 
-       hcd = container_of (bus, struct usb_hcd, self);
+       dev_dbg(&rhdev->dev, "usb %s%s\n",
+                       rhdev->auto_pm ? "auto-" : "", "resume");
        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)
+       status = hcd->driver->bus_resume(hcd);
+       if (status == 0) {
+               /* TRSMRCY = 10 msec */
+               msleep(10);
+               usb_set_device_state(rhdev, rhdev->actconfig
+                               ? USB_STATE_CONFIGURED
+                               : USB_STATE_ADDRESS);
                hcd->state = HC_STATE_RUNNING;
-       else {
-               dev_dbg(&bus->root_hub->dev, "%s fail, err %d\n",
+       } else {
+               hcd->state = old_state;
+               dev_dbg(&rhdev->dev, "bus %s fail, err %d\n",
                                "resume", status);
-               usb_hc_died(hcd);
+               if (status != -ESHUTDOWN)
+                       usb_hc_died(hcd);
        }
        return status;
 }
@@ -1371,55 +1524,6 @@ EXPORT_SYMBOL (usb_bus_start_enum);
 /*-------------------------------------------------------------------------*/
 
 /**
- * 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.
- * Context: in_interrupt()
- *
- * This hands the URB from HCD to its USB device driver, using its
- * completion function.  The HCD has freed all per-urb resources
- * (and is done using urb->hcpriv).  It also released all HCD locks;
- * 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)
-{
-       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 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,
-                                       sizeof (struct usb_ctrlrequest),
-                                       DMA_TO_DEVICE);
-               if (urb->transfer_buffer_length != 0
-                       && !(urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP))
-                       dma_unmap_single (hcd->self.controller, 
-                                       urb->transfer_dma,
-                                       urb->transfer_buffer_length,
-                                       usb_pipein (urb->pipe)
-                                           ? DMA_FROM_DEVICE
-                                           : DMA_TO_DEVICE);
-       }
-
-       usbmon_urb_complete (&hcd->self, urb);
-       /* pass ownership to the completion handler */
-       urb->complete (urb);
-       atomic_dec (&urb->use_count);
-       if (unlikely (urb->reject))
-               wake_up (&usb_kill_urb_queue);
-       usb_put_urb (urb);
-}
-EXPORT_SYMBOL (usb_hcd_giveback_urb);
-
-/*-------------------------------------------------------------------------*/
-
-/**
  * usb_hcd_irq - hook IRQs to HCD framework (bus glue)
  * @irq: the IRQ being raised
  * @__hcd: pointer to the HCD whose IRQ is being signaled
@@ -1518,7 +1622,6 @@ struct usb_hcd *usb_create_hcd (const struct hc_driver *driver,
        hcd->driver = driver;
        hcd->product_desc = (driver->product_desc) ? driver->product_desc :
                        "USB Host Controller";
-
        return hcd;
 }
 EXPORT_SYMBOL (usb_create_hcd);
@@ -1563,6 +1666,7 @@ int usb_add_hcd(struct usb_hcd *hcd,
 
        dev_info(hcd->self.controller, "%s\n", hcd->product_desc);
 
+       hcd->authorized_default = hcd->wireless? 0 : 1;
        set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
 
        /* HC is in reset state, but accessible.  Now do the one-time init,
@@ -1639,10 +1743,20 @@ int usb_add_hcd(struct usb_hcd *hcd,
        if ((retval = register_root_hub(hcd)) != 0)
                goto err_register_root_hub;
 
+       retval = sysfs_create_group(&rhdev->dev.kobj, &usb_bus_attr_group);
+       if (retval < 0) {
+               printk(KERN_ERR "Cannot register USB bus sysfs attributes: %d\n",
+                      retval);
+               goto error_create_attr_group;
+       }
        if (hcd->uses_new_polling && hcd->poll_rh)
                usb_hcd_poll_rh_status(hcd);
        return retval;
 
+error_create_attr_group:
+       mutex_lock(&usb_bus_list_lock);
+       usb_disconnect(&hcd->self.root_hub);
+       mutex_unlock(&usb_bus_list_lock);
 err_register_root_hub:
        hcd->driver->stop(hcd);
 err_hcd_driver_start:
@@ -1684,6 +1798,7 @@ void usb_remove_hcd(struct usb_hcd *hcd)
        cancel_work_sync(&hcd->wakeup_work);
 #endif
 
+       sysfs_remove_group(&hcd->self.root_hub->dev.kobj, &usb_bus_attr_group);
        mutex_lock(&usb_bus_list_lock);
        usb_disconnect(&hcd->self.root_hub);
        mutex_unlock(&usb_bus_list_lock);