Thank you, Pavel and Jacek 2017-02-12 18:45 GMT-02:00 Jacek Anaszewski <jacek.anaszewski@xxxxxxxxx>: > Hi Paulo, > > Thanks for the patch, > Pavel - thanks for the review. > > Patch applied to the for-4.12 branch of linux-leds.git. > > Best regards, > Jacek Anaszewski > > On 02/10/2017 12:07 AM, Paulo Costa wrote: >> 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: Paulo Costa <me@xxxxxxxxxxxxxxxxxx> >> CC: Pavel Machek <pavel@xxxxxx> >> --- >> v2: >> * Fix concurrency issues during initialization >> * Round up the division >> --- >> drivers/leds/trigger/ledtrig-cpu.c | 33 +++++++++++++++++++++++++++++++-- >> 1 file changed, 31 insertions(+), 2 deletions(-) >> >> diff --git a/drivers/leds/trigger/ledtrig-cpu.c b/drivers/leds/trigger/ledtrig-cpu.c >> index 22f0634..06ec733 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. >>