]> git.openfabrics.org - ~emulex/infiniband.git/commitdiff
USB: EHCI: prepare to make ehci-hcd a library module
authorAlan Stern <stern@rowland.harvard.edu>
Thu, 1 Nov 2012 15:12:58 +0000 (11:12 -0400)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 1 Nov 2012 15:51:12 +0000 (08:51 -0700)
This patch (as1624) prepares ehci-hcd for being split up into a core
library and separate platform driver modules.  A generic
ehci_hc_driver structure is created, containing all the "standard"
values, and a new mechanism is added whereby a driver module can
specify a set of overrides to those values.  In addition the
ehci_setup(), ehci_suspend(), and ehci_resume() routines need to be
EXPORTed for use by the drivers.

As a side effect of this change, a few routines no longer need to be
marked __maybe_unused.

Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
CC: Felipe Balbi <balbi@ti.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/usb/host/ehci-hcd.c
drivers/usb/host/ehci-hub.c
drivers/usb/host/ehci.h

index ab4a769a4104b448266782b3ad7b997a30d9d992..dee3541bfae821b9c7ad7c0fc1955e14cca02b91 100644 (file)
@@ -649,7 +649,7 @@ static int ehci_run (struct usb_hcd *hcd)
        return 0;
 }
 
-static int ehci_setup(struct usb_hcd *hcd)
+int ehci_setup(struct usb_hcd *hcd)
 {
        struct ehci_hcd *ehci = hcd_to_ehci(hcd);
        int retval;
@@ -680,6 +680,7 @@ static int ehci_setup(struct usb_hcd *hcd)
 
        return 0;
 }
+EXPORT_SYMBOL_GPL(ehci_setup);
 
 /*-------------------------------------------------------------------------*/
 
@@ -1085,7 +1086,7 @@ static int ehci_get_frame (struct usb_hcd *hcd)
 
 /* These routines handle the generic parts of controller suspend/resume */
 
-static int __maybe_unused ehci_suspend(struct usb_hcd *hcd, bool do_wakeup)
+int ehci_suspend(struct usb_hcd *hcd, bool do_wakeup)
 {
        struct ehci_hcd         *ehci = hcd_to_ehci(hcd);
 
@@ -1108,9 +1109,10 @@ static int __maybe_unused ehci_suspend(struct usb_hcd *hcd, bool do_wakeup)
 
        return 0;
 }
+EXPORT_SYMBOL_GPL(ehci_suspend);
 
 /* Returns 0 if power was preserved, 1 if power was lost */
-static int __maybe_unused ehci_resume(struct usb_hcd *hcd, bool hibernated)
+int ehci_resume(struct usb_hcd *hcd, bool hibernated)
 {
        struct ehci_hcd         *ehci = hcd_to_ehci(hcd);
 
@@ -1168,11 +1170,76 @@ static int __maybe_unused ehci_resume(struct usb_hcd *hcd, bool hibernated)
 
        return 1;
 }
+EXPORT_SYMBOL_GPL(ehci_resume);
 
 #endif
 
 /*-------------------------------------------------------------------------*/
 
+/*
+ * Generic structure: This gets copied for platform drivers so that
+ * individual entries can be overridden as needed.
+ */
+
+static const struct hc_driver ehci_hc_driver = {
+       .description =          hcd_name,
+       .product_desc =         "EHCI Host Controller",
+       .hcd_priv_size =        sizeof(struct ehci_hcd),
+
+       /*
+        * generic hardware linkage
+        */
+       .irq =                  ehci_irq,
+       .flags =                HCD_MEMORY | HCD_USB2,
+
+       /*
+        * basic lifecycle operations
+        */
+       .reset =                ehci_setup,
+       .start =                ehci_run,
+       .stop =                 ehci_stop,
+       .shutdown =             ehci_shutdown,
+
+       /*
+        * managing i/o requests and associated device resources
+        */
+       .urb_enqueue =          ehci_urb_enqueue,
+       .urb_dequeue =          ehci_urb_dequeue,
+       .endpoint_disable =     ehci_endpoint_disable,
+       .endpoint_reset =       ehci_endpoint_reset,
+       .clear_tt_buffer_complete =     ehci_clear_tt_buffer_complete,
+
+       /*
+        * scheduling support
+        */
+       .get_frame_number =     ehci_get_frame,
+
+       /*
+        * root hub support
+        */
+       .hub_status_data =      ehci_hub_status_data,
+       .hub_control =          ehci_hub_control,
+       .bus_suspend =          ehci_bus_suspend,
+       .bus_resume =           ehci_bus_resume,
+       .relinquish_port =      ehci_relinquish_port,
+       .port_handed_over =     ehci_port_handed_over,
+};
+
+void ehci_init_driver(struct hc_driver *drv,
+               const struct ehci_driver_overrides *over)
+{
+       /* Copy the generic table to drv and then apply the overrides */
+       *drv = ehci_hc_driver;
+
+       drv->product_desc = over->product_desc;
+       drv->hcd_priv_size += over->extra_priv_size;
+       if (over->reset)
+               drv->reset = over->reset;
+}
+EXPORT_SYMBOL_GPL(ehci_init_driver);
+
+/*-------------------------------------------------------------------------*/
+
 /*
  * The EHCI in ChipIdea HDRC cannot be a separate module or device,
  * because its registers (and irq) are shared between host/gadget/otg
index a59c61fea09f3fe9bb76c12a622821bfe7db88b3..4ccb97c0678f93fd8379af59584bd79e8b8d10ef 100644 (file)
@@ -1109,8 +1109,7 @@ error_exit:
        return retval;
 }
 
-static void __maybe_unused ehci_relinquish_port(struct usb_hcd *hcd,
-               int portnum)
+static void ehci_relinquish_port(struct usb_hcd *hcd, int portnum)
 {
        struct ehci_hcd         *ehci = hcd_to_ehci(hcd);
 
@@ -1119,8 +1118,7 @@ static void __maybe_unused ehci_relinquish_port(struct usb_hcd *hcd,
        set_owner(ehci, --portnum, PORT_OWNER);
 }
 
-static int __maybe_unused ehci_port_handed_over(struct usb_hcd *hcd,
-               int portnum)
+static int ehci_port_handed_over(struct usb_hcd *hcd, int portnum)
 {
        struct ehci_hcd         *ehci = hcd_to_ehci(hcd);
        u32 __iomem             *reg;
index 2262dcdaa3c1c2091eb412765e6720c0679637ca..24a8ada4701ca841e524b4dfeda04a2aefe92e93 100644 (file)
@@ -781,4 +781,21 @@ static inline u32 hc32_to_cpup (const struct ehci_hcd *ehci, const __hc32 *x)
 
 /*-------------------------------------------------------------------------*/
 
+/* Declarations of things exported for use by ehci platform drivers */
+
+struct ehci_driver_overrides {
+       const char      *product_desc;
+       size_t          extra_priv_size;
+       int             (*reset)(struct usb_hcd *hcd);
+};
+
+extern void    ehci_init_driver(struct hc_driver *drv,
+                               const struct ehci_driver_overrides *over);
+extern int     ehci_setup(struct usb_hcd *hcd);
+
+#ifdef CONFIG_PM
+extern int     ehci_suspend(struct usb_hcd *hcd, bool do_wakeup);
+extern int     ehci_resume(struct usb_hcd *hcd, bool hibernated);
+#endif /* CONFIG_PM */
+
 #endif /* __LINUX_EHCI_HCD_H */