Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux...
[firefly-linux-kernel-4.4.55.git] / drivers / usb / host / xhci.c
index 6fe577d46fa2d392e586d608efc3805666ac452c..8fe4e124ddd49f17fb3ac6d2088cedc15758d7b2 100644 (file)
@@ -390,6 +390,10 @@ static int xhci_try_enable_msi(struct usb_hcd *hcd)
        }
 
  legacy_irq:
+       if (!strlen(hcd->irq_descr))
+               snprintf(hcd->irq_descr, sizeof(hcd->irq_descr), "%s:usb%d",
+                        hcd->driver->description, hcd->self.busnum);
+
        /* fall back to legacy interrupt*/
        ret = request_irq(pdev->irq, &usb_hcd_irq, IRQF_SHARED,
                        hcd->irq_descr, hcd);
@@ -2678,6 +2682,20 @@ static int xhci_configure_endpoint(struct xhci_hcd *xhci,
        return ret;
 }
 
+static void xhci_check_bw_drop_ep_streams(struct xhci_hcd *xhci,
+       struct xhci_virt_device *vdev, int i)
+{
+       struct xhci_virt_ep *ep = &vdev->eps[i];
+
+       if (ep->ep_state & EP_HAS_STREAMS) {
+               xhci_warn(xhci, "WARN: endpoint 0x%02x has streams on set_interface, freeing streams.\n",
+                               xhci_get_endpoint_address(i));
+               xhci_free_stream_info(xhci, ep->stream_info);
+               ep->stream_info = NULL;
+               ep->ep_state &= ~EP_HAS_STREAMS;
+       }
+}
+
 /* Called after one or more calls to xhci_add_endpoint() or
  * xhci_drop_endpoint().  If this call fails, the USB core is expected
  * to call xhci_reset_bandwidth().
@@ -2742,8 +2760,10 @@ int xhci_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev)
        /* Free any rings that were dropped, but not changed. */
        for (i = 1; i < 31; ++i) {
                if ((le32_to_cpu(ctrl_ctx->drop_flags) & (1 << (i + 1))) &&
-                   !(le32_to_cpu(ctrl_ctx->add_flags) & (1 << (i + 1))))
+                   !(le32_to_cpu(ctrl_ctx->add_flags) & (1 << (i + 1)))) {
                        xhci_free_or_cache_endpoint_ring(xhci, virt_dev, i);
+                       xhci_check_bw_drop_ep_streams(xhci, virt_dev, i);
+               }
        }
        xhci_zero_in_ctx(xhci, virt_dev);
        /*
@@ -2759,6 +2779,7 @@ int xhci_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev)
                if (virt_dev->eps[i].ring) {
                        xhci_free_or_cache_endpoint_ring(xhci, virt_dev, i);
                }
+               xhci_check_bw_drop_ep_streams(xhci, virt_dev, i);
                virt_dev->eps[i].ring = virt_dev->eps[i].new_ring;
                virt_dev->eps[i].new_ring = NULL;
        }
@@ -2954,7 +2975,7 @@ static int xhci_check_streams_endpoint(struct xhci_hcd *xhci,
        ret = xhci_check_args(xhci_to_hcd(xhci), udev, ep, 1, true, __func__);
        if (ret <= 0)
                return -EINVAL;
-       if (ep->ss_ep_comp.bmAttributes == 0) {
+       if (usb_ss_max_streams(&ep->ss_ep_comp) == 0) {
                xhci_warn(xhci, "WARN: SuperSpeed Endpoint Companion"
                                " descriptor for ep 0x%x does not support streams\n",
                                ep->desc.bEndpointAddress);
@@ -3121,6 +3142,12 @@ int xhci_alloc_streams(struct usb_hcd *hcd, struct usb_device *udev,
        xhci_dbg(xhci, "Driver wants %u stream IDs (including stream 0).\n",
                        num_streams);
 
+       /* MaxPSASize value 0 (2 streams) means streams are not supported */
+       if (HCC_MAX_PSA(xhci->hcc_params) < 4) {
+               xhci_dbg(xhci, "xHCI controller does not support streams.\n");
+               return -ENOSYS;
+       }
+
        config_cmd = xhci_alloc_command(xhci, true, true, mem_flags);
        if (!config_cmd) {
                xhci_dbg(xhci, "Could not allocate xHCI command structure.\n");
@@ -3519,6 +3546,8 @@ int xhci_discover_or_reset_device(struct usb_hcd *hcd, struct usb_device *udev)
                struct xhci_virt_ep *ep = &virt_dev->eps[i];
 
                if (ep->ep_state & EP_HAS_STREAMS) {
+                       xhci_warn(xhci, "WARN: endpoint 0x%02x has streams on device reset, freeing streams.\n",
+                                       xhci_get_endpoint_address(i));
                        xhci_free_stream_info(xhci, ep->stream_info);
                        ep->stream_info = NULL;
                        ep->ep_state &= ~EP_HAS_STREAMS;
@@ -4733,6 +4762,9 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks)
        /* Accept arbitrarily long scatter-gather lists */
        hcd->self.sg_tablesize = ~0;
 
+       /* support to build packet from discontinuous buffers */
+       hcd->self.no_sg_constraint = 1;
+
        /* XHCI controllers don't stop the ep queue on short packets :| */
        hcd->self.no_stop_on_short = 1;
 
@@ -4757,14 +4789,6 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks)
                /* xHCI private pointer was set in xhci_pci_probe for the second
                 * registered roothub.
                 */
-               xhci = hcd_to_xhci(hcd);
-               /*
-                * Support arbitrarily aligned sg-list entries on hosts without
-                * TD fragment rules (which are currently unsupported).
-                */
-               if (xhci->hci_version < 0x100)
-                       hcd->self.no_sg_constraint = 1;
-
                return 0;
        }
 
@@ -4793,9 +4817,6 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks)
        if (xhci->hci_version > 0x96)
                xhci->quirks |= XHCI_SPURIOUS_SUCCESS;
 
-       if (xhci->hci_version < 0x100)
-               hcd->self.no_sg_constraint = 1;
-
        /* Make sure the HC is halted. */
        retval = xhci_halt(xhci);
        if (retval)