Merge remote-tracking branches 'asoc/fix/amd', 'asoc/fix/arizona', 'asoc/fix/dpcm...
[cascardo/linux.git] / drivers / usb / host / xhci.c
index 3f91270..0c8087d 100644 (file)
@@ -31,6 +31,7 @@
 
 #include "xhci.h"
 #include "xhci-trace.h"
+#include "xhci-mtk.h"
 
 #define DRIVER_AUTHOR "Sarah Sharp"
 #define DRIVER_DESC "'eXtensible' Host Controller (xHC) Driver"
@@ -634,7 +635,11 @@ int xhci_run(struct usb_hcd *hcd)
                        "// Set the interrupt modulation register");
        temp = readl(&xhci->ir_set->irq_control);
        temp &= ~ER_IRQ_INTERVAL_MASK;
-       temp |= (u32) 160;
+       /*
+        * the increment interval is 8 times as much as that defined
+        * in xHCI spec on MTK's controller
+        */
+       temp |= (u32) ((xhci->quirks & XHCI_MTK_HOST) ? 20 : 160);
        writel(temp, &xhci->ir_set->irq_control);
 
        /* Set the HCD state before we enable the irqs */
@@ -1549,7 +1554,9 @@ int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
                xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb,
                                "HW died, freeing TD.");
                urb_priv = urb->hcpriv;
-               for (i = urb_priv->td_cnt; i < urb_priv->length; i++) {
+               for (i = urb_priv->td_cnt;
+                    i < urb_priv->length && xhci->devs[urb->dev->slot_id];
+                    i++) {
                        td = urb_priv->td[i];
                        if (!list_empty(&td->td_list))
                                list_del_init(&td->td_list);
@@ -1698,6 +1705,9 @@ int xhci_drop_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
 
        xhci_endpoint_zero(xhci, xhci->devs[udev->slot_id], ep);
 
+       if (xhci->quirks & XHCI_MTK_HOST)
+               xhci_mtk_drop_ep_quirk(hcd, udev, ep);
+
        xhci_dbg(xhci, "drop ep 0x%x, slot id %d, new drop flags = %#x, new add flags = %#x\n",
                        (unsigned int) ep->desc.bEndpointAddress,
                        udev->slot_id,
@@ -1793,6 +1803,15 @@ int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
                return -ENOMEM;
        }
 
+       if (xhci->quirks & XHCI_MTK_HOST) {
+               ret = xhci_mtk_add_ep_quirk(hcd, udev, ep);
+               if (ret < 0) {
+                       xhci_free_or_cache_endpoint_ring(xhci,
+                               virt_dev, ep_index);
+                       return ret;
+               }
+       }
+
        ctrl_ctx->add_flags |= cpu_to_le32(added_ctxs);
        new_add_flags = le32_to_cpu(ctrl_ctx->add_flags);
 
@@ -4960,7 +4979,7 @@ EXPORT_SYMBOL_GPL(xhci_gen_setup);
 static const struct hc_driver xhci_hc_driver = {
        .description =          "xhci-hcd",
        .product_desc =         "xHCI Host Controller",
-       .hcd_priv_size =        sizeof(struct xhci_hcd *),
+       .hcd_priv_size =        sizeof(struct xhci_hcd),
 
        /*
         * generic hardware linkage
@@ -5059,6 +5078,10 @@ static int __init xhci_hcd_init(void)
        BUILD_BUG_ON(sizeof(struct xhci_intr_reg) != 8*32/8);
        /* xhci_run_regs has eight fields and embeds 128 xhci_intr_regs */
        BUILD_BUG_ON(sizeof(struct xhci_run_regs) != (8+8*128)*32/8);
+
+       if (usb_disabled())
+               return -ENODEV;
+
        return 0;
 }