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@xxxxxxxxxxxxxxxxxxx> CC: Felipe Balbi <balbi@xxxxxx> --- drivers/usb/host/ehci-hcd.c | 73 ++++++++++++++++++++++++++++++++++++++++++-- drivers/usb/host/ehci-hub.c | 6 +-- drivers/usb/host/ehci.h | 17 ++++++++++ 3 files changed, 89 insertions(+), 7 deletions(-) Index: usb-3.7/drivers/usb/host/ehci.h =================================================================== --- usb-3.7.orig/drivers/usb/host/ehci.h +++ usb-3.7/drivers/usb/host/ehci.h @@ -781,4 +781,21 @@ static inline u32 hc32_to_cpup (const st /*-------------------------------------------------------------------------*/ +/* 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 */ Index: usb-3.7/drivers/usb/host/ehci-hcd.c =================================================================== --- usb-3.7.orig/drivers/usb/host/ehci-hcd.c +++ usb-3.7/drivers/usb/host/ehci-hcd.c @@ -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 *hc return 0; } +EXPORT_SYMBOL_GPL(ehci_setup); /*-------------------------------------------------------------------------*/ @@ -1085,7 +1086,7 @@ static int ehci_get_frame (struct usb_hc /* 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(s 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(st 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: usb-3.7/drivers/usb/host/ehci-hub.c =================================================================== --- usb-3.7.orig/drivers/usb/host/ehci-hub.c +++ usb-3.7/drivers/usb/host/ehci-hub.c @@ -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_relinqui 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; -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html