From 4850c121b25bfdd9bc0647a2a111bcc2eadb4c16 Mon Sep 17 00:00:00 2001 From: John Bowler Date: Mon, 23 Jan 2006 06:29:51 +0000 Subject: ixp4xx-kernel: add patch for cpu activity monitor to new LEDS timer trigger in 2.6.15.1 - this adds two new triggers under a separate Kconfig setting, cpu-idle and cpu-activity. The latter lights the given LED when the cpu is active (optionally flashing or flickering it), the former makes the LED solid when the CPU is idle and flickers it when active. The patch also adds a duty_cycle setting to the triggers. --- .../2.6.15/951-ixp4xx-leds-cpu-activity.patch | 375 +++++++++++++++++++++ packages/linux/ixp4xx-kernel/2.6.15/defconfig | 2 +- packages/linux/ixp4xx-kernel_2.6.15.1.bb | 5 +- 3 files changed, 379 insertions(+), 3 deletions(-) create mode 100644 packages/linux/ixp4xx-kernel/2.6.15/951-ixp4xx-leds-cpu-activity.patch (limited to 'packages') diff --git a/packages/linux/ixp4xx-kernel/2.6.15/951-ixp4xx-leds-cpu-activity.patch b/packages/linux/ixp4xx-kernel/2.6.15/951-ixp4xx-leds-cpu-activity.patch new file mode 100644 index 0000000000..adfd659ab6 --- /dev/null +++ b/packages/linux/ixp4xx-kernel/2.6.15/951-ixp4xx-leds-cpu-activity.patch @@ -0,0 +1,375 @@ +This patches the new LEDs code to add cpu activity and +inactivity triggers to the timer triggers. The new triggers +flash an LED at a given rate when the CPU is active and +set it to on (cpu-idle) or off (cpu-activity trigger) when +the CPU is idle. + +The patch also adds a duty_cycle attribute to the LED +timer class, this allows control of the mark/space ratio +in the flash. Using duty cycles of about 50% far higher +flash rates become possible. + +Signed-off-by: John Bowler + +--- linux-2.6.15/arch/arm/kernel/process.c 1970-01-01 00:00:00.000000000 +0000 ++++ linux-2.6.15/arch/arm/kernel/process.c 1970-01-01 00:00:00.000000000 +0000 +@@ -27,6 +27,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -121,8 +122,10 @@ void cpu_idle(void) + if (!idle) + idle = default_idle; + leds_event(led_idle_start); ++ leds_idle(1); + while (!need_resched()) + idle(); ++ leds_idle(0); + leds_event(led_idle_end); + preempt_enable_no_resched(); + schedule(); +--- linux-2.6.15/drivers/leds/Kconfig 1970-01-01 00:00:00.000000000 +0000 ++++ linux-2.6.15/drivers/leds/Kconfig 1970-01-01 00:00:00.000000000 +0000 +@@ -59,5 +59,14 @@ config LEDS_TRIGGER_TIMER + This allows LEDs to be controlled by a programmable timer + via sysfs. If unsure, say Y. + ++config LEDS_TRIGGER_CPU_ACTIVITY ++ tristate "LED CPU activity trigger" ++ depends LEDS_TRIGGER_TIMER ++ help ++ This allows LEDs to be set to show cpu activity via sysfs. ++ The LED will blink when the cpu is active and stay steady ++ (on or off according to the trigger selected) when idle. ++ If unsure, say Y. ++ + endmenu + +--- linux-2.6.15/drivers/leds/led-triggers.c 1970-01-01 00:00:00.000000000 +0000 ++++ linux-2.6.15/drivers/leds/led-triggers.c 1970-01-01 00:00:00.000000000 +0000 +@@ -98,7 +98,7 @@ void led_trigger_event(struct led_trigge + if (!trigger) + return; + +- read_lock(&trigger->led_devs); ++ read_lock(&trigger->leddev_list_lock); + list_for_each(entry, &trigger->led_devs) { + struct led_device *led_dev; + +@@ -107,7 +107,7 @@ void led_trigger_event(struct led_trigge + leds_set_brightness(led_dev, brightness); + write_unlock(&led_dev->lock); + } +- read_unlock(&trigger->led_devs); ++ read_unlock(&trigger->leddev_list_lock); + } + + /* Caller must ensure led_dev->lock held for write */ +--- linux-2.6.15/drivers/leds/ledtrig-timer.c 1970-01-01 00:00:00.000000000 +0000 ++++ linux-2.6.15/drivers/leds/ledtrig-timer.c 1970-01-01 00:00:00.000000000 +0000 +@@ -24,46 +24,95 @@ + #include "leds.h" + + struct timer_trig_data { +- unsigned long frequency; /* frequency of blinking, in milliseconds */ ++ unsigned long frequency; /* length of space, in milliseconds */ ++ unsigned long duty_cycle; /* mark/space ratio as a percentage */ + struct timer_list timer; ++#ifdef CONFIG_LEDS_TRIGGER_CPU_ACTIVITY ++ unsigned long idle_brightness; ++ int is_idle; ++#endif ++}; ++ ++enum timer_property { ++ TimerFrequency, ++ TimerDutyCycle + }; + + static void leds_timer_function(unsigned long data) + { + struct led_device *led_dev = (struct led_device *) data; +- struct timer_trig_data *timer_data = led_dev->trigger_data; +- unsigned long value = 0; ++ struct timer_trig_data *timer_data; ++ unsigned long value; + + write_lock(&led_dev->lock); + ++ timer_data = led_dev->trigger_data; ++ ++#ifdef CONFIG_LEDS_TRIGGER_CPU_ACTIVITY ++ if (timer_data->is_idle) { ++ /* LED solid (or or off), no timer. */ ++ value = timer_data->idle_brightness; ++ } else if (!timer_data->frequency) { ++ /* Put the LED in the non-idle state. */ ++ value = 100-timer_data->idle_brightness; ++ } ++#else + if (!timer_data->frequency) { +- leds_set_brightness(led_dev, 0); +- write_unlock(&led_dev->lock); +- return; ++ value = 0; + } ++#endif ++ else { ++ unsigned long timeout = timer_data->frequency; ++ ++ /* LED flashing - toggle the brightness. */ ++ value = led_dev->brightness ? 0 : 100; ++ ++ /* If this is the 'mark' adjust by the duty cycle. */ ++ if (value) ++ timeout = timeout * timer_data->duty_cycle / 100; ++ ++ timeout = msecs_to_jiffies(timeout); ++ if (!timeout) ++ timeout = 1; + +- if (!led_dev->brightness) +- value = 100; ++ mod_timer(&timer_data->timer, jiffies + timeout); ++ } + + leds_set_brightness(led_dev, value); +- +- mod_timer(&timer_data->timer, jiffies + msecs_to_jiffies(timer_data->frequency)); + write_unlock(&led_dev->lock); + } + +-static ssize_t leds_show_frequency(struct class_device *dev, char *buf) ++static ssize_t leds_show_prop(struct class_device *dev, char *buf, enum timer_property what) + { + struct led_device *led_dev = dev->class_data; + struct timer_trig_data *timer_data = led_dev->trigger_data; ++ unsigned long value = 0; + + read_lock(&led_dev->lock); +- sprintf(buf, "%lu\n", timer_data->frequency); ++ switch (what) ++ { ++ case TimerFrequency: value = timer_data->frequency; break; ++ case TimerDutyCycle: value = timer_data->duty_cycle; break; ++ } + read_unlock(&led_dev->lock); + ++ sprintf(buf, "%lu\n", value); ++ + return strlen(buf) + 1; + } + +-static ssize_t leds_store_frequency(struct class_device *dev, const char *buf, size_t size) ++static ssize_t leds_show_frequency(struct class_device *dev, char *buf) ++{ ++ return leds_show_prop(dev, buf, TimerFrequency); ++} ++ ++static ssize_t leds_show_duty_cycle(struct class_device *dev, char *buf) ++{ ++ return leds_show_prop(dev, buf, TimerDutyCycle); ++} ++ ++static ssize_t leds_store_prop(struct class_device *dev, const char *buf, ++ size_t size, enum timer_property what) + { + struct led_device *led_dev = dev->class_data; + struct timer_trig_data *timer_data = led_dev->trigger_data; +@@ -74,17 +123,33 @@ static ssize_t leds_store_frequency(stru + if (after - buf > 0) { + ret = after - buf; + write_lock(&led_dev->lock); +- timer_data->frequency = state; +- mod_timer(&timer_data->timer, jiffies + msecs_to_jiffies(timer_data->frequency)); ++ switch (what) ++ { ++ case TimerFrequency: timer_data->frequency = state; break; ++ case TimerDutyCycle: timer_data->duty_cycle = state; break; ++ } ++ /* Cause the timer to fire in a jiffy */ ++ mod_timer(&timer_data->timer, jiffies + 1); + write_unlock(&led_dev->lock); + } + + return ret; + } + ++static ssize_t leds_store_frequency(struct class_device *dev, const char *buf, size_t size) ++{ ++ return leds_store_prop(dev, buf, size, TimerFrequency); ++} ++ ++static ssize_t leds_store_duty_cycle(struct class_device *dev, const char *buf, size_t size) ++{ ++ return leds_store_prop(dev, buf, size, TimerDutyCycle); ++} ++ + static CLASS_DEVICE_ATTR(frequency, 0644, leds_show_frequency, leds_store_frequency); ++static CLASS_DEVICE_ATTR(duty_cycle, 0644, leds_show_duty_cycle, leds_store_duty_cycle); + +-void timer_trig_activate(struct led_device *led_dev) ++static void do_activate(struct led_device *led_dev, unsigned long idle_brightness) + { + struct timer_trig_data *timer_data; + +@@ -94,6 +159,11 @@ void timer_trig_activate(struct led_devi + + led_dev->trigger_data = timer_data; + timer_data->frequency = 0; ++ timer_data->duty_cycle = 100; ++#ifdef CONFIG_LEDS_TRIGGER_CPU_ACTIVITY ++ timer_data->idle_brightness = idle_brightness; ++ timer_data->is_idle = 0; ++#endif + + init_timer(&timer_data->timer); + timer_data->timer.function = leds_timer_function; +@@ -101,12 +171,27 @@ void timer_trig_activate(struct led_devi + timer_data->timer.expires = 0; + + class_device_create_file(led_dev->class_dev, &class_device_attr_frequency); ++ class_device_create_file(led_dev->class_dev, &class_device_attr_duty_cycle); + } + +-void timer_trig_deactivate(struct led_device *led_dev) ++static void timer_trig_activate(struct led_device *led_dev) ++{ ++ do_activate(led_dev, 100); ++} ++ ++#ifdef CONFIG_LEDS_TRIGGER_CPU_ACTIVITY ++static void cpu_trig_activate(struct led_device *led_dev) ++{ ++ /* As above but the LED is off when the CPU is idle */ ++ do_activate(led_dev, 0); ++} ++#endif ++ ++static void timer_trig_deactivate(struct led_device *led_dev) + { + struct timer_trig_data *timer_data = led_dev->trigger_data; + if (timer_data) { ++ class_device_remove_file(led_dev->class_dev, &class_device_attr_duty_cycle); + class_device_remove_file(led_dev->class_dev, &class_device_attr_frequency); + del_timer_sync(&timer_data->timer); + kfree(timer_data); +@@ -119,16 +204,90 @@ static struct led_trigger timer_led_trig + .deactivate = timer_trig_deactivate, + }; + ++#ifdef CONFIG_LEDS_TRIGGER_CPU_ACTIVITY ++static struct led_trigger cpu_led_trigger = { ++ .name = "cpu-activity", ++ .activate = cpu_trig_activate, ++ .deactivate = timer_trig_deactivate, ++}; ++ ++static struct led_trigger idle_led_trigger = { ++ .name = "cpu-idle", ++ .activate = timer_trig_activate, ++ .deactivate = timer_trig_deactivate, ++}; ++ ++static int leds_do_idle = 0; ++#endif ++ + static int __init timer_trig_init(void) + { ++#ifdef CONFIG_LEDS_TRIGGER_CPU_ACTIVITY ++ int rc = led_trigger_register(&idle_led_trigger); ++ if (rc) ++ return rc; ++ rc = led_trigger_register(&cpu_led_trigger); ++ if (rc) ++ return rc; ++ leds_do_idle = 1; ++#endif + return led_trigger_register(&timer_led_trigger); + } + + static void __exit timer_trig_exit (void) + { + led_trigger_unregister(&timer_led_trigger); ++#ifdef CONFIG_LEDS_TRIGGER_CPU_ACTIVITY ++ leds_do_idle = 0; ++ led_trigger_unregister(&cpu_led_trigger); ++ led_trigger_unregister(&idle_led_trigger); ++#endif + } + ++#ifdef CONFIG_LEDS_TRIGGER_CPU_ACTIVITY ++static void leds_trigger_idle(struct led_trigger *trigger, int is_idle) ++{ ++ struct list_head *entry; ++ ++ if (!trigger) ++ return; ++ ++ read_lock(&trigger->leddev_list_lock); ++ list_for_each(entry, &trigger->led_devs) { ++ struct led_device *led_dev; ++ struct timer_trig_data *timer_data; ++ ++ /* The timer must be deactivated in this thread if the CPU ++ * is going idle, otherwise this function will simply stop ++ * the CPU ever becoming idle. ++ */ ++ led_dev = list_entry(entry, struct led_device, trig_list); ++ write_lock(&led_dev->lock); ++ timer_data = led_dev->trigger_data; ++ if (is_idle && !timer_data->is_idle && timer_data->frequency) ++ del_timer(&timer_data->timer); ++ timer_data->is_idle = is_idle; ++ write_unlock(&led_dev->lock); ++ ++ /* Force the LED to the correct state and instantiate ++ * a timer if necessary. ++ */ ++ leds_timer_function((unsigned long)led_dev); ++ } ++ read_unlock(&trigger->leddev_list_lock); ++} ++ ++void leds_idle(int is_idle) ++{ ++ if (leds_do_idle) { ++ leds_trigger_idle(&cpu_led_trigger, is_idle); ++ leds_trigger_idle(&idle_led_trigger, is_idle); ++ } ++} ++ ++EXPORT_SYMBOL_GPL(leds_idle); ++#endif ++ + module_init(timer_trig_init); + module_exit(timer_trig_exit); + +--- linux-2.6.15/include/linux/leds.h 1970-01-01 00:00:00.000000000 +0000 ++++ linux-2.6.15/include/linux/leds.h 1970-01-01 00:00:00.000000000 +0000 +@@ -89,3 +89,21 @@ void led_trigger_event(struct led_trigge + #define led_trigger_event(x, y) do {} while(0) + + #endif ++ ++/* ++ * CPU activity indication. ++ */ ++#ifdef CONFIG_LEDS_TRIGGER_CPU_ACTIVITY ++ ++/* Idle callback - call with is_idle==1 at the start of the idle loop ++ * and with is_idle==0 at the end. ++ */ ++void leds_idle(int is_idle); ++ ++#else ++ ++/* No CPU activity support. */ ++#define leds_idle(x) do {} while (0) ++ ++#endif ++ diff --git a/packages/linux/ixp4xx-kernel/2.6.15/defconfig b/packages/linux/ixp4xx-kernel/2.6.15/defconfig index 03bfef97d0..6d635ce2c2 100644 --- a/packages/linux/ixp4xx-kernel/2.6.15/defconfig +++ b/packages/linux/ixp4xx-kernel/2.6.15/defconfig @@ -1669,7 +1669,7 @@ CONFIG_CRYPTO_SERPENT=m CONFIG_CRYPTO_AES=m CONFIG_CRYPTO_CAST5=m CONFIG_CRYPTO_CAST6=m -# CONFIG_CRYPTO_TEA is not set +CONFIG_CRYPTO_TEA=m CONFIG_CRYPTO_ARC4=m CONFIG_CRYPTO_KHAZAD=m CONFIG_CRYPTO_ANUBIS=m diff --git a/packages/linux/ixp4xx-kernel_2.6.15.1.bb b/packages/linux/ixp4xx-kernel_2.6.15.1.bb index 545a88dd92..23eda4568a 100644 --- a/packages/linux/ixp4xx-kernel_2.6.15.1.bb +++ b/packages/linux/ixp4xx-kernel_2.6.15.1.bb @@ -3,12 +3,12 @@ # Increment PR_CONFIG for changes to the ixp4xx-kernel specific # defconfig (do *NOT* increment anything in here for changes # to other kernel configs!) -PR_CONFIG = "0" +PR_CONFIG = "1" # # Increment the number below (i.e. the digits after PR) when # making changes within this file or for changes to the patches # applied to the kernel. -PR = "r12.${PR_CONFIG}" +PR = "r13.${PR_CONFIG}" include ixp4xx-kernel.inc @@ -49,6 +49,7 @@ IXP4XX_PATCHES += "file://93-loft-maclist.patch;patch=1" IXP4XX_PATCHES += "file://94-nas100d-setup.patch;patch=1" IXP4XX_PATCHES += "file://94-nslu2-setup.patch;patch=1" IXP4XX_PATCHES += "file://95-ixp4xx-leds.patch;patch=1" +IXP4XX_PATCHES += "file://951-ixp4xx-leds-cpu-activity.patch;patch=1" IXP4XX_PATCHES += "file://96-loft-leds.patch;patch=1" IXP4XX_PATCHES += "file://96-nas100d-leds.patch;patch=1" IXP4XX_PATCHES += "file://96-nslu2-leds.patch;patch=1" -- cgit v1.2.3