Skip to content

Commit 93690cd

Browse files
elkablopavelmachek
authored andcommitted
leds: trigger: add support for LED-private device triggers
Some LED controllers may come with an internal HW triggering mechanism for the LED and the ability to switch between SW control and the internal HW control. This includes most PHYs, various ethernet switches, the Turris Omnia LED controller or AXP20X PMIC. This adds support for registering such triggers. This code is based on work by Pavel Machek <pavel@ucw.cz> and Ondřej Jirman <megous@megous.com>. Signed-off-by: Marek Behún <marek.behun@nic.cz> Acked-by: Jacek Anaszewski <jacek.anaszewski@gmail.com> Signed-off-by: Pavel Machek <pavel@ucw.cz>
1 parent 00253ec commit 93690cd

2 files changed

Lines changed: 30 additions & 6 deletions

File tree

drivers/leds/led-triggers.c

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,12 @@ LIST_HEAD(trigger_list);
2727

2828
/* Used by LED Class */
2929

30+
static inline bool
31+
trigger_relevant(struct led_classdev *led_cdev, struct led_trigger *trig)
32+
{
33+
return !trig->trigger_type || trig->trigger_type == led_cdev->trigger_type;
34+
}
35+
3036
ssize_t led_trigger_write(struct file *filp, struct kobject *kobj,
3137
struct bin_attribute *bin_attr, char *buf,
3238
loff_t pos, size_t count)
@@ -50,7 +56,7 @@ ssize_t led_trigger_write(struct file *filp, struct kobject *kobj,
5056

5157
down_read(&triggers_list_lock);
5258
list_for_each_entry(trig, &trigger_list, next_trig) {
53-
if (sysfs_streq(buf, trig->name)) {
59+
if (sysfs_streq(buf, trig->name) && trigger_relevant(led_cdev, trig)) {
5460
down_write(&led_cdev->trigger_lock);
5561
led_trigger_set(led_cdev, trig);
5662
up_write(&led_cdev->trigger_lock);
@@ -93,8 +99,12 @@ static int led_trigger_format(char *buf, size_t size,
9399
led_cdev->trigger ? "none" : "[none]");
94100

95101
list_for_each_entry(trig, &trigger_list, next_trig) {
96-
bool hit = led_cdev->trigger &&
97-
!strcmp(led_cdev->trigger->name, trig->name);
102+
bool hit;
103+
104+
if (!trigger_relevant(led_cdev, trig))
105+
continue;
106+
107+
hit = led_cdev->trigger && !strcmp(led_cdev->trigger->name, trig->name);
98108

99109
len += led_trigger_snprintf(buf + len, size - len,
100110
" %s%s%s", hit ? "[" : "",
@@ -243,7 +253,8 @@ void led_trigger_set_default(struct led_classdev *led_cdev)
243253
down_read(&triggers_list_lock);
244254
down_write(&led_cdev->trigger_lock);
245255
list_for_each_entry(trig, &trigger_list, next_trig) {
246-
if (!strcmp(led_cdev->default_trigger, trig->name)) {
256+
if (!strcmp(led_cdev->default_trigger, trig->name) &&
257+
trigger_relevant(led_cdev, trig)) {
247258
led_cdev->flags |= LED_INIT_DEFAULT_TRIGGER;
248259
led_trigger_set(led_cdev, trig);
249260
break;
@@ -280,7 +291,9 @@ int led_trigger_register(struct led_trigger *trig)
280291
down_write(&triggers_list_lock);
281292
/* Make sure the trigger's name isn't already in use */
282293
list_for_each_entry(_trig, &trigger_list, next_trig) {
283-
if (!strcmp(_trig->name, trig->name)) {
294+
if (!strcmp(_trig->name, trig->name) &&
295+
(trig->trigger_type == _trig->trigger_type ||
296+
!trig->trigger_type || !_trig->trigger_type)) {
284297
up_write(&triggers_list_lock);
285298
return -EEXIST;
286299
}
@@ -294,7 +307,8 @@ int led_trigger_register(struct led_trigger *trig)
294307
list_for_each_entry(led_cdev, &leds_list, node) {
295308
down_write(&led_cdev->trigger_lock);
296309
if (!led_cdev->trigger && led_cdev->default_trigger &&
297-
!strcmp(led_cdev->default_trigger, trig->name)) {
310+
!strcmp(led_cdev->default_trigger, trig->name) &&
311+
trigger_relevant(led_cdev, trig)) {
298312
led_cdev->flags |= LED_INIT_DEFAULT_TRIGGER;
299313
led_trigger_set(led_cdev, trig);
300314
}

include/linux/leds.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,10 @@ struct led_init_data {
5757
bool devname_mandatory;
5858
};
5959

60+
struct led_hw_trigger_type {
61+
int dummy;
62+
};
63+
6064
struct led_classdev {
6165
const char *name;
6266
enum led_brightness brightness;
@@ -141,6 +145,9 @@ struct led_classdev {
141145
void *trigger_data;
142146
/* true if activated - deactivate routine uses it to do cleanup */
143147
bool activated;
148+
149+
/* LEDs that have private triggers have this set */
150+
struct led_hw_trigger_type *trigger_type;
144151
#endif
145152

146153
#ifdef CONFIG_LEDS_BRIGHTNESS_HW_CHANGED
@@ -345,6 +352,9 @@ struct led_trigger {
345352
int (*activate)(struct led_classdev *led_cdev);
346353
void (*deactivate)(struct led_classdev *led_cdev);
347354

355+
/* LED-private triggers have this set */
356+
struct led_hw_trigger_type *trigger_type;
357+
348358
/* LEDs under control by this trigger (for simple triggers) */
349359
rwlock_t leddev_list_lock;
350360
struct list_head led_cdevs;

0 commit comments

Comments
 (0)