Revert "HID: usbhid: do not sleep when opening device"
authorJiri Kosina <jkosina@suse.cz>
Tue, 18 Aug 2020 17:54:04 +0000 (19:54 +0200)
committerJiri Kosina <jkosina@suse.cz>
Tue, 18 Aug 2020 17:54:04 +0000 (19:54 +0200)
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>
drivers/hid/usbhid/hid-core.c
drivers/hid/usbhid/usbhid.h

index 492dd641a25df2225c2d61915e4e7ab6c5a95e12..17a29ee0ac6c23346e2502df0130dc9a50d89db1 100644 (file)
@@ -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;
index c6ad684d099a10d7f7328ca1e0dbe93c7c0ef3f1..75fe85d3d27a0a25d6f5aad7123bcf527ae13261 100644 (file)
@@ -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 */