[lkml]   [2014]   [Oct]   [1]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
Messages in this thread
Patch in this message
SubjectRe: [PATCH] Route keyboard LEDs through the generic LEDs layer.
Andrew Morton, le Wed 01 Oct 2014 11:42:57 -0700, a écrit :
> On Mon, 31 Mar 2014 14:23:23 +0200 Samuel Thibault <> wrote:
> > This permits to reassign keyboard LEDs to something else than keyboard "leds"
> > state, by adding keyboard led and modifier triggers connected to a series
> > of VT input LEDs, themselves connected to VT input triggers, which
> > per-input device LEDs use by default. Userland can thus easily change the LED
> > behavior of (a priori) all input devices, or of particular input devices.
> >
> > This also permits to fix #7063 from userland by using a modifier to implement
> > proper CapsLock behavior and have the keyboard caps lock led show that modifier
> > state.
> When this patch is combined with current linux-next I'm getting the
> below lockdep splat. Config:

Yes, this was reported and I sent a fix some time ago (Tue, 26 Aug 2014
11:17:25 +0200), here is the patch again:

Subject: Defer input led work to workqueue

When the kbd changes its led state (e.g. caps lock), this triggers
(led_trigger_event) the kbd-capsl trigger, which is by default
used by the vt::capsl LED, which triggers (led_trigger_event) the
vt-capsl trigger. These two nested led_trigger_event calls take a
trig->leddev_list_lock lock and thus lockdep complains.

Actually the user can make the vt::capsl LED use its own vt-capsl
trigger and thus build a loop. This produces an immediate oops.

This changeset defers the second led_trigger_event call into a
workqueue, which avoids the nested locking altogether. This does
not prevent the user from shooting himself in the foot by creating a
vt::capsl <-> vt-capsl loop, but the only consequence is the workqueue
threads eating some CPU until the user breaks the loop, which is not too

Signed-off-by: Samuel Thibault <>

--- a/drivers/input/leds.c
+++ b/drivers/input/leds.c
@@ -100,13 +100,24 @@ static unsigned long vt_led_registered[B
/* Number of input devices having each LED */
static int vt_led_references[LED_CNT];

+static int vt_led_state[LED_CNT];
+static struct work_struct vt_led_work[LED_CNT];
+static void vt_led_cb(struct work_struct *work)
+ int led = work - vt_led_work;
+ led_trigger_event(&vt_led_triggers[led], vt_led_state[led]);
/* VT LED state change, tell the VT trigger. */
static void vt_led_set(struct led_classdev *cdev,
enum led_brightness brightness)
int led = cdev - vt_leds;

- led_trigger_event(&vt_led_triggers[led], !!brightness);
+ vt_led_state[led] = !!brightness;
+ schedule_work(&vt_led_work[led]);

/* LED state change for some keyboard, notify that keyboard. */
@@ -244,6 +255,22 @@ void input_led_disconnect(struct input_d

+static int __init input_led_init(void)
+ unsigned i;
+ for (i = 0; i < LED_CNT; i++)
+ INIT_WORK(&vt_led_work[i], vt_led_cb);
+ return 0;
+static void __exit input_led_exit(void)
MODULE_DESCRIPTION("User LED support for input layer");
MODULE_AUTHOR("Samuel Thibault <>");
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to
More majordomo info at
Please read the FAQ at

 \ /
  Last update: 2014-10-02 00:21    [W:0.158 / U:3.364 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site