diff options
Diffstat (limited to 'drivers/usb/host/xhci-ring.c')
-rw-r--r-- | drivers/usb/host/xhci-ring.c | 36 |
1 files changed, 35 insertions, 1 deletions
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index d5b952997423..d672ba14ff80 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c | |||
@@ -279,7 +279,8 @@ static void ring_ep_doorbell(struct xhci_hcd *xhci, | |||
279 | /* Don't ring the doorbell for this endpoint if there are pending | 279 | /* Don't ring the doorbell for this endpoint if there are pending |
280 | * cancellations because the we don't want to interrupt processing. | 280 | * cancellations because the we don't want to interrupt processing. |
281 | */ | 281 | */ |
282 | if (!ep_ring->cancels_pending && !(ep_ring->state & SET_DEQ_PENDING)) { | 282 | if (!ep_ring->cancels_pending && !(ep_ring->state & SET_DEQ_PENDING) |
283 | && !(ep_ring->state & EP_HALTED)) { | ||
283 | field = xhci_readl(xhci, db_addr) & DB_MASK; | 284 | field = xhci_readl(xhci, db_addr) & DB_MASK; |
284 | xhci_writel(xhci, field | EPI_TO_DB(ep_index), db_addr); | 285 | xhci_writel(xhci, field | EPI_TO_DB(ep_index), db_addr); |
285 | /* Flush PCI posted writes - FIXME Matthew Wilcox says this | 286 | /* Flush PCI posted writes - FIXME Matthew Wilcox says this |
@@ -603,6 +604,25 @@ static void handle_set_deq_completion(struct xhci_hcd *xhci, | |||
603 | ring_ep_doorbell(xhci, slot_id, ep_index); | 604 | ring_ep_doorbell(xhci, slot_id, ep_index); |
604 | } | 605 | } |
605 | 606 | ||
607 | static void handle_reset_ep_completion(struct xhci_hcd *xhci, | ||
608 | struct xhci_event_cmd *event, | ||
609 | union xhci_trb *trb) | ||
610 | { | ||
611 | int slot_id; | ||
612 | unsigned int ep_index; | ||
613 | |||
614 | slot_id = TRB_TO_SLOT_ID(trb->generic.field[3]); | ||
615 | ep_index = TRB_TO_EP_INDEX(trb->generic.field[3]); | ||
616 | /* This command will only fail if the endpoint wasn't halted, | ||
617 | * but we don't care. | ||
618 | */ | ||
619 | xhci_dbg(xhci, "Ignoring reset ep completion code of %u\n", | ||
620 | (unsigned int) GET_COMP_CODE(event->status)); | ||
621 | |||
622 | /* Clear our internal halted state and restart the ring */ | ||
623 | xhci->devs[slot_id]->ep_rings[ep_index]->state &= ~EP_HALTED; | ||
624 | ring_ep_doorbell(xhci, slot_id, ep_index); | ||
625 | } | ||
606 | 626 | ||
607 | static void handle_cmd_completion(struct xhci_hcd *xhci, | 627 | static void handle_cmd_completion(struct xhci_hcd *xhci, |
608 | struct xhci_event_cmd *event) | 628 | struct xhci_event_cmd *event) |
@@ -653,6 +673,9 @@ static void handle_cmd_completion(struct xhci_hcd *xhci, | |||
653 | case TRB_TYPE(TRB_CMD_NOOP): | 673 | case TRB_TYPE(TRB_CMD_NOOP): |
654 | ++xhci->noops_handled; | 674 | ++xhci->noops_handled; |
655 | break; | 675 | break; |
676 | case TRB_TYPE(TRB_RESET_EP): | ||
677 | handle_reset_ep_completion(xhci, event, xhci->cmd_ring->dequeue); | ||
678 | break; | ||
656 | default: | 679 | default: |
657 | /* Skip over unknown commands on the event ring */ | 680 | /* Skip over unknown commands on the event ring */ |
658 | xhci->error_bitmask |= 1 << 6; | 681 | xhci->error_bitmask |= 1 << 6; |
@@ -823,6 +846,7 @@ static int handle_tx_event(struct xhci_hcd *xhci, | |||
823 | break; | 846 | break; |
824 | case COMP_STALL: | 847 | case COMP_STALL: |
825 | xhci_warn(xhci, "WARN: Stalled endpoint\n"); | 848 | xhci_warn(xhci, "WARN: Stalled endpoint\n"); |
849 | ep_ring->state |= EP_HALTED; | ||
826 | status = -EPIPE; | 850 | status = -EPIPE; |
827 | break; | 851 | break; |
828 | case COMP_TRB_ERR: | 852 | case COMP_TRB_ERR: |
@@ -1656,3 +1680,13 @@ static int queue_set_tr_deq(struct xhci_hcd *xhci, int slot_id, | |||
1656 | return queue_command(xhci, (u32) addr | cycle_state, 0, 0, | 1680 | return queue_command(xhci, (u32) addr | cycle_state, 0, 0, |
1657 | trb_slot_id | trb_ep_index | type); | 1681 | trb_slot_id | trb_ep_index | type); |
1658 | } | 1682 | } |
1683 | |||
1684 | int xhci_queue_reset_ep(struct xhci_hcd *xhci, int slot_id, | ||
1685 | unsigned int ep_index) | ||
1686 | { | ||
1687 | u32 trb_slot_id = SLOT_ID_FOR_TRB(slot_id); | ||
1688 | u32 trb_ep_index = EP_ID_FOR_TRB(ep_index); | ||
1689 | u32 type = TRB_TYPE(TRB_RESET_EP); | ||
1690 | |||
1691 | return queue_command(xhci, 0, 0, 0, trb_slot_id | trb_ep_index | type); | ||
1692 | } | ||