xhci: Set slot and ep0 flags for address command.
Matt's AsMedia xHCI host controller was responding with a Context Error to an address device command after a configured device reset. Some sequence of events leads both the slot and endpoint zero add flags cleared to zero, which the AsMedia host doesn't like: [ 223.701839] xhci_hcd 0000:03:00.0: Slot ID 1 Input Context: [ 223.701841] xhci_hcd 0000:03:00.0: @ffff880137b25000 (virt) @ffffc000 (dma) 0x000000 - drop flags [ 223.701843] xhci_hcd 0000:03:00.0: @ffff880137b25004 (virt) @ffffc004 (dma) 0x000000 - add flags [ 223.701846] xhci_hcd 0000:03:00.0: @ffff880137b25008 (virt) @ffffc008 (dma) 0x000000 - rsvd2[0] [ 223.701848] xhci_hcd 0000:03:00.0: @ffff880137b2500c (virt) @ffffc00c (dma) 0x000000 - rsvd2[1] [ 223.701850] xhci_hcd 0000:03:00.0: @ffff880137b25010 (virt) @ffffc010 (dma) 0x000000 - rsvd2[2] [ 223.701852] xhci_hcd 0000:03:00.0: @ffff880137b25014 (virt) @ffffc014 (dma) 0x000000 - rsvd2[3] [ 223.701854] xhci_hcd 0000:03:00.0: @ffff880137b25018 (virt) @ffffc018 (dma) 0x000000 - rsvd2[4] [ 223.701857] xhci_hcd 0000:03:00.0: @ffff880137b2501c (virt) @ffffc01c (dma) 0x000000 - rsvd2[5] [ 223.701858] xhci_hcd 0000:03:00.0: Slot Context: [ 223.701860] xhci_hcd 0000:03:00.0: @ffff880137b25020 (virt) @ffffc020 (dma) 0x8400000 - dev_info [ 223.701862] xhci_hcd 0000:03:00.0: @ffff880137b25024 (virt) @ffffc024 (dma) 0x010000 - dev_info2 [ 223.701864] xhci_hcd 0000:03:00.0: @ffff880137b25028 (virt) @ffffc028 (dma) 0x000000 - tt_info [ 223.701866] xhci_hcd 0000:03:00.0: @ffff880137b2502c (virt) @ffffc02c (dma) 0x000000 - dev_state [ 223.701869] xhci_hcd 0000:03:00.0: @ffff880137b25030 (virt) @ffffc030 (dma) 0x000000 - rsvd[0] [ 223.701871] xhci_hcd 0000:03:00.0: @ffff880137b25034 (virt) @ffffc034 (dma) 0x000000 - rsvd[1] [ 223.701873] xhci_hcd 0000:03:00.0: @ffff880137b25038 (virt) @ffffc038 (dma) 0x000000 - rsvd[2] [ 223.701875] xhci_hcd 0000:03:00.0: @ffff880137b2503c (virt) @ffffc03c (dma) 0x000000 - rsvd[3] [ 223.701877] xhci_hcd 0000:03:00.0: Endpoint 00 Context: [ 223.701879] xhci_hcd 0000:03:00.0: @ffff880137b25040 (virt) @ffffc040 (dma) 0x000000 - ep_info [ 223.701881] xhci_hcd 0000:03:00.0: @ffff880137b25044 (virt) @ffffc044 (dma) 0x2000026 - ep_info2 [ 223.701883] xhci_hcd 0000:03:00.0: @ffff880137b25048 (virt) @ffffc048 (dma) 0xffffe8e0 - deq [ 223.701885] xhci_hcd 0000:03:00.0: @ffff880137b25050 (virt) @ffffc050 (dma) 0x000000 - tx_info [ 223.701887] xhci_hcd 0000:03:00.0: @ffff880137b25054 (virt) @ffffc054 (dma) 0x000000 - rsvd[0] [ 223.701889] xhci_hcd 0000:03:00.0: @ffff880137b25058 (virt) @ffffc058 (dma) 0x000000 - rsvd[1] [ 223.701892] xhci_hcd 0000:03:00.0: @ffff880137b2505c (virt) @ffffc05c (dma) 0x000000 - rsvd[2] ... [ 223.701927] xhci_hcd 0000:03:00.0: // Ding dong! [ 223.701992] xhci_hcd 0000:03:00.0: Setup ERROR: address device command for slot 1. The xHCI spec says that both flags must be set to one for the Address Device command. When the device is first enumerated, xhci_setup_addressable_virt_dev() does set those flags. However, when the device is addressed after it has been reset in the configured state, xhci_setup_addressable_virt_dev() is not called, and xhci_copy_ep0_dequeue_into_input_ctx() is called instead. That function relies on the flags being set up by previous commands, which apparently isn't a good assumption. Move the setting of the flags into the common parent function. This should be queued for stable kernels as old as 2.6.35, since that was the first introduction of xhci_copy_ep0_dequeue_into_input_ctx. Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com> Tested-by: Matt <mdm@iinet.net.au> Cc: stable@vger.kernel.org
This commit is contained in:
parent
f43d623164
commit
d31c285b3a
2 changed files with 4 additions and 6 deletions
|
@ -982,7 +982,6 @@ int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *ud
|
||||||
struct xhci_virt_device *dev;
|
struct xhci_virt_device *dev;
|
||||||
struct xhci_ep_ctx *ep0_ctx;
|
struct xhci_ep_ctx *ep0_ctx;
|
||||||
struct xhci_slot_ctx *slot_ctx;
|
struct xhci_slot_ctx *slot_ctx;
|
||||||
struct xhci_input_control_ctx *ctrl_ctx;
|
|
||||||
u32 port_num;
|
u32 port_num;
|
||||||
struct usb_device *top_dev;
|
struct usb_device *top_dev;
|
||||||
|
|
||||||
|
@ -994,12 +993,8 @@ int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *ud
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
ep0_ctx = xhci_get_ep_ctx(xhci, dev->in_ctx, 0);
|
ep0_ctx = xhci_get_ep_ctx(xhci, dev->in_ctx, 0);
|
||||||
ctrl_ctx = xhci_get_input_control_ctx(xhci, dev->in_ctx);
|
|
||||||
slot_ctx = xhci_get_slot_ctx(xhci, dev->in_ctx);
|
slot_ctx = xhci_get_slot_ctx(xhci, dev->in_ctx);
|
||||||
|
|
||||||
/* 2) New slot context and endpoint 0 context are valid*/
|
|
||||||
ctrl_ctx->add_flags = cpu_to_le32(SLOT_FLAG | EP0_FLAG);
|
|
||||||
|
|
||||||
/* 3) Only the control endpoint is valid - one endpoint context */
|
/* 3) Only the control endpoint is valid - one endpoint context */
|
||||||
slot_ctx->dev_info |= cpu_to_le32(LAST_CTX(1) | udev->route);
|
slot_ctx->dev_info |= cpu_to_le32(LAST_CTX(1) | udev->route);
|
||||||
switch (udev->speed) {
|
switch (udev->speed) {
|
||||||
|
|
|
@ -3504,6 +3504,10 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev)
|
||||||
/* Otherwise, update the control endpoint ring enqueue pointer. */
|
/* Otherwise, update the control endpoint ring enqueue pointer. */
|
||||||
else
|
else
|
||||||
xhci_copy_ep0_dequeue_into_input_ctx(xhci, udev);
|
xhci_copy_ep0_dequeue_into_input_ctx(xhci, udev);
|
||||||
|
ctrl_ctx = xhci_get_input_control_ctx(xhci, virt_dev->in_ctx);
|
||||||
|
ctrl_ctx->add_flags = cpu_to_le32(SLOT_FLAG | EP0_FLAG);
|
||||||
|
ctrl_ctx->drop_flags = 0;
|
||||||
|
|
||||||
xhci_dbg(xhci, "Slot ID %d Input Context:\n", udev->slot_id);
|
xhci_dbg(xhci, "Slot ID %d Input Context:\n", udev->slot_id);
|
||||||
xhci_dbg_ctx(xhci, virt_dev->in_ctx, 2);
|
xhci_dbg_ctx(xhci, virt_dev->in_ctx, 2);
|
||||||
|
|
||||||
|
@ -3585,7 +3589,6 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev)
|
||||||
virt_dev->address = (le32_to_cpu(slot_ctx->dev_state) & DEV_ADDR_MASK)
|
virt_dev->address = (le32_to_cpu(slot_ctx->dev_state) & DEV_ADDR_MASK)
|
||||||
+ 1;
|
+ 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->add_flags = 0;
|
ctrl_ctx->add_flags = 0;
|
||||||
ctrl_ctx->drop_flags = 0;
|
ctrl_ctx->drop_flags = 0;
|
||||||
|
|
||||||
|
|
Reference in a new issue