• Alan Stern's avatar
    USB: dummy-hcd: Fix erroneous synchronization change · 7dbd8f4c
    Alan Stern authored
    A recent change to the synchronization in dummy-hcd was incorrect.
    The issue was that dummy_udc_stop() contained no locking and therefore
    could race with various gadget driver callbacks, and the fix was to
    add locking and issue the callbacks with the private spinlock held.
    
    UDC drivers aren't supposed to do this.  Gadget driver callback
    routines are allowed to invoke functions in the UDC driver, and these
    functions will generally try to acquire the private spinlock.  This
    would deadlock the driver.
    
    The correct solution is to drop the spinlock before issuing callbacks,
    and avoid races by emulating the synchronize_irq() call that all real
    UDC drivers must perform in their ->udc_stop() routines after
    disabling interrupts.  This involves adding a flag to dummy-hcd's
    private structure to keep track of whether interrupts are supposed to
    be enabled, and adding a counter to keep track of ongoing callbacks so
    that dummy_udc_stop() can wait for them all to finish.
    
    A real UDC driver won't receive disconnect, reset, suspend, resume, or
    setup events once it has disabled interrupts.  dummy-hcd will receive
    them but won't try to issue any gadget driver callbacks, which should
    be just as good.
    Signed-off-by: default avatarAlan Stern <stern@rowland.harvard.edu>
    Fixes: f16443a0 ("USB: gadgetfs, dummy-hcd, net2280: fix locking for callbacks")
    CC: <stable@vger.kernel.org>
    Signed-off-by: default avatarFelipe Balbi <felipe.balbi@linux.intel.com>
    7dbd8f4c
dummy_hcd.c 71.9 KB