Commit 5ab92a7c authored by Linus Walleij's avatar Linus Walleij Committed by Jacek Anaszewski

leds: handle suspend/resume in heartbeat trigger

The following phenomena was observed: when suspending the
system, sometimes the heartbeat LED was left on, glowing and
wasting power while the rest of the system is asleep, also
disturbing power dissapation measures on the odd suspend
cycle when it's left on.

Clearly this is not how we want the heartbeat trigger to
work: it should turn off and leave the LED off during
system suspend.

This removes the heartbeat trigger when preparing suspend and
restores it during resume. The trigger code will make sure all
LEDs are left in OFF state after removing the trigger, and
will re-enable the trigger on all LEDs after resuming.

Cc: linux-pm@vger.kernel.org
Signed-off-by: default avatarLinus Walleij <linus.walleij@linaro.org>
Reviewed-by: default avatarUlf Hansson <ulf.hansson@linaro.org>
Signed-off-by: default avatarJacek Anaszewski <j.anaszewski@samsung.com>
parent 7cfe749f
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/leds.h> #include <linux/leds.h>
#include <linux/reboot.h> #include <linux/reboot.h>
#include <linux/suspend.h>
#include "../leds.h" #include "../leds.h"
static int panic_heartbeats; static int panic_heartbeats;
...@@ -154,6 +155,30 @@ static struct led_trigger heartbeat_led_trigger = { ...@@ -154,6 +155,30 @@ static struct led_trigger heartbeat_led_trigger = {
.deactivate = heartbeat_trig_deactivate, .deactivate = heartbeat_trig_deactivate,
}; };
static int heartbeat_pm_notifier(struct notifier_block *nb,
unsigned long pm_event, void *unused)
{
int rc;
switch (pm_event) {
case PM_SUSPEND_PREPARE:
case PM_HIBERNATION_PREPARE:
case PM_RESTORE_PREPARE:
led_trigger_unregister(&heartbeat_led_trigger);
break;
case PM_POST_SUSPEND:
case PM_POST_HIBERNATION:
case PM_POST_RESTORE:
rc = led_trigger_register(&heartbeat_led_trigger);
if (rc)
pr_err("could not re-register heartbeat trigger\n");
break;
default:
break;
}
return NOTIFY_DONE;
}
static int heartbeat_reboot_notifier(struct notifier_block *nb, static int heartbeat_reboot_notifier(struct notifier_block *nb,
unsigned long code, void *unused) unsigned long code, void *unused)
{ {
...@@ -168,6 +193,10 @@ static int heartbeat_panic_notifier(struct notifier_block *nb, ...@@ -168,6 +193,10 @@ static int heartbeat_panic_notifier(struct notifier_block *nb,
return NOTIFY_DONE; return NOTIFY_DONE;
} }
static struct notifier_block heartbeat_pm_nb = {
.notifier_call = heartbeat_pm_notifier,
};
static struct notifier_block heartbeat_reboot_nb = { static struct notifier_block heartbeat_reboot_nb = {
.notifier_call = heartbeat_reboot_notifier, .notifier_call = heartbeat_reboot_notifier,
}; };
...@@ -184,12 +213,14 @@ static int __init heartbeat_trig_init(void) ...@@ -184,12 +213,14 @@ static int __init heartbeat_trig_init(void)
atomic_notifier_chain_register(&panic_notifier_list, atomic_notifier_chain_register(&panic_notifier_list,
&heartbeat_panic_nb); &heartbeat_panic_nb);
register_reboot_notifier(&heartbeat_reboot_nb); register_reboot_notifier(&heartbeat_reboot_nb);
register_pm_notifier(&heartbeat_pm_nb);
} }
return rc; return rc;
} }
static void __exit heartbeat_trig_exit(void) static void __exit heartbeat_trig_exit(void)
{ {
unregister_pm_notifier(&heartbeat_pm_nb);
unregister_reboot_notifier(&heartbeat_reboot_nb); unregister_reboot_notifier(&heartbeat_reboot_nb);
atomic_notifier_chain_unregister(&panic_notifier_list, atomic_notifier_chain_unregister(&panic_notifier_list,
&heartbeat_panic_nb); &heartbeat_panic_nb);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment