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.balbi@xxxxxxxxxxxxxxx> --- Changes since v1: - move allocation/deallocation of array to xhci_mem_init/cleanup() --- drivers/usb/host/xhci-hub.c | 2 +- drivers/usb/host/xhci-mem.c | 11 +++++++++-- drivers/usb/host/xhci-ring.c | 2 +- drivers/usb/host/xhci.h | 2 +- 4 files changed, 12 insertions(+), 5 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..e7edc79851f2 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); @@ -1867,6 +1867,8 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci) } } + kfree(xhci->devs); + no_bw: xhci->cmd_ring_reserved_trbs = 0; xhci->num_usb2_ports = 0; @@ -2378,6 +2380,11 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) "// 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); + if (!xhci->devs) + goto fail; + /* * Section 5.4.8 - doorbell array must be * "physically contiguous and 64-byte (cache line) aligned". @@ -2535,7 +2542,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.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.11.0 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html