[PATCH] USB: allow multiple types of EHCI controllers to be built as modules

In some systems we may have both a platform EHCI controller and PCI EHCI
controller.  Previously we couldn't build the EHCI support as a module due
to conflicting module_init() calls in the code.

Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 79f2d8b..7d7c97c 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -889,19 +889,59 @@
 
 #ifdef CONFIG_PCI
 #include "ehci-pci.c"
-#define	EHCI_BUS_GLUED
+#define	PCI_DRIVER		ehci_pci_driver
 #endif
 
 #ifdef CONFIG_PPC_83xx
 #include "ehci-fsl.c"
-#define	EHCI_BUS_GLUED
+#define	PLATFORM_DRIVER		ehci_fsl_driver
 #endif
 
 #ifdef CONFIG_SOC_AU1X00
 #include "ehci-au1xxx.c"
-#define	EHCI_BUS_GLUED
+#define	PLATFORM_DRIVER		ehci_hcd_au1xxx_driver
 #endif
 
-#ifndef	EHCI_BUS_GLUED
+#if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER)
 #error "missing bus glue for ehci-hcd"
 #endif
+
+static int __init ehci_hcd_init(void)
+{
+	int retval = 0;
+
+	pr_debug("%s: block sizes: qh %Zd qtd %Zd itd %Zd sitd %Zd\n",
+		 hcd_name,
+		 sizeof(struct ehci_qh), sizeof(struct ehci_qtd),
+		 sizeof(struct ehci_itd), sizeof(struct ehci_sitd));
+
+#ifdef PLATFORM_DRIVER
+	retval = platform_driver_register(&PLATFORM_DRIVER);
+	if (retval < 0)
+		return retval;
+#endif
+
+#ifdef PCI_DRIVER
+	retval = pci_register_driver(&PCI_DRIVER);
+	if (retval < 0) {
+#ifdef PLATFORM_DRIVER
+		platform_driver_unregister(&PLATFORM_DRIVER);
+#endif
+	}
+#endif
+
+	return retval;
+}
+module_init(ehci_hcd_init);
+
+static void __exit ehci_hcd_cleanup(void)
+{
+#ifdef PLATFORM_DRIVER
+	platform_driver_unregister(&PLATFORM_DRIVER);
+#endif
+#ifdef PCI_DRIVER
+	pci_unregister_driver(&PCI_DRIVER);
+#endif
+}
+module_exit(ehci_hcd_cleanup);
+