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