Allocate the internal virtual device array dynamically based on the
maximum number of slots reported by the host controller. Previously,
the array was always allocated to the absolute maximum of 255 entries.
Repurpose the 'MAX_HC_SLOTS' macro to limit the number of enabled slots.
This mirrors how the maximum number of ports and interrupters are handled.
The allocation now uses kcalloc_node(), which zeroes the memory
automatically, making the explicit memset() call unnecessary.
Signed-off-by: Niklas Neronin <niklas.neronin@linux.intel.com>
Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
Link: https://patch.msgid.link/20260603091132.1110849-16-mathias.nyman@linux.intel.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
xhci_dbg_trace(xhci, trace_xhci_dbg_init, "Freed command ring");
xhci_cleanup_command_queue(xhci);
- for (i = xhci->max_slots; i > 0; i--)
- xhci_free_virt_devices_depth_first(xhci, i);
+ if (xhci->devs) {
+ for (i = xhci->max_slots; i > 0; i--)
+ xhci_free_virt_devices_depth_first(xhci, i);
+ kfree(xhci->devs);
+ }
dma_pool_destroy(xhci->segment_pool);
xhci->segment_pool = NULL;
xhci->rh_bw = NULL;
xhci->port_caps = NULL;
xhci->interrupters = NULL;
+ xhci->devs = NULL;
xhci->usb2_rhub.bus_state.bus_suspended = 0;
xhci->usb3_rhub.bus_state.bus_suspended = 0;
xhci_dbg_trace(xhci, trace_xhci_dbg_init, "Starting %s", __func__);
+ xhci_dbg_trace(xhci, trace_xhci_dbg_init, "Allocating internal virtual device array");
+ xhci->devs = kcalloc_node(xhci->max_slots + 1, sizeof(*xhci->devs), flags,
+ dev_to_node(dev));
+ if (!xhci->devs)
+ goto fail;
+
xhci->dcbaa.ctx_array =
dma_alloc_coherent(dev, array_size(sizeof(*dcbaa->ctx_array), xhci->max_slots + 1),
&dcbaa->dma, flags);
if (xhci->hci_version > 0x100)
xhci->hcc_params2 = readl(&xhci->cap_regs->hcc_params2);
- xhci->max_slots = HCS_MAX_SLOTS(hcs_params1);
+ xhci->max_slots = min(HCS_MAX_SLOTS(hcs_params1), MAX_HC_SLOTS);
xhci->max_ports = min(HCS_MAX_PORTS(hcs_params1), MAX_HC_PORTS);
/* xhci-plat or xhci-pci might have set max_interrupters already */
if (!xhci->max_interrupters)
init_completion(&xhci->cmd_ring_stop_completion);
xhci_hcd_page_size(xhci);
- memset(xhci->devs, 0, MAX_HC_SLOTS * sizeof(*xhci->devs));
-
/* Allocate xHCI data structures */
retval = xhci_mem_init(xhci, GFP_KERNEL);
if (retval)
/* 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
+/*
+ * Max number of Devices Slots. xHCI specification section 5.3.3
+ * Valid values are in the range of 1 to 255.
+ */
+#define MAX_HC_SLOTS 255
/*
* Max Number of Ports. xHCI specification section 5.3.3
* Valid values are in the range of 1 to 255.
/* these are not thread safe so use mutex */
struct mutex mutex;
/* 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;