This callback is on an 'atomic notificaitons' queue but is written as a blocking notifier. Convert to use a work-queue to run from non-atomic context. Signed-off-by: NeilBrown <neilb@xxxxxxx> diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h index b3c065a..fb90d94 100644 --- a/drivers/usb/musb/musb_core.h +++ b/drivers/usb/musb/musb_core.h @@ -352,6 +352,8 @@ struct musb { struct timer_list otg_timer; struct notifier_block nb; + struct work_struct notify_work; + unsigned long event; struct dma_controller *dma_controller; diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c index ba85f27..a0fe317 100644 --- a/drivers/usb/musb/omap2430.c +++ b/drivers/usb/musb/omap2430.c @@ -223,11 +223,11 @@ static inline void omap2430_low_level_init(struct musb *musb) musb_writel(musb->mregs, OTG_FORCESTDBY, l); } -/* blocking notifier support */ -static int musb_otg_notifications(struct notifier_block *nb, - unsigned long event, void *unused) +/* work function for atomic notifier */ +static void musb_otg_notify_work(struct work_struct *ws) { - struct musb *musb = container_of(nb, struct musb, nb); + struct musb *musb = container_of(ws, struct musb, notify_work); + unsigned long event = musb->event; struct device *dev = musb->controller; struct musb_hdrc_platform_data *pdata = dev->platform_data; struct omap_musb_board_data *data = pdata->board_data; @@ -274,8 +274,18 @@ static int musb_otg_notifications(struct notifier_block *nb, break; default: dev_dbg(musb->controller, "ID float\n"); - return NOTIFY_DONE; + break; } +} + +static int musb_otg_notifications(struct notifier_block *nb, + unsigned long event, + void *unused) +{ + struct musb *musb = container_of(nb, struct musb, nb); + + musb->event = event; + schedule_work(&musb->notify_work); return NOTIFY_OK; } @@ -323,6 +333,7 @@ static int omap2430_musb_init(struct musb *musb) musb_readl(musb->mregs, OTG_INTERFSEL), musb_readl(musb->mregs, OTG_SIMENABLE)); + INIT_WORK(&musb->notify_work, musb_otg_notify_work); musb->nb.notifier_call = musb_otg_notifications; status = otg_register_notifier(musb->xceiv, &musb->nb); @@ -386,6 +397,7 @@ static void omap2430_musb_disable(struct musb *musb) static int omap2430_musb_exit(struct musb *musb) { del_timer_sync(&musb_idle_timer); + cancel_work_sync(&musb->notify_work); omap2430_low_level_exit(musb); otg_put_transceiver(musb->xceiv);
Attachment:
signature.asc
Description: PGP signature