aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/xhci.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/host/xhci.c')
-rw-r--r--drivers/usb/host/xhci.c30
1 files changed, 29 insertions, 1 deletions
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 1f7d35b3a937..bf7da58b5751 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -183,7 +183,11 @@ int xhci_reset(struct xhci_hcd *xhci)
xhci_dbg_trace(xhci, trace_xhci_dbg_init, "// Reset the HC");
command = readl(&xhci->op_regs->command);
+#ifdef CONFIG_USB_DWC3_OTG
+ command |= CMD_LRESET;
+#else
command |= CMD_RESET;
+#endif
writel(command, &xhci->op_regs->command);
/* Existing Intel xHCI controllers require a delay of 1 mS,
@@ -197,7 +201,12 @@ int xhci_reset(struct xhci_hcd *xhci)
udelay(1000);
ret = xhci_handshake(&xhci->op_regs->command,
- CMD_RESET, 0, 10 * 1000 * 1000);
+#ifdef CONFIG_USB_DWC3_OTG
+ CMD_LRESET,
+#else
+ CMD_RESET,
+#endif
+ 0, 10 * 1000 * 1000);
if (ret)
return ret;
@@ -718,6 +727,12 @@ static void xhci_stop(struct usb_hcd *hcd)
/* Only halt host and free memory after both hcds are removed */
if (!usb_hcd_is_primary_hcd(hcd)) {
+ /* Remove shared_hcd if no otg ports are present */
+ if (!hcd->self.otg_port) {
+ /* usb core will free this hcd shortly, unset pointer */
+ xhci->shared_hcd = NULL;
+ }
+
mutex_unlock(&xhci->mutex);
return;
}
@@ -1670,8 +1685,21 @@ static int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
goto err_giveback;
}
+ ep_index = xhci_get_endpoint_index(&urb->ep->desc);
+ ep = &xhci->devs[urb->dev->slot_id]->eps[ep_index];
+ ep_ring = xhci_urb_to_transfer_ring(xhci, urb);
+ if (!ep_ring) {
+ ret = -EINVAL;
+ goto done;
+ }
+
+ /* Delete the stream timer */
+ if ((xhci->quirks & XHCI_STREAM_QUIRK) && (urb->stream_id > 0))
+ del_timer(&ep_ring->stream_timer);
+
i = urb_priv->num_tds_done;
if (i < urb_priv->num_tds)
+
xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb,
"Cancel URB %p, dev %s, ep 0x%x, "
"starting at offset 0x%llx",