HCD core allocates memory for HCD private data in usb_create_[shared_]hcd() so make use of that mechanism to allocate the struct xhci_hcd. Introduce struct xhci_driver_overrides to provide the size of HCD private data and hc_driver operation overrides. As of now we only need to override the reset and start methods. Signed-off-by: Roger Quadros <rogerq@xxxxxx> --- drivers/usb/host/xhci-pci.c | 17 ++++++++--------- drivers/usb/host/xhci-plat.c | 18 ++++++++++-------- drivers/usb/host/xhci.c | 30 +++++++++++++++++------------- drivers/usb/host/xhci.h | 19 +++++++++++++++++-- 4 files changed, 52 insertions(+), 32 deletions(-) diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index 7f76c8a..4ad2c14 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -42,6 +42,13 @@ static const char hcd_name[] = "xhci_hcd"; static struct hc_driver __read_mostly xhci_pci_hc_driver; +static int xhci_pci_setup(struct usb_hcd *hcd); + +static const struct xhci_driver_overrides xhci_pci_overrides __initconst = { + .extra_priv_size = sizeof(struct xhci_hcd), + .reset = xhci_pci_setup, +}; + /* called after powerup, by probe or system-pm "wakeup" */ static int xhci_pci_reinit(struct xhci_hcd *xhci, struct pci_dev *pdev) { @@ -182,7 +189,6 @@ static int xhci_pci_setup(struct usb_hcd *hcd) if (!retval) return retval; - kfree(xhci); return retval; } @@ -223,11 +229,6 @@ static int xhci_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) goto dealloc_usb2_hcd; } - /* Set the xHCI pointer before xhci_pci_setup() (aka hcd_driver.reset) - * is called by usb_add_hcd(). - */ - *((struct xhci_hcd **) xhci->shared_hcd->hcd_priv) = xhci; - retval = usb_add_hcd(xhci->shared_hcd, dev->irq, IRQF_SHARED); if (retval) @@ -266,8 +267,6 @@ static void xhci_pci_remove(struct pci_dev *dev) /* Workaround for spurious wakeups at shutdown with HSW */ if (xhci->quirks & XHCI_SPURIOUS_WAKEUP) pci_set_power_state(dev, PCI_D3hot); - - kfree(xhci); } #ifdef CONFIG_PM @@ -349,7 +348,7 @@ static struct pci_driver xhci_pci_driver = { static int __init xhci_pci_init(void) { - xhci_init_driver(&xhci_pci_hc_driver, xhci_pci_setup); + xhci_init_driver(&xhci_pci_hc_driver, &xhci_pci_overrides); #ifdef CONFIG_PM xhci_pci_hc_driver.pci_suspend = xhci_pci_suspend; xhci_pci_hc_driver.pci_resume = xhci_pci_resume; diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c index 08d402b..517fb4c 100644 --- a/drivers/usb/host/xhci-plat.c +++ b/drivers/usb/host/xhci-plat.c @@ -25,6 +25,15 @@ static struct hc_driver __read_mostly xhci_plat_hc_driver; +static int xhci_plat_setup(struct usb_hcd *hcd); +static int xhci_plat_start(struct usb_hcd *hcd); + +static const struct xhci_driver_overrides xhci_plat_overrides __initconst = { + .extra_priv_size = sizeof(struct xhci_hcd), + .reset = xhci_plat_setup, + .start = xhci_plat_start, +}; + static void xhci_plat_quirks(struct device *dev, struct xhci_hcd *xhci) { /* @@ -147,11 +156,6 @@ static int xhci_plat_probe(struct platform_device *pdev) if ((node && of_property_read_bool(node, "usb3-lpm-capable")) || (pdata && pdata->usb3_lpm_capable)) xhci->quirks |= XHCI_LPM_SUPPORT; - /* - * Set the xHCI pointer before xhci_plat_setup() (aka hcd_driver.reset) - * is called by usb_add_hcd(). - */ - *((struct xhci_hcd **) xhci->shared_hcd->hcd_priv) = xhci; if (HCC_MAX_PSA(xhci->hcc_params) >= 4) xhci->shared_hcd->can_do_streams = 1; @@ -191,7 +195,6 @@ static int xhci_plat_remove(struct platform_device *dev) if (!IS_ERR(clk)) clk_disable_unprepare(clk); usb_put_hcd(hcd); - kfree(xhci); return 0; } @@ -255,8 +258,7 @@ MODULE_ALIAS("platform:xhci-hcd"); static int __init xhci_plat_init(void) { - xhci_init_driver(&xhci_plat_hc_driver, xhci_plat_setup); - xhci_plat_hc_driver.start = xhci_plat_start; + xhci_init_driver(&xhci_plat_hc_driver, &xhci_plat_overrides); return platform_driver_register(&usb_xhci_driver); } module_init(xhci_plat_init); diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index ec8ac16..01118f7 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -4832,10 +4832,7 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks) hcd->self.no_stop_on_short = 1; if (usb_hcd_is_primary_hcd(hcd)) { - xhci = kzalloc(sizeof(struct xhci_hcd), GFP_KERNEL); - if (!xhci) - return -ENOMEM; - *((struct xhci_hcd **) hcd->hcd_priv) = xhci; + xhci = hcd_to_xhci(hcd); xhci->main_hcd = hcd; /* Mark the first roothub as being USB 2.0. * The xHCI driver will register the USB 3.0 roothub. @@ -4883,13 +4880,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) - goto error; + return retval; xhci_dbg(xhci, "Resetting HCD\n"); /* Reset the internal HC memory state and registers. */ retval = xhci_reset(xhci); if (retval) - goto error; + return retval; xhci_dbg(xhci, "Reset complete\n"); /* Set dma_mask and coherent_dma_mask to 64-bits, @@ -4904,16 +4901,13 @@ 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) - goto error; + return retval; 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; -error: - kfree(xhci); - return retval; } EXPORT_SYMBOL_GPL(xhci_gen_setup); @@ -4978,11 +4972,21 @@ static const struct hc_driver xhci_hc_driver = { .find_raw_port_number = xhci_find_raw_port_number, }; -void xhci_init_driver(struct hc_driver *drv, int (*setup_fn)(struct usb_hcd *)) +void xhci_init_driver(struct hc_driver *drv, + const struct xhci_driver_overrides *over) { - BUG_ON(!setup_fn); + BUG_ON(!over); + + /* Copy the generic table to drv then apply the overrides */ *drv = xhci_hc_driver; - drv->reset = setup_fn; + + if (over) { + drv->hcd_priv_size += over->extra_priv_size; + if (over->reset) + drv->reset = over->reset; + if (over->start) + drv->start = over->start; + } } EXPORT_SYMBOL_GPL(xhci_init_driver); diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 9745147..0567364 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1586,10 +1586,24 @@ struct xhci_hcd { #define COMP_MODE_RCVRY_MSECS 2000 }; +/* Platform specific overrides to generic XHCI hc_driver ops */ +struct xhci_driver_overrides { + size_t extra_priv_size; + int (*reset)(struct usb_hcd *hcd); + int (*start)(struct usb_hcd *hcd); +}; + /* convert between an HCD pointer and the corresponding EHCI_HCD */ static inline struct xhci_hcd *hcd_to_xhci(struct usb_hcd *hcd) { - return *((struct xhci_hcd **) (hcd->hcd_priv)); + struct usb_hcd *primary_hcd; + + if (usb_hcd_is_primary_hcd(hcd)) + primary_hcd = hcd; + else + primary_hcd = hcd->primary_hcd; + + return (struct xhci_hcd *) (primary_hcd->hcd_priv); } static inline struct usb_hcd *xhci_to_hcd(struct xhci_hcd *xhci) @@ -1743,7 +1757,8 @@ int xhci_run(struct usb_hcd *hcd); void xhci_stop(struct usb_hcd *hcd); void xhci_shutdown(struct usb_hcd *hcd); int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks); -void xhci_init_driver(struct hc_driver *drv, int (*setup_fn)(struct usb_hcd *)); +void xhci_init_driver(struct hc_driver *drv, + const struct xhci_driver_overrides *over); #ifdef CONFIG_PM int xhci_suspend(struct xhci_hcd *xhci, bool do_wakeup); -- 2.1.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