This commit was manufactured by cvs2svn to create tag
[linux-2.6.git] / drivers / usb / gadget / dummy_hcd.c
index 4c1b157..0c99e07 100644 (file)
@@ -146,6 +146,8 @@ struct dummy {
        u8                              fifo_buf [FIFO_SIZE];
        u16                             devstatus;
 
+       struct hcd_dev                  *hdev;
+
        /*
         * MASTER/HOST side support
         */
@@ -157,8 +159,6 @@ struct dummy {
        struct completion               released;
        unsigned                        resuming:1;
        unsigned long                   re_timeout;
-
-       struct usb_device               *udev;
 };
 
 static struct dummy    *the_controller;
@@ -739,9 +739,11 @@ stop_activity (struct dummy *dum, struct usb_gadget_driver *driver)
        struct dummy_ep *ep;
 
        /* prevent any more requests */
+       dum->hdev = 0;
        dum->address = 0;
 
-       /* The timer is left running so that outstanding URBs can fail */
+       /* this might not succeed ... */
+       del_timer (&dum->timer);
 
        /* nuke any pending requests first, so driver i/o is quiesced */
        list_for_each_entry (ep, &dum->gadget.ep_list, ep.ep_list)
@@ -782,6 +784,7 @@ usb_gadget_unregister_driver (struct usb_gadget_driver *driver)
 
        driver_unregister (&driver->driver);
 
+       del_timer_sync (&dum->timer);
        return 0;
 }
 EXPORT_SYMBOL (usb_gadget_unregister_driver);
@@ -822,12 +825,7 @@ static int dummy_urb_enqueue (
        dum = container_of (hcd, struct dummy, hcd);
        spin_lock_irqsave (&dum->lock, flags);
 
-       if (!dum->udev) {
-               dum->udev = urb->dev;
-               usb_get_dev (dum->udev);
-       } else if (unlikely (dum->udev != urb->dev))
-               dev_err (hardware, "usb_device address has changed!\n");
-
+       dum->hdev = urb->dev->hcpriv;
        urb->hcpriv = dum;
        if (usb_pipetype (urb->pipe) == PIPE_CONTROL)
                urb->error_count = 1;           /* mark as a new urb */
@@ -1034,12 +1032,17 @@ static struct dummy_ep *find_endpoint (struct dummy *dum, u8 address)
 static void dummy_timer (unsigned long _dum)
 {
        struct dummy            *dum = (struct dummy *) _dum;
-       struct hcd_dev          *hdev;
+       struct hcd_dev          *hdev = dum->hdev;
        struct list_head        *entry, *tmp;
        unsigned long           flags;
        int                     limit, total;
        int                     i;
 
+       if (!hdev) {
+               dev_err (hardware, "timer fired with device gone?\n");
+               return;
+       }
+
        /* simplistic model for one frame's bandwidth */
        switch (dum->gadget.speed) {
        case USB_SPEED_LOW:
@@ -1060,14 +1063,6 @@ static void dummy_timer (unsigned long _dum)
 
        /* look at each urb queued by the host side driver */
        spin_lock_irqsave (&dum->lock, flags);
-
-       if (!dum->udev) {
-               dev_err (hardware, "timer fired with no URBs pending?\n");
-               spin_unlock_irqrestore (&dum->lock, flags);
-               return;
-       }
-       hdev = dum->udev->hcpriv;
-
        for (i = 0; i < DUMMY_ENDPOINTS; i++) {
                if (!ep_name [i])
                        break;
@@ -1339,11 +1334,7 @@ return_urb:
 
        /* want a 1 msec delay here */
        if (!list_empty (&hdev->urb_list))
-               mod_timer (&dum->timer, jiffies + msecs_to_jiffies(1));
-       else {
-               usb_put_dev (dum->udev);
-               dum->udev = NULL;
-       }
+               mod_timer (&dum->timer, jiffies + 1);
 
        spin_unlock_irqrestore (&dum->lock, flags);
 }
@@ -1580,12 +1571,10 @@ show_urbs (struct device *dev, char *buf)
        struct urb              *urb;
        size_t                  size = 0;
        unsigned long           flags;
-       struct hcd_dev          *hdev;
 
        spin_lock_irqsave (&dum->lock, flags);
-       if (dum->udev) {
-               hdev = dum->udev->hcpriv;
-               list_for_each_entry (urb, &hdev->urb_list, urb_list) {
+       if (dum->hdev) {
+               list_for_each_entry (urb, &dum->hdev->urb_list, urb_list) {
                        size_t          temp;
 
                        temp = show_urb (buf, PAGE_SIZE - size, urb);