Instead of always defaulting to a 256-entry array,
we can dynamically allocate devs based on what HW
tells us it supports.

Note that we can't, yet, purge MAX_HC_SLOTS
completely because of struct
xhci_device_context_array reliance on it.

Signed-off-by: Felipe Balbi <felipe.ba...@linux.intel.com>
---
 drivers/usb/host/xhci-hub.c  |  2 +-
 drivers/usb/host/xhci-mem.c  |  4 ++--
 drivers/usb/host/xhci-ring.c |  2 +-
 drivers/usb/host/xhci.c      | 19 +++++++++++++++----
 drivers/usb/host/xhci.h      |  2 +-
 5 files changed, 20 insertions(+), 9 deletions(-)

diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
index 0ef16900efed..ba5ffeef305d 100644
--- a/drivers/usb/host/xhci-hub.c
+++ b/drivers/usb/host/xhci-hub.c
@@ -356,7 +356,7 @@ int xhci_find_slot_id_by_port(struct usb_hcd *hcd, struct 
xhci_hcd *xhci,
        enum usb_device_speed speed;
 
        slot_id = 0;
-       for (i = 0; i < MAX_HC_SLOTS; i++) {
+       for (i = 0; i <= HCS_MAX_SLOTS(xhci->hcs_params1); i++) {
                if (!xhci->devs[i])
                        continue;
                speed = xhci->devs[i]->udev->speed;
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index 321de2e0161b..3d9d6e893c79 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -1828,7 +1828,7 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci)
                }
        }
 
-       for (i = 1; i < MAX_HC_SLOTS; ++i)
+       for (i = 1; i <= HCS_MAX_SLOTS(xhci->hcs_params1); ++i)
                xhci_free_virt_device(xhci, i);
 
        dma_pool_destroy(xhci->segment_pool);
@@ -2535,7 +2535,7 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
         * something other than the default (~1ms minimum between interrupts).
         * See section 5.5.1.2.
         */
-       for (i = 0; i < MAX_HC_SLOTS; ++i)
+       for (i = 0; i <= HCS_MAX_SLOTS(xhci->hcs_params1); ++i)
                xhci->devs[i] = NULL;
        for (i = 0; i < USB_MAXCHILDREN; ++i) {
                xhci->bus_state[0].resume_done[i] = 0;
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index bdf6b13d9b67..76402b44f832 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -895,7 +895,7 @@ void xhci_stop_endpoint_command_watchdog(unsigned long arg)
                 * doesn't touch the memory.
                 */
        }
-       for (i = 0; i < MAX_HC_SLOTS; i++) {
+       for (i = 0; i <= HCS_MAX_SLOTS(xhci->hcs_params1); i++) {
                if (!xhci->devs[i])
                        continue;
                for (j = 0; j < 31; j++)
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 1cd56417cbec..1113b5fea7b4 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -766,6 +766,8 @@ void xhci_shutdown(struct usb_hcd *hcd)
        /* Yet another workaround for spurious wakeups at shutdown with HSW */
        if (xhci->quirks & XHCI_SPURIOUS_WAKEUP)
                pci_set_power_state(to_pci_dev(hcd->self.controller), 
PCI_D3hot);
+
+       kfree(xhci->devs);
 }
 
 #ifdef CONFIG_PM
@@ -4896,6 +4898,11 @@ int xhci_gen_setup(struct usb_hcd *hcd, 
xhci_get_quirks_t get_quirks)
 
        xhci->quirks |= quirks;
 
+       xhci->devs = kcalloc(HCS_MAX_SLOTS(xhci->hcs_params1) + 1,
+                       sizeof(struct xhci_virt_device *), GFP_KERNEL);
+       if (!xhci->devs)
+               return -ENOMEM;
+
        get_quirks(dev, xhci);
 
        /* In xhci controllers which follow xhci 1.0 spec gives a spurious
@@ -4908,13 +4915,13 @@ int xhci_gen_setup(struct usb_hcd *hcd, 
xhci_get_quirks_t get_quirks)
        /* Make sure the HC is halted. */
        retval = xhci_halt(xhci);
        if (retval)
-               return retval;
+               goto err;
 
        xhci_dbg(xhci, "Resetting HCD\n");
        /* Reset the internal HC memory state and registers. */
        retval = xhci_reset(xhci);
        if (retval)
-               return retval;
+               goto err;
        xhci_dbg(xhci, "Reset complete\n");
 
        /*
@@ -4940,7 +4947,7 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t 
get_quirks)
                 */
                retval = dma_set_mask(dev, DMA_BIT_MASK(32));
                if (retval)
-                       return retval;
+                       goto err;
                xhci_dbg(xhci, "Enabling 32-bit DMA addresses.\n");
                dma_set_coherent_mask(dev, DMA_BIT_MASK(32));
        }
@@ -4949,13 +4956,17 @@ int xhci_gen_setup(struct usb_hcd *hcd, 
xhci_get_quirks_t get_quirks)
        /* Initialize HCD and host controller data structures. */
        retval = xhci_init(hcd);
        if (retval)
-               return retval;
+               goto err;
        xhci_dbg(xhci, "Called HCD init\n");
 
        xhci_info(xhci, "hcc params 0x%08x hci version 0x%x quirks 0x%08x\n",
                  xhci->hcc_params, xhci->hci_version, xhci->quirks);
 
        return 0;
+
+err:
+       kfree(xhci->devs);
+       return retval;
 }
 EXPORT_SYMBOL_GPL(xhci_gen_setup);
 
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index 8ccc11a974b8..f6e5bc3d819b 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -1583,7 +1583,7 @@ struct xhci_hcd {
        /* For USB 3.0 LPM enable/disable. */
        struct xhci_command             *lpm_command;
        /* Internal mirror of the HW's dcbaa */
-       struct xhci_virt_device *devs[MAX_HC_SLOTS];
+       struct xhci_virt_device **devs;
        /* For keeping track of bandwidth domains per roothub. */
        struct xhci_root_port_bw_info   *rh_bw;
 
-- 
2.10.1

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

Reply via email to