aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/xhci-ring.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/host/xhci-ring.c')
-rw-r--r--drivers/usb/host/xhci-ring.c61
1 files changed, 54 insertions, 7 deletions
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index c831194b0966..35374ddc31c1 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -469,7 +469,6 @@ void xhci_queue_new_dequeue_state(struct xhci_hcd *xhci,
469 * ring running. 469 * ring running.
470 */ 470 */
471 ep_ring->state |= SET_DEQ_PENDING; 471 ep_ring->state |= SET_DEQ_PENDING;
472 xhci_ring_cmd_db(xhci);
473} 472}
474 473
475/* 474/*
@@ -538,6 +537,7 @@ static void handle_stopped_endpoint(struct xhci_hcd *xhci,
538 if (deq_state.new_deq_ptr && deq_state.new_deq_seg) { 537 if (deq_state.new_deq_ptr && deq_state.new_deq_seg) {
539 xhci_queue_new_dequeue_state(xhci, ep_ring, 538 xhci_queue_new_dequeue_state(xhci, ep_ring,
540 slot_id, ep_index, &deq_state); 539 slot_id, ep_index, &deq_state);
540 xhci_ring_cmd_db(xhci);
541 } else { 541 } else {
542 /* Otherwise just ring the doorbell to restart the ring */ 542 /* Otherwise just ring the doorbell to restart the ring */
543 ring_ep_doorbell(xhci, slot_id, ep_index); 543 ring_ep_doorbell(xhci, slot_id, ep_index);
@@ -651,18 +651,31 @@ static void handle_reset_ep_completion(struct xhci_hcd *xhci,
651{ 651{
652 int slot_id; 652 int slot_id;
653 unsigned int ep_index; 653 unsigned int ep_index;
654 struct xhci_ring *ep_ring;
654 655
655 slot_id = TRB_TO_SLOT_ID(trb->generic.field[3]); 656 slot_id = TRB_TO_SLOT_ID(trb->generic.field[3]);
656 ep_index = TRB_TO_EP_INDEX(trb->generic.field[3]); 657 ep_index = TRB_TO_EP_INDEX(trb->generic.field[3]);
658 ep_ring = xhci->devs[slot_id]->ep_rings[ep_index];
657 /* This command will only fail if the endpoint wasn't halted, 659 /* This command will only fail if the endpoint wasn't halted,
658 * but we don't care. 660 * but we don't care.
659 */ 661 */
660 xhci_dbg(xhci, "Ignoring reset ep completion code of %u\n", 662 xhci_dbg(xhci, "Ignoring reset ep completion code of %u\n",
661 (unsigned int) GET_COMP_CODE(event->status)); 663 (unsigned int) GET_COMP_CODE(event->status));
662 664
663 /* Clear our internal halted state and restart the ring */ 665 /* HW with the reset endpoint quirk needs to have a configure endpoint
664 xhci->devs[slot_id]->ep_rings[ep_index]->state &= ~EP_HALTED; 666 * command complete before the endpoint can be used. Queue that here
665 ring_ep_doorbell(xhci, slot_id, ep_index); 667 * because the HW can't handle two commands being queued in a row.
668 */
669 if (xhci->quirks & XHCI_RESET_EP_QUIRK) {
670 xhci_dbg(xhci, "Queueing configure endpoint command\n");
671 xhci_queue_configure_endpoint(xhci,
672 xhci->devs[slot_id]->in_ctx->dma, slot_id);
673 xhci_ring_cmd_db(xhci);
674 } else {
675 /* Clear our internal halted state and restart the ring */
676 ep_ring->state &= ~EP_HALTED;
677 ring_ep_doorbell(xhci, slot_id, ep_index);
678 }
666} 679}
667 680
668static void handle_cmd_completion(struct xhci_hcd *xhci, 681static void handle_cmd_completion(struct xhci_hcd *xhci,
@@ -671,6 +684,10 @@ static void handle_cmd_completion(struct xhci_hcd *xhci,
671 int slot_id = TRB_TO_SLOT_ID(event->flags); 684 int slot_id = TRB_TO_SLOT_ID(event->flags);
672 u64 cmd_dma; 685 u64 cmd_dma;
673 dma_addr_t cmd_dequeue_dma; 686 dma_addr_t cmd_dequeue_dma;
687 struct xhci_input_control_ctx *ctrl_ctx;
688 unsigned int ep_index;
689 struct xhci_ring *ep_ring;
690 unsigned int ep_state;
674 691
675 cmd_dma = event->cmd_trb; 692 cmd_dma = event->cmd_trb;
676 cmd_dequeue_dma = xhci_trb_virt_to_dma(xhci->cmd_ring->deq_seg, 693 cmd_dequeue_dma = xhci_trb_virt_to_dma(xhci->cmd_ring->deq_seg,
@@ -698,8 +715,39 @@ static void handle_cmd_completion(struct xhci_hcd *xhci,
698 xhci_free_virt_device(xhci, slot_id); 715 xhci_free_virt_device(xhci, slot_id);
699 break; 716 break;
700 case TRB_TYPE(TRB_CONFIG_EP): 717 case TRB_TYPE(TRB_CONFIG_EP):
701 xhci->devs[slot_id]->cmd_status = GET_COMP_CODE(event->status); 718 /*
702 complete(&xhci->devs[slot_id]->cmd_completion); 719 * Configure endpoint commands can come from the USB core
720 * configuration or alt setting changes, or because the HW
721 * needed an extra configure endpoint command after a reset
722 * endpoint command. In the latter case, the xHCI driver is
723 * not waiting on the configure endpoint command.
724 */
725 ctrl_ctx = xhci_get_input_control_ctx(xhci,
726 xhci->devs[slot_id]->in_ctx);
727 /* Input ctx add_flags are the endpoint index plus one */
728 ep_index = xhci_last_valid_endpoint(ctrl_ctx->add_flags) - 1;
729 ep_ring = xhci->devs[slot_id]->ep_rings[ep_index];
730 if (!ep_ring) {
731 /* This must have been an initial configure endpoint */
732 xhci->devs[slot_id]->cmd_status =
733 GET_COMP_CODE(event->status);
734 complete(&xhci->devs[slot_id]->cmd_completion);
735 break;
736 }
737 ep_state = ep_ring->state;
738 xhci_dbg(xhci, "Completed config ep cmd - last ep index = %d, "
739 "state = %d\n", ep_index, ep_state);
740 if (xhci->quirks & XHCI_RESET_EP_QUIRK &&
741 ep_state & EP_HALTED) {
742 /* Clear our internal halted state and restart ring */
743 xhci->devs[slot_id]->ep_rings[ep_index]->state &=
744 ~EP_HALTED;
745 ring_ep_doorbell(xhci, slot_id, ep_index);
746 } else {
747 xhci->devs[slot_id]->cmd_status =
748 GET_COMP_CODE(event->status);
749 complete(&xhci->devs[slot_id]->cmd_completion);
750 }
703 break; 751 break;
704 case TRB_TYPE(TRB_EVAL_CONTEXT): 752 case TRB_TYPE(TRB_EVAL_CONTEXT):
705 xhci->devs[slot_id]->cmd_status = GET_COMP_CODE(event->status); 753 xhci->devs[slot_id]->cmd_status = GET_COMP_CODE(event->status);
@@ -958,7 +1006,6 @@ static int handle_tx_event(struct xhci_hcd *xhci,
958 xhci_queue_reset_ep(xhci, slot_id, ep_index); 1006 xhci_queue_reset_ep(xhci, slot_id, ep_index);
959 xhci_cleanup_stalled_ring(xhci, 1007 xhci_cleanup_stalled_ring(xhci,
960 td->urb->dev, 1008 td->urb->dev,
961 td->urb->ep,
962 ep_index, ep_ring); 1009 ep_index, ep_ring);
963 xhci_ring_cmd_db(xhci); 1010 xhci_ring_cmd_db(xhci);
964 goto td_cleanup; 1011 goto td_cleanup;