aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
authorSarah Sharp <sarah.a.sharp@linux.intel.com>2011-02-23 18:46:42 -0500
committerSarah Sharp <sarah.a.sharp@linux.intel.com>2011-03-13 21:23:53 -0400
commitbf161e85fb153c0dd5a95faca73fd6a9d237c389 (patch)
tree950c8f7048754e0603e516b295badb869e832e2d /drivers/usb
parent0c9ffe0f6286a02bf82f8d7fb7274aec2ad977f1 (diff)
xhci: Update internal dequeue pointers after stalls.
When an endpoint stalls, the xHCI driver must move the endpoint ring's dequeue pointer past the stalled transfer. To do that, the driver issues a Set TR Dequeue Pointer command, which will complete some time later. Takashi was having issues with USB 1.1 audio devices that stalled, and his analysis of the code was that the old code would not update the xHCI driver's ring dequeue pointer after the command completes. However, the dequeue pointer is set in xhci_find_new_dequeue_state(), just before the set command is issued to the hardware. Setting the dequeue pointer before the Set TR Dequeue Pointer command completes is a dangerous thing to do, since the xHCI hardware can fail the command. Instead, store the new dequeue pointer in the xhci_virt_ep structure, and update the ring's dequeue pointer when the Set TR dequeue pointer command completes. While we're at it, make sure we can't queue another Set TR Dequeue Command while the first one is still being processed. This just won't work with the internal xHCI state code. I'm still not sure if this is the right thing to do, since we might have a case where a driver queues multiple URBs to a control ring, one of the URBs Stalls, and then the driver tries to cancel the second URB. There may be a race condition there where the xHCI driver might try to issue multiple Set TR Dequeue Pointer commands, but I would have to think very hard about how the Stop Endpoint and cancellation code works. Keep the fix simple until when/if we run into that case. This patch should be queued to kernels all the way back to 2.6.31. Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com> Tested-by: Takashi Iwai <tiwai@suse.de> Cc: stable@kernel.org
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/host/xhci-ring.c29
-rw-r--r--drivers/usb/host/xhci.h9
2 files changed, 35 insertions, 3 deletions
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index bd0f2343ef9c..3577cd663ebc 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -501,9 +501,6 @@ void xhci_find_new_dequeue_state(struct xhci_hcd *xhci,
501 addr = xhci_trb_virt_to_dma(state->new_deq_seg, state->new_deq_ptr); 501 addr = xhci_trb_virt_to_dma(state->new_deq_seg, state->new_deq_ptr);
502 xhci_dbg(xhci, "New dequeue pointer = 0x%llx (DMA)\n", 502 xhci_dbg(xhci, "New dequeue pointer = 0x%llx (DMA)\n",
503 (unsigned long long) addr); 503 (unsigned long long) addr);
504 xhci_dbg(xhci, "Setting dequeue pointer in internal ring state.\n");
505 ep_ring->dequeue = state->new_deq_ptr;
506 ep_ring->deq_seg = state->new_deq_seg;
507} 504}
508 505
509static void td_to_noop(struct xhci_hcd *xhci, struct xhci_ring *ep_ring, 506static void td_to_noop(struct xhci_hcd *xhci, struct xhci_ring *ep_ring,
@@ -945,9 +942,26 @@ static void handle_set_deq_completion(struct xhci_hcd *xhci,
945 } else { 942 } else {
946 xhci_dbg(xhci, "Successful Set TR Deq Ptr cmd, deq = @%08llx\n", 943 xhci_dbg(xhci, "Successful Set TR Deq Ptr cmd, deq = @%08llx\n",
947 ep_ctx->deq); 944 ep_ctx->deq);
945 if (xhci_trb_virt_to_dma(dev->eps[ep_index].queued_deq_seg,
946 dev->eps[ep_index].queued_deq_ptr) ==
947 (ep_ctx->deq & ~(EP_CTX_CYCLE_MASK))) {
948 /* Update the ring's dequeue segment and dequeue pointer
949 * to reflect the new position.
950 */
951 ep_ring->deq_seg = dev->eps[ep_index].queued_deq_seg;
952 ep_ring->dequeue = dev->eps[ep_index].queued_deq_ptr;
953 } else {
954 xhci_warn(xhci, "Mismatch between completed Set TR Deq "
955 "Ptr command & xHCI internal state.\n");
956 xhci_warn(xhci, "ep deq seg = %p, deq ptr = %p\n",
957 dev->eps[ep_index].queued_deq_seg,
958 dev->eps[ep_index].queued_deq_ptr);
959 }
948 } 960 }
949 961
950 dev->eps[ep_index].ep_state &= ~SET_DEQ_PENDING; 962 dev->eps[ep_index].ep_state &= ~SET_DEQ_PENDING;
963 dev->eps[ep_index].queued_deq_seg = NULL;
964 dev->eps[ep_index].queued_deq_ptr = NULL;
951 /* Restart any rings with pending URBs */ 965 /* Restart any rings with pending URBs */
952 ring_doorbell_for_active_rings(xhci, slot_id, ep_index); 966 ring_doorbell_for_active_rings(xhci, slot_id, ep_index);
953} 967}
@@ -3283,6 +3297,7 @@ static int queue_set_tr_deq(struct xhci_hcd *xhci, int slot_id,
3283 u32 trb_ep_index = EP_ID_FOR_TRB(ep_index); 3297 u32 trb_ep_index = EP_ID_FOR_TRB(ep_index);
3284 u32 trb_stream_id = STREAM_ID_FOR_TRB(stream_id); 3298 u32 trb_stream_id = STREAM_ID_FOR_TRB(stream_id);
3285 u32 type = TRB_TYPE(TRB_SET_DEQ); 3299 u32 type = TRB_TYPE(TRB_SET_DEQ);
3300 struct xhci_virt_ep *ep;
3286 3301
3287 addr = xhci_trb_virt_to_dma(deq_seg, deq_ptr); 3302 addr = xhci_trb_virt_to_dma(deq_seg, deq_ptr);
3288 if (addr == 0) { 3303 if (addr == 0) {
@@ -3291,6 +3306,14 @@ static int queue_set_tr_deq(struct xhci_hcd *xhci, int slot_id,
3291 deq_seg, deq_ptr); 3306 deq_seg, deq_ptr);
3292 return 0; 3307 return 0;
3293 } 3308 }
3309 ep = &xhci->devs[slot_id]->eps[ep_index];
3310 if ((ep->ep_state & SET_DEQ_PENDING)) {
3311 xhci_warn(xhci, "WARN Cannot submit Set TR Deq Ptr\n");
3312 xhci_warn(xhci, "A Set TR Deq Ptr command is pending.\n");
3313 return 0;
3314 }
3315 ep->queued_deq_seg = deq_seg;
3316 ep->queued_deq_ptr = deq_ptr;
3294 return queue_command(xhci, lower_32_bits(addr) | cycle_state, 3317 return queue_command(xhci, lower_32_bits(addr) | cycle_state,
3295 upper_32_bits(addr), trb_stream_id, 3318 upper_32_bits(addr), trb_stream_id,
3296 trb_slot_id | trb_ep_index | type, false); 3319 trb_slot_id | trb_ep_index | type, false);
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index e69f1cdf4b5b..7aca6b16e986 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -644,6 +644,9 @@ struct xhci_ep_ctx {
644#define AVG_TRB_LENGTH_FOR_EP(p) ((p) & 0xffff) 644#define AVG_TRB_LENGTH_FOR_EP(p) ((p) & 0xffff)
645#define MAX_ESIT_PAYLOAD_FOR_EP(p) (((p) & 0xffff) << 16) 645#define MAX_ESIT_PAYLOAD_FOR_EP(p) (((p) & 0xffff) << 16)
646 646
647/* deq bitmasks */
648#define EP_CTX_CYCLE_MASK (1 << 0)
649
647 650
648/** 651/**
649 * struct xhci_input_control_context 652 * struct xhci_input_control_context
@@ -746,6 +749,12 @@ struct xhci_virt_ep {
746 struct timer_list stop_cmd_timer; 749 struct timer_list stop_cmd_timer;
747 int stop_cmds_pending; 750 int stop_cmds_pending;
748 struct xhci_hcd *xhci; 751 struct xhci_hcd *xhci;
752 /* Dequeue pointer and dequeue segment for a submitted Set TR Dequeue
753 * command. We'll need to update the ring's dequeue segment and dequeue
754 * pointer after the command completes.
755 */
756 struct xhci_segment *queued_deq_seg;
757 union xhci_trb *queued_deq_ptr;
749 /* 758 /*
750 * Sometimes the xHC can not process isochronous endpoint ring quickly 759 * Sometimes the xHC can not process isochronous endpoint ring quickly
751 * enough, and it will miss some isoc tds on the ring and generate 760 * enough, and it will miss some isoc tds on the ring and generate