diff options
author | Jiri Kosina <jkosina@suse.cz> | 2020-08-18 19:54:04 +0200 |
---|---|---|
committer | Jiri Kosina <jkosina@suse.cz> | 2020-08-18 19:54:04 +0200 |
commit | 5b0545dc184442fa509a311b8c855370441ad5bc (patch) | |
tree | 83e837a88256849230b8dda787357666dc0ef774 /drivers/hid | |
parent | 25a097f5204675550afb879ee18238ca917cba7a (diff) |
Revert "HID: usbhid: do not sleep when opening device"
This reverts commit d3132792285859253c466354fd8d54d1fe0ba786.
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>
Diffstat (limited to 'drivers/hid')
-rw-r--r-- | drivers/hid/usbhid/hid-core.c | 53 | ||||
-rw-r--r-- | drivers/hid/usbhid/usbhid.h | 2 |
2 files changed, 24 insertions, 31 deletions
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c index 492dd641a25d..17a29ee0ac6c 100644 --- a/drivers/hid/usbhid/hid-core.c +++ b/drivers/hid/usbhid/hid-core.c @@ -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; diff --git a/drivers/hid/usbhid/usbhid.h b/drivers/hid/usbhid/usbhid.h index c6ad684d099a..75fe85d3d27a 100644 --- a/drivers/hid/usbhid/usbhid.h +++ b/drivers/hid/usbhid/usbhid.h @@ -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 */ |