aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host
diff options
context:
space:
mode:
authorSarah Sharp <sarah.a.sharp@linux.intel.com>2011-11-03 16:06:08 -0400
committerHerton Ronaldo Krzesinski <herton.krzesinski@canonical.com>2011-12-12 08:06:58 -0500
commit9e3a3f6d153b1f6ff13899b2a7cc08c7f824e3b8 (patch)
tree911e50ac84e2315a33f0ab7cfd5828dadd002aee /drivers/usb/host
parentfa089edc067a35e5da8288f0c1bdf4aa705c055d (diff)
xhci: Set slot and ep0 flags for address command.
BugLink: http://bugs.launchpad.net/bugs/897514 commit d31c285b3a71cf9056e6a060de41f37780b0af86 upstream. 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> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> Signed-off-by: Tim Gardner <tim.gardner@canonical.com>
Diffstat (limited to 'drivers/usb/host')
-rw-r--r--drivers/usb/host/xhci-mem.c5
-rw-r--r--drivers/usb/host/xhci.c5
2 files changed, 4 insertions, 6 deletions
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index 104620b3764..ffeee575fd2 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -875,7 +875,6 @@ int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *ud
875 struct xhci_virt_device *dev; 875 struct xhci_virt_device *dev;
876 struct xhci_ep_ctx *ep0_ctx; 876 struct xhci_ep_ctx *ep0_ctx;
877 struct xhci_slot_ctx *slot_ctx; 877 struct xhci_slot_ctx *slot_ctx;
878 struct xhci_input_control_ctx *ctrl_ctx;
879 u32 port_num; 878 u32 port_num;
880 struct usb_device *top_dev; 879 struct usb_device *top_dev;
881 880
@@ -887,12 +886,8 @@ int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *ud
887 return -EINVAL; 886 return -EINVAL;
888 } 887 }
889 ep0_ctx = xhci_get_ep_ctx(xhci, dev->in_ctx, 0); 888 ep0_ctx = xhci_get_ep_ctx(xhci, dev->in_ctx, 0);
890 ctrl_ctx = xhci_get_input_control_ctx(xhci, dev->in_ctx);
891 slot_ctx = xhci_get_slot_ctx(xhci, dev->in_ctx); 889 slot_ctx = xhci_get_slot_ctx(xhci, dev->in_ctx);
892 890
893 /* 2) New slot context and endpoint 0 context are valid*/
894 ctrl_ctx->add_flags = cpu_to_le32(SLOT_FLAG | EP0_FLAG);
895
896 /* 3) Only the control endpoint is valid - one endpoint context */ 891 /* 3) Only the control endpoint is valid - one endpoint context */
897 slot_ctx->dev_info |= cpu_to_le32(LAST_CTX(1) | (u32) udev->route); 892 slot_ctx->dev_info |= cpu_to_le32(LAST_CTX(1) | (u32) udev->route);
898 switch (udev->speed) { 893 switch (udev->speed) {
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index fb61e9d8e17..eb31f9e45ba 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -2875,6 +2875,10 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev)
2875 /* Otherwise, update the control endpoint ring enqueue pointer. */ 2875 /* Otherwise, update the control endpoint ring enqueue pointer. */
2876 else 2876 else
2877 xhci_copy_ep0_dequeue_into_input_ctx(xhci, udev); 2877 xhci_copy_ep0_dequeue_into_input_ctx(xhci, udev);
2878 ctrl_ctx = xhci_get_input_control_ctx(xhci, virt_dev->in_ctx);
2879 ctrl_ctx->add_flags = cpu_to_le32(SLOT_FLAG | EP0_FLAG);
2880 ctrl_ctx->drop_flags = 0;
2881
2878 xhci_dbg(xhci, "Slot ID %d Input Context:\n", udev->slot_id); 2882 xhci_dbg(xhci, "Slot ID %d Input Context:\n", udev->slot_id);
2879 xhci_dbg_ctx(xhci, virt_dev->in_ctx, 2); 2883 xhci_dbg_ctx(xhci, virt_dev->in_ctx, 2);
2880 2884
@@ -2956,7 +2960,6 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev)
2956 virt_dev->address = (le32_to_cpu(slot_ctx->dev_state) & DEV_ADDR_MASK) 2960 virt_dev->address = (le32_to_cpu(slot_ctx->dev_state) & DEV_ADDR_MASK)
2957 + 1; 2961 + 1;
2958 /* Zero the input context control for later use */ 2962 /* Zero the input context control for later use */
2959 ctrl_ctx = xhci_get_input_control_ctx(xhci, virt_dev->in_ctx);
2960 ctrl_ctx->add_flags = 0; 2963 ctrl_ctx->add_flags = 0;
2961 ctrl_ctx->drop_flags = 0; 2964 ctrl_ctx->drop_flags = 0;
2962 2965