Index: usb-devel/drivers/usb/gadget/udc/dummy_hcd.c =================================================================== --- usb-devel.orig/drivers/usb/gadget/udc/dummy_hcd.c +++ usb-devel/drivers/usb/gadget/udc/dummy_hcd.c @@ -460,11 +460,15 @@ static void set_link_state(struct dummy_ unsigned int reset = USB_PORT_STAT_RESET & (~dum_hcd->old_status) & dum_hcd->port_status; + if (reset) + dev_info(&dum->gadget.dev, "Dummy %p reset, ints_enabled %d\n", dum, dum->ints_enabled); + /* Report reset and disconnect events to the driver */ if (dum->ints_enabled && (disconnect || reset)) { stop_activity(dum); ++dum->callback_usage; spin_unlock(&dum->lock); + udelay(1000); if (reset) usb_gadget_udc_reset(&dum->gadget, dum->driver); else @@ -908,21 +912,6 @@ static int dummy_pullup(struct usb_gadge spin_lock_irqsave(&dum->lock, flags); dum->pullup = (value != 0); set_link_state(dum_hcd); - if (value == 0) { - /* - * Emulate synchronize_irq(): wait for callbacks to finish. - * This seems to be the best place to emulate the call to - * synchronize_irq() that's in usb_gadget_remove_driver(). - * Doing it in dummy_udc_stop() would be too late since it - * is called after the unbind callback and unbind shouldn't - * be invoked until all the other callbacks are finished. - */ - while (dum->callback_usage > 0) { - spin_unlock_irqrestore(&dum->lock, flags); - usleep_range(1000, 2000); - spin_lock_irqsave(&dum->lock, flags); - } - } spin_unlock_irqrestore(&dum->lock, flags); usb_hcd_poll_rh_status(dummy_hcd_to_hcd(dum_hcd)); @@ -945,6 +934,26 @@ static void dummy_udc_async_callbacks(st spin_lock_irq(&dum->lock); dum->ints_enabled = enable; + dev_info(&_gadget->dev, "Dummy %p ints_enabled <- %d A\n", dum, dum->ints_enabled); + if (!enable) { + /* + * Emulate synchronize_irq(): wait for callbacks to finish. + * This seems to be the best place to emulate the call to + * synchronize_irq() that's in usb_gadget_remove_driver(). + * It has to come after dum->ints_enabled is clear. But + * doing it in dummy_udc_stop() would be too late since that + * routine is called after the unbind callback, and unbind + * shouldn't be invoked until all the other callbacks are + * finished. + */ + while (dum->callback_usage > 0) { + spin_unlock_irq(&dum->lock); + usleep_range(1000, 2000); + spin_lock_irq(&dum->lock); + } + if (dum->ints_enabled) + dev_info(&_gadget->dev, "Dummy %p ints_enabled = %d !\n", dum, dum->ints_enabled); + } spin_unlock_irq(&dum->lock); } @@ -1032,6 +1041,7 @@ static int dummy_udc_stop(struct usb_gad spin_lock_irq(&dum->lock); dum->ints_enabled = 0; + dev_info(&g->dev, "Dummy %p ints_enabled <- %d B\n", dum, dum->ints_enabled); stop_activity(dum); dum->driver = NULL; spin_unlock_irq(&dum->lock);