Skip to content

Commit d313279

Browse files
dtorJiri Kosina
authored andcommitted
HID: usbhid: do not sleep when opening device
usbhid tries to give the device 50 milliseconds to drain its queues when opening the device, but does it naively by simply sleeping in open handler, which slows down device probing (and thus may affect overall boot time). However we do not need to sleep as we can instead mark a point of time in the future when we should start processing the events. Reported-by: Nicolas Boichat <[email protected]> Signed-off-by: Dmitry Torokhov <[email protected]> Reviewed-by: Guenter Roeck <[email protected]> Signed-off-by: Jiri Kosina <[email protected]>
1 parent a789d5f commit d313279

File tree

2 files changed

+31
-24
lines changed

2 files changed

+31
-24
lines changed

drivers/hid/usbhid/hid-core.c

Lines changed: 29 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include <linux/wait.h>
2727
#include <linux/workqueue.h>
2828
#include <linux/string.h>
29+
#include <linux/timekeeping.h>
2930

3031
#include <linux/usb.h>
3132

@@ -95,6 +96,18 @@ static int hid_start_in(struct hid_device *hid)
9596
set_bit(HID_NO_BANDWIDTH, &usbhid->iofl);
9697
} else {
9798
clear_bit(HID_NO_BANDWIDTH, &usbhid->iofl);
99+
100+
if (test_bit(HID_RESUME_RUNNING, &usbhid->iofl)) {
101+
/*
102+
* In case events are generated while nobody was
103+
* listening, some are released when the device
104+
* is re-opened. Wait 50 msec for the queue to
105+
* empty before allowing events to go through
106+
* hid.
107+
*/
108+
usbhid->input_start_time =
109+
ktime_add_ms(ktime_get_coarse(), 50);
110+
}
98111
}
99112
}
100113
spin_unlock_irqrestore(&usbhid->lock, flags);
@@ -280,20 +293,23 @@ static void hid_irq_in(struct urb *urb)
280293
if (!test_bit(HID_OPENED, &usbhid->iofl))
281294
break;
282295
usbhid_mark_busy(usbhid);
283-
if (!test_bit(HID_RESUME_RUNNING, &usbhid->iofl)) {
284-
hid_input_report(urb->context, HID_INPUT_REPORT,
285-
urb->transfer_buffer,
286-
urb->actual_length, 1);
287-
/*
288-
* autosuspend refused while keys are pressed
289-
* because most keyboards don't wake up when
290-
* a key is released
291-
*/
292-
if (hid_check_keys_pressed(hid))
293-
set_bit(HID_KEYS_PRESSED, &usbhid->iofl);
294-
else
295-
clear_bit(HID_KEYS_PRESSED, &usbhid->iofl);
296+
if (test_bit(HID_RESUME_RUNNING, &usbhid->iofl)) {
297+
if (ktime_before(ktime_get_coarse(),
298+
usbhid->input_start_time))
299+
break;
300+
clear_bit(HID_RESUME_RUNNING, &usbhid->iofl);
296301
}
302+
hid_input_report(urb->context, HID_INPUT_REPORT,
303+
urb->transfer_buffer, urb->actual_length, 1);
304+
/*
305+
* autosuspend refused while keys are pressed
306+
* because most keyboards don't wake up when
307+
* a key is released
308+
*/
309+
if (hid_check_keys_pressed(hid))
310+
set_bit(HID_KEYS_PRESSED, &usbhid->iofl);
311+
else
312+
clear_bit(HID_KEYS_PRESSED, &usbhid->iofl);
297313
break;
298314
case -EPIPE: /* stall */
299315
usbhid_mark_busy(usbhid);
@@ -720,17 +736,6 @@ static int usbhid_open(struct hid_device *hid)
720736

721737
usb_autopm_put_interface(usbhid->intf);
722738

723-
/*
724-
* In case events are generated while nobody was listening,
725-
* some are released when the device is re-opened.
726-
* Wait 50 msec for the queue to empty before allowing events
727-
* to go through hid.
728-
*/
729-
if (res == 0)
730-
msleep(50);
731-
732-
clear_bit(HID_RESUME_RUNNING, &usbhid->iofl);
733-
734739
Done:
735740
mutex_unlock(&usbhid->mutex);
736741
return res;

drivers/hid/usbhid/usbhid.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
#include <linux/types.h>
1515
#include <linux/slab.h>
16+
#include <linux/ktime.h>
1617
#include <linux/list.h>
1718
#include <linux/mutex.h>
1819
#include <linux/timer.h>
@@ -83,6 +84,7 @@ struct usbhid_device {
8384
struct mutex mutex; /* start/stop/open/close */
8485
spinlock_t lock; /* fifo spinlock */
8586
unsigned long iofl; /* I/O flags (CTRL_RUNNING, OUT_RUNNING) */
87+
ktime_t input_start_time; /* When to start handling input */
8688
struct timer_list io_retry; /* Retry timer */
8789
unsigned long stop_retry; /* Time to give up, in jiffies */
8890
unsigned int retry_delay; /* Delay length in ms */

0 commit comments

Comments
 (0)