Commit 0b88b71c authored by Paulo Costa's avatar Paulo Costa Committed by Jacek Anaszewski

leds/trigger/cpu: Add LED trigger for all CPUs aggregated

Currently there is one CPU led trigger per cpu ('cpu0', 'cpu1', ...)

This patch adds a new trigger, 'cpu', with brightness proportional to
the number of active CPUs.

If multiple brightness levels aren't supported on the LED,
it effectively indicates if there is any CPU active.

This is particularly useful on tiny linux boards with more CPU cores than LED pins.
Signed-off-by: default avatarPaulo Costa <me@paulo.costa.nom.br>
Acked-by: default avatarPavel Machek <pavel@ucw.cz>
Signed-off-by: default avatarJacek Anaszewski <jacek.anaszewski@gmail.com>
parent c1ae3cfa
...@@ -31,12 +31,16 @@ ...@@ -31,12 +31,16 @@
#define MAX_NAME_LEN 8 #define MAX_NAME_LEN 8
struct led_trigger_cpu { struct led_trigger_cpu {
bool is_active;
char name[MAX_NAME_LEN]; char name[MAX_NAME_LEN];
struct led_trigger *_trig; struct led_trigger *_trig;
}; };
static DEFINE_PER_CPU(struct led_trigger_cpu, cpu_trig); static DEFINE_PER_CPU(struct led_trigger_cpu, cpu_trig);
static struct led_trigger *trig_cpu_all;
static atomic_t num_active_cpus = ATOMIC_INIT(0);
/** /**
* ledtrig_cpu - emit a CPU event as a trigger * ledtrig_cpu - emit a CPU event as a trigger
* @evt: CPU event to be emitted * @evt: CPU event to be emitted
...@@ -47,26 +51,46 @@ static DEFINE_PER_CPU(struct led_trigger_cpu, cpu_trig); ...@@ -47,26 +51,46 @@ static DEFINE_PER_CPU(struct led_trigger_cpu, cpu_trig);
void ledtrig_cpu(enum cpu_led_event ledevt) void ledtrig_cpu(enum cpu_led_event ledevt)
{ {
struct led_trigger_cpu *trig = this_cpu_ptr(&cpu_trig); struct led_trigger_cpu *trig = this_cpu_ptr(&cpu_trig);
bool is_active = trig->is_active;
/* Locate the correct CPU LED */ /* Locate the correct CPU LED */
switch (ledevt) { switch (ledevt) {
case CPU_LED_IDLE_END: case CPU_LED_IDLE_END:
case CPU_LED_START: case CPU_LED_START:
/* Will turn the LED on, max brightness */ /* Will turn the LED on, max brightness */
led_trigger_event(trig->_trig, LED_FULL); is_active = true;
break; break;
case CPU_LED_IDLE_START: case CPU_LED_IDLE_START:
case CPU_LED_STOP: case CPU_LED_STOP:
case CPU_LED_HALTED: case CPU_LED_HALTED:
/* Will turn the LED off */ /* Will turn the LED off */
led_trigger_event(trig->_trig, LED_OFF); is_active = false;
break; break;
default: default:
/* Will leave the LED as it is */ /* Will leave the LED as it is */
break; break;
} }
if (is_active != trig->is_active) {
unsigned int active_cpus;
unsigned int total_cpus;
/* Update trigger state */
trig->is_active = is_active;
atomic_add(is_active ? 1 : -1, &num_active_cpus);
active_cpus = atomic_read(&num_active_cpus);
total_cpus = num_present_cpus();
led_trigger_event(trig->_trig,
is_active ? LED_FULL : LED_OFF);
led_trigger_event(trig_cpu_all,
DIV_ROUND_UP(LED_FULL * active_cpus, total_cpus));
}
} }
EXPORT_SYMBOL(ledtrig_cpu); EXPORT_SYMBOL(ledtrig_cpu);
...@@ -112,6 +136,11 @@ static int __init ledtrig_cpu_init(void) ...@@ -112,6 +136,11 @@ static int __init ledtrig_cpu_init(void)
/* Supports up to 9999 cpu cores */ /* Supports up to 9999 cpu cores */
BUILD_BUG_ON(CONFIG_NR_CPUS > 9999); BUILD_BUG_ON(CONFIG_NR_CPUS > 9999);
/*
* Registering a trigger for all CPUs.
*/
led_trigger_register_simple("cpu", &trig_cpu_all);
/* /*
* Registering CPU led trigger for each CPU core here * Registering CPU led trigger for each CPU core here
* ignores CPU hotplug, but after this CPU hotplug works * ignores CPU hotplug, but after this CPU hotplug works
......
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