This series of patches begins the process of splitting ohci-hcd up into a core library module and independent pci driver modules.
Patch 1/3 prepares the way by exporting a few functions from ohci-hcd and adding a new mechanism for platform-specific drivers to initialize their hc_driver structures. This deserves to be done in the core because almost all of the entries in these structures are pure boilerplate -- practically none of the drivers need to override more than three of the standard core values.
Patch 2/3 is part of separating the ohci pci host controller driver from ohci-hcd host code. Moved sb800_prefetch() function from ohci-pci.c to pci-quirks.c file and EXPORTed, this is part of the effort to move the ohci pci related code to generic pci code.
Patch 3/3 separate out ohci-pci into independent driver modules.
Manjunath Goudar (3): USB: OHCI: prepare to make ohci-hcd a library module USB: OHCI: Generic changes to make ohci-pci a separate driver USB: OHCI: make ohci-pci a separate driver
drivers/usb/host/Kconfig | 4 +- drivers/usb/host/Makefile | 3 + drivers/usb/host/ohci-hcd.c | 129 +++++++++++++++++++++++++--------- drivers/usb/host/ohci-hub.c | 1 - drivers/usb/host/ohci-pci.c | 152 ++++++++++++----------------------------- drivers/usb/host/ohci-q.c | 8 ++- drivers/usb/host/ohci.h | 21 ++++++ drivers/usb/host/pci-quirks.c | 14 ++++ drivers/usb/host/pci-quirks.h | 3 + 9 files changed, 189 insertions(+), 146 deletions(-)
This patch prepares ohci-hcd for being split up into a core library and separate platform driver modules. A generic ohci_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 ohci_restart(),ohci_suspend() and ohci_resume() routines need to be EXPORTed for use by the drivers.
Added ohci_setip(() and ohci_start() routine for to start the generic controller rather than each having its own idiosyncratic approach. This allow to clean duplicated code in most of SOC driver
In V2: -ohci_hcd_init() ohci_run() and ohci_stop() are not made non-static. -Adds the ohci_setup() and ohci_start() routine.
In V3: -purpose of ohci_setup() and ohci_start() function description written in the patch description. -ohci_init() are not made non-static but now called beginning of the ohci_restart(). -ohci_run() signature change reverted back. -unrelated changes removed. -duplicate comment line removed. -inline ohci_suspend() and ohci_resume() is not needed so removed from ohci.h file.
In V4: -ohci-init() EXPORTed because it is called by all bus glue modules. -ohci-setup() removed from 1/2 added into 2/2 patch.
In V5: -Again ohci_setup() is added and EXPORTed because to replace the ohci_init() from all bus glues. -ohci_init() is not made non-static function.
In V6: -ohci_init() call is removed from ohci_quirk_nec_worker(), because it is already called in ohci_restart().
Signed-off-by: Manjunath Goudar manjunath.goudar@linaro.org Cc: Arnd Bergmann arnd@arndb.de Cc: Greg KH greg@kroah.com Cc: Alan Stern stern@rowland.harvard.edu Cc: linux-usb@vger.kernel.org --- drivers/usb/host/ohci-hcd.c | 103 +++++++++++++++++++++++++++++++++++++++---- drivers/usb/host/ohci-hub.c | 1 - drivers/usb/host/ohci-pci.c | 7 --- drivers/usb/host/ohci.h | 17 +++++++ 4 files changed, 111 insertions(+), 17 deletions(-)
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index 9e6de95..13ebbb7 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -79,13 +79,7 @@ static const char hcd_name [] = "ohci_hcd"; #include "pci-quirks.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); - -#if defined(CONFIG_PM) || defined(CONFIG_PCI) -static int ohci_restart (struct ohci_hcd *ohci); -#endif - #ifdef CONFIG_PCI static void sb800_prefetch(struct ohci_hcd *ohci, int on); #else @@ -768,6 +762,30 @@ retry: return 0; }
+/* ohci_setup routine for generic controller initialization */ + +int ohci_setup(struct usb_hcd *hcd) +{ + struct ohci_hcd *ohci = hcd_to_ohci(hcd); + + return ohci_init(ohci); +} +EXPORT_SYMBOL_GPL(ohci_setup); + +/* ohci_start routine for generic controller start of all OHCI bus glue */ +static int ohci_start(struct usb_hcd *hcd) +{ + struct ohci_hcd *ohci = hcd_to_ohci(hcd); + int ret; + + ret = ohci_run(ohci); + if (ret < 0) { + ohci_err(ohci, "can't start\n"); + ohci_stop(hcd); + } + return ret; +} + /*-------------------------------------------------------------------------*/
/* an interrupt happens */ @@ -949,12 +967,13 @@ static void ohci_stop (struct usb_hcd *hcd) #if defined(CONFIG_PM) || defined(CONFIG_PCI)
/* must not be called from interrupt context */ -static int ohci_restart (struct ohci_hcd *ohci) +int ohci_restart(struct ohci_hcd *ohci) { int temp; int i; struct urb_priv *priv;
+ ohci_init(ohci); spin_lock_irq(&ohci->lock); ohci->rh_state = OHCI_RH_HALTED;
@@ -1008,12 +1027,13 @@ static int ohci_restart (struct ohci_hcd *ohci) ohci_dbg(ohci, "restart complete\n"); return 0; } +EXPORT_SYMBOL_GPL(ohci_restart);
#endif
#ifdef CONFIG_PM
-static int __maybe_unused ohci_suspend(struct usb_hcd *hcd, bool do_wakeup) +int ohci_suspend(struct usb_hcd *hcd, bool do_wakeup) { struct ohci_hcd *ohci = hcd_to_ohci (hcd); unsigned long flags; @@ -1031,9 +1051,10 @@ static int __maybe_unused ohci_suspend(struct usb_hcd *hcd, bool do_wakeup)
return 0; } +EXPORT_SYMBOL_GPL(ohci_suspend);
-static int __maybe_unused ohci_resume(struct usb_hcd *hcd, bool hibernated) +int ohci_resume(struct usb_hcd *hcd, bool hibernated) { struct ohci_hcd *ohci = hcd_to_ohci(hcd); int port; @@ -1081,8 +1102,72 @@ static int __maybe_unused ohci_resume(struct usb_hcd *hcd, bool hibernated)
return 0; } +EXPORT_SYMBOL_GPL(ohci_resume); + +#endif + +/*-------------------------------------------------------------------------*/ + +/* + * Generic structure: This gets copied for platform drivers so that + * individual entries can be overridden as needed. + */
+static const struct hc_driver ohci_hc_driver = { + .description = hcd_name, + .product_desc = "OHCI Host Controller", + .hcd_priv_size = sizeof(struct ohci_hcd), + + /* + * generic hardware linkage + */ + .irq = ohci_irq, + .flags = HCD_MEMORY | HCD_USB11, + + /* + * basic lifecycle operations + */ + .reset = ohci_setup, + .start = ohci_start, + .stop = ohci_stop, + .shutdown = ohci_shutdown, + + /* + * managing i/o requests and associated device resources + */ + .urb_enqueue = ohci_urb_enqueue, + .urb_dequeue = ohci_urb_dequeue, + .endpoint_disable = ohci_endpoint_disable, + + /* + * scheduling support + */ + .get_frame_number = ohci_get_frame, + + /* + * root hub support + */ + .hub_status_data = ohci_hub_status_data, + .hub_control = ohci_hub_control, +#ifdef CONFIG_PM + .bus_suspend = ohci_bus_suspend, + .bus_resume = ohci_bus_resume, #endif + .start_port_reset = ohci_start_port_reset, +}; + +void ohci_init_driver(struct hc_driver *drv, + const struct ohci_driver_overrides *over) +{ + /* Copy the generic table to drv and then apply the overrides */ + *drv = ohci_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(ohci_init_driver);
/*-------------------------------------------------------------------------*/
diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c index 60ff422..2347ab8 100644 --- a/drivers/usb/host/ohci-hub.c +++ b/drivers/usb/host/ohci-hub.c @@ -176,7 +176,6 @@ __acquires(ohci->lock) if (status == -EBUSY) { if (!autostopped) { spin_unlock_irq (&ohci->lock); - (void) ohci_init (ohci); status = ohci_restart (ohci);
usb_root_hub_lost_power(hcd->self.root_hub); diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c index 951514e..2c27a5f 100644 --- a/drivers/usb/host/ohci-pci.c +++ b/drivers/usb/host/ohci-pci.c @@ -123,13 +123,6 @@ static void ohci_quirk_nec_worker(struct work_struct *work) struct ohci_hcd *ohci = container_of(work, struct ohci_hcd, nec_work); int status;
- status = ohci_init(ohci); - if (status != 0) { - ohci_err(ohci, "Restarting NEC controller failed in %s, %d\n", - "ohci_init", status); - return; - } - status = ohci_restart(ohci); if (status != 0) ohci_err(ohci, "Restarting NEC controller failed in %s, %d\n", diff --git a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h index d329914..3b58482 100644 --- a/drivers/usb/host/ohci.h +++ b/drivers/usb/host/ohci.h @@ -718,3 +718,20 @@ static inline u32 roothub_status (struct ohci_hcd *hc) { return ohci_readl (hc, &hc->regs->roothub.status); } static inline u32 roothub_portstatus (struct ohci_hcd *hc, int i) { return read_roothub (hc, portstatus [i], 0xffe0fce0); } + +/* Declarations of things exported for use by ohci platform drivers */ + +struct ohci_driver_overrides { + const char *product_desc; + size_t extra_priv_size; + int (*reset)(struct usb_hcd *hcd); +}; + +extern void ohci_init_driver(struct hc_driver *drv, + const struct ohci_driver_overrides *over); +extern int ohci_restart(struct ohci_hcd *ohci); +extern int ohci_setup(struct usb_hcd *hcd); +#ifdef CONFIG_PM +extern int ohci_suspend(struct usb_hcd *hcd, bool do_wakeup); +extern int ohci_resume(struct usb_hcd *hcd, bool hibernated); +#endif
Note that this changes is part of separating the ohci pci host controller driver from ohci-hcd host code. This contains : -Moved sb800_prefetch() function from ohci-pci.c to pci-quirks.c file and EXPORTed, this is part of the effort to move the ohci pci related code to generic pci code. -Passed "pci_dev" argument instead of "ohci_hcd" in sb800_prefetch() function to avoid extra include file in pci-quirks.c.
Signed-off-by: Manjunath Goudar manjunath.goudar@linaro.org Cc: Arnd Bergmann arnd@arndb.de Cc: Greg KH greg@kroah.com Cc: Alan Stern stern@rowland.harvard.edu Cc: linux-usb@vger.kernel.org --- drivers/usb/host/ohci-hcd.c | 11 +---------- drivers/usb/host/ohci-pci.c | 13 ------------- drivers/usb/host/ohci-q.c | 6 ++++-- drivers/usb/host/pci-quirks.c | 12 ++++++++++++ drivers/usb/host/pci-quirks.h | 2 ++ 5 files changed, 19 insertions(+), 25 deletions(-)
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index 13ebbb7..2490b81 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -80,15 +80,6 @@ static const char hcd_name [] = "ohci_hcd";
static void ohci_dump (struct ohci_hcd *ohci, int verbose); static void ohci_stop (struct usb_hcd *hcd); -#ifdef CONFIG_PCI -static void sb800_prefetch(struct ohci_hcd *ohci, int on); -#else -static inline void sb800_prefetch(struct ohci_hcd *ohci, int on) -{ - return; -} -#endif -
#include "ohci-hub.c" #include "ohci-dbg.c" @@ -1275,7 +1266,7 @@ MODULE_LICENSE ("GPL"); #define PLATFORM_DRIVER ohci_platform_driver #endif
-#if !defined(PCI_DRIVER) && \ +#if !defined(PCI_DRIVER) && \ !defined(PLATFORM_DRIVER) && \ !defined(OMAP1_PLATFORM_DRIVER) && \ !defined(OMAP3_PLATFORM_DRIVER) && \ diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c index 2c27a5f..c3fa936 100644 --- a/drivers/usb/host/ohci-pci.c +++ b/drivers/usb/host/ohci-pci.c @@ -168,19 +168,6 @@ static int ohci_quirk_amd700(struct usb_hcd *hcd) return 0; }
-static void sb800_prefetch(struct ohci_hcd *ohci, int on) -{ - struct pci_dev *pdev; - u16 misc; - - pdev = to_pci_dev(ohci_to_hcd(ohci)->self.controller); - pci_read_config_word(pdev, 0x50, &misc); - if (on == 0) - pci_write_config_word(pdev, 0x50, misc & 0xfcff); - else - pci_write_config_word(pdev, 0x50, misc | 0x0300); -} - /* List of quirks for OHCI */ static const struct pci_device_id ohci_pci_quirks[] = { { diff --git a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c index 88731b7..78e0095 100644 --- a/drivers/usb/host/ohci-q.c +++ b/drivers/usb/host/ohci-q.c @@ -41,6 +41,7 @@ finish_urb(struct ohci_hcd *ohci, struct urb *urb, int status) __releases(ohci->lock) __acquires(ohci->lock) { + struct pci_dev *pdev = to_pci_dev(ohci_to_hcd(ohci)->self.controller); // ASSERT (urb->hcpriv != 0);
urb_free_priv (ohci, urb->hcpriv); @@ -55,7 +56,7 @@ __acquires(ohci->lock) if (quirk_amdiso(ohci)) usb_amd_quirk_pll_enable(); if (quirk_amdprefetch(ohci)) - sb800_prefetch(ohci, 0); + sb800_prefetch(pdev, 0); } break; case PIPE_INTERRUPT: @@ -580,6 +581,7 @@ static void td_submit_urb ( struct urb *urb ) { struct urb_priv *urb_priv = urb->hcpriv; + struct pci_dev *pdev = to_pci_dev(ohci_to_hcd(ohci)->self.controller); dma_addr_t data; int data_len = urb->transfer_buffer_length; int cnt = 0; @@ -689,7 +691,7 @@ static void td_submit_urb ( if (quirk_amdiso(ohci)) usb_amd_quirk_pll_disable(); if (quirk_amdprefetch(ohci)) - sb800_prefetch(ohci, 1); + sb800_prefetch(pdev, 1); } periodic = ohci_to_hcd(ohci)->self.bandwidth_isoc_reqs++ == 0 && ohci_to_hcd(ohci)->self.bandwidth_int_reqs == 0; diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c index 4c338ec..5f01540 100644 --- a/drivers/usb/host/pci-quirks.c +++ b/drivers/usb/host/pci-quirks.c @@ -91,6 +91,18 @@ static struct amd_chipset_info {
static DEFINE_SPINLOCK(amd_lock);
+void sb800_prefetch(struct pci_dev *pdev, int on) +{ + u16 misc; + + pci_read_config_word(pdev, 0x50, &misc); + if (on == 0) + pci_write_config_word(pdev, 0x50, misc & 0xfcff); + else + pci_write_config_word(pdev, 0x50, misc | 0x0300); +} +EXPORT_SYMBOL_GPL(sb800_prefetch); + int usb_amd_find_chipset_info(void) { u8 rev = 0; diff --git a/drivers/usb/host/pci-quirks.h b/drivers/usb/host/pci-quirks.h index 7f69a39..7c5fbc1 100644 --- a/drivers/usb/host/pci-quirks.h +++ b/drivers/usb/host/pci-quirks.h @@ -11,11 +11,13 @@ void usb_amd_quirk_pll_enable(void); bool usb_is_intel_switchable_xhci(struct pci_dev *pdev); void usb_enable_xhci_ports(struct pci_dev *xhci_pdev); void usb_disable_xhci_ports(struct pci_dev *xhci_pdev); +void sb800_prefetch(struct pci_dev *pdev, int on); #else static inline void usb_amd_quirk_pll_disable(void) {} static inline void usb_amd_quirk_pll_enable(void) {} static inline void usb_amd_dev_put(void) {} static inline void usb_disable_xhci_ports(struct pci_dev *xhci_pdev) {} +static inline void sb800_prefetch(struct pci_dev *pdev, int on) {} #endif /* CONFIG_PCI */
#endif /* __LINUX_USB_PCI_QUIRKS_H */
This patch splits the PCI portion of ohci-hcd out into its own separate driver module, called ohci-pci.
The major point of difficulty lies in ohci-pci's many vendor- and device-specific workarounds. Some of them have to be applied before calling ohci_start() some after, which necessitates a fair amount of code motion. The other platform drivers require much smaller changes.
The complete sb800_prefetch() function moved to ohci-q.c,because its only related to ohci-pci driver.
V2: - few specific content of pci related code in ohci_pci_start function has been moved to ohci_pci_reset and rest of the generic code is written in ohci_start of ohci-hcd.c file. V3: - ohci_restart() has been called in ohci_pci_reset() function for to reset the ohci pci.
V4: -sb800_prefetch() moved to ohci-q.c,because its only related to ohci-pci. -no longer _creating_ CONFIG_USB_OHCI_PCI,creating CONFIG_USB_OHCI_HCD_PCI. -overrides renamed with pci_override,its giving proper meaning.
V5: -sb800_prefetch() moved to pci-quirks.c,because its only related to pci.
V6: -sb800_prefetch() function has been moved to pci-quirks.c made as separate patch in 2/3. -Most of the generic ohci pci changes moved in 2/3 patch,now this is complete ohci-pci separation patch.
Signed-off-by: Manjunath Goudar manjunath.goudar@linaro.org Cc: Arnd Bergmann arnd@arndb.de Cc: Greg KH greg@kroah.com Cc: Alan Stern stern@rowland.harvard.edu Cc: linux-usb@vger.kernel.org --- drivers/usb/host/Kconfig | 4 +- drivers/usb/host/Makefile | 3 + drivers/usb/host/ohci-hcd.c | 15 ----- drivers/usb/host/ohci-pci.c | 132 ++++++++++++++--------------------------- drivers/usb/host/ohci-q.c | 2 + drivers/usb/host/ohci.h | 4 ++ drivers/usb/host/pci-quirks.c | 2 + drivers/usb/host/pci-quirks.h | 1 + 8 files changed, 59 insertions(+), 104 deletions(-)
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 64d7209..7e75387 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -377,7 +377,7 @@ config USB_FUSBH200_HCD module will be called fusbh200-hcd.
config USB_OHCI_HCD - tristate "OHCI HCD support" + tristate "OHCI HCD (USB 1.1) support" depends on USB_ARCH_HAS_OHCI select ISP1301_OMAP if MACH_OMAP_H2 || MACH_OMAP_H3 depends on USB_ISP1301 || !ARCH_LPC32XX @@ -446,7 +446,7 @@ config USB_OHCI_HCD_PPC_OF default USB_OHCI_HCD_PPC_OF_BE || USB_OHCI_HCD_PPC_OF_LE
config USB_OHCI_HCD_PCI - bool "OHCI support for PCI-bus USB controllers" + tristate "OHCI support for PCI-bus USB controllers" depends on PCI && (STB03xxx || PPC_MPC52xx || USB_OHCI_HCD_PPC_OF) default y select USB_OHCI_LITTLE_ENDIAN diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index 661c558..2214ded 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile @@ -42,7 +42,10 @@ obj-$(CONFIG_USB_EHCI_TEGRA) +=ehci-tegra.o obj-$(CONFIG_USB_OXU210HP_HCD) += oxu210hp-hcd.o obj-$(CONFIG_USB_ISP116X_HCD) += isp116x-hcd.o obj-$(CONFIG_USB_ISP1362_HCD) += isp1362-hcd.o + obj-$(CONFIG_USB_OHCI_HCD) += ohci-hcd.o +obj-$(CONFIG_USB_OHCI_HCD_PCI) += ohci-pci.o + obj-$(CONFIG_USB_UHCI_HCD) += uhci-hcd.o obj-$(CONFIG_USB_FHCI_HCD) += fhci.o obj-$(CONFIG_USB_XHCI_HCD) += xhci-hcd.o diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index 2490b81..36fc3f7 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -1166,11 +1166,6 @@ MODULE_AUTHOR (DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE ("GPL");
-#ifdef CONFIG_PCI -#include "ohci-pci.c" -#define PCI_DRIVER ohci_pci_driver -#endif - #if defined(CONFIG_ARCH_SA1100) && defined(CONFIG_SA1111) #include "ohci-sa1111.c" #define SA1111_DRIVER ohci_hcd_sa1111_driver @@ -1341,12 +1336,6 @@ static int __init ohci_hcd_mod_init(void) goto error_sa1111; #endif
-#ifdef PCI_DRIVER - retval = pci_register_driver(&PCI_DRIVER); - if (retval < 0) - goto error_pci; -#endif - #ifdef SM501_OHCI_DRIVER retval = platform_driver_register(&SM501_OHCI_DRIVER); if (retval < 0) @@ -1440,10 +1429,6 @@ static int __init ohci_hcd_mod_init(void) platform_driver_unregister(&SM501_OHCI_DRIVER); error_sm501: #endif -#ifdef PCI_DRIVER - pci_unregister_driver(&PCI_DRIVER); - error_pci: -#endif #ifdef SA1111_DRIVER sa1111_driver_unregister(&SA1111_DRIVER); error_sa1111: diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c index c3fa936..ea088c1 100644 --- a/drivers/usb/host/ohci-pci.c +++ b/drivers/usb/host/ohci-pci.c @@ -14,12 +14,19 @@ * 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/pci.h> #include <linux/io.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/pci.h> +#include <linux/usb.h> +#include <linux/usb/hcd.h> + +#include "ohci.h" +#include "pci-quirks.h" + +#define DRIVER_DESC "OHCI PCI platform driver" + +static const char hcd_name[] = "ohci-pci";
/*-------------------------------------------------------------------------*/ @@ -229,10 +236,10 @@ static const struct pci_device_id ohci_pci_quirks[] = { static int ohci_pci_reset (struct usb_hcd *hcd) { struct ohci_hcd *ohci = hcd_to_ohci (hcd); + struct pci_dev *pdev = to_pci_dev(hcd->self.controller); int ret = 0;
if (hcd->self.controller) { - struct pci_dev *pdev = to_pci_dev(hcd->self.controller); const struct pci_device_id *quirk_id;
quirk_id = pci_match_id(ohci_pci_quirks, pdev); @@ -242,94 +249,24 @@ static int ohci_pci_reset (struct usb_hcd *hcd) ret = quirk(hcd); } } - if (ret == 0) { - ohci_hcd_init (ohci); - return ohci_init (ohci); - } - return ret; -} - - -static int ohci_pci_start (struct usb_hcd *hcd) -{ - struct ohci_hcd *ohci = hcd_to_ohci (hcd); - int ret; - -#ifdef CONFIG_PM /* avoid warnings about unused pdev */ - if (hcd->self.controller) { - struct pci_dev *pdev = to_pci_dev(hcd->self.controller); - - /* RWC may not be set for add-in PCI cards, since boot - * firmware probably ignored them. This transfers PCI - * PM wakeup capabilities. - */ - if (device_can_wakeup(&pdev->dev)) - ohci->hc_control |= OHCI_CTRL_RWC; - } -#endif /* CONFIG_PM */ - - ret = ohci_run (ohci); - if (ret < 0) { - ohci_err (ohci, "can't start\n"); - ohci_stop (hcd); - } + if (ret == 0) + ohci_setup(hcd); + /* + * After ohci setup RWC may not be set for add-in PCI cards. + * This transfers PCI PM wakeup capabilities. + */ + if (device_can_wakeup(&pdev->dev)) + ohci->hc_control |= OHCI_CTRL_RWC; return ret; }
+static struct hc_driver __read_mostly ohci_pci_hc_driver;
-/*-------------------------------------------------------------------------*/ - -static const struct hc_driver ohci_pci_hc_driver = { - .description = hcd_name, - .product_desc = "OHCI Host Controller", - .hcd_priv_size = sizeof(struct ohci_hcd), - - /* - * generic hardware linkage - */ - .irq = ohci_irq, - .flags = HCD_MEMORY | HCD_USB11, - - /* - * basic lifecycle operations - */ +static const struct ohci_driver_overrides pci_overrides __initconst = { + .product_desc = "OHCI PCI host controller", .reset = ohci_pci_reset, - .start = ohci_pci_start, - .stop = ohci_stop, - .shutdown = ohci_shutdown, - -#ifdef CONFIG_PM - .pci_suspend = ohci_suspend, - .pci_resume = ohci_resume, -#endif - - /* - * managing i/o requests and associated device resources - */ - .urb_enqueue = ohci_urb_enqueue, - .urb_dequeue = ohci_urb_dequeue, - .endpoint_disable = ohci_endpoint_disable, - - /* - * scheduling support - */ - .get_frame_number = ohci_get_frame, - - /* - * root hub support - */ - .hub_status_data = ohci_hub_status_data, - .hub_control = ohci_hub_control, -#ifdef CONFIG_PM - .bus_suspend = ohci_bus_suspend, - .bus_resume = ohci_bus_resume, -#endif - .start_port_reset = ohci_start_port_reset, };
-/*-------------------------------------------------------------------------*/ - - static const struct pci_device_id pci_ids [] = { { /* handle any USB OHCI controller */ PCI_DEVICE_CLASS(PCI_CLASS_SERIAL_USB_OHCI, ~0), @@ -357,3 +294,24 @@ static struct pci_driver ohci_pci_driver = { }, #endif }; + +static int __init ohci_pci_init(void) +{ + if (usb_disabled()) + return -ENODEV; + + pr_info("%s: " DRIVER_DESC "\n", hcd_name); + + ohci_init_driver(&ohci_pci_hc_driver, &pci_overrides); + return pci_register_driver(&ohci_pci_driver); +} +module_init(ohci_pci_init); + +static void __exit ohci_pci_cleanup(void) +{ + pci_unregister_driver(&ohci_pci_driver); +} +module_exit(ohci_pci_cleanup); + +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_LICENSE("GPL"); diff --git a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c index 78e0095..0ed8187 100644 --- a/drivers/usb/host/ohci-q.c +++ b/drivers/usb/host/ohci-q.c @@ -9,6 +9,8 @@
#include <linux/irq.h> #include <linux/slab.h> +#include "ohci.h" +#include "pci-quirks.h"
static void urb_free_priv (struct ohci_hcd *hc, urb_priv_t *urb_priv) { diff --git a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h index 3b58482..ecc471a 100644 --- a/drivers/usb/host/ohci.h +++ b/drivers/usb/host/ohci.h @@ -12,6 +12,9 @@ * __leXX (normally) or __beXX (given OHCI_BIG_ENDIAN), depending on the * host controller implementation. */ +#ifndef __USB_HOST_OHCI_H +#define __USB_HOST_OHCI_H + typedef __u32 __bitwise __hc32; typedef __u16 __bitwise __hc16;
@@ -735,3 +738,4 @@ extern int ohci_setup(struct usb_hcd *hcd); extern int ohci_suspend(struct usb_hcd *hcd, bool do_wakeup); extern int ohci_resume(struct usb_hcd *hcd, bool hibernated); #endif +#endif diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c index 5f01540..112c85f 100644 --- a/drivers/usb/host/pci-quirks.c +++ b/drivers/usb/host/pci-quirks.c @@ -17,6 +17,8 @@ #include <linux/export.h> #include <linux/acpi.h> #include <linux/dmi.h> +#include <linux/usb.h> +#include <linux/usb/hcd.h> #include "pci-quirks.h" #include "xhci-ext-caps.h"
diff --git a/drivers/usb/host/pci-quirks.h b/drivers/usb/host/pci-quirks.h index 7c5fbc1..ba4d76b 100644 --- a/drivers/usb/host/pci-quirks.h +++ b/drivers/usb/host/pci-quirks.h @@ -1,6 +1,7 @@ #ifndef __LINUX_USB_PCI_QUIRKS_H #define __LINUX_USB_PCI_QUIRKS_H
+struct ohci_hcd; #ifdef CONFIG_PCI void uhci_reset_hc(struct pci_dev *pdev, unsigned long base); int uhci_check_and_reset_hc(struct pci_dev *pdev, unsigned long base);
On Thursday 23 May 2013, Manjunath Goudar wrote:
@@ -1275,7 +1266,7 @@ MODULE_LICENSE ("GPL"); #define PLATFORM_DRIVER ohci_platform_driver #endif -#if !defined(PCI_DRIVER) && \ +#if !defined(PCI_DRIVER) && \ !defined(PLATFORM_DRIVER) && \ !defined(OMAP1_PLATFORM_DRIVER) && \ !defined(OMAP3_PLATFORM_DRIVER) && \
This part didn't really belong here, otherwise the patch looks right to me.
Arnd
On Thu, 23 May 2013, Manjunath Goudar wrote:
This patch prepares ohci-hcd for being split up into a core library and separate platform driver modules. A generic ohci_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 ohci_restart(),ohci_suspend() and ohci_resume() routines need to be EXPORTed for use by the drivers.
Added ohci_setip(() and ohci_start() routine for to start the generic controller rather than each having its own idiosyncratic approach. This allow to clean duplicated code in most of SOC driver
This patch looks good.
Acked-by: Alan Stern stern@rowland.harvard.edu
On Thu, 23 May 2013, Manjunath Goudar wrote:
Note that this changes is part of separating the ohci pci host controller driver from ohci-hcd host code. This contains : -Moved sb800_prefetch() function from ohci-pci.c to pci-quirks.c file and EXPORTed, this is part of the effort to move the ohci pci related code to generic pci code. -Passed "pci_dev" argument instead of "ohci_hcd" in sb800_prefetch() function to avoid extra include file in pci-quirks.c.
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index 13ebbb7..2490b81 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c
@@ -1275,7 +1266,7 @@ MODULE_LICENSE ("GPL"); #define PLATFORM_DRIVER ohci_platform_driver #endif -#if !defined(PCI_DRIVER) && \ +#if !defined(PCI_DRIVER) && \ !defined(PLATFORM_DRIVER) && \ !defined(OMAP1_PLATFORM_DRIVER) && \ !defined(OMAP3_PLATFORM_DRIVER) && \
As Arnd mentioned, this doesn't belong here.
diff --git a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c index 88731b7..78e0095 100644 --- a/drivers/usb/host/ohci-q.c +++ b/drivers/usb/host/ohci-q.c @@ -41,6 +41,7 @@ finish_urb(struct ohci_hcd *ohci, struct urb *urb, int status) __releases(ohci->lock) __acquires(ohci->lock) {
- struct pci_dev *pdev = to_pci_dev(ohci_to_hcd(ohci)->self.controller);
You shouldn't call to_pci_dev(). At this point you don't know if the controller is a PCI device or not. Instead, just do
struct device *dev = ohci_to_hcd(ohci)->self.controller;
Then in sb800_prefetch(), where it makes sense, you can call to_pci_dev().
@@ -580,6 +581,7 @@ static void td_submit_urb ( struct urb *urb ) { struct urb_priv *urb_priv = urb->hcpriv;
- struct pci_dev *pdev = to_pci_dev(ohci_to_hcd(ohci)->self.controller);
Same thing here.
Otherwise this is okay.
Alan Stern
On Thu, 23 May 2013, Manjunath Goudar wrote:
This patch splits the PCI portion of ohci-hcd out into its own separate driver module, called ohci-pci.
The major point of difficulty lies in ohci-pci's many vendor- and device-specific workarounds. Some of them have to be applied before calling ohci_start() some after, which necessitates a fair amount of code motion. The other platform drivers require much smaller changes.
The complete sb800_prefetch() function moved to ohci-q.c,because its only related to ohci-pci driver.
V2:
- few specific content of pci related code in ohci_pci_start function has been moved to ohci_pci_reset and rest of the generic code is written in ohci_start of ohci-hcd.c file.
V3:
- ohci_restart() has been called in ohci_pci_reset() function for to reset the ohci pci.
V4: -sb800_prefetch() moved to ohci-q.c,because its only related to ohci-pci. -no longer _creating_ CONFIG_USB_OHCI_PCI,creating CONFIG_USB_OHCI_HCD_PCI. -overrides renamed with pci_override,its giving proper meaning.
V5: -sb800_prefetch() moved to pci-quirks.c,because its only related to pci.
V6: -sb800_prefetch() function has been moved to pci-quirks.c made as separate patch in 2/3. -Most of the generic ohci pci changes moved in 2/3 patch,now this is complete ohci-pci separation patch.
This patch has a lot of extra stuff in it. It looks like you forgot to undo a bunch of things from the previous version, things that are no longer needed.
As I said before, you really need to proofread your patches before emailing them. Don't rely on other people to find your mistakes.
Also, you left out one thing that should still be here. What happened to the part about changing
#if !defined(PCI_DRIVER) && \
to
#if !ENABLED(CONFIG_USB_OHCI_HCD_PCI) && \
?
Alan Stern
On Thursday 23 May 2013, Alan Stern wrote:
On Thu, 23 May 2013, Manjunath Goudar wrote:
Also, you left out one thing that should still be here. What happened to the part about changing
#if !defined(PCI_DRIVER) && \
to
#if !ENABLED(CONFIG_USB_OHCI_HCD_PCI) && \
This section of the driver is gone now since 86510bb248 "USB: OHCI: clarify Kconfig dependencies", so the change is no longer needed.
Arnd
On Thu, 23 May 2013, Arnd Bergmann wrote:
On Thursday 23 May 2013, Alan Stern wrote:
On Thu, 23 May 2013, Manjunath Goudar wrote:
Also, you left out one thing that should still be here. What happened to the part about changing
#if !defined(PCI_DRIVER) && \
to
#if !ENABLED(CONFIG_USB_OHCI_HCD_PCI) && \
This section of the driver is gone now since 86510bb248 "USB: OHCI: clarify Kconfig dependencies", so the change is no longer needed.
I don't know what tree you're referring to. That commit is not present in Greg's usb-linus or usb-next branches. The usb-next branch is what I use for new development.
Alan Stern
On Thursday 23 May 2013, Alan Stern wrote:
This section of the driver is gone now since 86510bb248 "USB: OHCI: clarify Kconfig dependencies", so the change is no longer needed.
I don't know what tree you're referring to. That commit is not present in Greg's usb-linus or usb-next branches. The usb-next branch is what I use for new development.
Sorry, my mistake. I had looked at a temporary tree based on linux-next, and I thought that Greg had applied my patch and put it into usb-next, but instead it's a patch I had sitting on the branch I used for build testing. I have not yet submitted that one again, and I'm sure that Manjunath doesn't have it on his machine, so your comment still applies.
Arnd