From: Atsushi Nemoto Add an LED trigger acts like a heart beat. This can be used as a replacement of CONFIG_HEARTBEAT code exists in some arch's timer code. Signed-off-by: Atsushi Nemoto Acked-by: Richard Purdie Cc: "Nish Aravamudan" Signed-off-by: Andrew Morton --- drivers/leds/Kconfig | 9 ++ drivers/leds/Makefile | 1 drivers/leds/ledtrig-heartbeat.c | 118 +++++++++++++++++++++++++++++ 3 files changed, 128 insertions(+) diff -puN drivers/leds/Kconfig~led-add-led-heartbeat-trigger drivers/leds/Kconfig --- a/drivers/leds/Kconfig~led-add-led-heartbeat-trigger +++ a/drivers/leds/Kconfig @@ -93,5 +93,14 @@ config LEDS_TRIGGER_IDE_DISK This allows LEDs to be controlled by IDE disk activity. If unsure, say Y. +config LEDS_TRIGGER_HEARTBEAT + tristate "LED Heartbeat Trigger" + depends LEDS_TRIGGERS + help + This allows LEDs to be controlled by a CPU load average. + The flash frequency is a hyperbolic function of the 5-minute + load average. + If unsure, say Y. + endmenu diff -puN /dev/null drivers/leds/ledtrig-heartbeat.c --- /dev/null +++ a/drivers/leds/ledtrig-heartbeat.c @@ -0,0 +1,118 @@ +/* + * LED Heartbeat Trigger + * + * Copyright (C) 2006 Atsushi Nemoto + * + * Based on Richard Purdie's ledtrig-timer.c and some arch's + * CONFIG_HEARTBEAT code. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ +#include +#include +#include +#include +#include +#include +#include "leds.h" + +struct heartbeat_trig_data { + unsigned int phase; + unsigned int period; + struct timer_list timer; +}; + +static void led_heartbeat_function(unsigned long data) +{ + struct led_classdev *led_cdev = (struct led_classdev *) data; + struct heartbeat_trig_data *heartbeat_data = led_cdev->trigger_data; + unsigned long brightness = LED_OFF; + unsigned long delay = 0; + + /* acts like an actual heart beat -- ie thump-thump-pause... */ + switch (heartbeat_data->phase) { + case 0: + /* + * The hyperbolic function below modifies the + * heartbeat period length in dependency of the + * current (5min) load. It goes through the points + * f(0)=126, f(1)=86, f(5)=51, f(inf)->30. + */ + heartbeat_data->period = 30 + + (672 << FSHIFT) / (5 * avenrun[0] + (7 << FSHIFT)); + heartbeat_data->period = heartbeat_data->period * HZ / 100; + delay = 7 * HZ / 100; + heartbeat_data->phase++; + brightness = LED_FULL; + break; + case 1: + delay = heartbeat_data->period / 4 - 7 * HZ / 100; + heartbeat_data->phase++; + break; + case 2: + delay = 7 * HZ / 100; + heartbeat_data->phase++; + brightness = LED_FULL; + break; + default: + delay = heartbeat_data->period - heartbeat_data->period / 4 - + 7 * HZ / 100; + heartbeat_data->phase = 0; + break; + } + + led_set_brightness(led_cdev, brightness); + mod_timer(&heartbeat_data->timer, jiffies + delay); +} + +static void heartbeat_trig_activate(struct led_classdev *led_cdev) +{ + struct heartbeat_trig_data *heartbeat_data; + + heartbeat_data = kzalloc(sizeof(*heartbeat_data), GFP_KERNEL); + if (!heartbeat_data) + return; + + led_cdev->trigger_data = heartbeat_data; + init_timer(&heartbeat_data->timer); + heartbeat_data->timer.function = led_heartbeat_function; + heartbeat_data->timer.data = (unsigned long) led_cdev; + heartbeat_data->phase = 0; + led_heartbeat_function(heartbeat_data->timer.data); +} + +static void heartbeat_trig_deactivate(struct led_classdev *led_cdev) +{ + struct heartbeat_trig_data *heartbeat_data = led_cdev->trigger_data; + + if (heartbeat_data) { + del_timer_sync(&heartbeat_data->timer); + kfree(heartbeat_data); + } +} + +static struct led_trigger heartbeat_led_trigger = { + .name = "heartbeat", + .activate = heartbeat_trig_activate, + .deactivate = heartbeat_trig_deactivate, +}; + +static int __init heartbeat_trig_init(void) +{ + return led_trigger_register(&heartbeat_led_trigger); +} + +static void __exit heartbeat_trig_exit(void) +{ + led_trigger_unregister(&heartbeat_led_trigger); +} + +module_init(heartbeat_trig_init); +module_exit(heartbeat_trig_exit); + +MODULE_AUTHOR("Atsushi Nemoto "); +MODULE_DESCRIPTION("Heartbeat LED trigger"); +MODULE_LICENSE("GPL"); diff -puN drivers/leds/Makefile~led-add-led-heartbeat-trigger drivers/leds/Makefile --- a/drivers/leds/Makefile~led-add-led-heartbeat-trigger +++ a/drivers/leds/Makefile @@ -16,3 +16,4 @@ obj-$(CONFIG_LEDS_AMS_DELTA) += leds-am # LED Triggers obj-$(CONFIG_LEDS_TRIGGER_TIMER) += ledtrig-timer.o obj-$(CONFIG_LEDS_TRIGGER_IDE_DISK) += ledtrig-ide-disk.o +obj-$(CONFIG_LEDS_TRIGGER_HEARTBEAT) += ledtrig-heartbeat.o _