The musb struct is currently allocated along with the hcd, which makes it difficult to build a driver that only acts as gadget device. Fix this by allocating musb directly, and keep the hcd around as a pointer in the musb struct. struct hc_driver musb_hc_driver can now also be static to musb_host.c, and the macro musb_to_hcd() is just a pointer dereferencer for now, and will be eliminated later. Signed-off-by: Daniel Mack <zonque@xxxxxxxxx> Acked-by: Peter Korsgaard <jacmet@xxxxxxxxxx> --- drivers/usb/musb/musb_core.c | 40 ++++++++++++++++---------------- drivers/usb/musb/musb_core.h | 1 + drivers/usb/musb/musb_host.c | 54 ++++++++++++++++++++++++++++++++++++++------ drivers/usb/musb/musb_host.h | 19 +++++++--------- 4 files changed, 75 insertions(+), 39 deletions(-) diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index adf069d..f3519d3 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -404,7 +404,8 @@ void musb_hnp_stop(struct musb *musb) break; case OTG_STATE_B_HOST: dev_dbg(musb->controller, "HNP: Disabling HR\n"); - hcd->self.is_b_host = 0; + if (hcd) + hcd->self.is_b_host = 0; musb->xceiv->state = OTG_STATE_B_PERIPHERAL; MUSB_DEV_MODE(musb); reg = musb_readb(mbase, MUSB_POWER); @@ -726,7 +727,8 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb, dev_dbg(musb->controller, "HNP: CONNECT, now b_host\n"); b_host: musb->xceiv->state = OTG_STATE_B_HOST; - hcd->self.is_b_host = 1; + if (hcd) + hcd->self.is_b_host = 1; musb->ignore_disconnect = 0; del_timer(&musb->otg_timer); break; @@ -768,7 +770,8 @@ b_host: * in hnp_stop() is currently not used... */ musb_root_disconnect(musb); - musb_to_hcd(musb)->self.is_b_host = 0; + if (musb->hcd) + musb->hcd->self.is_b_host = 0; musb->xceiv->state = OTG_STATE_B_PERIPHERAL; MUSB_DEV_MODE(musb); musb_g_disconnect(musb); @@ -1714,24 +1717,18 @@ static struct musb *allocate_instance(struct device *dev, struct musb *musb; struct musb_hw_ep *ep; int epnum; - struct usb_hcd *hcd; + int ret; - hcd = usb_create_hcd(&musb_hc_driver, dev, dev_name(dev)); - if (!hcd) + musb = devm_kzalloc(dev, sizeof(*musb), GFP_KERNEL); + if (!musb) return NULL; - /* usbcore sets dev->driver_data to hcd, and sometimes uses that... */ - musb = hcd_to_musb(hcd); INIT_LIST_HEAD(&musb->control); INIT_LIST_HEAD(&musb->in_bulk); INIT_LIST_HEAD(&musb->out_bulk); - hcd->uses_new_polling = 1; - hcd->has_tt = 1; - musb->vbuserr_retry = VBUSERR_RETRY_COUNT; musb->a_wait_bcon = OTG_TIME_A_WAIT_BCON; - dev_set_drvdata(dev, musb); musb->mregs = mbase; musb->ctrl_base = mbase; musb->nIrq = -ENODEV; @@ -1746,7 +1743,16 @@ static struct musb *allocate_instance(struct device *dev, musb->controller = dev; + ret = musb_host_alloc(musb); + if (ret < 0) + goto err_free; + + dev_set_drvdata(dev, musb); + return musb; + +err_free: + return NULL; } static void musb_free(struct musb *musb) @@ -1772,7 +1778,7 @@ static void musb_free(struct musb *musb) dma_controller_destroy(c); } - usb_put_hcd(musb_to_hcd(musb)); + musb_host_free(musb); } /* @@ -1789,7 +1795,6 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl) int status; struct musb *musb; struct musb_hdrc_platform_data *plat = dev->platform_data; - struct usb_hcd *hcd; /* The driver might handle more features than the board; OK. * Fail when the board needs a feature that's not enabled. @@ -1890,13 +1895,6 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl) musb->irq_wake = 0; } - /* host side needs more setup */ - hcd = musb_to_hcd(musb); - otg_set_host(musb->xceiv->otg, &hcd->self); - hcd->self.otg_port = 1; - musb->xceiv->otg->host = &hcd->self; - hcd->power_budget = 2 * (plat->power ? : 250); - /* program PHY to use external vBus if required */ if (plat->extvbus) { u8 busctl = musb_read_ulpi_buscontrol(musb->mregs); diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h index 87da041..6b65847 100644 --- a/drivers/usb/musb/musb_core.h +++ b/drivers/usb/musb/musb_core.h @@ -402,6 +402,7 @@ struct musb { enum musb_g_ep0_state ep0_state; struct usb_gadget g; /* the gadget */ struct usb_gadget_driver *gadget_driver; /* its driver */ + struct usb_hcd *hcd; /* the usb hcd */ /* * FIXME: Remove this flag. diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c index 8b977d2..38834b2 100644 --- a/drivers/usb/musb/musb_host.c +++ b/drivers/usb/musb/musb_host.c @@ -95,6 +95,16 @@ * of transfers between endpoints, or anything clever. */ +struct musb_hcd_link { + struct musb *musb; +}; + +struct musb *hcd_to_musb(struct usb_hcd *hcd) +{ + struct musb_hcd_link *link = (struct musb_hcd_link *) hcd->hcd_priv; + return link->musb; +} + static void musb_ep_program(struct musb *musb, u8 epnum, struct urb *urb, int is_out, @@ -2464,7 +2474,6 @@ static int musb_bus_resume(struct usb_hcd *hcd) return 0; } - #ifndef CONFIG_MUSB_PIO_ONLY #define MUSB_USB_DMA_ALIGN 4 @@ -2576,10 +2585,10 @@ static void musb_unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb) } #endif /* !CONFIG_MUSB_PIO_ONLY */ -const struct hc_driver musb_hc_driver = { +static const struct hc_driver musb_hc_driver = { .description = "musb-hcd", .product_desc = "MUSB HDRC host driver", - .hcd_priv_size = sizeof(struct musb), + .hcd_priv_size = sizeof(struct musb_hcd_link), .flags = HCD_USB2 | HCD_MEMORY, /* not using irq handler or reset hooks from usbcore, since @@ -2608,16 +2617,47 @@ const struct hc_driver musb_hc_driver = { /* .hub_irq_enable = NULL, */ }; +int musb_host_alloc(struct musb *musb) +{ + struct device *dev = musb->controller; + struct musb_hcd_link *link; + + /* usbcore sets dev->driver_data to hcd, and sometimes uses that... */ + musb->hcd = usb_create_hcd(&musb_hc_driver, dev, dev_name(dev)); + if (!musb->hcd) + return -EINVAL; + + link = (struct musb_hcd_link *) musb->hcd->hcd_priv; + link->musb = musb; + + musb->hcd->self.uses_pio_for_control = 1; + musb->hcd->uses_new_polling = 1; + musb->hcd->has_tt = 1; + + return 0; +} + +void musb_host_cleanup(struct musb *musb) +{ + usb_remove_hcd(musb->hcd); + musb->hcd = NULL; +} + +void musb_host_free(struct musb *musb) +{ + usb_put_hcd(musb->hcd); +} + void musb_host_resume_root_hub(struct musb *musb) { - usb_hcd_resume_root_hub(musb_to_hcd(musb)); + usb_hcd_resume_root_hub(musb->hcd); } void musb_host_poke_root_hub(struct musb *musb) { MUSB_HST_MODE(musb); - if (musb_to_hcd(musb)->status_urb) - usb_hcd_poll_rh_status(musb_to_hcd(musb)); + if (musb->hcd->status_urb) + usb_hcd_poll_rh_status(musb->hcd); else - usb_hcd_resume_root_hub(musb_to_hcd(musb)); + usb_hcd_resume_root_hub(musb->hcd); } diff --git a/drivers/usb/musb/musb_host.h b/drivers/usb/musb/musb_host.h index c63e585..e47035e 100644 --- a/drivers/usb/musb/musb_host.h +++ b/drivers/usb/musb/musb_host.h @@ -37,15 +37,9 @@ #include <linux/scatterlist.h> -static inline struct usb_hcd *musb_to_hcd(struct musb *musb) -{ - return container_of((void *) musb, struct usb_hcd, hcd_priv); -} +#define musb_to_hcd(MUSB) ((MUSB)->hcd) -static inline struct musb *hcd_to_musb(struct usb_hcd *hcd) -{ - return (struct musb *) (hcd->hcd_priv); -} +extern struct musb *hcd_to_musb(struct usb_hcd *); /* stored in "usb_host_endpoint.hcpriv" for scheduled endpoints */ struct musb_qh { @@ -85,10 +79,15 @@ static inline struct musb_qh *first_qh(struct list_head *q) } extern irqreturn_t musb_h_ep0_irq(struct musb *); +extern int musb_host_alloc(struct musb *); +extern void musb_host_tx(struct musb *, u8); +extern void musb_host_rx(struct musb *, u8); +extern void musb_root_disconnect(struct musb *musb); +extern void musb_host_free(struct musb *); +extern void musb_host_cleanup(struct musb *); extern void musb_host_tx(struct musb *, u8); extern void musb_host_rx(struct musb *, u8); extern void musb_root_disconnect(struct musb *musb); - extern void musb_host_resume_root_hub(struct musb *musb); extern void musb_host_poke_root_hub(struct musb *musb); @@ -99,8 +98,6 @@ extern int musb_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wIndex, char *buf, u16 wLength); -extern const struct hc_driver musb_hc_driver; - static inline struct urb *next_urb(struct musb_qh *qh) { struct list_head *queue; -- 1.8.1.4 -- 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