aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorHans de Goede <hdegoede@redhat.com>2013-10-03 18:29:49 -0400
committerSarah Sharp <sarah.a.sharp@linux.intel.com>2014-03-04 18:38:02 -0500
commit9aad95e292f58d00aa0f2e30c7f7dafd7fc7491c (patch)
treeb0dda7e01959c435e0e4f08bb812e4f69bde3657 /drivers
parent95241dbdf8281ece1355b8673b882d6a182f3c7d (diff)
xhci: For streams the dequeue ptr must be read from the stream ctx
This fixes TR dequeue validation failing on Intel XHCI controllers with the following warning: Mismatch between completed Set TR Deq Ptr command & xHCI internal state. Interestingly enough reading the deq ptr from the ep ctx after a TR Deq Ptr command does work on a Nec XHCI controller, it seems the Nec writes the ptr to both the ep and stream contexts when streams are used. Signed-off-by: Hans de Goede <hdegoede@redhat.com> Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/usb/host/xhci-ring.c22
-rw-r--r--drivers/usb/host/xhci.h1
2 files changed, 16 insertions, 7 deletions
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index f17e5c8c1cb3..b3d27e6467ea 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -1081,12 +1081,14 @@ static void xhci_handle_cmd_set_deq(struct xhci_hcd *xhci, int slot_id,
1081 unsigned int stream_id; 1081 unsigned int stream_id;
1082 struct xhci_ring *ep_ring; 1082 struct xhci_ring *ep_ring;
1083 struct xhci_virt_device *dev; 1083 struct xhci_virt_device *dev;
1084 struct xhci_virt_ep *ep;
1084 struct xhci_ep_ctx *ep_ctx; 1085 struct xhci_ep_ctx *ep_ctx;
1085 struct xhci_slot_ctx *slot_ctx; 1086 struct xhci_slot_ctx *slot_ctx;
1086 1087
1087 ep_index = TRB_TO_EP_INDEX(le32_to_cpu(trb->generic.field[3])); 1088 ep_index = TRB_TO_EP_INDEX(le32_to_cpu(trb->generic.field[3]));
1088 stream_id = TRB_TO_STREAM_ID(le32_to_cpu(trb->generic.field[2])); 1089 stream_id = TRB_TO_STREAM_ID(le32_to_cpu(trb->generic.field[2]));
1089 dev = xhci->devs[slot_id]; 1090 dev = xhci->devs[slot_id];
1091 ep = &dev->eps[ep_index];
1090 1092
1091 ep_ring = xhci_stream_id_to_ring(dev, ep_index, stream_id); 1093 ep_ring = xhci_stream_id_to_ring(dev, ep_index, stream_id);
1092 if (!ep_ring) { 1094 if (!ep_ring) {
@@ -1134,12 +1136,19 @@ static void xhci_handle_cmd_set_deq(struct xhci_hcd *xhci, int slot_id,
1134 * cancelling URBs, which might not be an error... 1136 * cancelling URBs, which might not be an error...
1135 */ 1137 */
1136 } else { 1138 } else {
1139 u64 deq;
1140 /* 4.6.10 deq ptr is written to the stream ctx for streams */
1141 if (ep->ep_state & EP_HAS_STREAMS) {
1142 struct xhci_stream_ctx *ctx =
1143 &ep->stream_info->stream_ctx_array[stream_id];
1144 deq = le64_to_cpu(ctx->stream_ring) & SCTX_DEQ_MASK;
1145 } else {
1146 deq = le64_to_cpu(ep_ctx->deq) & ~EP_CTX_CYCLE_MASK;
1147 }
1137 xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb, 1148 xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb,
1138 "Successful Set TR Deq Ptr cmd, deq = @%08llx", 1149 "Successful Set TR Deq Ptr cmd, deq = @%08llx", deq);
1139 le64_to_cpu(ep_ctx->deq)); 1150 if (xhci_trb_virt_to_dma(ep->queued_deq_seg,
1140 if (xhci_trb_virt_to_dma(dev->eps[ep_index].queued_deq_seg, 1151 ep->queued_deq_ptr) == deq) {
1141 dev->eps[ep_index].queued_deq_ptr) ==
1142 (le64_to_cpu(ep_ctx->deq) & ~(EP_CTX_CYCLE_MASK))) {
1143 /* Update the ring's dequeue segment and dequeue pointer 1152 /* Update the ring's dequeue segment and dequeue pointer
1144 * to reflect the new position. 1153 * to reflect the new position.
1145 */ 1154 */
@@ -1148,8 +1157,7 @@ static void xhci_handle_cmd_set_deq(struct xhci_hcd *xhci, int slot_id,
1148 } else { 1157 } else {
1149 xhci_warn(xhci, "Mismatch between completed Set TR Deq Ptr command & xHCI internal state.\n"); 1158 xhci_warn(xhci, "Mismatch between completed Set TR Deq Ptr command & xHCI internal state.\n");
1150 xhci_warn(xhci, "ep deq seg = %p, deq ptr = %p\n", 1159 xhci_warn(xhci, "ep deq seg = %p, deq ptr = %p\n",
1151 dev->eps[ep_index].queued_deq_seg, 1160 ep->queued_deq_seg, ep->queued_deq_ptr);
1152 dev->eps[ep_index].queued_deq_ptr);
1153 } 1161 }
1154 } 1162 }
1155 1163
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index 2c77bf7ab9e5..d280e9213d08 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -703,6 +703,7 @@ struct xhci_ep_ctx {
703 703
704/* deq bitmasks */ 704/* deq bitmasks */
705#define EP_CTX_CYCLE_MASK (1 << 0) 705#define EP_CTX_CYCLE_MASK (1 << 0)
706#define SCTX_DEQ_MASK (~0xfL)
706 707
707 708
708/** 709/**