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 <oleg.karfich@wago.com> Signed-off-by: Heinrich Toews <ht@twx-software.de>
This commit is contained in:
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user