forked from Minki/linux
Revert "HID: usbhid: do not sleep when opening device"
This reverts commit d313279228
.
This patch causes a regression with quite a few devices, as probing fails
because of the race where the first IRQ is dropped on the floor (after
hid_device_io_start() happens, but before the 50ms timeout passess), and
report descriptor never gets parsed and populated.
As this is just a boot time micro-optimization, let's revert the
patch for 5.9 now, and fix this properly eventually for next merge
window.
Link: https://bugzilla.kernel.org/show_bug.cgi?id=208935
Reported-by: Johannes Hirte <johannes.hirte@datenkhaos.de>
Reported-by: Marius Zachmann <mail@mariuszachmann.de>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
This commit is contained in:
parent
25a097f520
commit
5b0545dc18
@ -26,7 +26,6 @@
|
||||
#include <linux/wait.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/timekeeping.h>
|
||||
|
||||
#include <linux/usb.h>
|
||||
|
||||
@ -96,18 +95,6 @@ static int hid_start_in(struct hid_device *hid)
|
||||
set_bit(HID_NO_BANDWIDTH, &usbhid->iofl);
|
||||
} else {
|
||||
clear_bit(HID_NO_BANDWIDTH, &usbhid->iofl);
|
||||
|
||||
if (test_bit(HID_RESUME_RUNNING, &usbhid->iofl)) {
|
||||
/*
|
||||
* In case events are generated while nobody was
|
||||
* listening, some are released when the device
|
||||
* is re-opened. Wait 50 msec for the queue to
|
||||
* empty before allowing events to go through
|
||||
* hid.
|
||||
*/
|
||||
usbhid->input_start_time =
|
||||
ktime_add_ms(ktime_get_coarse(), 50);
|
||||
}
|
||||
}
|
||||
}
|
||||
spin_unlock_irqrestore(&usbhid->lock, flags);
|
||||
@ -293,23 +280,20 @@ static void hid_irq_in(struct urb *urb)
|
||||
if (!test_bit(HID_OPENED, &usbhid->iofl))
|
||||
break;
|
||||
usbhid_mark_busy(usbhid);
|
||||
if (test_bit(HID_RESUME_RUNNING, &usbhid->iofl)) {
|
||||
if (ktime_before(ktime_get_coarse(),
|
||||
usbhid->input_start_time))
|
||||
break;
|
||||
clear_bit(HID_RESUME_RUNNING, &usbhid->iofl);
|
||||
if (!test_bit(HID_RESUME_RUNNING, &usbhid->iofl)) {
|
||||
hid_input_report(urb->context, HID_INPUT_REPORT,
|
||||
urb->transfer_buffer,
|
||||
urb->actual_length, 1);
|
||||
/*
|
||||
* autosuspend refused while keys are pressed
|
||||
* because most keyboards don't wake up when
|
||||
* a key is released
|
||||
*/
|
||||
if (hid_check_keys_pressed(hid))
|
||||
set_bit(HID_KEYS_PRESSED, &usbhid->iofl);
|
||||
else
|
||||
clear_bit(HID_KEYS_PRESSED, &usbhid->iofl);
|
||||
}
|
||||
hid_input_report(urb->context, HID_INPUT_REPORT,
|
||||
urb->transfer_buffer, urb->actual_length, 1);
|
||||
/*
|
||||
* autosuspend refused while keys are pressed
|
||||
* because most keyboards don't wake up when
|
||||
* a key is released
|
||||
*/
|
||||
if (hid_check_keys_pressed(hid))
|
||||
set_bit(HID_KEYS_PRESSED, &usbhid->iofl);
|
||||
else
|
||||
clear_bit(HID_KEYS_PRESSED, &usbhid->iofl);
|
||||
break;
|
||||
case -EPIPE: /* stall */
|
||||
usbhid_mark_busy(usbhid);
|
||||
@ -736,6 +720,17 @@ static int usbhid_open(struct hid_device *hid)
|
||||
|
||||
usb_autopm_put_interface(usbhid->intf);
|
||||
|
||||
/*
|
||||
* In case events are generated while nobody was listening,
|
||||
* some are released when the device is re-opened.
|
||||
* Wait 50 msec for the queue to empty before allowing events
|
||||
* to go through hid.
|
||||
*/
|
||||
if (res == 0)
|
||||
msleep(50);
|
||||
|
||||
clear_bit(HID_RESUME_RUNNING, &usbhid->iofl);
|
||||
|
||||
Done:
|
||||
mutex_unlock(&usbhid->mutex);
|
||||
return res;
|
||||
|
@ -13,7 +13,6 @@
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/ktime.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/timer.h>
|
||||
@ -84,7 +83,6 @@ struct usbhid_device {
|
||||
struct mutex mutex; /* start/stop/open/close */
|
||||
spinlock_t lock; /* fifo spinlock */
|
||||
unsigned long iofl; /* I/O flags (CTRL_RUNNING, OUT_RUNNING) */
|
||||
ktime_t input_start_time; /* When to start handling input */
|
||||
struct timer_list io_retry; /* Retry timer */
|
||||
unsigned long stop_retry; /* Time to give up, in jiffies */
|
||||
unsigned int retry_delay; /* Delay length in ms */
|
||||
|
Loading…
Reference in New Issue
Block a user