summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSarah Sharp <sarah.a.sharp@linux.intel.com>2009-11-11 10:28:44 -0800
committerGreg Kroah-Hartman <gregkh@suse.de>2009-12-11 11:55:23 -0800
commitbcef3fd57019e5fc0c8df402b040a52826422a4b (patch)
treeab98ded86bd3bcfc2f03629d421bcdfd8462c13a
parent5ad6a529c28db36010ec56c5ee8120addc712b51 (diff)
downloadblackbird-op-linux-bcef3fd57019e5fc0c8df402b040a52826422a4b.tar.gz
blackbird-op-linux-bcef3fd57019e5fc0c8df402b040a52826422a4b.zip
USB: xhci: Handle errors that cause endpoint halts.
The xHCI 0.95 and 0.96 specification defines several transfer buffer request completion codes that indicate a USB transaction error occurred. When a stall, babble, transaction, or split transaction error completion code is set, the xHCI has halted that endpoint ring. Software must issue a Reset Endpoint command and a Set Transfer Ring Dequeue Pointer command to clean up the halted ring. The USB device driver is supposed to call into usb_reset_endpoint() when an endpoint stalls. That calls into the xHCI driver to issue the proper commands. However, drivers don't call that function for the other errors that cause the xHC to halt the endpoint ring. If a babble, transaction, or split transaction error occurs, check if the endpoint context reports a halted condition, and clean up the endpoint ring if it does. Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r--drivers/usb/host/xhci-ring.c79
1 files changed, 60 insertions, 19 deletions
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 1549b9ceb91a..2e346334a363 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -1037,6 +1037,45 @@ struct xhci_segment *trb_in_td(struct xhci_segment *start_seg,
return 0;
}
+static void xhci_cleanup_halted_endpoint(struct xhci_hcd *xhci,
+ unsigned int slot_id, unsigned int ep_index,
+ struct xhci_td *td, union xhci_trb *event_trb)
+{
+ struct xhci_virt_ep *ep = &xhci->devs[slot_id]->eps[ep_index];
+ ep->ep_state |= EP_HALTED;
+ ep->stopped_td = td;
+ ep->stopped_trb = event_trb;
+ xhci_queue_reset_ep(xhci, slot_id, ep_index);
+ xhci_cleanup_stalled_ring(xhci, td->urb->dev, ep_index);
+ xhci_ring_cmd_db(xhci);
+}
+
+/* Check if an error has halted the endpoint ring. The class driver will
+ * cleanup the halt for a non-default control endpoint if we indicate a stall.
+ * However, a babble and other errors also halt the endpoint ring, and the class
+ * driver won't clear the halt in that case, so we need to issue a Set Transfer
+ * Ring Dequeue Pointer command manually.
+ */
+static int xhci_requires_manual_halt_cleanup(struct xhci_hcd *xhci,
+ struct xhci_ep_ctx *ep_ctx,
+ unsigned int trb_comp_code)
+{
+ /* TRB completion codes that may require a manual halt cleanup */
+ if (trb_comp_code == COMP_TX_ERR ||
+ trb_comp_code == COMP_BABBLE ||
+ trb_comp_code == COMP_SPLIT_ERR)
+ /* The 0.96 spec says a babbling control endpoint
+ * is not halted. The 0.96 spec says it is. Some HW
+ * claims to be 0.95 compliant, but it halts the control
+ * endpoint anyway. Check if a babble halted the
+ * endpoint.
+ */
+ if ((ep_ctx->ep_info & EP_STATE_MASK) == EP_STATE_HALTED)
+ return 1;
+
+ return 0;
+}
+
/*
* If this function returns an error condition, it means it got a Transfer
* event with a corrupted Slot ID, Endpoint ID, or TRB DMA address.
@@ -1191,15 +1230,14 @@ static int handle_tx_event(struct xhci_hcd *xhci,
else
status = 0;
break;
- case COMP_BABBLE:
- /* The 0.96 spec says a babbling control endpoint
- * is not halted. The 0.96 spec says it is. Some HW
- * claims to be 0.95 compliant, but it halts the control
- * endpoint anyway. Check if a babble halted the
- * endpoint.
- */
- if (ep_ctx->ep_info != EP_STATE_HALTED)
+
+ default:
+ if (!xhci_requires_manual_halt_cleanup(xhci,
+ ep_ctx, trb_comp_code))
break;
+ xhci_dbg(xhci, "TRB error code %u, "
+ "halted endpoint index = %u\n",
+ trb_comp_code, ep_index);
/* else fall through */
case COMP_STALL:
/* Did we transfer part of the data (middle) phase? */
@@ -1211,15 +1249,9 @@ static int handle_tx_event(struct xhci_hcd *xhci,
else
td->urb->actual_length = 0;
- ep->stopped_td = td;
- ep->stopped_trb = event_trb;
- xhci_queue_reset_ep(xhci, slot_id, ep_index);
- xhci_cleanup_stalled_ring(xhci, td->urb->dev, ep_index);
- xhci_ring_cmd_db(xhci);
+ xhci_cleanup_halted_endpoint(xhci,
+ slot_id, ep_index, td, event_trb);
goto td_cleanup;
- default:
- /* Others already handled above */
- break;
}
/*
* Did we transfer any data, despite the errors that might have
@@ -1357,16 +1389,25 @@ static int handle_tx_event(struct xhci_hcd *xhci,
ep->stopped_td = td;
ep->stopped_trb = event_trb;
} else {
- if (trb_comp_code == COMP_STALL ||
- trb_comp_code == COMP_BABBLE) {
+ if (trb_comp_code == COMP_STALL) {
/* The transfer is completed from the driver's
* perspective, but we need to issue a set dequeue
* command for this stalled endpoint to move the dequeue
* pointer past the TD. We can't do that here because
- * the halt condition must be cleared first.
+ * the halt condition must be cleared first. Let the
+ * USB class driver clear the stall later.
*/
ep->stopped_td = td;
ep->stopped_trb = event_trb;
+ } else if (xhci_requires_manual_halt_cleanup(xhci,
+ ep_ctx, trb_comp_code)) {
+ /* Other types of errors halt the endpoint, but the
+ * class driver doesn't call usb_reset_endpoint() unless
+ * the error is -EPIPE. Clear the halted status in the
+ * xHCI hardware manually.
+ */
+ xhci_cleanup_halted_endpoint(xhci,
+ slot_id, ep_index, td, event_trb);
} else {
/* Update ring dequeue pointer */
while (ep_ring->dequeue != td->last_trb)
OpenPOWER on IntegriCloud