Commit cd33a321 authored by Roger Quadros's avatar Roger Quadros Committed by Greg Kroah-Hartman

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: default avatarRoger Quadros <rogerq@ti.com>
Signed-off-by: default avatarMathias Nyman <mathias.nyman@linux.intel.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 2cfef79d
...@@ -45,6 +45,13 @@ static const char hcd_name[] = "xhci_hcd"; ...@@ -45,6 +45,13 @@ static const char hcd_name[] = "xhci_hcd";
static struct hc_driver __read_mostly xhci_pci_hc_driver; 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" */ /* called after powerup, by probe or system-pm "wakeup" */
static int xhci_pci_reinit(struct xhci_hcd *xhci, struct pci_dev *pdev) 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) ...@@ -206,7 +213,6 @@ static int xhci_pci_setup(struct usb_hcd *hcd)
if (!retval) if (!retval)
return retval; return retval;
kfree(xhci);
return retval; return retval;
} }
...@@ -247,11 +253,6 @@ static int xhci_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) ...@@ -247,11 +253,6 @@ static int xhci_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
goto dealloc_usb2_hcd; 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, retval = usb_add_hcd(xhci->shared_hcd, dev->irq,
IRQF_SHARED); IRQF_SHARED);
if (retval) if (retval)
...@@ -290,8 +291,6 @@ static void xhci_pci_remove(struct pci_dev *dev) ...@@ -290,8 +291,6 @@ static void xhci_pci_remove(struct pci_dev *dev)
/* Workaround for spurious wakeups at shutdown with HSW */ /* Workaround for spurious wakeups at shutdown with HSW */
if (xhci->quirks & XHCI_SPURIOUS_WAKEUP) if (xhci->quirks & XHCI_SPURIOUS_WAKEUP)
pci_set_power_state(dev, PCI_D3hot); pci_set_power_state(dev, PCI_D3hot);
kfree(xhci);
} }
#ifdef CONFIG_PM #ifdef CONFIG_PM
...@@ -379,7 +378,7 @@ static struct pci_driver xhci_pci_driver = { ...@@ -379,7 +378,7 @@ static struct pci_driver xhci_pci_driver = {
static int __init xhci_pci_init(void) 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 #ifdef CONFIG_PM
xhci_pci_hc_driver.pci_suspend = xhci_pci_suspend; xhci_pci_hc_driver.pci_suspend = xhci_pci_suspend;
xhci_pci_hc_driver.pci_resume = xhci_pci_resume; xhci_pci_hc_driver.pci_resume = xhci_pci_resume;
......
...@@ -26,6 +26,15 @@ ...@@ -26,6 +26,15 @@
static struct hc_driver __read_mostly xhci_plat_hc_driver; 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) 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) ...@@ -147,11 +156,6 @@ static int xhci_plat_probe(struct platform_device *pdev)
if ((node && of_property_read_bool(node, "usb3-lpm-capable")) || if ((node && of_property_read_bool(node, "usb3-lpm-capable")) ||
(pdata && pdata->usb3_lpm_capable)) (pdata && pdata->usb3_lpm_capable))
xhci->quirks |= XHCI_LPM_SUPPORT; 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) if (HCC_MAX_PSA(xhci->hcc_params) >= 4)
xhci->shared_hcd->can_do_streams = 1; xhci->shared_hcd->can_do_streams = 1;
...@@ -207,7 +211,6 @@ static int xhci_plat_remove(struct platform_device *dev) ...@@ -207,7 +211,6 @@ static int xhci_plat_remove(struct platform_device *dev)
if (!IS_ERR(clk)) if (!IS_ERR(clk))
clk_disable_unprepare(clk); clk_disable_unprepare(clk);
usb_put_hcd(hcd); usb_put_hcd(hcd);
kfree(xhci);
return 0; return 0;
} }
...@@ -271,8 +274,7 @@ MODULE_ALIAS("platform:xhci-hcd"); ...@@ -271,8 +274,7 @@ MODULE_ALIAS("platform:xhci-hcd");
static int __init xhci_plat_init(void) static int __init xhci_plat_init(void)
{ {
xhci_init_driver(&xhci_plat_hc_driver, xhci_plat_setup); xhci_init_driver(&xhci_plat_hc_driver, &xhci_plat_overrides);
xhci_plat_hc_driver.start = xhci_plat_start;
return platform_driver_register(&usb_xhci_driver); return platform_driver_register(&usb_xhci_driver);
} }
module_init(xhci_plat_init); module_init(xhci_plat_init);
......
...@@ -4832,10 +4832,7 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks) ...@@ -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; hcd->self.no_stop_on_short = 1;
if (usb_hcd_is_primary_hcd(hcd)) { if (usb_hcd_is_primary_hcd(hcd)) {
xhci = kzalloc(sizeof(struct xhci_hcd), GFP_KERNEL); xhci = hcd_to_xhci(hcd);
if (!xhci)
return -ENOMEM;
*((struct xhci_hcd **) hcd->hcd_priv) = xhci;
xhci->main_hcd = hcd; xhci->main_hcd = hcd;
/* Mark the first roothub as being USB 2.0. /* Mark the first roothub as being USB 2.0.
* The xHCI driver will register the USB 3.0 roothub. * 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) ...@@ -4883,13 +4880,13 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks)
/* Make sure the HC is halted. */ /* Make sure the HC is halted. */
retval = xhci_halt(xhci); retval = xhci_halt(xhci);
if (retval) if (retval)
goto error; return retval;
xhci_dbg(xhci, "Resetting HCD\n"); xhci_dbg(xhci, "Resetting HCD\n");
/* Reset the internal HC memory state and registers. */ /* Reset the internal HC memory state and registers. */
retval = xhci_reset(xhci); retval = xhci_reset(xhci);
if (retval) if (retval)
goto error; return retval;
xhci_dbg(xhci, "Reset complete\n"); xhci_dbg(xhci, "Reset complete\n");
/* Set dma_mask and coherent_dma_mask to 64-bits, /* 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) ...@@ -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. */ /* Initialize HCD and host controller data structures. */
retval = xhci_init(hcd); retval = xhci_init(hcd);
if (retval) if (retval)
goto error; return retval;
xhci_dbg(xhci, "Called HCD init\n"); xhci_dbg(xhci, "Called HCD init\n");
xhci_info(xhci, "hcc params 0x%08x hci version 0x%x quirks 0x%08x\n", xhci_info(xhci, "hcc params 0x%08x hci version 0x%x quirks 0x%08x\n",
xhci->hcc_params, xhci->hci_version, xhci->quirks); xhci->hcc_params, xhci->hci_version, xhci->quirks);
return 0; return 0;
error:
kfree(xhci);
return retval;
} }
EXPORT_SYMBOL_GPL(xhci_gen_setup); EXPORT_SYMBOL_GPL(xhci_gen_setup);
...@@ -4978,11 +4972,21 @@ static const struct hc_driver xhci_hc_driver = { ...@@ -4978,11 +4972,21 @@ static const struct hc_driver xhci_hc_driver = {
.find_raw_port_number = xhci_find_raw_port_number, .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 = 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); EXPORT_SYMBOL_GPL(xhci_init_driver);
......
...@@ -1591,10 +1591,24 @@ struct xhci_hcd { ...@@ -1591,10 +1591,24 @@ struct xhci_hcd {
#define COMP_MODE_RCVRY_MSECS 2000 #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 */ /* convert between an HCD pointer and the corresponding EHCI_HCD */
static inline struct xhci_hcd *hcd_to_xhci(struct usb_hcd *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) static inline struct usb_hcd *xhci_to_hcd(struct xhci_hcd *xhci)
...@@ -1748,7 +1762,8 @@ int xhci_run(struct usb_hcd *hcd); ...@@ -1748,7 +1762,8 @@ int xhci_run(struct usb_hcd *hcd);
void xhci_stop(struct usb_hcd *hcd); void xhci_stop(struct usb_hcd *hcd);
void xhci_shutdown(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); 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 #ifdef CONFIG_PM
int xhci_suspend(struct xhci_hcd *xhci, bool do_wakeup); int xhci_suspend(struct xhci_hcd *xhci, bool do_wakeup);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment