diff options
-rw-r--r-- | drivers/usb/host/xhci-ring.c | 29 | ||||
-rw-r--r-- | drivers/usb/host/xhci.h | 9 |
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 | ||
509 | static void td_to_noop(struct xhci_hcd *xhci, struct xhci_ring *ep_ring, | 506 | static 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 |