Merge tag 'pwm/for-4.4-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/thierry...
[cascardo/linux.git] / drivers / usb / host / xhci-mem.c
index 41f841f..c48cbe7 100644 (file)
@@ -1828,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");
@@ -2072,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);
@@ -2094,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;