linux 2.6.16.38 w/ vs2.0.3-rc1
[linux-2.6.git] / drivers / usb / core / hcd.c
index fb4d058..9e82afc 100644 (file)
@@ -22,6 +22,7 @@
  * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/version.h>
 #include <linux/kernel.h>
@@ -33,7 +34,6 @@
 #include <asm/scatterlist.h>
 #include <linux/device.h>
 #include <linux/dma-mapping.h>
-#include <linux/mutex.h>
 #include <asm/irq.h>
 #include <asm/byteorder.h>
 
@@ -93,7 +93,7 @@ struct usb_busmap {
 static struct usb_busmap busmap;
 
 /* used when updating list of hcds */
-DEFINE_MUTEX(usb_bus_list_lock);       /* exported only for usbfs */
+DECLARE_MUTEX (usb_bus_list_lock);     /* exported only for usbfs */
 EXPORT_SYMBOL_GPL (usb_bus_list_lock);
 
 /* used for controlling access to virtual root hubs */
@@ -344,7 +344,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;
@@ -366,39 +367,21 @@ 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] = (device_may_wakeup(&hcd->self.root_hub->dev)
-                                       << USB_DEVICE_REMOTE_WAKEUP)
+               tbuf [0] = (hcd->remote_wakeup << 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)
-                       device_set_wakeup_enable(&hcd->self.root_hub->dev, 0);
+                       hcd->remote_wakeup = 0;
                else
                        goto error;
                break;
        case DeviceOutRequest | USB_REQ_SET_FEATURE:
-               if (device_can_wakeup(&hcd->self.root_hub->dev)
-                               && wValue == USB_DEVICE_REMOTE_WAKEUP)
-                       device_set_wakeup_enable(&hcd->self.root_hub->dev, 1);
+               if (hcd->can_wakeup && wValue == USB_DEVICE_REMOTE_WAKEUP)
+                       hcd->remote_wakeup = 1;
                else
                        goto error;
                break;
@@ -427,7 +410,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 (device_can_wakeup(&hcd->self.root_hub->dev))
+                       if (hcd->can_wakeup)
                                patch_wakeup = 1;
                        break;
                case USB_DT_STRING << 8:
@@ -779,14 +762,14 @@ static int usb_register_bus(struct usb_bus *bus)
 {
        int busnum;
 
-       mutex_lock(&usb_bus_list_lock);
+       down (&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);
-               mutex_unlock(&usb_bus_list_lock);
+               up(&usb_bus_list_lock);
                return -E2BIG;
        }
 
@@ -794,7 +777,7 @@ static int usb_register_bus(struct usb_bus *bus)
                                             bus->controller, "usb_host%d", busnum);
        if (IS_ERR(bus->class_dev)) {
                clear_bit(busnum, busmap.busmap);
-               mutex_unlock(&usb_bus_list_lock);
+               up(&usb_bus_list_lock);
                return PTR_ERR(bus->class_dev);
        }
 
@@ -802,7 +785,7 @@ static int usb_register_bus(struct usb_bus *bus)
 
        /* Add it to the local list of buses */
        list_add (&bus->bus_list, &usb_bus_list);
-       mutex_unlock(&usb_bus_list_lock);
+       up (&usb_bus_list_lock);
 
        usb_notify_add_bus(bus);
 
@@ -827,9 +810,9 @@ static void usb_deregister_bus (struct usb_bus *bus)
         * controller code, as well as having it call this when cleaning
         * itself up
         */
-       mutex_lock(&usb_bus_list_lock);
+       down (&usb_bus_list_lock);
        list_del (&bus->bus_list);
-       mutex_unlock(&usb_bus_list_lock);
+       up (&usb_bus_list_lock);
 
        usb_notify_remove_bus(bus);
 
@@ -840,17 +823,18 @@ static void usb_deregister_bus (struct usb_bus *bus)
 
 /**
  * register_root_hub - called by usb_add_hcd() to register a root hub
+ * @usb_dev: the usb root hub device to be registered.
  * @hcd: host controller for this root hub
  *
  * 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).
+ * 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).
  */
-static int register_root_hub(struct usb_hcd *hcd)
+static int register_root_hub (struct usb_device *usb_dev,
+               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;
 
@@ -861,12 +845,14 @@ static int register_root_hub(struct usb_hcd *hcd)
        set_bit (devnum, usb_dev->bus->devmap.devicemap);
        usb_set_device_state(usb_dev, USB_STATE_ADDRESS);
 
-       mutex_lock(&usb_bus_list_lock);
+       down (&usb_bus_list_lock);
+       usb_dev->bus->root_hub = usb_dev;
 
        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) {
-               mutex_unlock(&usb_bus_list_lock);
+               usb_dev->bus->root_hub = NULL;
+               up (&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;
@@ -874,10 +860,11 @@ static int register_root_hub(struct usb_hcd *hcd)
 
        retval = usb_new_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);
        }
-       mutex_unlock(&usb_bus_list_lock);
+       up (&usb_bus_list_lock);
 
        if (retval == 0) {
                spin_lock_irq (&hcd_root_hub_lock);
@@ -1104,6 +1091,7 @@ 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);
 }
 
 
@@ -1143,6 +1131,7 @@ static int hcd_submit_urb (struct urb *urb, gfp_t mem_flags)
        case HC_STATE_RUNNING:
        case HC_STATE_RESUMING:
 doit:
+               usb_get_dev (urb->dev);
                list_add_tail (&urb->urb_list, &ep->urb_list);
                status = 0;
                break;
@@ -1783,10 +1772,12 @@ int usb_add_hcd(struct usb_hcd *hcd,
 
        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.)
-        */
+       /* 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;
+       }
+
        if ((retval = hcd_buffer_create(hcd)) != 0) {
                dev_dbg(hcd->self.controller, "pool alloc failed\n");
                return retval;
@@ -1795,46 +1786,25 @@ int usb_add_hcd(struct usb_hcd *hcd,
        if ((retval = usb_register_bus(&hcd->self)) < 0)
                goto err_register_bus;
 
-       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;
-
-       /* 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;
-       }
+       if (hcd->driver->irq) {
+               char    buf[8], *bufp = buf;
 
-       /* 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");
+#ifdef __sparc__
+               bufp = __irq_itoa(irqnum);
+#else
+               sprintf(buf, "%d", irqnum);
+#endif
 
-       /* 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 %d failed\n", irqnum);
+                                       "request interrupt %s failed\n", bufp);
                        goto err_request_irq;
                }
                hcd->irq = irqnum;
-               dev_info(hcd->self.controller, "irq %d, %s 0x%08llx\n", irqnum,
+               dev_info(hcd->self.controller, "irq %s, %s 0x%08llx\n", bufp,
                                (hcd->driver->flags & HCD_MEMORY) ?
                                        "io mem" : "io base",
                                        (unsigned long long)hcd->rsrc_start);
@@ -1847,32 +1817,56 @@ int usb_add_hcd(struct usb_hcd *hcd,
                                        (unsigned long long)hcd->rsrc_start);
        }
 
+       /* Allocate the root hub before calling hcd->driver->start(),
+        * but don't register it until afterward so that the hardware
+        * is running.
+        */
+       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;
+       }
+
+       /* Although in principle hcd->driver->start() might need to use rhdev,
+        * none of the current drivers do.
+        */
        if ((retval = hcd->driver->start(hcd)) < 0) {
                dev_err(hcd->self.controller, "startup error %d\n", retval);
                goto err_hcd_driver_start;
        }
 
-       /* starting here, usbcore will pay attention to this root hub */
+       /* 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(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(hcd)) != 0)
+       if ((retval = register_root_hub(rhdev, hcd)) != 0)
                goto err_register_root_hub;
 
        if (hcd->uses_new_polling && hcd->poll_rh)
                usb_hcd_poll_rh_status(hcd);
        return retval;
 
-err_register_root_hub:
+ err_register_root_hub:
        hcd->driver->stop(hcd);
-err_hcd_driver_start:
+
+ err_hcd_driver_start:
+       usb_put_dev(rhdev);
+
+ err_allocate_root_hub:
        if (hcd->irq >= 0)
                free_irq(irqnum, hcd);
-err_request_irq:
-err_hcd_driver_setup:
-       hcd->self.root_hub = NULL;
-       usb_put_dev(rhdev);
-err_allocate_root_hub:
+
+ err_request_irq:
        usb_deregister_bus(&hcd->self);
-err_register_bus:
+
+ err_register_bus:
        hcd_buffer_destroy(hcd);
        return retval;
 } 
@@ -1898,9 +1892,9 @@ void usb_remove_hcd(struct usb_hcd *hcd)
        hcd->rh_registered = 0;
        spin_unlock_irq (&hcd_root_hub_lock);
 
-       mutex_lock(&usb_bus_list_lock);
+       down(&usb_bus_list_lock);
        usb_disconnect(&hcd->self.root_hub);
-       mutex_unlock(&usb_bus_list_lock);
+       up(&usb_bus_list_lock);
 
        hcd->poll_rh = 0;
        del_timer_sync(&hcd->rh_timer);