提交 c8d4af8e 编写于 作者: A Andiry Xu 提交者: Greg Kroah-Hartman

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: NAndiry Xu <andiry.xu@amd.com>
Signed-off-by: NSarah Sharp <sarah.a.sharp@linux.intel.com>
上级 f0615c45
...@@ -2594,16 +2594,14 @@ static int hub_set_address(struct usb_device *udev, int devnum) ...@@ -2594,16 +2594,14 @@ static int hub_set_address(struct usb_device *udev, int devnum)
return 0; return 0;
if (udev->state != USB_STATE_DEFAULT) if (udev->state != USB_STATE_DEFAULT)
return -EINVAL; return -EINVAL;
if (hcd->driver->address_device) { if (hcd->driver->address_device)
retval = hcd->driver->address_device(hcd, udev); retval = hcd->driver->address_device(hcd, udev);
} else { else
retval = usb_control_msg(udev, usb_sndaddr0pipe(), retval = usb_control_msg(udev, usb_sndaddr0pipe(),
USB_REQ_SET_ADDRESS, 0, devnum, 0, USB_REQ_SET_ADDRESS, 0, devnum, 0,
NULL, 0, USB_CTRL_SET_TIMEOUT); NULL, 0, USB_CTRL_SET_TIMEOUT);
if (retval == 0)
update_address(udev, devnum);
}
if (retval == 0) { if (retval == 0) {
update_address(udev, devnum);
/* Device now using proper address. */ /* Device now using proper address. */
usb_set_device_state(udev, USB_STATE_ADDRESS); usb_set_device_state(udev, USB_STATE_ADDRESS);
usb_ep0_reinit(udev); usb_ep0_reinit(udev);
...@@ -3097,16 +3095,17 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1, ...@@ -3097,16 +3095,17 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
udev->speed = USB_SPEED_UNKNOWN; udev->speed = USB_SPEED_UNKNOWN;
/* /*
* xHCI needs to issue an address device command later * Set the address.
* in the hub_port_init sequence for SS/HS/FS/LS devices. * 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)) { choose_address(udev);
/* set the address */ if (udev->devnum <= 0) {
choose_address(udev); status = -ENOTCONN; /* Don't retry */
if (udev->devnum <= 0) { goto loop;
status = -ENOTCONN; /* Don't retry */
goto loop;
}
} }
/* reset (non-USB 3.0 devices) and get descriptor */ /* reset (non-USB 3.0 devices) and get descriptor */
......
...@@ -2287,15 +2287,15 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev) ...@@ -2287,15 +2287,15 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev)
* address given back to us by the HC. * address given back to us by the HC.
*/ */
slot_ctx = xhci_get_slot_ctx(xhci, virt_dev->out_ctx); 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 */ /* Zero the input context control for later use */
ctrl_ctx = xhci_get_input_control_ctx(xhci, virt_dev->in_ctx); ctrl_ctx = xhci_get_input_control_ctx(xhci, virt_dev->in_ctx);
ctrl_ctx->add_flags = 0; ctrl_ctx->add_flags = 0;
ctrl_ctx->drop_flags = 0; ctrl_ctx->drop_flags = 0;
xhci_dbg(xhci, "Device address = %d\n", udev->devnum); xhci_dbg(xhci, "Internal device address = %d\n", virt_dev->address);
/* XXX Meh, not sure if anyone else but choose_address uses this. */
set_bit(udev->devnum, udev->bus->devmap.devicemap);
return 0; return 0;
} }
......
...@@ -746,6 +746,8 @@ struct xhci_virt_device { ...@@ -746,6 +746,8 @@ struct xhci_virt_device {
/* Rings saved to ensure old alt settings can be re-instated */ /* Rings saved to ensure old alt settings can be re-instated */
struct xhci_ring **ring_cache; struct xhci_ring **ring_cache;
int num_rings_cached; int num_rings_cached;
/* Store xHC assigned device address */
int address;
#define XHCI_MAX_RINGS_CACHED 31 #define XHCI_MAX_RINGS_CACHED 31
struct xhci_virt_ep eps[31]; struct xhci_virt_ep eps[31];
struct completion cmd_completion; struct completion cmd_completion;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册