From 869a9bb51597f069e4976b586bf217f27cc4f290 Mon Sep 17 00:00:00 2001 From: Heinrich Toews Date: Thu, 18 Jun 2026 17:38:07 +0200 Subject: [PATCH] leds: rgb: wago-m4: switch to brightness_set_blocking wago_led_set() acquires send_lock (a mutex) and is therefore a sleeping function. Assigning it to brightness_set violates the LED core API contract: brightness_set is called directly from atomic context (timer/softirq) and must not sleep. On non-RT kernels this would trigger BUG: scheduling while atomic. Use brightness_set_blocking instead. The LED core automatically defers calls through a workqueue, making the sleeping path safe. Update the function signature to return int and add return 0 as required by the blocking callback prototype. Reported-by: Oleg Karfich Signed-off-by: Heinrich Toews --- drivers/leds/rgb/wago-m4-led-wrapper.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/leds/rgb/wago-m4-led-wrapper.c b/drivers/leds/rgb/wago-m4-led-wrapper.c index cf71344782e9..8aa3501c0490 100644 --- a/drivers/leds/rgb/wago-m4-led-wrapper.c +++ b/drivers/leds/rgb/wago-m4-led-wrapper.c @@ -350,7 +350,7 @@ static const struct attribute_group wago_led_attr_group = { #endif /* CONFIG_LEDS_WAGO_M4_WRAPPER_SYSFS_PASSTHROUGH */ -static void wago_led_set(struct led_classdev *led_cdev, +static int wago_led_set(struct led_classdev *led_cdev, enum led_brightness brightness) { struct led_classdev_mc *mc_cdev = lcdev_to_mccdev(led_cdev); @@ -393,6 +393,8 @@ static void wago_led_set(struct led_classdev *led_cdev, mutex_lock(&priv->send_lock); wago_send(priv, &msg, sizeof(msg)); mutex_unlock(&priv->send_lock); + + return 0; } /* ------------------------------------------------------------------------- @@ -420,7 +422,7 @@ static void wago_led_init_subled(struct wago_led *led) led->mc_cdev.subled_info = led->subled_info; led->mc_cdev.num_colors = WAGO_LED_NUM_CHANNELS; - led->mc_cdev.led_cdev.brightness_set = wago_led_set; + led->mc_cdev.led_cdev.brightness_set_blocking = wago_led_set; led->mc_cdev.led_cdev.max_brightness = LED_FULL; led->mc_cdev.led_cdev.flags = LED_CORE_SUSPENDRESUME; led->mc_cdev.led_cdev.color = LED_COLOR_ID_MULTI;