• Inaky Perez-Gonzalez's avatar
    USB: Introduce usb_queue_reset() to do resets from atomic contexts · dc023dce
    Inaky Perez-Gonzalez authored
    This patch introduces a new call to be able to do a USB reset from an
    atomic contect. This is quite helpful in USB callbacks to handle
    errors (when the only thing that can be done is to do a device
    reset).
    
    It is done queuing a work struct that will do the actual reset. The
    struct is "attached" to an interface so pending requests from an
    interface are removed when said interface is unbound from the driver.
    
    The call flow then becomes:
    
    usb_queue_reset_device()
      __usb_queue_reset_device() [workqueue]
        usb_reset_device()
    
    usb_probe_interface()
      usb_cancel_queue_reset()      [error path]
    
    usb_unbind_interface()
      usb_cancel_queue_reset()
    
    usb_driver_release_interface()
      usb_cancel_queue_reset()
    
    Note usb_cancel_queue_reset() needs smarts to try not to unqueue when
    it is actually being executed. This happens when we run the reset from
    the workqueue: usb_reset_device() is called and on interface unbind
    time, usb_cancel_queue_reset() would be called. That would deadlock on
    cancel_work_sync(). To avoid that, we set (before running
    usb_reset_device()) usb_intf->reset_running and clear it inmediately
    after returning.
    
    Patch is against 2.6.28-rc2 and depends on
    http://marc.info/?l=linux-usb&m=122581634925308&w=2 (as submitted by
    Alan Stern).
    Signed-off-by: default avatarInaky Perez-Gonzalez <inaky@linux.intel.com>
    Cc: Alan Stern <stern@rowland.harvard.edu>
    Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
    dc023dce
hub.c 100 KB