usb: don't update devnum for wusb devices
[safe/jmp/linux-2.6] / drivers / usb / core / hub.c
index baae2aa..eb57fcc 100644 (file)
@@ -1245,6 +1245,13 @@ static void release_address(struct usb_device *udev)
        }
 }
 
+static void update_address(struct usb_device *udev, int devnum)
+{
+       /* The address for a WUSB device is managed by wusbcore. */
+       if (!udev->wusb)
+               udev->devnum = devnum;
+}
+
 #ifdef CONFIG_USB_SUSPEND
 
 static void usb_stop_pm(struct usb_device *udev)
@@ -1733,7 +1740,7 @@ static int hub_port_reset(struct usb_hub *hub, int port1,
                case 0:
                        /* TRSTRCY = 10 ms; plus some extra */
                        msleep(10 + 40);
-                       udev->devnum = 0;       /* Device now at address 0 */
+                       update_address(udev, 0);
                        /* FALL THROUGH */
                case -ENOTCONN:
                case -ENODEV:
@@ -2211,12 +2218,13 @@ static int hub_port_debounce(struct usb_hub *hub, int port1)
        return portstatus;
 }
 
-static void ep0_reinit(struct usb_device *udev)
+void usb_ep0_reinit(struct usb_device *udev)
 {
        usb_disable_endpoint(udev, 0 + USB_DIR_IN);
        usb_disable_endpoint(udev, 0 + USB_DIR_OUT);
        usb_enable_endpoint(udev, &udev->ep0);
 }
+EXPORT_SYMBOL_GPL(usb_ep0_reinit);
 
 #define usb_sndaddr0pipe()     (PIPE_CONTROL << 30)
 #define usb_rcvaddr0pipe()     ((PIPE_CONTROL << 30) | USB_DIR_IN)
@@ -2235,9 +2243,10 @@ static int hub_set_address(struct usb_device *udev, int devnum)
                USB_REQ_SET_ADDRESS, 0, devnum, 0,
                NULL, 0, USB_CTRL_SET_TIMEOUT);
        if (retval == 0) {
-               udev->devnum = devnum;  /* Device now using proper address */
+               /* Device now using proper address. */
+               update_address(udev, devnum);
                usb_set_device_state(udev, USB_STATE_ADDRESS);
-               ep0_reinit(udev);
+               usb_ep0_reinit(udev);
        }
        return retval;
 }
@@ -2419,26 +2428,33 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
 #undef GET_DESCRIPTOR_BUFSIZE
                }
 
-               for (j = 0; j < SET_ADDRESS_TRIES; ++j) {
-                       retval = hub_set_address(udev, devnum);
-                       if (retval >= 0)
+               /*
+                * If device is WUSB, we already assigned an
+                * unauthorized address in the Connect Ack sequence;
+                * authorization will assign the final address.
+                */
+               if (udev->wusb == 0) {
+                       for (j = 0; j < SET_ADDRESS_TRIES; ++j) {
+                               retval = hub_set_address(udev, devnum);
+                               if (retval >= 0)
+                                       break;
+                               msleep(200);
+                       }
+                       if (retval < 0) {
+                               dev_err(&udev->dev,
+                                       "device not accepting address %d, error %d\n",
+                                       devnum, retval);
+                               goto fail;
+                       }
+
+                       /* cope with hardware quirkiness:
+                        *  - let SET_ADDRESS settle, some device hardware wants it
+                        *  - read ep0 maxpacket even for high and low speed,
+                        */
+                       msleep(10);
+                       if (USE_NEW_SCHEME(retry_counter))
                                break;
-                       msleep(200);
-               }
-               if (retval < 0) {
-                       dev_err(&udev->dev,
-                               "device not accepting address %d, error %d\n",
-                               devnum, retval);
-                       goto fail;
-               }
-               /* cope with hardware quirkiness:
-                *  - let SET_ADDRESS settle, some device hardware wants it
-                *  - read ep0 maxpacket even for high and low speed,
-                */
-               msleep(10);
-               if (USE_NEW_SCHEME(retry_counter))
-                       break;
+               }
 
                retval = usb_get_device_descriptor(udev, 8);
                if (retval < 8) {
@@ -2455,7 +2471,7 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
        if (retval)
                goto fail;
 
-       i = udev->descriptor.bMaxPacketSize0 == 0xff?
+       i = udev->descriptor.bMaxPacketSize0 == 0xff?   /* wusb device? */
            512 : udev->descriptor.bMaxPacketSize0;
        if (le16_to_cpu(udev->ep0.desc.wMaxPacketSize) != i) {
                if (udev->speed != USB_SPEED_FULL ||
@@ -2466,7 +2482,7 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
                }
                dev_dbg(&udev->dev, "ep0 maxpacket = %d\n", i);
                udev->ep0.desc.wMaxPacketSize = cpu_to_le16(i);
-               ep0_reinit(udev);
+               usb_ep0_reinit(udev);
        }
   
        retval = usb_get_device_descriptor(udev, USB_DT_DEVICE_SIZE);
@@ -2483,7 +2499,7 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
 fail:
        if (retval) {
                hub_port_disable(hub, port1, 0);
-               udev->devnum = devnum;  /* for disconnect processing */
+               update_address(udev, devnum);   /* for disconnect processing */
        }
        mutex_unlock(&usb_address0_mutex);
        return retval;
@@ -2722,7 +2738,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
 loop_disable:
                hub_port_disable(hub, port1, 1);
 loop:
-               ep0_reinit(udev);
+               usb_ep0_reinit(udev);
                release_address(udev);
                usb_put_dev(udev);
                if ((status == -ENOTCONN) || (status == -ENOTSUPP))
@@ -3157,7 +3173,7 @@ int usb_reset_device(struct usb_device *udev)
 
                /* ep0 maxpacket size may change; let the HCD know about it.
                 * Other endpoints will be handled by re-enumeration. */
-               ep0_reinit(udev);
+               usb_ep0_reinit(udev);
                ret = hub_port_init(parent_hub, udev, port1, i);
                if (ret >= 0 || ret == -ENOTCONN || ret == -ENODEV)
                        break;