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.c36
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
607static 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
607static void handle_cmd_completion(struct xhci_hcd *xhci, 627static 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
1684int 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}