Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 27 Mar 2018 10:59:57 +0000
From:      bugzilla-noreply@freebsd.org
To:        freebsd-usb@FreeBSD.org
Subject:   [Bug 226968] IRQ storm on cpu0 timer when holding down key on USB keyboard
Message-ID:  <bug-226968-17-Nr0XiwFMES@https.bugs.freebsd.org/bugzilla/>
In-Reply-To: <bug-226968-17@https.bugs.freebsd.org/bugzilla/>
References:  <bug-226968-17@https.bugs.freebsd.org/bugzilla/>

index | next in thread | previous in thread | raw e-mail

https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=226968

--- Comment #3 from Hans Petter Selasky <hselasky@FreeBSD.org> ---
Hi,

I have been discussing some patches with Bruce Evans on this topic. The problem
is the keyboard repeat rate is zero, which cause the timer to trigger
instantly. This issue fell off my radar. Here is the last patch WIP:

Index: sys/arm/samsung/exynos/chrome_kb.c
===================================================================
--- sys/arm/samsung/exynos/chrome_kb.c
+++ sys/arm/samsung/exynos/chrome_kb.c
@@ -514,17 +514,8 @@
         if (!KBD_HAS_DEVICE(kbd)) {
             return (0);
         }
-        if (((int *)arg)[1] < 0) {
-            return (EINVAL);
-        }
-        if (((int *)arg)[0] < 0) {
-            return (EINVAL);
-        }
-        if (((int *)arg)[0] < 200)    /* fastest possible value */
-            kbd->kb_delay1 = 200;
-        else
-            kbd->kb_delay1 = ((int *)arg)[0];
-        kbd->kb_delay2 = ((int *)arg)[1];
+        kbd->kb_delay1 = KEYBOARD_REPEAT_GET(arg,0,200,1000);
+        kbd->kb_delay2 = KEYBOARD_REPEAT_GET(arg,1,34,504);
         return (0);

     case KDSETRAD:            /* set keyboard repeat rate (old
Index: sys/arm/versatile/pl050.c
===================================================================
--- sys/arm/versatile/pl050.c
+++ sys/arm/versatile/pl050.c
@@ -418,17 +418,8 @@
         if (!KBD_HAS_DEVICE(kbd)) {
             return (0);
         }
-        if (((int *)arg)[1] < 0) {
-            return (EINVAL);
-        }
-        if (((int *)arg)[0] < 0) {
-            return (EINVAL);
-        }
-        if (((int *)arg)[0] < 200)    /* fastest possible value */
-            kbd->kb_delay1 = 200;
-        else
-            kbd->kb_delay1 = ((int *)arg)[0];
-        kbd->kb_delay2 = ((int *)arg)[1];
+        kbd->kb_delay1 = KEYBOARD_REPEAT_GET(arg,0,200,1000);
+        kbd->kb_delay2 = KEYBOARD_REPEAT_GET(arg,1,34,504);
         return (0);

 #if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5) || \
Index: sys/dev/adb/adb_kbd.c
===================================================================
--- sys/dev/adb/adb_kbd.c
+++ sys/dev/adb/adb_kbd.c
@@ -780,16 +780,8 @@
     case KDSETREPEAT:
         if (!KBD_HAS_DEVICE(kbd))
             return 0;
-        if (((int *)data)[1] < 0)
-            return EINVAL;
-        if (((int *)data)[0] < 0)
-            return EINVAL;
-        else if (((int *)data)[0] == 0)  /* fastest possible value */
-            kbd->kb_delay1 = 200;
-        else
-            kbd->kb_delay1 = ((int *)data)[0];
-        kbd->kb_delay2 = ((int *)data)[1];
-
+        kbd->kb_delay1 = KEYBOARD_REPEAT_GET(data,0,200,1000);
+        kbd->kb_delay2 = KEYBOARD_REPEAT_GET(data,1,34,504);
         break;

     case KDSETRAD:
Index: sys/dev/gpio/gpiokeys.c
===================================================================
--- sys/dev/gpio/gpiokeys.c
+++ sys/dev/gpio/gpiokeys.c
@@ -822,17 +822,8 @@
         if (!KBD_HAS_DEVICE(kbd)) {
             return (0);
         }
-        if (((int *)arg)[1] < 0) {
-            return (EINVAL);
-        }
-        if (((int *)arg)[0] < 0) {
-            return (EINVAL);
-        }
-        if (((int *)arg)[0] < 200)    /* fastest possible value */
-            kbd->kb_delay1 = 200;
-        else
-            kbd->kb_delay1 = ((int *)arg)[0];
-        kbd->kb_delay2 = ((int *)arg)[1];
+        kbd->kb_delay1 = KEYBOARD_REPEAT_GET(arg,0,200,1000);
+        kbd->kb_delay2 = KEYBOARD_REPEAT_GET(arg,1,34,504);
         return (0);

 #if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5) || \
Index: sys/dev/usb/input/ukbd.c
===================================================================
--- sys/dev/usb/input/ukbd.c
+++ sys/dev/usb/input/ukbd.c
@@ -1946,14 +1946,8 @@
         if (!KBD_HAS_DEVICE(kbd)) {
             return (0);
         }
-        /*
-         * Convert negative, zero and tiny args to the same limits
-         * as atkbd.  We could support delays of 1 msec, but
-         * anything much shorter than the shortest atkbd value
-         * of 250.34 is almost unusable as well as incompatible.
-         */
-        kbd->kb_delay1 = imax(((int *)arg)[0], 250);
-        kbd->kb_delay2 = imax(((int *)arg)[1], 34);
+        kbd->kb_delay1 = KEYBOARD_REPEAT_GET(arg,0,200,1000);
+        kbd->kb_delay2 = KEYBOARD_REPEAT_GET(arg,1,34,504);
 #ifdef EVDEV_SUPPORT
         if (sc->sc_evdev != NULL)
             evdev_push_repeats(sc->sc_evdev, kbd);
Index: sys/sys/kbio.h
===================================================================
--- sys/sys/kbio.h
+++ sys/sys/kbio.h
@@ -87,6 +87,15 @@
     int        kb_repeat[2];
 };
 typedef struct keyboard_repeat keyboard_repeat_t;
+
+#define    KEYBOARD_REPEAT_GET(p,i,min,max) ({    \
+    const struct keyboard_repeat *__ptr =    \
+    (const struct keyboard_repeat *)(p);    \
+    __ptr->kb_repeat[i] < (min) ? (int)(min) :    \
+    __ptr->kb_repeat[i] > (max) ? (int)(max) :    \
+    __ptr->kb_repeat[i];            \
+})
+
 #define KDSETREPEAT    _IOW('K', 102, keyboard_repeat_t)
 #define KDGETREPEAT    _IOR('K', 103, keyboard_repeat_t)

-- 
You are receiving this mail because:
You are the assignee for the bug.

help

Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?bug-226968-17-Nr0XiwFMES>