diff --git a/drivers/leds/leds-gpio.c b/drivers/leds/leds-gpio.c index 092eb59a7d325d29a1ed36b80002a1485d2710f7..5d848553262324b71cedfb091fe0a5d2cd4b954a 100644 --- a/drivers/leds/leds-gpio.c +++ b/drivers/leds/leds-gpio.c @@ -103,6 +103,8 @@ static int create_gpio_led(const struct gpio_led *template, led_dat->cdev.flags |= LED_CORE_SUSPENDRESUME; if (template->panic_indicator) led_dat->cdev.flags |= LED_PANIC_INDICATOR; + else if (template->panic_indicator_off) + led_dat->cdev.flags |= LED_PANIC_INDICATOR_OFF; if (template->retain_state_shutdown) led_dat->cdev.flags |= LED_RETAIN_AT_SHUTDOWN; @@ -169,6 +171,8 @@ static struct gpio_leds_priv *gpio_leds_create(struct platform_device *pdev) led.retain_state_shutdown = 1; if (fwnode_property_present(child, "panic-indicator")) led.panic_indicator = 1; + else if (fwnode_property_present(child, "panic-indicator-off")) + led.panic_indicator_off = 1; ret = create_gpio_led(&led, led_dat, dev, child, NULL); if (ret < 0) { diff --git a/drivers/leds/trigger/ledtrig-panic.c b/drivers/leds/trigger/ledtrig-panic.c index 64abf2e91608a5ecdbb80c8fd706f389ee62159c..94764036392e9cd481eac5112930ed7930eaf519 100644 --- a/drivers/leds/trigger/ledtrig-panic.c +++ b/drivers/leds/trigger/ledtrig-panic.c @@ -12,19 +12,25 @@ #include <linux/leds.h> #include "../leds.h" -static struct led_trigger *trigger; +enum led_panic_type { + OFF, + BLINK, + PANIC_TYPE_COUNT, +}; + +static struct led_trigger *trigger[PANIC_TYPE_COUNT]; /* * This is called in a special context by the atomic panic * notifier. This means the trigger can be changed without * worrying about locking. */ -static void led_trigger_set_panic(struct led_classdev *led_cdev) +static void led_trigger_set_panic(struct led_classdev *led_cdev, const char *type) { struct led_trigger *trig; list_for_each_entry(trig, &trigger_list, next_trig) { - if (strcmp("panic", trig->name)) + if (strcmp(type, trig->name)) continue; if (led_cdev->trigger) list_del(&led_cdev->trig_list); @@ -47,8 +53,11 @@ static int led_trigger_panic_notifier(struct notifier_block *nb, struct led_classdev *led_cdev; list_for_each_entry(led_cdev, &leds_list, node) - if (led_cdev->flags & LED_PANIC_INDICATOR) - led_trigger_set_panic(led_cdev); + if (led_cdev->flags & LED_PANIC_INDICATOR_OFF) + led_trigger_set_panic(led_cdev, "panic_off"); + else if (led_cdev->flags & LED_PANIC_INDICATOR) + led_trigger_set_panic(led_cdev, "panic"); + return NOTIFY_DONE; } @@ -56,9 +65,10 @@ static struct notifier_block led_trigger_panic_nb = { .notifier_call = led_trigger_panic_notifier, }; -static long led_panic_blink(int state) +static long led_panic_activity(int state) { - led_trigger_event(trigger, state ? LED_FULL : LED_OFF); + led_trigger_event(trigger[OFF], LED_OFF); + led_trigger_event(trigger[BLINK], state ? LED_FULL : LED_OFF); return 0; } @@ -67,8 +77,9 @@ static int __init ledtrig_panic_init(void) atomic_notifier_chain_register(&panic_notifier_list, &led_trigger_panic_nb); - led_trigger_register_simple("panic", &trigger); - panic_blink = led_panic_blink; + led_trigger_register_simple("panic_off", &trigger[OFF]); + led_trigger_register_simple("panic", &trigger[BLINK]); + panic_blink = led_panic_activity; return 0; } device_initcall(ledtrig_panic_init); diff --git a/include/linux/leds.h b/include/linux/leds.h index a0b730be40ad2f1bd6c98669ea1b2277dafcc802..fcbff7eda92ad65fb6a6f7136e1c65ca101adec5 100644 --- a/include/linux/leds.h +++ b/include/linux/leds.h @@ -85,6 +85,7 @@ struct led_classdev { #define LED_BRIGHT_HW_CHANGED BIT(21) #define LED_RETAIN_AT_SHUTDOWN BIT(22) #define LED_INIT_DEFAULT_TRIGGER BIT(23) +#define LED_PANIC_INDICATOR_OFF BIT(24) /* set_brightness_work / blink_timer flags, atomic, private. */ unsigned long work_flags; @@ -521,6 +522,7 @@ struct gpio_led { unsigned active_low : 1; unsigned retain_state_suspended : 1; unsigned panic_indicator : 1; + unsigned panic_indicator_off : 1; unsigned default_state : 2; unsigned retain_state_shutdown : 1; /* default_state should be one of LEDS_GPIO_DEFSTATE_(ON|OFF|KEEP) */