From b4b7ff4b08e691656c9d77c758fc355833128ac0 Mon Sep 17 00:00:00 2001 From: André Fabian Silva Delgado Date: Wed, 20 Jan 2016 14:01:31 -0300 Subject: Linux-libre 4.4-gnu --- drivers/usb/host/xhci-mem.c | 50 +++++++++++++++++++++++++++++++++++++-------- 1 file changed, 41 insertions(+), 9 deletions(-) (limited to 'drivers/usb/host/xhci-mem.c') diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 41f841fa6..c48cbe731 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -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; -- cgit v1.2.3-54-g00ecf