These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / drivers / usb / host / xhci-mem.c
index 9a8c936..c48cbe7 100644 (file)
@@ -1498,10 +1498,10 @@ int xhci_endpoint_init(struct xhci_hcd *xhci,
         * use Event Data TRBs, and we don't chain in a link TRB on short
         * transfers, we're basically dividing by 1.
         *
-        * xHCI 1.0 specification indicates that the Average TRB Length should
-        * be set to 8 for control endpoints.
+        * xHCI 1.0 and 1.1 specification indicates that the Average TRB Length
+        * should be set to 8 for control endpoints.
         */
-       if (usb_endpoint_xfer_control(&ep->desc) && xhci->hci_version == 0x100)
+       if (usb_endpoint_xfer_control(&ep->desc) && xhci->hci_version >= 0x100)
                ep_ctx->tx_info |= cpu_to_le32(AVG_TRB_LENGTH_FOR_EP(8));
        else
                ep_ctx->tx_info |=
@@ -1792,8 +1792,7 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci)
        int size;
        int i, j, num_ports;
 
-       if (timer_pending(&xhci->cmd_timer))
-               del_timer_sync(&xhci->cmd_timer);
+       del_timer_sync(&xhci->cmd_timer);
 
        /* Free the Event Ring Segment Table and the actual Event Ring */
        size = sizeof(struct xhci_erst_entry)*(xhci->erst.num_entries);
@@ -1829,24 +1828,20 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci)
        for (i = 1; i < MAX_HC_SLOTS; ++i)
                xhci_free_virt_device(xhci, i);
 
-       if (xhci->segment_pool)
-               dma_pool_destroy(xhci->segment_pool);
+       dma_pool_destroy(xhci->segment_pool);
        xhci->segment_pool = NULL;
        xhci_dbg_trace(xhci, trace_xhci_dbg_init, "Freed segment pool");
 
-       if (xhci->device_pool)
-               dma_pool_destroy(xhci->device_pool);
+       dma_pool_destroy(xhci->device_pool);
        xhci->device_pool = NULL;
        xhci_dbg_trace(xhci, trace_xhci_dbg_init, "Freed device context pool");
 
-       if (xhci->small_streams_pool)
-               dma_pool_destroy(xhci->small_streams_pool);
+       dma_pool_destroy(xhci->small_streams_pool);
        xhci->small_streams_pool = NULL;
        xhci_dbg_trace(xhci, trace_xhci_dbg_init,
                        "Freed small stream array pool");
 
-       if (xhci->medium_streams_pool)
-               dma_pool_destroy(xhci->medium_streams_pool);
+       dma_pool_destroy(xhci->medium_streams_pool);
        xhci->medium_streams_pool = NULL;
        xhci_dbg_trace(xhci, trace_xhci_dbg_init,
                        "Freed medium stream array pool");
@@ -2073,14 +2068,23 @@ static void xhci_add_in_port(struct xhci_hcd *xhci, unsigned int num_ports,
 {
        u32 temp, port_offset, port_count;
        int i;
+       struct xhci_hub *rhub;
 
-       if (major_revision > 0x03) {
+       temp = readl(addr);
+
+       if (XHCI_EXT_PORT_MAJOR(temp) == 0x03) {
+               rhub = &xhci->usb3_rhub;
+       } else if (XHCI_EXT_PORT_MAJOR(temp) <= 0x02) {
+               rhub = &xhci->usb2_rhub;
+       } else {
                xhci_warn(xhci, "Ignoring unknown port speed, "
                                "Ext Cap %p, revision = 0x%x\n",
                                addr, major_revision);
                /* Ignoring port protocol we can't understand. FIXME */
                return;
        }
+       rhub->maj_rev = XHCI_EXT_PORT_MAJOR(temp);
+       rhub->min_rev = XHCI_EXT_PORT_MINOR(temp);
 
        /* Port offset and count in the third dword, see section 7.2 */
        temp = readl(addr + 2);
@@ -2095,6 +2099,33 @@ static void xhci_add_in_port(struct xhci_hcd *xhci, unsigned int num_ports,
                /* WTF? "Valid values are ‘1’ to MaxPorts" */
                return;
 
+       rhub->psi_count = XHCI_EXT_PORT_PSIC(temp);
+       if (rhub->psi_count) {
+               rhub->psi = kcalloc(rhub->psi_count, sizeof(*rhub->psi),
+                                   GFP_KERNEL);
+               if (!rhub->psi)
+                       rhub->psi_count = 0;
+
+               rhub->psi_uid_count++;
+               for (i = 0; i < rhub->psi_count; i++) {
+                       rhub->psi[i] = readl(addr + 4 + i);
+
+                       /* count unique ID values, two consecutive entries can
+                        * have the same ID if link is assymetric
+                        */
+                       if (i && (XHCI_EXT_PORT_PSIV(rhub->psi[i]) !=
+                                 XHCI_EXT_PORT_PSIV(rhub->psi[i - 1])))
+                               rhub->psi_uid_count++;
+
+                       xhci_dbg(xhci, "PSIV:%d PSIE:%d PLT:%d PFD:%d LP:%d PSIM:%d\n",
+                                 XHCI_EXT_PORT_PSIV(rhub->psi[i]),
+                                 XHCI_EXT_PORT_PSIE(rhub->psi[i]),
+                                 XHCI_EXT_PORT_PLT(rhub->psi[i]),
+                                 XHCI_EXT_PORT_PFD(rhub->psi[i]),
+                                 XHCI_EXT_PORT_LP(rhub->psi[i]),
+                                 XHCI_EXT_PORT_PSIM(rhub->psi[i]));
+               }
+       }
        /* cache usb2 port capabilities */
        if (major_revision < 0x03 && xhci->num_ext_caps < max_caps)
                xhci->ext_caps[xhci->num_ext_caps++] = temp;
@@ -2321,6 +2352,10 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
 
        INIT_LIST_HEAD(&xhci->cmd_list);
 
+       /* init command timeout timer */
+       setup_timer(&xhci->cmd_timer, xhci_handle_command_timeout,
+                   (unsigned long)xhci);
+
        page_size = readl(&xhci->op_regs->page_size);
        xhci_dbg_trace(xhci, trace_xhci_dbg_init,
                        "Supported page size register = 0x%x", page_size);
@@ -2505,10 +2540,6 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
                        "Wrote ERST address to ir_set 0.");
        xhci_print_ir_set(xhci, 0);
 
-       /* init command timeout timer */
-       setup_timer(&xhci->cmd_timer, xhci_handle_command_timeout,
-                   (unsigned long)xhci);
-
        /*
         * XXX: Might need to set the Interrupter Moderation Register to
         * something other than the default (~1ms minimum between interrupts).