diff options
Diffstat (limited to 'packages/linux/ixp4xx-kernel/2.6.15/951-ixp4xx-leds-cpu-activity.patch')
-rw-r--r-- | packages/linux/ixp4xx-kernel/2.6.15/951-ixp4xx-leds-cpu-activity.patch | 592 |
1 files changed, 0 insertions, 592 deletions
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 deleted file mode 100644 index b6b3897005..0000000000 --- a/packages/linux/ixp4xx-kernel/2.6.15/951-ixp4xx-leds-cpu-activity.patch +++ /dev/null @@ -1,592 +0,0 @@ -This patches the new LEDs code to add cpu activity and -inactivity triggers to the timer triggers. The new triggers -set the LED with the trigger to different states (on, -flashing or off) according to whether or not all CPUs -are idle. - -Signed-off-by: John Bowler <jbowler@acm.org> - -diff -rup linux-2.6.15.2/.pc/951-ixp4xx-leds-cpu-activity.patch/arch/arm/kernel/process.c linux-2.6.15.2/arch/arm/kernel/process.c ---- 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 <linux/kallsyms.h> - #include <linux/init.h> - #include <linux/cpu.h> -+#include <linux/leds.h> - - #include <asm/system.h> - #include <asm/io.h> -@@ -81,6 +82,12 @@ void (*pm_power_off)(void); - EXPORT_SYMBOL(pm_power_off); - - /* -+ * CPU activity indicator. -+ */ -+void (*leds_idle)(int is_idle); -+EXPORT_SYMBOL(leds_idle); -+ -+/* - * This is our default idle handler. We need to disable - * interrupts here to ensure we don't miss a wakeup call. - */ -@@ -121,8 +128,12 @@ void cpu_idle(void) - if (!idle) - idle = default_idle; - leds_event(led_idle_start); -+ if (leds_idle) -+ leds_idle(1); - while (!need_resched()) - idle(); -+ if (leds_idle) -+ leds_idle(0); - leds_event(led_idle_end); - preempt_enable_no_resched(); - schedule(); -diff -rup linux-2.6.15.2/.pc/951-ixp4xx-leds-cpu-activity.patch/drivers/leds/Kconfig linux-2.6.15.2/drivers/leds/Kconfig ---- 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 -@@ -66,5 +66,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 - -diff -rup linux-2.6.15.2/.pc/951-ixp4xx-leds-cpu-activity.patch/drivers/leds/Makefile linux-2.6.15.2/drivers/leds/Makefile ---- linux-2.6.15/drivers/leds/Makefile 1970-01-01 00:00:00.000000000 +0000 -+++ linux-2.6.15/drivers/leds/Makefile 1970-01-01 00:00:00.000000000 +0000 -@@ -13,3 +13,4 @@ obj-$(CONFIG_LEDS_TOSA) += leds-tosa.o - - # LED Triggers - obj-$(CONFIG_LEDS_TRIGGER_TIMER) += ledtrig-timer.o -+obj-$(CONFIG_LEDS_TRIGGER_CPU_ACTIVITY) += ledtrig-cpu.o -diff -rup linux-2.6.15.2/.pc/951-ixp4xx-leds-cpu-activity.patch/drivers/leds/ledtrig-cpu.c linux-2.6.15.2/drivers/leds/ledtrig-cpu.c ---- linux-2.6.15/drivers/leds/ledtrig-cpu.c 1970-01-01 00:00:00.000000000 +0000 -+++ linux-2.6.15/drivers/leds/ledtrig-cpu.c 1970-01-01 00:00:00.000000000 +0000 -@@ -0,0 +1,501 @@ -+/* -+ * LEDs CPU activity trigger -+ * -+ * Author: John Bowler <jbowler@acm.org> -+ * -+ * Copyright (c) 2006 John Bowler -+ * -+ * Permission is hereby granted, free of charge, to any -+ * person obtaining a copy of this software and associated -+ * documentation files (the "Software"), to deal in the -+ * Software without restriction, including without -+ * limitation the rights to use, copy, modify, merge, -+ * publish, distribute, sublicense, and/or sell copies of -+ * the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the -+ * following conditions: -+ * -+ * The above copyright notice and this permission notice -+ * shall be included in all copies or substantial portions -+ * of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF -+ * ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED -+ * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -+ * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -+ * SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR -+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ */ -+ -+#include <linux/config.h> -+#include <linux/ctype.h> -+#include <linux/kernel.h> -+#include <linux/module.h> -+#include <linux/init.h> -+#include <linux/spinlock.h> -+#include <linux/timer.h> -+#include <linux/device.h> -+ -+#include <linux/leds.h> -+#include "leds.h" -+ -+//#include <linux/list.h> -+//#include <linux/sysdev.h> -+ -+ -+/* -+ * To simplify this the LED state is given for each case of -+ * CPU state - idle or active. The LED can be: -+ * -+ * off -+ * flash - slow for idle, fast (flicker) for active -+ * on -+ * -+ * This gives two useless states - off/off and on/on -+ */ -+typedef enum cpu_trigger_led_state { -+ cpu_led_off, -+ cpu_led_flash, -+ cpu_led_on, -+ cpu_led_invalid -+} cpu_trigger_led_state; -+ -+static const char *const cpu_trigger_names[] = { -+ "off", -+ "flash", -+ "on", -+ "invalid" -+}; -+ -+/* Forward declaration - this is called back when an LED property -+ * is changed. -+ */ -+static void leds_cpu_trigger_state_change(void); -+ -+/* -+ * These constants define the actual mark/space of the flashing -+ * in jiffies. msecs_to_jiffies rounds up and is compile time -+ * evaluable for constant arguments. Writing the ?: stuff below -+ * this way ensures the compiler doesn't think it needs to -+ * compile in the math of msecs_to_jiffies. -+ * -+ * These values have been determined by experiment to work well -+ * for the ready/status LED on a LinkSys NSLU2 (light piped) and -+ * for the user LED on a Loft (Gateway Avila variant) board where -+ * the LED was directly visible. Light Output Varies Everywhere. -+ */ -+#define LEDS_CPU_ACTIVE_MARK msecs_to_jiffies(40) -+#define LEDS_CPU_IDLE_MARK msecs_to_jiffies(800) -+#define LEDS_CPU_ACTIVE_SPACE msecs_to_jiffies(60) -+#define LEDS_CPU_IDLE_SPACE msecs_to_jiffies(800) -+ -+ -+/* -+ * Individual LEDs ------------------------------------------------------------ -+ */ -+struct cpu_trigger_data { -+ cpu_trigger_led_state active; /* Behaviour when the CPU is active. */ -+ cpu_trigger_led_state idle; /* Behaviour when the CPU is idle. */ -+}; -+ -+/* -+ * LED state change - called when the state of a single LED might -+ * have changed. Returns true if the LED is blinking. The argument -+ * is the blink state - the brightness of the blinking LED. -+ */ -+static int leds_cpu_trigger_led_state_change(struct led_device *led, -+ int is_active, enum led_brightness brightness) -+{ -+ int is_blinking = 0; -+ -+ write_lock(&led->lock); -+ { -+ struct cpu_trigger_data *data = led->trigger_data; -+ -+ /* Find the new brightness for the LED, if the LED is -+ * set to flash then the brightness passed in is the -+ * required value. -+ */ -+ if (likely(data != 0)) -+ switch (is_active ? data->active : data->idle) { -+ case cpu_led_off: brightness = LED_OFF; break; -+ case cpu_led_flash: is_blinking = 1; break; -+ case cpu_led_on: brightness = LED_FULL; break; -+ } -+ else -+ brightness = is_active ? LED_FULL : LED_OFF; -+ -+ led_set_brightness(led, brightness); -+ } -+ write_unlock(&led->lock); -+ -+ return is_blinking; -+} -+ -+/* -+ * sysfs properties, the property is output at an list of the -+ * values with the current setting enclosed in [] -+ */ -+static ssize_t leds_cpu_trigger_show_prop(struct class_device *dev, char *buf, -+ size_t where) -+{ -+ struct led_device *led = dev->class_data; -+ cpu_trigger_led_state item = cpu_led_invalid, i; -+ char *next; -+ -+ read_lock(&led->lock); -+ { -+ if (likely(led->trigger_data != 0)) -+ item = *(const cpu_trigger_led_state*)( -+ led->trigger_data + where); -+ } -+ read_unlock(&led->lock); -+ -+ for (i=0, next=buf; i<cpu_led_invalid; ++i) { -+ const char *name = cpu_trigger_names[i]; -+ size_t len = strlen(name); -+ -+ if (i == item) -+ *next++ = '['; -+ memcpy(next, name, len); -+ next += len; -+ if (i == item) -+ *next++ = ']'; -+ *next++ = ' '; -+ } -+ -+ next[-1] = '\n'; -+ *next++ = 0; -+ -+ return next - buf; -+} -+ -+static ssize_t leds_cpu_trigger_show_active(struct class_device *dev, char *buf) -+{ -+ return leds_cpu_trigger_show_prop(dev, buf, -+ offsetof(struct cpu_trigger_data, active)); -+} -+ -+static ssize_t leds_cpu_trigger_show_idle(struct class_device *dev, char *buf) -+{ -+ return leds_cpu_trigger_show_prop(dev, buf, -+ offsetof(struct cpu_trigger_data, idle)); -+} -+ -+/* -+ * Any matching leading substring selects a property - so "onoffonoff" -+ * sets the property to off. -+ */ -+static ssize_t leds_cpu_trigger_store_prop(struct class_device *dev, -+ const char *buf, size_t size, size_t where) -+{ -+ size_t rc = 0; -+ cpu_trigger_led_state value = 0/*sic*/; -+ struct led_device *led; -+ -+ /* ignore space characters before the value. */ -+ while (rc < size && isspace(buf[rc])) -+ ++rc; -+ if (rc >= size) -+ return rc; -+ -+ /* look for a simple match against the trigger name, case -+ * sensitive. -+ */ -+ do { -+ const char *name = cpu_trigger_names[value]; -+ size_t len = strlen(name); -+ if (len <= size && memcmp(buf+rc, name, len) == 0) { -+ rc = len; -+ break; -+ } -+ if (++value >= cpu_led_invalid) -+ return -EINVAL; -+ } while (1); -+ -+ led = dev->class_data; -+ write_lock(&led->lock); -+ { -+ if (likely(led->trigger_data != 0)) -+ *(cpu_trigger_led_state*)( -+ led->trigger_data + where) = value; -+ -+ } -+ write_unlock(&led->lock); -+ -+ return rc; -+} -+ -+static ssize_t leds_cpu_trigger_store_active(struct class_device *dev, -+ const char *buf, size_t size) -+{ -+ ssize_t rc = leds_cpu_trigger_store_prop(dev, buf, size, -+ offsetof(struct cpu_trigger_data, active)); -+ /* -+ * At least one CPU must be active (otherwise who is doing this?) -+ * Call down into the global state below to cause an update -+ * to happen now. -+ */ -+ leds_cpu_trigger_state_change(); -+ return rc; -+} -+ -+static ssize_t leds_cpu_trigger_store_idle(struct class_device *dev, -+ const char *buf, size_t size) -+{ -+ return leds_cpu_trigger_store_prop(dev, buf, size, -+ offsetof(struct cpu_trigger_data, idle)); -+} -+ -+static CLASS_DEVICE_ATTR(active, 0644, leds_cpu_trigger_show_active, -+ leds_cpu_trigger_store_active); -+ -+static CLASS_DEVICE_ATTR(idle, 0644, leds_cpu_trigger_show_idle, -+ leds_cpu_trigger_store_idle); -+ -+/* -+ * Activate and deactivate are called on individual LEDs when the -+ * LED trigger property is changed. The LED write lock is held. -+ */ -+static void leds_cpu_trigger_activate(struct led_device *led) -+{ -+ /* -+ * The initial setting of the trigger is simple CPU activity -+ * with the LED off for idle and on for active. Consequently -+ * there is no need to mess with the global state initially, -+ * we know the CPU is active at this moment! -+ */ -+ struct cpu_trigger_data *data = kmalloc(sizeof *data, GFP_KERNEL); -+ if (unlikely(data == 0)) -+ return; -+ -+ data->active = cpu_led_on; -+ data->idle = cpu_led_off; -+ led->trigger_data = data; -+ -+ class_device_create_file(led->class_dev, &class_device_attr_active); -+ class_device_create_file(led->class_dev, &class_device_attr_idle); -+ -+ led_set_brightness(led, LED_FULL); -+} -+ -+static void leds_cpu_trigger_deactivate(struct led_device *led) -+{ -+ struct cpu_trigger_data *data = led->trigger_data; -+ if (likely(data != 0)) { -+ led_set_brightness(led, LED_OFF); -+ -+ class_device_remove_file(led->class_dev, &class_device_attr_idle); -+ class_device_remove_file(led->class_dev, &class_device_attr_active); -+ -+ led->trigger_data = 0; -+ kfree(data); -+ } -+} -+ -+ -+/* -+ * Global state -------------------------------------------------------------- -+ * -+ * This is global because the CPU state is global and we only need one timer to -+ * do this stuff. -+ */ -+typedef struct leds_cpu_trigger_data { -+ struct led_trigger trigger; /* the lock in here protects everything */ -+ struct timer_list timer; -+ unsigned long last_active_time; /* record of last jiffies */ -+ unsigned long last_idle_time; /* record of last jiffies */ -+ int count_active; /* number of active CPUs */ -+} leds_cpu_trigger_data; -+ -+/* -+ * Mark state - uses the current time (jiffies) to work out -+ * whether this is a mark or space. -+ */ -+static int leds_cpu_trigger_mark(struct leds_cpu_trigger_data *data, -+ unsigned long now) { -+ if (data->count_active > 0) { -+ unsigned long elapsed = now - data->last_active_time; -+ elapsed %= LEDS_CPU_ACTIVE_SPACE + LEDS_CPU_ACTIVE_MARK; -+ data->last_active_time = now - elapsed; -+ return elapsed > LEDS_CPU_ACTIVE_SPACE; -+ } else { -+ unsigned long elapsed = now - data->last_idle_time; -+ elapsed %= LEDS_CPU_IDLE_SPACE + LEDS_CPU_IDLE_MARK; -+ data->last_idle_time = now - elapsed; -+ return elapsed > LEDS_CPU_IDLE_SPACE; -+ } -+} -+ -+ -+/* -+ * State change - given information about the nature of the -+ * (possible) state change call up to each LED to adjust its -+ * state. Returns true if any LED is blinking. The lock -+ * must be held (a read lock is adequate). -+ */ -+static int leds_cpu_trigger_scan_leds(struct leds_cpu_trigger_data *data, -+ unsigned long now) -+{ -+ int blinking = 0; -+ const int active = data->count_active > 0; -+ const enum led_brightness brightness = -+ leds_cpu_trigger_mark(data, now) ? LED_FULL : LED_OFF; -+ struct list_head *entry; -+ -+ list_for_each(entry, &data->trigger.led_devs) { -+ struct led_device *led = -+ list_entry(entry, struct led_device, trig_list); -+ -+ blinking |= leds_cpu_trigger_led_state_change(led, -+ active, brightness); -+ } -+ -+ return blinking; -+} -+ -+/* -+ * Set the timer correctly according to the current state, the lock -+ * must be held for write. -+ */ -+static void leds_cpu_trigger_set_timer(struct leds_cpu_trigger_data *state, -+ unsigned long now) -+{ -+ unsigned long next; -+ if (state->count_active > 0) { -+ next = state->last_active_time; -+ if (now - next > LEDS_CPU_ACTIVE_SPACE) -+ next += LEDS_CPU_ACTIVE_MARK; -+ next += LEDS_CPU_ACTIVE_SPACE; -+ } else { -+ next = state->last_idle_time; -+ if (now - next > LEDS_CPU_IDLE_SPACE) -+ next += LEDS_CPU_IDLE_MARK; -+ next += LEDS_CPU_IDLE_SPACE; -+ } -+ mod_timer(&state->timer, next); -+} -+ -+/* -+ * The timer callback if the LED is currently flashing, the callback -+ * calls the state change function and, if that returns true, meaning -+ * that at least one LED is still blinking, the timer is restarted -+ * with the correct timeout. -+ */ -+static void leds_cpu_trigger_timer_callback(unsigned long data) -+{ -+ struct leds_cpu_trigger_data *state = -+ (struct leds_cpu_trigger_data *)data; -+ -+ write_lock(&state->trigger.leddev_list_lock); -+ { -+ unsigned long now = jiffies; -+ -+ /* If at least one LED is set to flash; set the timer -+ * again (this won't reset the timer set within the -+ * idle loop). -+ */ -+ if (leds_cpu_trigger_scan_leds(state, now)) -+ leds_cpu_trigger_set_timer(state, now); -+ } -+ write_unlock(&state->trigger.leddev_list_lock); -+} -+ -+ -+/* -+ * There is one global control structure, one timer and one set -+ * of state for active CPUs shared across all the LEDs. Individual -+ * LEDs say how this state to be handled. It is currently *not* -+ * possible to show per-cpu activity on individual LEDs, the code -+ * maintains a count of active CPUs and the state is only 'idle' -+ * if all CPUs are idle. -+ */ -+static struct leds_cpu_trigger_data leds_cpu_trigger = { -+ .trigger = { -+ .name = "cpu", -+ .activate = leds_cpu_trigger_activate, -+ .deactivate = leds_cpu_trigger_deactivate, -+ } , -+ .timer = TIMER_INITIALIZER(leds_cpu_trigger_timer_callback, 0, -+ (unsigned long)&leds_cpu_trigger), -+ .last_active_time = 0, -+ .last_idle_time = 0, -+ .count_active = 0, -+}; -+ -+/* -+ * State change - callback from an individual LED on a property change which -+ * might require a redisplay. -+ */ -+static void leds_cpu_trigger_state_change() { -+ write_lock(&leds_cpu_trigger.trigger.leddev_list_lock); -+ { -+ unsigned long now = jiffies; -+ -+ if (leds_cpu_trigger_scan_leds(&leds_cpu_trigger, now) && -+ !timer_pending(&leds_cpu_trigger.timer)) -+ leds_cpu_trigger_set_timer(&leds_cpu_trigger, now); -+ } -+ write_unlock(&leds_cpu_trigger.trigger.leddev_list_lock); -+} -+ -+/* -+ * Called from every CPU at the start and end of the idle loop. -+ * The active count is initially 0, even though CPUs are running, -+ * so the code below must check for the resultant underflow. -+ * -+ * If the idle behaviour is 'flash' then when the timer times out -+ * it will take the CPU out of idle, set the active state (which -+ * may also be flash), drop back into idle and reset the timer to -+ * the idle timeout... -+ */ -+static void leds_cpu_trigger_idle(int is_idle) -+{ -+ write_lock(&leds_cpu_trigger.trigger.leddev_list_lock); -+ if ((is_idle && leds_cpu_trigger.count_active > 0 && -+ --leds_cpu_trigger.count_active == 0) || -+ (!is_idle && leds_cpu_trigger.count_active < num_online_cpus() && -+ ++leds_cpu_trigger.count_active == 1)) { -+ unsigned long now = jiffies; -+ -+ /* State change - the system just became idle or active, -+ * call the del_timer first in an attempt to minimise -+ * getting a timer interrupt which will take us unnecessarily -+ * out of idle (this doesn't matter). -+ */ -+ del_timer(&leds_cpu_trigger.timer); -+ if (leds_cpu_trigger_scan_leds(&leds_cpu_trigger, now)) -+ leds_cpu_trigger_set_timer(&leds_cpu_trigger, now); -+ } -+ write_unlock(&leds_cpu_trigger.trigger.leddev_list_lock); -+} -+ -+/* -+ * Module init and exit - register the trigger, then store -+ * the idle callback in the arch-specific global. For this -+ * module to link (into the kernel) or load (into a running -+ * kernel) the architecture must define the leds_idle global. -+ */ -+static int __init leds_cpu_trigger_init(void) -+{ -+ int rc = led_trigger_register(&leds_cpu_trigger.trigger); -+ leds_idle = leds_cpu_trigger_idle; -+ return rc; -+} -+module_init(leds_cpu_trigger_init); -+ -+static void __exit leds_cpu_trigger_exit(void) -+{ -+ leds_idle = 0; -+ del_timer_sync(&leds_cpu_trigger.timer); -+ led_trigger_unregister(&leds_cpu_trigger.trigger); -+} -+module_exit(leds_cpu_trigger_exit); -+ -+MODULE_AUTHOR("John Bowler <jbowler@acm.org>"); -+MODULE_DESCRIPTION("CPU activity LED trigger"); -+MODULE_LICENSE("MIT"); -diff -rup linux-2.6.15.2/.pc/951-ixp4xx-leds-cpu-activity.patch/include/linux/leds.h linux-2.6.15.2/include/linux/leds.h ---- 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 -@@ -95,3 +95,12 @@ void led_trigger_event(struct led_trigge - #define led_trigger_event(x, y) do {} while(0) - - #endif -+ -+/* -+ * CPU activity indication. -+ */ -+/* Idle callback - call with is_idle==1 at the start of the idle loop -+ * and with is_idle==0 at the end. This symbol must be defined by -+ * the arch core to be able to use LEDS_TRIGGER_CPU_ACTIVITY -+ */ -+extern void (*leds_idle)(int is_idle); |