From 2282e125a406e09331c5a785e3df29035c99a607 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Mon, 2 Jul 2018 22:05:21 +0200 Subject: leds: triggers: let struct led_trigger::activate() return an error code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Given that activating a trigger can fail, let the callback return an indication. This prevents to have a trigger active according to the "trigger" sysfs attribute but not functional. All users are changed accordingly to return 0 for now. There is no intended change in behaviour. Signed-off-by: Uwe Kleine-König Acked-by: Pavel Machek Signed-off-by: Jacek Anaszewski --- include/linux/leds.h | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'include/linux') diff --git a/include/linux/leds.h b/include/linux/leds.h index b7e82550e655..ba5baaaa43bf 100644 --- a/include/linux/leds.h +++ b/include/linux/leds.h @@ -253,7 +253,7 @@ static inline bool led_sysfs_is_disabled(struct led_classdev *led_cdev) struct led_trigger { /* Trigger Properties */ const char *name; - void (*activate)(struct led_classdev *led_cdev); + int (*activate)(struct led_classdev *led_cdev); void (*deactivate)(struct led_classdev *led_cdev); /* LEDs under control by this trigger (for simple triggers) */ @@ -288,8 +288,8 @@ extern void led_trigger_blink_oneshot(struct led_trigger *trigger, unsigned long *delay_off, int invert); extern void led_trigger_set_default(struct led_classdev *led_cdev); -extern void led_trigger_set(struct led_classdev *led_cdev, - struct led_trigger *trigger); +extern int led_trigger_set(struct led_classdev *led_cdev, + struct led_trigger *trigger); extern void led_trigger_remove(struct led_classdev *led_cdev); static inline void *led_get_trigger_data(struct led_classdev *led_cdev) @@ -334,8 +334,12 @@ static inline void led_trigger_blink_oneshot(struct led_trigger *trigger, unsigned long *delay_off, int invert) {} static inline void led_trigger_set_default(struct led_classdev *led_cdev) {} -static inline void led_trigger_set(struct led_classdev *led_cdev, - struct led_trigger *trigger) {} +static inline int led_trigger_set(struct led_classdev *led_cdev, + struct led_trigger *trigger) +{ + return 0; +} + static inline void led_trigger_remove(struct led_classdev *led_cdev) {} static inline void *led_get_trigger_data(struct led_classdev *led_cdev) { -- cgit v1.2.3-71-gd317 From a7e7a3156300a7e1982b03cc9cb8fb0c86434c49 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Mon, 2 Jul 2018 22:05:22 +0200 Subject: leds: triggers: add device attribute support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As many triggers use device attributes, add support for these in led_trigger_set which allows simplifying the drivers accordingly. Signed-off-by: Uwe Kleine-König Acked-by: Pavel Machek Signed-off-by: Jacek Anaszewski --- drivers/leds/led-triggers.c | 12 ++++++++++++ include/linux/leds.h | 11 +++++++++++ 2 files changed, 23 insertions(+) (limited to 'include/linux') diff --git a/drivers/leds/led-triggers.c b/drivers/leds/led-triggers.c index a8786f4b3453..3f3e8728d82c 100644 --- a/drivers/leds/led-triggers.c +++ b/drivers/leds/led-triggers.c @@ -127,6 +127,7 @@ int led_trigger_set(struct led_classdev *led_cdev, struct led_trigger *trig) led_stop_software_blink(led_cdev); if (led_cdev->trigger->deactivate) led_cdev->trigger->deactivate(led_cdev); + device_remove_groups(led_cdev->dev, led_cdev->trigger->groups); led_cdev->trigger = NULL; led_set_brightness(led_cdev, LED_OFF); } @@ -143,6 +144,12 @@ int led_trigger_set(struct led_classdev *led_cdev, struct led_trigger *trig) if (ret) goto err_activate; + + ret = device_add_groups(led_cdev->dev, trig->groups); + if (ret) { + dev_err(led_cdev->dev, "Failed to add trigger attributes\n"); + goto err_add_groups; + } } if (event) { @@ -156,7 +163,12 @@ int led_trigger_set(struct led_classdev *led_cdev, struct led_trigger *trig) return 0; +err_add_groups: + + if (trig->deactivate) + trig->deactivate(led_cdev); err_activate: + led_cdev->trigger = NULL; write_lock_irqsave(&led_cdev->trigger->leddev_list_lock, flags); list_del(&led_cdev->trig_list); diff --git a/include/linux/leds.h b/include/linux/leds.h index ba5baaaa43bf..33484a5c7478 100644 --- a/include/linux/leds.h +++ b/include/linux/leds.h @@ -262,8 +262,19 @@ struct led_trigger { /* Link to next registered trigger */ struct list_head next_trig; + + const struct attribute_group **groups; }; +/* + * Currently the attributes in struct led_trigger::groups are added directly to + * the LED device. As this might change in the future, the following + * macros abstract getting the LED device and its trigger_data from the dev + * parameter passed to the attribute accessor functions. + */ +#define led_trigger_get_led(dev) ((struct led_classdev *)dev_get_drvdata((dev))) +#define led_trigger_get_drvdata(dev) (led_get_trigger_data(led_trigger_get_led(dev))) + ssize_t led_trigger_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count); ssize_t led_trigger_show(struct device *dev, struct device_attribute *attr, -- cgit v1.2.3-71-gd317 From a0b750768371e410d77b60bcf49c18bd45078d55 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Mon, 2 Jul 2018 22:05:24 +0200 Subject: leds: triggers: define module_led_trigger helper MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This helps to simplify modules that provide a simple led_trigger. It's inspired by module_platform_driver, module_i2c_driver et al. Signed-off-by: Uwe Kleine-König Acked-by: Pavel Machek Signed-off-by: Jacek Anaszewski --- include/linux/leds.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'include/linux') diff --git a/include/linux/leds.h b/include/linux/leds.h index 33484a5c7478..a3ee10846a4b 100644 --- a/include/linux/leds.h +++ b/include/linux/leds.h @@ -326,6 +326,10 @@ static inline void *led_get_trigger_data(struct led_classdev *led_cdev) extern void led_trigger_rename_static(const char *name, struct led_trigger *trig); +#define module_led_trigger(__led_trigger) \ + module_driver(__led_trigger, led_trigger_register, \ + led_trigger_unregister) + #else /* Trigger has no members */ -- cgit v1.2.3-71-gd317 From 9acc560de2aac73ef99c54f0fdfb86b4684296b5 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Mon, 2 Jul 2018 22:05:25 +0200 Subject: leds: triggers: new function led_set_trigger_data() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is the natural counter part to the already existing led_get_trigger_data(). Signed-off-by: Uwe Kleine-König Acked-by: Pavel Machek Signed-off-by: Jacek Anaszewski --- include/linux/leds.h | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'include/linux') diff --git a/include/linux/leds.h b/include/linux/leds.h index a3ee10846a4b..834683d603f9 100644 --- a/include/linux/leds.h +++ b/include/linux/leds.h @@ -303,6 +303,12 @@ extern int led_trigger_set(struct led_classdev *led_cdev, struct led_trigger *trigger); extern void led_trigger_remove(struct led_classdev *led_cdev); +static inline void led_set_trigger_data(struct led_classdev *led_cdev, + void *trigger_data) +{ + led_cdev->trigger_data = trigger_data; +} + static inline void *led_get_trigger_data(struct led_classdev *led_cdev) { return led_cdev->trigger_data; @@ -356,6 +362,7 @@ static inline int led_trigger_set(struct led_classdev *led_cdev, } static inline void led_trigger_remove(struct led_classdev *led_cdev) {} +static inline void led_set_trigger_data(struct led_classdev *led_cdev) {} static inline void *led_get_trigger_data(struct led_classdev *led_cdev) { return NULL; -- cgit v1.2.3-71-gd317