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> --- 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..7b1b58ad6aac 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..05c8132f77c8 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..44cade15792b 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..c8bbff4e57db 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), + 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 majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html