diff options
-rw-r--r-- | drivers/leds/trigger/ledtrig-cpu.c | 33 |
1 files changed, 31 insertions, 2 deletions
diff --git a/drivers/leds/trigger/ledtrig-cpu.c b/drivers/leds/trigger/ledtrig-cpu.c index a41896468cb3..66a626091936 100644 --- a/drivers/leds/trigger/ledtrig-cpu.c +++ b/drivers/leds/trigger/ledtrig-cpu.c @@ -31,12 +31,16 @@ #define MAX_NAME_LEN 8 struct led_trigger_cpu { + bool is_active; char name[MAX_NAME_LEN]; struct led_trigger *_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 * @evt: CPU event to be emitted @@ -47,26 +51,46 @@ static DEFINE_PER_CPU(struct led_trigger_cpu, cpu_trig); void ledtrig_cpu(enum cpu_led_event ledevt) { struct led_trigger_cpu *trig = this_cpu_ptr(&cpu_trig); + bool is_active = trig->is_active; /* Locate the correct CPU LED */ switch (ledevt) { case CPU_LED_IDLE_END: case CPU_LED_START: /* Will turn the LED on, max brightness */ - led_trigger_event(trig->_trig, LED_FULL); + is_active = true; break; case CPU_LED_IDLE_START: case CPU_LED_STOP: case CPU_LED_HALTED: /* Will turn the LED off */ - led_trigger_event(trig->_trig, LED_OFF); + is_active = false; break; default: /* Will leave the LED as it is */ 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); @@ -113,6 +137,11 @@ static int __init ledtrig_cpu_init(void) 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 * ignores CPU hotplug, but after this CPU hotplug works * fine with this trigger. |