OSDN Git Service

usb: xhci: cleanup xhci_hcd allocation
authorRoger Quadros <rogerq@ti.com>
Fri, 29 May 2015 14:01:46 +0000 (17:01 +0300)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 31 May 2015 06:45:30 +0000 (15:45 +0900)
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@ti.com>
Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/usb/host/xhci-pci.c
drivers/usb/host/xhci-plat.c
drivers/usb/host/xhci.c
drivers/usb/host/xhci.h

index 2af32e2..4a4cb1d 100644 (file)
@@ -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;
index 783e819..0bc4309 100644 (file)
 
 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);
index ec8ac16..01118f7 100644 (file)
@@ -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);
 
index ea75e8c..11a231d 100644 (file)
@@ -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);