• Alan Stern's avatar
    HID: usbhid: fix inconsistent reset/resume/reset-resume behavior · 7ed849b9
    Alan Stern authored
    commit 972e6a99 upstream.
    
    The usbhid driver has inconsistently duplicated code in its post-reset,
    resume, and reset-resume pathways.
    
    	reset-resume doesn't check HID_STARTED before trying to
    	restart the I/O queues.
    
    	resume fails to clear the HID_SUSPENDED flag if HID_STARTED
    	isn't set.
    
    	resume calls usbhid_restart_queues() with usbhid->lock held
    	and the others call it without holding the lock.
    
    The first item in particular causes a problem following a reset-resume
    if the driver hasn't started up its I/O.  URB submission fails because
    usbhid->urbin is NULL, and this triggers an unending reset-retry loop.
    
    This patch fixes the problem by creating a new subroutine,
    hid_restart_io(), to carry out all the common activities.  It also
    adds some checks that were missing in the original code:
    
    	After a reset, there's no need to clear any halted endpoints.
    
    	After a resume, if a reset is pending there's no need to
    	restart any I/O until the reset is finished.
    
    	After a resume, if the interrupt-IN endpoint is halted there's
    	no need to submit the input URB until the halt has been
    	cleared.
    Signed-off-by: default avatarAlan Stern <stern@rowland.harvard.edu>
    Reported-by: default avatarDaniel Fraga <fragabr@gmail.com>
    Tested-by: default avatarDaniel Fraga <fragabr@gmail.com>
    CC: <stable@vger.kernel.org>
    Signed-off-by: default avatarJiri Kosina <jkosina@suse.cz>
    Signed-off-by: default avatarWilly Tarreau <w@1wt.eu>
    7ed849b9
hid-core.c 44.5 KB