USB HID random timeout failures fix proposal

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi,


I made a patch that does to tackle the USB HID device random behavior by

re-trying to send command 400ms, 20ms sleep per try.

---------------------------------------------------------------------------------------

>From d4214685de329ebe07dfd2298bce46dfae5f80bf Mon Sep 17 00:00:00 2001
From: Lauri Jakku <lja@xxxxxx>
Date: Tue, 4 Feb 2020 04:52:01 +0200
Subject: [PATCH] USB HID random timeout failures fixed by trying 20 times
 send, 20ms apart, control messages, if error is timeout.

Signed-off-by: Lauri Jakku <lja@xxxxxx>
---
 drivers/usb/core/message.c | 30 +++++++++++++++++++++++++-----
 1 file changed, 25 insertions(+), 5 deletions(-)

diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index 5adf489428aa..5d615b2f92d8 100644
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -20,6 +20,7 @@
 #include <linux/usb/hcd.h>     /* for usbcore internals */
 #include <linux/usb/of.h>
 #include <asm/byteorder.h>
+#include <linux/errno.h>
 
 #include "usb.h"
 
@@ -137,7 +138,10 @@ int usb_control_msg(struct usb_device *dev, unsigned int pipe, __u8 request,
                    __u16 size, int timeout)
 {
        struct usb_ctrlrequest *dr;
-       int ret;
+       int ret = -ETIMEDOUT;
+
+       /* retry_cnt * 10ms, max retry time set to 400ms */
+       int retry_cnt = 20;
 
        dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_NOIO);
        if (!dr)
@@ -149,11 +153,27 @@ int usb_control_msg(struct usb_device *dev, unsigned int pipe, __u8 request,
        dr->wIndex = cpu_to_le16(index);
        dr->wLength = cpu_to_le16(size);
 
-       ret = usb_internal_control_msg(dev, pipe, dr, data, size, timeout);
+       do {
+               ret = usb_internal_control_msg(dev,
+                                       pipe,
+                                       dr,
+                                       data,
+                                       size,
+                                       timeout);
+
+               /*
+                * Linger a bit, prior to the next control message
+                * or if return value is timeout, but do try few
+                * times (max 200ms) before quitting.
+                */
+               if (dev->quirks & USB_QUIRK_DELAY_CTRL_MSG)
+                       msleep(200);
+               else if (ret == -ETIMEDOUT)
+                       msleep(20);
+
+               /* Loop while timeout, max retry_cnt times. */
+       } while ((retry_cnt-- > 0) && (ret == -ETIMEDOUT));
 
-       /* Linger a bit, prior to the next control message. */
-       if (dev->quirks & USB_QUIRK_DELAY_CTRL_MSG)
-               msleep(200);
 
        kfree(dr);
 
-- 
2.25.0


-- 
Br,
Lauri J.




[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux