From cd33a32157e42483ffea31e32b1cee4f11ff9592 Mon Sep 17 00:00:00 2001 From: Roger Quadros Date: Fri, 29 May 2015 17:01:46 +0300 Subject: [PATCH] usb: xhci: cleanup xhci_hcd allocation 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 Signed-off-by: Mathias Nyman Signed-off-by: Greg Kroah-Hartman --- 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 2af32e26fafc..4a4cb1d91ac8 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -45,6 +45,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) { @@ -206,7 +213,6 @@ static int xhci_pci_setup(struct usb_hcd *hcd) if (!retval) return retval; - kfree(xhci); return retval; } @@ -247,11 +253,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) @@ -290,8 +291,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 @@ -379,7 +378,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 783e819139a7..0bc4309cb8a8 100644 --- a/drivers/usb/host/xhci-plat.c +++ b/drivers/usb/host/xhci-plat.c @@ -26,6 +26,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; @@ -207,7 +211,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; } @@ -271,8 +274,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 ec8ac1674854..01118f734436 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 ea75e8ccd3c1..11a231d61409 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1591,10 +1591,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) @@ -1748,7 +1762,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.20.1