• Alan Stern's avatar
    USB: don't cancel queued resets when unbinding drivers · 524134d4
    Alan Stern authored
    The USB stack provides a mechanism for drivers to request an
    asynchronous device reset (usb_queue_reset_device()).  The mechanism
    uses a work item (reset_ws) embedded in the usb_interface structure
    used by the driver, and the reset is carried out by a work queue
    routine.
    
    The asynchronous reset can race with driver unbinding.  When this
    happens, we try to cancel the queued reset before unbinding the
    driver, on the theory that the driver won't care about any resets once
    it is unbound.
    
    However, thanks to the fact that lockdep now tracks work queue
    accesses, this can provoke a lockdep warning in situations where the
    device reset causes another interface's driver to be unbound; see
    
    	http://marc.info/?l=linux-usb&m=141893165203776&w=2
    
    for an example.  The reason is that the work routine for reset_ws in
    one interface calls cancel_queued_work() for the reset_ws in another
    interface.  Lockdep thinks this might lead to a work routine trying to
    cancel itself.  The simplest solution is not to cancel queued resets
    when unbinding drivers.
    
    This means we now need to acquire a reference to the usb_interface
    when queuing a reset_ws work item and to drop the reference when the
    work routine finishes.  We also need to make sure that the
    usb_interface structure doesn't outlive its parent usb_device; this
    means acquiring and dropping a reference when the interface is created
    and destroyed.
    
    In addition, cancelling a queued reset can fail (if the device is in
    the middle of an earlier reset), and this can cause usb_reset_device()
    to try to rebind an interface that has been deallocated (see
    http://marc.info/?l=linux-usb&m=142175717016628&w=2 for details).
    Acquiring the extra references prevents this failure.
    Signed-off-by: default avatarAlan Stern <stern@rowland.harvard.edu>
    Reported-by: default avatarRussell King - ARM Linux <linux@arm.linux.org.uk>
    Reported-by: default avatarOlivier Sobrie <olivier@sobrie.be>
    Tested-by: default avatarOlivier Sobrie <olivier@sobrie.be>
    Cc: stable <stable@vger.kernel.org> # 3.19
    Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
    524134d4
hub.c 162 KB