diff options
author | Andiry Xu <andiry.xu@amd.com> | 2010-10-14 10:22:51 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-10-22 13:22:12 -0400 |
commit | c8d4af8e2af12cd4835ba5c4b54bdafe9deda71a (patch) | |
tree | e89c7c700bfe5022eaba3508a818a51717bbd12d /drivers/usb/core | |
parent | f0615c45ce5feb141c1172480c5198d4b8d25436 (diff) |
USB: core: use kernel assigned address for devices under xHCI
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>
Diffstat (limited to 'drivers/usb/core')
-rw-r--r-- | drivers/usb/core/hub.c | 27 |
1 files changed, 13 insertions, 14 deletions
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 5da546c4fd79..f07ab71859dd 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c | |||
@@ -2594,16 +2594,14 @@ static int hub_set_address(struct usb_device *udev, int devnum) | |||
2594 | return 0; | 2594 | return 0; |
2595 | if (udev->state != USB_STATE_DEFAULT) | 2595 | if (udev->state != USB_STATE_DEFAULT) |
2596 | return -EINVAL; | 2596 | return -EINVAL; |
2597 | if (hcd->driver->address_device) { | 2597 | if (hcd->driver->address_device) |
2598 | retval = hcd->driver->address_device(hcd, udev); | 2598 | retval = hcd->driver->address_device(hcd, udev); |
2599 | } else { | 2599 | else |
2600 | retval = usb_control_msg(udev, usb_sndaddr0pipe(), | 2600 | retval = usb_control_msg(udev, usb_sndaddr0pipe(), |
2601 | USB_REQ_SET_ADDRESS, 0, devnum, 0, | 2601 | USB_REQ_SET_ADDRESS, 0, devnum, 0, |
2602 | NULL, 0, USB_CTRL_SET_TIMEOUT); | 2602 | NULL, 0, USB_CTRL_SET_TIMEOUT); |
2603 | if (retval == 0) | ||
2604 | update_address(udev, devnum); | ||
2605 | } | ||
2606 | if (retval == 0) { | 2603 | if (retval == 0) { |
2604 | update_address(udev, devnum); | ||
2607 | /* Device now using proper address. */ | 2605 | /* Device now using proper address. */ |
2608 | usb_set_device_state(udev, USB_STATE_ADDRESS); | 2606 | usb_set_device_state(udev, USB_STATE_ADDRESS); |
2609 | usb_ep0_reinit(udev); | 2607 | usb_ep0_reinit(udev); |
@@ -3097,16 +3095,17 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1, | |||
3097 | udev->speed = USB_SPEED_UNKNOWN; | 3095 | udev->speed = USB_SPEED_UNKNOWN; |
3098 | 3096 | ||
3099 | /* | 3097 | /* |
3100 | * xHCI needs to issue an address device command later | 3098 | * Set the address. |
3101 | * in the hub_port_init sequence for SS/HS/FS/LS devices. | 3099 | * Note xHCI needs to issue an address device command later |
3100 | * in the hub_port_init sequence for SS/HS/FS/LS devices, | ||
3101 | * and xHC will assign an address to the device. But use | ||
3102 | * kernel assigned address here, to avoid any address conflict | ||
3103 | * issue. | ||
3102 | */ | 3104 | */ |
3103 | if (!(hcd->driver->flags & HCD_USB3)) { | 3105 | choose_address(udev); |
3104 | /* set the address */ | 3106 | if (udev->devnum <= 0) { |
3105 | choose_address(udev); | 3107 | status = -ENOTCONN; /* Don't retry */ |
3106 | if (udev->devnum <= 0) { | 3108 | goto loop; |
3107 | status = -ENOTCONN; /* Don't retry */ | ||
3108 | goto loop; | ||
3109 | } | ||
3110 | } | 3109 | } |
3111 | 3110 | ||
3112 | /* reset (non-USB 3.0 devices) and get descriptor */ | 3111 | /* reset (non-USB 3.0 devices) and get descriptor */ |