Instead of *always* allocating an array of 256 pointers, we can
dynamically allocate it based on number of maximum slots $this XHCI
implementation supports.

Signed-off-by: Felipe Balbi <[email protected]>
---
 drivers/usb/host/xhci-mem.c | 45 ++++++++++++++++++++++++++++++---------------
 drivers/usb/host/xhci.h     |  4 +---
 2 files changed, 31 insertions(+), 18 deletions(-)

diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index 2b7c3504a95a..916eb2e30029 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -1815,6 +1815,7 @@ void xhci_free_command(struct xhci_hcd *xhci,
 void xhci_mem_cleanup(struct xhci_hcd *xhci)
 {
        struct device   *dev = xhci_to_hcd(xhci)->self.controller;
+       int max_slots;
        int size;
        int i, j, num_ports;
 
@@ -1851,7 +1852,8 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci)
                }
        }
 
-       for (i = 1; i <= HCS_MAX_SLOTS(xhci->hcs_params1); i++)
+       max_slots = HCS_MAX_SLOTS(xhci->hcs_params1) + 1;
+       for (i = 1; i < max_slots; i++)
                xhci_free_virt_device(xhci, i);
 
        dma_pool_destroy(xhci->segment_pool);
@@ -1872,11 +1874,13 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci)
        xhci_dbg_trace(xhci, trace_xhci_dbg_init,
                        "Freed medium stream array pool");
 
-       if (xhci->dcbaa)
-               dma_free_coherent(dev, sizeof(*xhci->dcbaa),
-                               xhci->dcbaa, xhci->dcbaa->dma);
-       xhci->dcbaa = NULL;
+       if (xhci->dcbaa->dev_context_ptrs)
+               dma_free_coherent(dev, sizeof(__le64) * max_slots,
+                               xhci->dcbaa->dev_context_ptrs,
+                               xhci->dcbaa->dma);
 
+       kfree(xhci->dcbaa);
+       xhci->dcbaa = NULL;
        scratchpad_free(xhci);
 
        if (!xhci->rh_bw)
@@ -2205,6 +2209,7 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
        u64             val_64;
        struct xhci_segment     *seg;
        u32 page_size, temp;
+       int max_slots;
        int i;
 
        INIT_LIST_HEAD(&xhci->cmd_list);
@@ -2236,17 +2241,22 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
         * Program the Number of Device Slots Enabled field in the CONFIG
         * register with the max value of slots the HC can handle.
         */
-       val = HCS_MAX_SLOTS(readl(&xhci->cap_regs->hcs_params1));
+       max_slots = HCS_MAX_SLOTS(readl(&xhci->cap_regs->hcs_params1));
        xhci_dbg_trace(xhci, trace_xhci_dbg_init,
-                       "// xHC can handle at most %d device slots.", val);
+                       "// xHC can handle at most %d device slots.", 
max_slots);
+
        val2 = readl(&xhci->op_regs->config_reg);
-       val |= (val2 & ~HCS_SLOTS_MASK);
+       val = max_slots | (val2 & ~HCS_SLOTS_MASK);
+
+       /* XHCI needs offset 0 to be unused */
+       max_slots += 1;
+
        xhci_dbg_trace(xhci, trace_xhci_dbg_init,
                        "// Setting Max device slots reg = 0x%x.", val);
        writel(val, &xhci->op_regs->config_reg);
 
-       xhci->devs = kcalloc(HCS_MAX_SLOTS(xhci->hcs_params1) + 1,
-                       sizeof(struct xhci_virt_device *), GFP_KERNEL);
+       xhci->devs = kcalloc(max_slots, sizeof(struct xhci_virt_device *),
+                       GFP_KERNEL);
        if (!xhci->devs)
                goto fail;
 
@@ -2254,16 +2264,21 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
         * Section 5.4.8 - doorbell array must be
         * "physically contiguous and 64-byte (cache line) aligned".
         */
-       xhci->dcbaa = dma_alloc_coherent(dev, sizeof(*xhci->dcbaa), &dma,
-                       flags);
+       xhci->dcbaa = kzalloc(sizeof(*xhci->dcbaa), GFP_KERNEL);
        if (!xhci->dcbaa)
                goto fail;
-       memset(xhci->dcbaa, 0, sizeof *(xhci->dcbaa));
-       xhci->dcbaa->dma = dma;
+
+       xhci->dcbaa->dev_context_ptrs = dma_alloc_coherent(dev, sizeof(__le64) *
+                       max_slots, &xhci->dcbaa->dma, flags);
+       if (!xhci->dcbaa->dev_context_ptrs)
+               goto fail;
+
+       memset(xhci->dcbaa->dev_context_ptrs, 0, sizeof (__le64) *
+                       max_slots);
        xhci_dbg_trace(xhci, trace_xhci_dbg_init,
                        "// Device context base array address = 0x%llx (DMA), 
%p (virt)",
                        (unsigned long long)xhci->dcbaa->dma, xhci->dcbaa);
-       xhci_write_64(xhci, dma, &xhci->op_regs->dcbaa_ptr);
+       xhci_write_64(xhci, xhci->dcbaa->dma, &xhci->op_regs->dcbaa_ptr);
 
        /*
         * Initialize the ring segment pool.  The ring must be a contiguous
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index 57731f6dba6c..37fd2b27f5b7 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -37,8 +37,6 @@
 /* xHCI PCI Configuration Registers */
 #define XHCI_SBRN_OFFSET       (0x60)
 
-/* Max number of USB devices for any host controller - limit in section 6.1 */
-#define MAX_HC_SLOTS           256
 /* Section 5.3.3 - MaxPorts */
 #define MAX_HC_PORTS           127
 
@@ -1033,7 +1031,7 @@ struct xhci_tt_bw_info {
  */
 struct xhci_device_context_array {
        /* 64-bit device addresses; we only write 32-bit addresses */
-       __le64                  dev_context_ptrs[MAX_HC_SLOTS];
+       __le64                  *dev_context_ptrs;
        /* private xHCD pointers */
        dma_addr_t      dma;
 };
-- 
2.11.0

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to