[PATCH 1/3] leds: create a trigger for ARM CPU activity

Bryan Wu bryan.wu at canonical.com
Fri Jun 24 21:42:31 EDT 2011


On Thu, Jun 23, 2011 at 1:33 AM, Linus Walleij
<linus.walleij at stericsson.com> wrote:
> From: Linus Walleij <linus.walleij at linaro.org>
>
> Attempting to consolidate the ARM LED code, this removes the
> custom RealView LED trigger code to turn LEDs on and off in
> response to CPU activity and replace it with a standard trigger.
> It uses the existing kernel hooks deep inside <asm/leds.h> to
> get CPU activity.
>

I've been thinking about moving the arm led_event interface to
drivers/leds/. And maybe other machines can simply benefit from this
trigger driver, since the led_event interface is actually not really
ARM specific.

So what about add a new trigger just named ledtrig-cpu.c which can be
shared by other machines as well as ARM monsters.

> Cc: Bryan Wu <bryan.wu at canonical.com>
> Cc: Richard Purdie <rpurdie at rpsys.net>
> Signed-off-by: Linus Walleij <linus.walleij at linaro.org>
> ---
>  drivers/leds/Kconfig           |   15 +++++
>  drivers/leds/Makefile          |    1 +
>  drivers/leds/ledtrig-arm-cpu.c |  114 ++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 130 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/leds/ledtrig-arm-cpu.c
>
> diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
> index 713d43b..f725ae2 100644
> --- a/drivers/leds/Kconfig
> +++ b/drivers/leds/Kconfig
> @@ -446,6 +446,21 @@ config LEDS_TRIGGER_BACKLIGHT
>
>          If unsure, say N.
>
> +# Notice that this uses the CONFIG_LEDS i.e. the "old" LEDS
> +config LEDS_TRIGGER_ARM_CPU
> +       bool "LED ARM CPU Trigger"
> +       depends on LEDS_TRIGGERS && ARM
> +       select LEDS
> +       select LEDS_CPU
> +       default y if ARCH_REALVIEW
> +       default y if ARCH_VERSATILE

How about remove this and let REALVIEW to select this option

> +       help
> +         This allows LEDs to be controlled by active ARM CPUs. This
> +         shows the active CPUs across an array of LEDs so you can see
> +         what CPUs are active on the system at any given moment.
> +
> +         If unsure, say N.
> +
>  config LEDS_TRIGGER_GPIO
>        tristate "LED GPIO Trigger"
>        depends on LEDS_TRIGGERS
> diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
> index bbfd2e3..a32a99c 100644
> --- a/drivers/leds/Makefile
> +++ b/drivers/leds/Makefile
> @@ -53,4 +53,5 @@ obj-$(CONFIG_LEDS_TRIGGER_IDE_DISK)   += ledtrig-ide-disk.o
>  obj-$(CONFIG_LEDS_TRIGGER_HEARTBEAT)   += ledtrig-heartbeat.o
>  obj-$(CONFIG_LEDS_TRIGGER_BACKLIGHT)   += ledtrig-backlight.o
>  obj-$(CONFIG_LEDS_TRIGGER_GPIO)                += ledtrig-gpio.o
> +obj-$(CONFIG_LEDS_TRIGGER_ARM_CPU)     += ledtrig-arm-cpu.o
>  obj-$(CONFIG_LEDS_TRIGGER_DEFAULT_ON)  += ledtrig-default-on.o
> diff --git a/drivers/leds/ledtrig-arm-cpu.c b/drivers/leds/ledtrig-arm-cpu.c
> new file mode 100644
> index 0000000..7776d61
> --- /dev/null
> +++ b/drivers/leds/ledtrig-arm-cpu.c
> @@ -0,0 +1,114 @@
> +/*
> + * ledtrig-arm-cpu.c - LED trigger based on ARM CPU activity
> + *
> + * Copyright 2011 Linus Walleij <linus.walleij at linaro.org>
> + *
> + * 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 <linux/module.h>
> +#include <linux/kernel.h>
> +#include <linux/init.h>
> +#include <linux/leds.h>
> +#include <linux/slab.h>
> +#include <linux/percpu.h>
> +#include <asm/leds.h>

How about moving this out to drivers/leds/ledtrigg-cpu.h?

> +#include "leds.h"
> +
> +struct arm_cpu_trig_data {
> +       struct led_classdev *led;
> +};
> +
> +static DEFINE_PER_CPU(struct arm_cpu_trig_data *, arm_cpu_triggers);
> +
> +void arm_cpu_leds_event(led_event_t ledevt)
> +{
> +       struct arm_cpu_trig_data *trigdata = __get_cpu_var(arm_cpu_triggers);
> +
> +       if (!trigdata)
> +               return;
> +
> +       /* Locate the correct CPU LED */
> +
> +       switch (ledevt) {
> +       case led_halted:
> +       case led_idle_start:
> +               /* Will turn the LED off */
> +               if (trigdata->led)
> +                       led_set_brightness(trigdata->led, LED_OFF);
> +               break;
> +
> +       case led_idle_end:
> +               /* Will turn the LED on, max brightness */
> +               if (trigdata->led)
> +                       led_set_brightness(trigdata->led,
> +                                          trigdata->led->max_brightness);
> +               break;
> +
> +       default:
> +               /* Will leave the LED as it is */
> +               break;
> +       }
> +}
> +
> +static void arm_cpu_trig_activate_cpu(void *data)
> +{
> +       struct arm_cpu_trig_data *arm_cpu_data;
> +       struct led_classdev *led = data;
> +       int my_cpu = smp_processor_id();
> +       unsigned long target_cpu = (unsigned long) led->trigger_data;
> +
> +       if (target_cpu != my_cpu)
> +               return;
> +
> +       arm_cpu_data = kzalloc(sizeof(*arm_cpu_data), GFP_KERNEL);
> +       if (!arm_cpu_data)
> +               return;
> +
> +       dev_info(led->dev, "led %s indicate activity on CPU %d\n",
> +                led->name, my_cpu);
> +
> +       arm_cpu_data->led = led;
> +       __get_cpu_var(arm_cpu_triggers) = arm_cpu_data;
> +}
> +
> +static void arm_cpu_trig_activate(struct led_classdev *led)
> +{
> +       on_each_cpu(arm_cpu_trig_activate_cpu, led, 1);
> +
> +       /* Hook into ARM core kernel event callback */
> +       leds_event = arm_cpu_leds_event;
> +}
> +
> +static void arm_cpu_trig_deactivate(struct led_classdev *led)
> +{
> +       struct arm_cpu_trig_data *arm_cpu_data = led->trigger_data;
> +
> +       if (arm_cpu_data)
> +               kfree(arm_cpu_data);
> +}
> +
> +static struct led_trigger arm_cpu_led_trigger = {
> +       .name           = "arm-cpu",
> +       .activate       = arm_cpu_trig_activate,
> +       .deactivate     = arm_cpu_trig_deactivate,
> +};
> +
> +static int __init arm_cpu_trig_init(void)
> +{
> +       return led_trigger_register(&arm_cpu_led_trigger);
> +}
> +module_init(arm_cpu_trig_init);
> +
> +static void __exit arm_cpu_trig_exit(void)
> +{
> +       led_trigger_unregister(&arm_cpu_led_trigger);
> +}
> +module_exit(arm_cpu_trig_exit);
> +
> +MODULE_AUTHOR("Linus Walleij <linus.walleij at linaro.org>");
> +MODULE_DESCRIPTION("ARM CPU LED trigger");
> +MODULE_LICENSE("GPL");
> --
> 1.7.3.2
>
>

Thanks, this work is really what I want to do.
-- 
Bryan Wu <bryan.wu at canonical.com>
Kernel Developer    +86.138-1617-6545 Mobile
Ubuntu Kernel Team
Canonical Ltd.      www.canonical.com
Ubuntu - Linux for human beings | www.ubuntu.com



More information about the linux-arm-kernel mailing list