USB: core: use kernel assigned address for devices under xHCI
authorAndiry Xu <andiry.xu@amd.com>
Thu, 14 Oct 2010 14:22:51 +0000 (07:22 -0700)
committerGreg Kroah-Hartman <gregkh@suse.de>
Fri, 22 Oct 2010 17:22:12 +0000 (10:22 -0700)
xHCI driver uses hardware assigned device address. This may cause device
address conflict in certain cases.

Use kernel assigned address for devices under xHCI. Store the xHC assigned
address locally in xHCI driver.

Signed-off-by: Andiry Xu <andiry.xu@amd.com>
Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
drivers/usb/core/hub.c
drivers/usb/host/xhci.c
drivers/usb/host/xhci.h

index 5da546c4fd7980a7619e8a83fdcebfe77086ce46..f07ab71859dd765715543d52dff728b7103383fb 100644 (file)
@@ -2594,16 +2594,14 @@ static int hub_set_address(struct usb_device *udev, int devnum)
                return 0;
        if (udev->state != USB_STATE_DEFAULT)
                return -EINVAL;
-       if (hcd->driver->address_device) {
+       if (hcd->driver->address_device)
                retval = hcd->driver->address_device(hcd, udev);
-       } else {
+       else
                retval = usb_control_msg(udev, usb_sndaddr0pipe(),
                                USB_REQ_SET_ADDRESS, 0, devnum, 0,
                                NULL, 0, USB_CTRL_SET_TIMEOUT);
-               if (retval == 0)
-                       update_address(udev, devnum);
-       }
        if (retval == 0) {
+               update_address(udev, devnum);
                /* Device now using proper address. */
                usb_set_device_state(udev, USB_STATE_ADDRESS);
                usb_ep0_reinit(udev);
@@ -3097,16 +3095,17 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
                        udev->speed = USB_SPEED_UNKNOWN;
 
                /*
-                * xHCI needs to issue an address device command later
-                * in the hub_port_init sequence for SS/HS/FS/LS devices.
+                * Set the address.
+                * Note xHCI needs to issue an address device command later
+                * in the hub_port_init sequence for SS/HS/FS/LS devices,
+                * and xHC will assign an address to the device. But use
+                * kernel assigned address here, to avoid any address conflict
+                * issue.
                 */
-               if (!(hcd->driver->flags & HCD_USB3)) {
-                       /* set the address */
-                       choose_address(udev);
-                       if (udev->devnum <= 0) {
-                               status = -ENOTCONN;     /* Don't retry */
-                               goto loop;
-                       }
+               choose_address(udev);
+               if (udev->devnum <= 0) {
+                       status = -ENOTCONN;     /* Don't retry */
+                       goto loop;
                }
 
                /* reset (non-USB 3.0 devices) and get descriptor */
index 7928af5c91cb8fcd6f66630dd3014b125b868be6..caccecb7368e3ec7b2141f5fb9cd5c614b5c62f0 100644 (file)
@@ -2287,15 +2287,15 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev)
         * address given back to us by the HC.
         */
        slot_ctx = xhci_get_slot_ctx(xhci, virt_dev->out_ctx);
-       udev->devnum = (slot_ctx->dev_state & DEV_ADDR_MASK) + 1;
+       /* Use kernel assigned address for devices; store xHC assigned
+        * address locally. */
+       virt_dev->address = (slot_ctx->dev_state & DEV_ADDR_MASK) + 1;
        /* Zero the input context control for later use */
        ctrl_ctx = xhci_get_input_control_ctx(xhci, virt_dev->in_ctx);
        ctrl_ctx->add_flags = 0;
        ctrl_ctx->drop_flags = 0;
 
-       xhci_dbg(xhci, "Device address = %d\n", udev->devnum);
-       /* XXX Meh, not sure if anyone else but choose_address uses this. */
-       set_bit(udev->devnum, udev->bus->devmap.devicemap);
+       xhci_dbg(xhci, "Internal device address = %d\n", virt_dev->address);
 
        return 0;
 }
index 490409f918f2e06be4d185425343c135af2d1496..a7181b491e67d43b4723ebf5d23bb18eb0296573 100644 (file)
@@ -746,6 +746,8 @@ struct xhci_virt_device {
        /* Rings saved to ensure old alt settings can be re-instated */
        struct xhci_ring                **ring_cache;
        int                             num_rings_cached;
+       /* Store xHC assigned device address */
+       int                             address;
 #define        XHCI_MAX_RINGS_CACHED   31
        struct xhci_virt_ep             eps[31];
        struct completion               cmd_completion;
This page took 0.05021 seconds and 5 git commands to generate.