Hello,

There is a problem when the OHCI module is compiled with multiple bus
glue as a module.
Since the glues are #included, if there is several of them, the
module_init / module_exit causes
problem. This only happens when in module of course (if not in module
module_init is
replaces by some init_call).

The attached patch is a proposed fix. It only fixes the "PCI" glue, it's
just a proof of concept.
If the method is ok for you, I'll do it for all the glues but I didn't
want to do the change for
all the 11 bus glues if the method isn't the good one ...

I've tested with both the PCI bus glues and the OHCI-OF ones (the latter
one is not yet
in the official tree) and both compiled fine in module and in kernel.

The annoying thing is those warnings for each glue :
drivers/usb/host/ohci.h:606: warning: 'periodic_reinit' defined but not used
drivers/usb/host/ohci.h:630: warning: 'roothub_a' defined but not used
drivers/usb/host/ohci.h:636: warning: 'roothub_portstatus' defined but
not used

But theses are used by some but not all glues ... I don't know exactly
why they've
been put in the .h but unless someone sees an objection, I'll move them
to ohci-hcd.c
and just keep the inlines one and the declaration in the .h.


    Sylvain


diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
index a2e58c8..686c7aa 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -16,3 +16,7 @@ obj-$(CONFIG_USB_SL811_HCD)   += sl811-hcd
 obj-$(CONFIG_USB_SL811_CS)     += sl811_cs.o
 obj-$(CONFIG_USB_U132_HCD)     += u132-hcd.o
 obj-$(CONFIG_ETRAX_ARCH_V10)   += hc_crisv10.o
+
+ifeq ($(CONFIG_PCI),y)
+obj-$(CONFIG_USB_OHCI_HCD)     += ohci-pci.o
+endif
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
index ea4714e..53b25a6 100644
--- a/drivers/usb/host/ohci-hcd.c
+++ b/drivers/usb/host/ohci-hcd.c
@@ -127,15 +127,11 @@ #endif
 
 /*-------------------------------------------------------------------------*/
 
-static const char      hcd_name [] = "ohci_hcd";
-
 #define        STATECHANGE_DELAY       msecs_to_jiffies(300)
 
 #include "ohci.h"
 
 static void ohci_dump (struct ohci_hcd *ohci, int verbose);
-static int ohci_init (struct ohci_hcd *ohci);
-static void ohci_stop (struct usb_hcd *hcd);
 
 #include "ohci-hub.c"
 #include "ohci-dbg.c"
@@ -170,7 +166,7 @@ MODULE_PARM_DESC (no_handshake, "true (n
 /*
  * queue up an urb for anything except the root hub
  */
-static int ohci_urb_enqueue (
+int ohci_urb_enqueue (
        struct usb_hcd  *hcd,
        struct usb_host_endpoint *ep,
        struct urb      *urb,
@@ -302,6 +298,7 @@ fail:
        spin_unlock_irqrestore (&ohci->lock, flags);
        return retval;
 }
+EXPORT_SYMBOL_GPL(ohci_urb_enqueue);
 
 /*
  * decouple the URB from the HC queues (TDs, urb_priv); it's
@@ -309,7 +306,7 @@ fail:
  * asynchronously, and we might be dealing with an urb that's
  * partially transferred, or an ED with other urbs being unlinked.
  */
-static int ohci_urb_dequeue (struct usb_hcd *hcd, struct urb *urb)
+int ohci_urb_dequeue (struct usb_hcd *hcd, struct urb *urb)
 {
        struct ohci_hcd         *ohci = hcd_to_ohci (hcd);
        unsigned long           flags;
@@ -342,6 +339,7 @@ #endif                
        spin_unlock_irqrestore (&ohci->lock, flags);
        return 0;
 }
+EXPORT_SYMBOL_GPL(ohci_urb_dequeue);
 
 /*-------------------------------------------------------------------------*/
 
@@ -349,7 +347,7 @@ #endif                
  * including ED memory, dummy TD, and bulk/intr data toggle
  */
 
-static void
+void
 ohci_endpoint_disable (struct usb_hcd *hcd, struct usb_host_endpoint *ep)
 {
        struct ohci_hcd         *ohci = hcd_to_ohci (hcd);
@@ -403,26 +401,29 @@ sanitize:
        spin_unlock_irqrestore (&ohci->lock, flags);
        return;
 }
+EXPORT_SYMBOL_GPL(ohci_endpoint_disable);
 
-static int ohci_get_frame (struct usb_hcd *hcd)
+int ohci_get_frame (struct usb_hcd *hcd)
 {
        struct ohci_hcd         *ohci = hcd_to_ohci (hcd);
 
        return ohci_frame_no(ohci);
 }
+EXPORT_SYMBOL_GPL(ohci_get_frame);
 
-static void ohci_usb_reset (struct ohci_hcd *ohci)
+void ohci_usb_reset (struct ohci_hcd *ohci)
 {
        ohci->hc_control = ohci_readl (ohci, &ohci->regs->control);
        ohci->hc_control &= OHCI_CTRL_RWC;
        ohci_writel (ohci, ohci->hc_control, &ohci->regs->control);
 }
+EXPORT_SYMBOL_GPL(ohci_usb_reset);
 
 /* ohci_shutdown forcibly disables IRQs and DMA, helping kexec and
  * other cases where the next software may expect clean state from the
  * "firmware".  this is bus-neutral, unlike shutdown() methods.
  */
-static void
+void
 ohci_shutdown (struct usb_hcd *hcd)
 {
        struct ohci_hcd *ohci;
@@ -433,6 +434,7 @@ ohci_shutdown (struct usb_hcd *hcd)
        /* flush the writes */
        (void) ohci_readl (ohci, &ohci->regs->control);
 }
+EXPORT_SYMBOL_GPL(ohci_shutdown);
 
 /*-------------------------------------------------------------------------*
  * HC functions
@@ -440,7 +442,7 @@ ohci_shutdown (struct usb_hcd *hcd)
 
 /* init memory, and kick BIOS/SMM off */
 
-static int ohci_init (struct ohci_hcd *ohci)
+int ohci_init (struct ohci_hcd *ohci)
 {
        int ret;
        struct usb_hcd *hcd = ohci_to_hcd(ohci);
@@ -507,6 +509,7 @@ #endif
 
        return ret;
 }
+EXPORT_SYMBOL_GPL(ohci_init);
 
 /*-------------------------------------------------------------------------*/
 
@@ -514,7 +517,7 @@ #endif
  * resets USB and controller
  * enable interrupts 
  */
-static int ohci_run (struct ohci_hcd *ohci)
+int ohci_run (struct ohci_hcd *ohci)
 {
        u32                     mask, temp;
        int                     first = ohci->fminterval == 0;
@@ -686,12 +689,13 @@ retry:
 
        return 0;
 }
+EXPORT_SYMBOL_GPL(ohci_run);
 
 /*-------------------------------------------------------------------------*/
 
 /* an interrupt happens */
 
-static irqreturn_t ohci_irq (struct usb_hcd *hcd)
+irqreturn_t ohci_irq (struct usb_hcd *hcd)
 {
        struct ohci_hcd         *ohci = hcd_to_ohci (hcd);
        struct ohci_regs __iomem *regs = ohci->regs;
@@ -780,10 +784,11 @@ static irqreturn_t ohci_irq (struct usb_
 
        return IRQ_HANDLED;
 }
+EXPORT_SYMBOL_GPL(ohci_irq);
 
 /*-------------------------------------------------------------------------*/
 
-static void ohci_stop (struct usb_hcd *hcd)
+void ohci_stop (struct usb_hcd *hcd)
 {      
        struct ohci_hcd         *ohci = hcd_to_ohci (hcd);
 
@@ -809,6 +814,7 @@ static void ohci_stop (struct usb_hcd *h
                ohci->hcca_dma = 0;
        }
 }
+EXPORT_SYMBOL_GPL(ohci_stop);
 
 /*-------------------------------------------------------------------------*/
 
@@ -816,7 +822,7 @@ static void ohci_stop (struct usb_hcd *h
 
 #ifdef CONFIG_PM
 
-static int ohci_restart (struct ohci_hcd *ohci)
+int ohci_restart (struct ohci_hcd *ohci)
 {
        int temp;
        int i;
@@ -889,6 +895,7 @@ static int ohci_restart (struct ohci_hcd
        }
        return 0;
 }
+EXPORT_SYMBOL_GPL(ohci_restart);
 #endif
 
 /*-------------------------------------------------------------------------*/
@@ -899,9 +906,6 @@ MODULE_AUTHOR (DRIVER_AUTHOR);
 MODULE_DESCRIPTION (DRIVER_INFO);
 MODULE_LICENSE ("GPL");
 
-#ifdef CONFIG_PCI
-#include "ohci-pci.c"
-#endif
 
 #ifdef CONFIG_SA1111
 #include "ohci-sa1111.c"
diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c
index 6995ea3..03f1dda 100644
--- a/drivers/usb/host/ohci-hub.c
+++ b/drivers/usb/host/ohci-hub.c
@@ -37,12 +37,13 @@ #define dbg_port(hc,label,num,value) \
 /*-------------------------------------------------------------------------*/
 
 /* hcd->hub_irq_enable() */
-static void ohci_rhsc_enable (struct usb_hcd *hcd)
+void ohci_rhsc_enable (struct usb_hcd *hcd)
 {
        struct ohci_hcd         *ohci = hcd_to_ohci (hcd);
 
        ohci_writel (ohci, OHCI_INTR_RHSC, &ohci->regs->intrenable);
 }
+EXPORT_SYMBOL_GPL(ohci_rhsc_enable);
 
 #define OHCI_SCHED_ENABLES \
        (OHCI_CTRL_CLE|OHCI_CTRL_BLE|OHCI_CTRL_PLE|OHCI_CTRL_IE)
@@ -132,8 +133,6 @@ static inline struct ed *find_head (stru
        return ed;
 }
 
-static int ohci_restart (struct ohci_hcd *ohci);
-
 /* caller has locked the root hub */
 static int ohci_rh_resume (struct ohci_hcd *ohci)
 __releases(ohci->lock)
@@ -298,7 +297,7 @@ skip_resume:
 
 #ifdef CONFIG_PM
 
-static int ohci_bus_suspend (struct usb_hcd *hcd)
+int ohci_bus_suspend (struct usb_hcd *hcd)
 {
        struct ohci_hcd         *ohci = hcd_to_ohci (hcd);
        int                     rc;
@@ -312,8 +311,9 @@ static int ohci_bus_suspend (struct usb_
        spin_unlock_irq (&ohci->lock);
        return rc;
 }
+EXPORT_SYMBOL_GPL(ohci_bus_suspend);
 
-static int ohci_bus_resume (struct usb_hcd *hcd)
+int ohci_bus_resume (struct usb_hcd *hcd)
 {
        struct ohci_hcd         *ohci = hcd_to_ohci (hcd);
        int                     rc;
@@ -334,6 +334,7 @@ static int ohci_bus_resume (struct usb_h
                usb_hcd_poll_rh_status(hcd);
        return rc;
 }
+EXPORT_SYMBOL_GPL(ohci_bus_resume);
 
 #endif /* CONFIG_PM */
 
@@ -341,7 +342,7 @@ #endif      /* CONFIG_PM */
 
 /* build "status change" packet (one or two bytes) from HC registers */
 
-static int
+int
 ohci_hub_status_data (struct usb_hcd *hcd, char *buf)
 {
        struct ohci_hcd *ohci = hcd_to_ohci (hcd);
@@ -454,6 +455,7 @@ done:
 
        return changed ? length : 0;
 }
+EXPORT_SYMBOL_GPL(ohci_hub_status_data);
 
 /*-------------------------------------------------------------------------*/
 
@@ -499,7 +501,7 @@ ohci_hub_descriptor (
 
 #ifdef CONFIG_USB_OTG
 
-static int ohci_start_port_reset (struct usb_hcd *hcd, unsigned port)
+int ohci_start_port_reset (struct usb_hcd *hcd, unsigned port)
 {
        struct ohci_hcd *ohci = hcd_to_ohci (hcd);
        u32                     status;
@@ -522,10 +524,15 @@ static void start_hnp(struct ohci_hcd *o
 
 #else
 
-#define        ohci_start_port_reset           NULL
+int ohci_start_port_reset (struct usb_hcd *hcd, unsigned port)
+{
+       return 0;
+}
 
 #endif
 
+EXPORT_SYMBOL_GPL(ohci_start_port_reset);
+
 /*-------------------------------------------------------------------------*/
 
 
@@ -580,7 +587,7 @@ static inline void root_port_reset (stru
        /* caller synchronizes using PRSC */
 }
 
-static int ohci_hub_control (
+int ohci_hub_control (
        struct usb_hcd  *hcd,
        u16             typeReq,
        u16             wValue,
@@ -708,4 +715,5 @@ error:
        }
        return retval;
 }
+EXPORT_SYMBOL_GPL(ohci_hub_control);
 
diff --git a/drivers/usb/host/ohci-mem.c b/drivers/usb/host/ohci-mem.c
index d976614..608fb69 100644
--- a/drivers/usb/host/ohci-mem.c
+++ b/drivers/usb/host/ohci-mem.c
@@ -23,12 +23,13 @@
 
 /*-------------------------------------------------------------------------*/
 
-static void ohci_hcd_init (struct ohci_hcd *ohci)
+void ohci_hcd_init (struct ohci_hcd *ohci)
 {
        ohci->next_statechange = jiffies;
        spin_lock_init (&ohci->lock);
        INIT_LIST_HEAD (&ohci->pending);
 }
+EXPORT_SYMBOL_GPL(ohci_hcd_init);
 
 /*-------------------------------------------------------------------------*/
 
diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c
index 8744185..db1850e 100644
--- a/drivers/usb/host/ohci-pci.c
+++ b/drivers/usb/host/ohci-pci.c
@@ -13,12 +13,22 @@
  *
  * This file is licenced under the GPL.
  */
- 
-#ifndef CONFIG_PCI
-#error "This file is PCI bus glue.  CONFIG_PCI must be defined."
-#endif
 
-/*-------------------------------------------------------------------------*/
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/usb.h>
+#include "../core/hcd.h"
+#include "ohci.h"
+
+
+#define DRIVER_VERSION "2006 August 04"
+#define DRIVER_AUTHOR "Roman Weissgaerber, David Brownell"
+#define DRIVER_DESC "OHCI PCI Bus glue"
+#define DRIVER_INFO DRIVER_VERSION " " DRIVER_DESC
+
+static const char hcd_name [] = "ohci_hcd-pci";
+
 
 static int
 ohci_pci_reset (struct usb_hcd *hcd)
@@ -163,7 +173,7 @@ #endif      /* CONFIG_PM */
 
 static const struct hc_driver ohci_pci_hc_driver = {
        .description =          hcd_name,
-       .product_desc =         "OHCI Host Controller",
+       .product_desc =         "OHCI Host Controller - PCI",
        .hcd_priv_size =        sizeof(struct ohci_hcd),
 
        /*
@@ -258,3 +268,9 @@ static void __exit ohci_hcd_pci_cleanup 
        pci_unregister_driver (&ohci_pci_driver);
 }
 module_exit (ohci_hcd_pci_cleanup);
+
+
+MODULE_AUTHOR (DRIVER_AUTHOR);
+MODULE_DESCRIPTION (DRIVER_INFO);
+MODULE_LICENSE ("GPL");
+
diff --git a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h
index a2f42a2..94c5c98 100644
--- a/drivers/usb/host/ohci.h
+++ b/drivers/usb/host/ohci.h
@@ -634,3 +634,31 @@ static inline u32 roothub_status (struct
        { return ohci_readl (hc, &hc->regs->roothub.status); }
 static u32 roothub_portstatus (struct ohci_hcd *hc, int i)
        { return read_roothub (hc, portstatus [i], 0xffe0fce0); }
+
+/*-------------------------------------------------------------------------*/
+
+/* Prototypes for function exported by ohci-hcd for the bus glues */
+extern int ohci_urb_enqueue (struct usb_hcd *hcd, struct usb_host_endpoint *ep,
+                               struct urb *urb, gfp_t mem_flags);
+extern int ohci_urb_dequeue (struct usb_hcd *hcd, struct urb *urb);
+extern void ohci_endpoint_disable (struct usb_hcd *hcd,
+                                       struct usb_host_endpoint *ep);
+extern int ohci_get_frame (struct usb_hcd *hcd);
+extern void ohci_usb_reset (struct ohci_hcd *ohci);
+extern void ohci_shutdown(struct usb_hcd *hcd);
+extern int ohci_init (struct ohci_hcd *ohci);
+extern int ohci_run (struct ohci_hcd *ohci);
+extern irqreturn_t ohci_irq (struct usb_hcd *hcd);
+extern void ohci_stop (struct usb_hcd *hcd);
+extern int ohci_restart (struct ohci_hcd *ohci);
+
+extern void ohci_hcd_init (struct ohci_hcd *ohci);
+
+extern void ohci_rhsc_enable (struct usb_hcd *hcd);
+extern int ohci_bus_suspend (struct usb_hcd *hcd);
+extern int ohci_bus_resume (struct usb_hcd *hcd);
+extern int ohci_hub_status_data (struct usb_hcd *hcd, char *buf);
+extern int ohci_start_port_reset (struct usb_hcd *hcd, unsigned port);
+extern int ohci_hub_control (struct usb_hcd  *hcd, u16 typeReq,
+               u16 wValue, u16 wIndex, char *buf, u16 wLength);
+

-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys - and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
linux-usb-devel@lists.sourceforge.net
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to