]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/usb/core/hcd.c
Merge master.kernel.org:/home/rmk/linux-2.6-serial
[linux-2.6-omap-h63xx.git] / drivers / usb / core / hcd.c
index 6c7ca5b08cd60c86dc51f35226bcfdf7ffa7cdc1..0018bbc4de3414bae4bd447e619b169239e593fc 100644 (file)
  */
 
 #include <linux/config.h>
-
-#ifdef CONFIG_USB_DEBUG
-#define DEBUG
-#endif
-
 #include <linux/module.h>
 #include <linux/version.h>
 #include <linux/kernel.h>
@@ -862,9 +857,7 @@ static int register_root_hub (struct usb_device *usb_dev,
                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",
@@ -1320,11 +1313,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;
@@ -1654,13 +1648,15 @@ irqreturn_t usb_hcd_irq (int irq, void *__hcd, struct pt_regs * r)
        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)
                return IRQ_NONE;
 
-       hcd->saw_irq = 1;
-       if (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;
 }
@@ -1773,6 +1769,8 @@ int usb_add_hcd(struct usb_hcd *hcd,
 
        dev_info(hcd->self.controller, "%s\n", hcd->product_desc);
 
+       set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+
        /* 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");
@@ -1827,8 +1825,6 @@ int usb_add_hcd(struct usb_hcd *hcd,
                retval = -ENOMEM;
                goto err_allocate_root_hub;
        }
-       rhdev->speed = (hcd->driver->flags & HCD_USB2) ? USB_SPEED_HIGH :
-                       USB_SPEED_FULL;
 
        /* Although in principle hcd->driver->start() might need to use rhdev,
         * none of the current drivers do.
@@ -1846,6 +1842,9 @@ int usb_add_hcd(struct usb_hcd *hcd,
                dev_dbg(hcd->self.controller, "supports USB remote wakeup\n");
        hcd->remote_wakeup = hcd->can_wakeup;
 
+       rhdev->speed = (hcd->driver->flags & HCD_USB2) ? USB_SPEED_HIGH :
+                       USB_SPEED_FULL;
+       rhdev->bus_mA = min(500u, hcd->power_budget);
        if ((retval = register_root_hub(rhdev, hcd)) != 0)
                goto err_register_root_hub;
 
@@ -1891,7 +1890,10 @@ 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);
+
+       down(&usb_bus_list_lock);
        usb_disconnect(&hcd->self.root_hub);
+       up(&usb_bus_list_lock);
 
        hcd->poll_rh = 0;
        del_timer_sync(&hcd->rh_timer);