usb: core: Don't hold the device lock while sleeping in do_proc_control()
Since commitae8709b296
("USB: core: Make do_proc_control() and do_proc_bulk() killable") if a device has the USB_QUIRK_DELAY_CTRL_MSG quirk set, it will temporarily block all other URBs (e.g. interrupts) while sleeping due to a control. This results in noticeable delays when, for example, a userspace usbfs application is sending URB interrupts at a high rate to a keyboard and simultaneously updates the lock indicators using controls. Interrupts with direction set to IN are also affected by this, meaning that delivery of HID reports (containing scancodes) to the usbfs application is delayed as well. This patch fixes the regression by calling msleep() while the device mutex is unlocked, as was the case originally with usb_control_msg(). Fixes:ae8709b296
("USB: core: Make do_proc_control() and do_proc_bulk() killable") Cc: stable <stable@kernel.org> Acked-by: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: Tasos Sahanidis <tasos@tasossah.com> Link: https://lore.kernel.org/r/3e299e2a-13b9-ddff-7fee-6845e868bc06@tasossah.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
ab7aa2866d
commit
0543e4e885
@ -1209,12 +1209,16 @@ static int do_proc_control(struct usb_dev_state *ps,
|
||||
|
||||
usb_unlock_device(dev);
|
||||
i = usbfs_start_wait_urb(urb, tmo, &actlen);
|
||||
|
||||
/* Linger a bit, prior to the next control message. */
|
||||
if (dev->quirks & USB_QUIRK_DELAY_CTRL_MSG)
|
||||
msleep(200);
|
||||
usb_lock_device(dev);
|
||||
snoop_urb(dev, NULL, pipe, actlen, i, COMPLETE, tbuf, actlen);
|
||||
if (!i && actlen) {
|
||||
if (copy_to_user(ctrl->data, tbuf, actlen)) {
|
||||
ret = -EFAULT;
|
||||
goto recv_fault;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -1231,6 +1235,10 @@ static int do_proc_control(struct usb_dev_state *ps,
|
||||
|
||||
usb_unlock_device(dev);
|
||||
i = usbfs_start_wait_urb(urb, tmo, &actlen);
|
||||
|
||||
/* Linger a bit, prior to the next control message. */
|
||||
if (dev->quirks & USB_QUIRK_DELAY_CTRL_MSG)
|
||||
msleep(200);
|
||||
usb_lock_device(dev);
|
||||
snoop_urb(dev, NULL, pipe, actlen, i, COMPLETE, NULL, 0);
|
||||
}
|
||||
@ -1242,10 +1250,6 @@ static int do_proc_control(struct usb_dev_state *ps,
|
||||
}
|
||||
ret = (i < 0 ? i : actlen);
|
||||
|
||||
recv_fault:
|
||||
/* Linger a bit, prior to the next control message. */
|
||||
if (dev->quirks & USB_QUIRK_DELAY_CTRL_MSG)
|
||||
msleep(200);
|
||||
done:
|
||||
kfree(dr);
|
||||
usb_free_urb(urb);
|
||||
|
Loading…
Reference in New Issue
Block a user