why not reuse the musb_irq_work? On Wed, Apr 2, 2014 at 7:58 PM, Daniel Mack <zonque@xxxxxxxxx> wrote: > Handle BABBLE interrupt error conditions from a work struct handler. > This indirection is necessary as we can't be certain that the phy > functions don't sleep. > > Platform layer implementation may pass a babble error down to the core > in order to handle it. > > Signed-off-by: Daniel Mack <zonque@xxxxxxxxx> > --- > drivers/usb/musb/musb_core.c | 35 +++++++++++++++++++++++++++++++++++ > drivers/usb/musb/musb_core.h | 1 + > 2 files changed, 36 insertions(+) > > diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c > index 0757690..61da471 100644 > --- a/drivers/usb/musb/musb_core.c > +++ b/drivers/usb/musb/musb_core.c > @@ -848,6 +848,10 @@ b_host: > } > } > > + /* handle babble condition */ > + if (int_usb & MUSB_INTR_BABBLE) > + schedule_work(&musb->recover_work); > + > #if 0 > /* REVISIT ... this would be for multiplexing periodic endpoints, or > * supporting transfer phasing to prevent exceeding ISO bandwidth > @@ -1746,6 +1750,34 @@ static void musb_irq_work(struct work_struct *data) > } > } > > +/* Recover from babble interrupt conditions */ > +static void musb_recover_work(struct work_struct *data) > +{ > + struct musb *musb = container_of(data, struct musb, recover_work); > + int status; > + > + musb_platform_reset(musb); > + > + usb_phy_vbus_off(musb->xceiv); > + udelay(100); > + > + usb_phy_vbus_on(musb->xceiv); > + udelay(100); > + > + /* > + * When a babble condition occurs, the musb controller removes the > + * session bit and the endpoint config is lost. > + */ > + if (musb->dyn_fifo) > + status = ep_config_from_table(musb); > + else > + status = ep_config_from_hw(musb); > + > + /* start the session again */ > + if (status == 0) > + musb_start(musb); > +} > + > /* -------------------------------------------------------------------------- > * Init support > */ > @@ -1913,6 +1945,7 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl) > > /* Init IRQ workqueue before request_irq */ > INIT_WORK(&musb->irq_work, musb_irq_work); > + INIT_WORK(&musb->recover_work, musb_recover_work); > INIT_DELAYED_WORK(&musb->deassert_reset_work, musb_deassert_reset); > INIT_DELAYED_WORK(&musb->finish_resume_work, musb_host_finish_resume); > > @@ -2008,6 +2041,7 @@ fail4: > > fail3: > cancel_work_sync(&musb->irq_work); > + cancel_work_sync(&musb->recover_work); > cancel_delayed_work_sync(&musb->finish_resume_work); > cancel_delayed_work_sync(&musb->deassert_reset_work); > if (musb->dma_controller) > @@ -2073,6 +2107,7 @@ static int musb_remove(struct platform_device *pdev) > dma_controller_destroy(musb->dma_controller); > > cancel_work_sync(&musb->irq_work); > + cancel_work_sync(&musb->recover_work); > cancel_delayed_work_sync(&musb->finish_resume_work); > cancel_delayed_work_sync(&musb->deassert_reset_work); > musb_free(musb); > diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h > index 5514e4c..47e8874 100644 > --- a/drivers/usb/musb/musb_core.h > +++ b/drivers/usb/musb/musb_core.h > @@ -297,6 +297,7 @@ struct musb { > > irqreturn_t (*isr)(int, void *); > struct work_struct irq_work; > + struct work_struct recover_work; > struct delayed_work deassert_reset_work; > struct delayed_work finish_resume_work; > u16 hwvers; > -- > 1.8.5.3 > > -- > 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 -- 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