diff options
author | Felix Fietkau <nbd@openwrt.org> | 2008-10-18 21:43:30 +0000 |
---|---|---|
committer | Felix Fietkau <nbd@openwrt.org> | 2008-10-18 21:43:30 +0000 |
commit | 1e570a9288856bcd288a80115f2233c9c785706c (patch) | |
tree | 8491af08bde47e22f96c01e6f560206b3fd02a4a /target/linux/generic-2.6/files/drivers/leds | |
parent | 487c622ac0c37f3cd26add56df9081ea7caf3835 (diff) | |
download | upstream-1e570a9288856bcd288a80115f2233c9c785706c.tar.gz upstream-1e570a9288856bcd288a80115f2233c9c785706c.tar.bz2 upstream-1e570a9288856bcd288a80115f2233c9c785706c.zip |
change the way ./files* and the generic kernel files are applied. ./files now applies to *ALL* kernel versions, and is copied along with ./files-* - this gets rid of quite a bit of redundancy in the extra kernel drivers.
SVN-Revision: 13010
Diffstat (limited to 'target/linux/generic-2.6/files/drivers/leds')
4 files changed, 0 insertions, 1033 deletions
diff --git a/target/linux/generic-2.6/files/drivers/leds/leds-alix.c b/target/linux/generic-2.6/files/drivers/leds/leds-alix.c deleted file mode 100644 index 103ca7dfa4..0000000000 --- a/target/linux/generic-2.6/files/drivers/leds/leds-alix.c +++ /dev/null @@ -1,172 +0,0 @@ -/* - * LEDs driver for PCEngines ALIX 2/3 series - * - * Copyright (C) 2007 Petr Liebman - * - * Based on leds-wrap.c - * - * 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/kernel.h> -#include <linux/init.h> -#include <linux/platform_device.h> -#include <linux/leds.h> -#include <linux/err.h> -#include <asm/io.h> - -#define DRVNAME "alix-led" - -#define ALIX_LED1_PORT (0x6100) -#define ALIX_LED1_ON (1<<22) -#define ALIX_LED1_OFF (1<<6) - -#define ALIX_LED2_PORT (0x6180) -#define ALIX_LED2_ON (1<<25) -#define ALIX_LED2_OFF (1<<9) - -#define ALIX_LED3_PORT (0x6180) -#define ALIX_LED3_ON (1<<27) -#define ALIX_LED3_OFF (1<<11) - - -static struct platform_device *pdev; - -static void alix_led_set_1(struct led_classdev *led_cdev, - enum led_brightness value) -{ - if (value) - outl(ALIX_LED1_ON, ALIX_LED1_PORT); - else - outl(ALIX_LED1_OFF, ALIX_LED1_PORT); -} - -static void alix_led_set_2(struct led_classdev *led_cdev, - enum led_brightness value) -{ - if (value) - outl(ALIX_LED2_ON, ALIX_LED2_PORT); - else - outl(ALIX_LED2_OFF, ALIX_LED2_PORT); -} - -static void alix_led_set_3(struct led_classdev *led_cdev, - enum led_brightness value) -{ - if (value) - outl(ALIX_LED3_ON, ALIX_LED3_PORT); - else - outl(ALIX_LED3_OFF, ALIX_LED3_PORT); -} - -static struct led_classdev alix_led_1 = { - .name = "alix:1", - .brightness_set = alix_led_set_1, -}; - -static struct led_classdev alix_led_2 = { - .name = "alix:2", - .brightness_set = alix_led_set_2, -}; - -static struct led_classdev alix_led_3 = { - .name = "alix:3", - .brightness_set = alix_led_set_3, -}; - - -#ifdef CONFIG_PM -static int alix_led_suspend(struct platform_device *dev, - pm_message_t state) -{ - led_classdev_suspend(&alix_led_1); - led_classdev_suspend(&alix_led_2); - led_classdev_suspend(&alix_led_3); - return 0; -} - -static int alix_led_resume(struct platform_device *dev) -{ - led_classdev_resume(&alix_led_1); - led_classdev_resume(&alix_led_2); - led_classdev_resume(&alix_led_3); - return 0; -} -#else -#define alix_led_suspend NULL -#define alix_led_resume NULL -#endif - -static int alix_led_probe(struct platform_device *pdev) -{ - int ret; - - ret = led_classdev_register(&pdev->dev, &alix_led_1); - if (ret >= 0) - { - ret = led_classdev_register(&pdev->dev, &alix_led_2); - if (ret >= 0) - { - ret = led_classdev_register(&pdev->dev, &alix_led_3); - if (ret < 0) - led_classdev_unregister(&alix_led_2); - } - if (ret < 0) - led_classdev_unregister(&alix_led_1); - } - return ret; -} - -static int alix_led_remove(struct platform_device *pdev) -{ - led_classdev_unregister(&alix_led_1); - led_classdev_unregister(&alix_led_2); - led_classdev_unregister(&alix_led_3); - return 0; -} - -static struct platform_driver alix_led_driver = { - .probe = alix_led_probe, - .remove = alix_led_remove, - .suspend = alix_led_suspend, - .resume = alix_led_resume, - .driver = { - .name = DRVNAME, - .owner = THIS_MODULE, - }, -}; - -static int __init alix_led_init(void) -{ - int ret; - - ret = platform_driver_register(&alix_led_driver); - if (ret < 0) - goto out; - - pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0); - if (IS_ERR(pdev)) { - ret = PTR_ERR(pdev); - platform_driver_unregister(&alix_led_driver); - goto out; - } - -out: - return ret; -} - -static void __exit alix_led_exit(void) -{ - platform_device_unregister(pdev); - platform_driver_unregister(&alix_led_driver); -} - -module_init(alix_led_init); -module_exit(alix_led_exit); - -MODULE_AUTHOR("Petr Liebman"); -MODULE_DESCRIPTION("PCEngines ALIX LED driver"); -MODULE_LICENSE("GPL"); - diff --git a/target/linux/generic-2.6/files/drivers/leds/ledtrig-default-on.c b/target/linux/generic-2.6/files/drivers/leds/ledtrig-default-on.c deleted file mode 100644 index 92995e40cf..0000000000 --- a/target/linux/generic-2.6/files/drivers/leds/ledtrig-default-on.c +++ /dev/null @@ -1,45 +0,0 @@ -/* - * LED Kernel Default ON Trigger - * - * Copyright 2008 Nick Forbes <nick.forbes@incepta.com> - * - * Based on Richard Purdie's ledtrig-timer.c. - * - * 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 "leds.h" - -static void defon_trig_activate(struct led_classdev *led_cdev) -{ - led_set_brightness(led_cdev, LED_FULL); -} - -static struct led_trigger defon_led_trigger = { - .name = "default-on", - .activate = defon_trig_activate, -}; - -static int __init defon_trig_init(void) -{ - return led_trigger_register(&defon_led_trigger); -} - -static void __exit defon_trig_exit(void) -{ - led_trigger_unregister(&defon_led_trigger); -} - -module_init(defon_trig_init); -module_exit(defon_trig_exit); - -MODULE_AUTHOR("Nick Forbes <nick.forbes@incepta.com>"); -MODULE_DESCRIPTION("Default-ON LED trigger"); -MODULE_LICENSE("GPL"); diff --git a/target/linux/generic-2.6/files/drivers/leds/ledtrig-morse.c b/target/linux/generic-2.6/files/drivers/leds/ledtrig-morse.c deleted file mode 100644 index cb47480a36..0000000000 --- a/target/linux/generic-2.6/files/drivers/leds/ledtrig-morse.c +++ /dev/null @@ -1,365 +0,0 @@ -/* - * LED Morse Trigger - * - * Copyright (C) 2007 Gabor Juhos <juhosg at openwrt.org> - * - * This file was based on: drivers/led/ledtrig-timer.c - * Copyright 2005-2006 Openedhand Ltd. - * Author: Richard Purdie <rpurdie@openedhand.com> - * - * also based on the patch '[PATCH] 2.5.59 morse code panics' posted - * in the LKML by Tomas Szepe at Thu, 30 Jan 2003 - * Copyright (C) 2002 Andrew Rodland <arodland@noln.com> - * Copyright (C) 2003 Tomas Szepe <szepe@pinerecords.com> - * - * 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/kernel.h> -#include <linux/version.h> -#include <linux/module.h> -#include <linux/jiffies.h> -#include <linux/init.h> -#include <linux/list.h> -#include <linux/spinlock.h> -#include <linux/device.h> -#include <linux/sysdev.h> -#include <linux/timer.h> -#include <linux/ctype.h> -#include <linux/leds.h> - -#include "leds.h" - -#define MORSE_DELAY_BASE (HZ/2) - -#define MORSE_STATE_BLINK_START 0 -#define MORSE_STATE_BLINK_STOP 1 - -#define MORSE_DIT_LEN 1 -#define MORSE_DAH_LEN 3 -#define MORSE_SPACE_LEN 7 - -struct morse_trig_data { - unsigned long delay; - char *msg; - - unsigned char morse; - unsigned char state; - char *msgpos; - struct timer_list timer; -}; - -const unsigned char morsetable[] = { - 0122, 0, 0310, 0, 0, 0163, /* "#$%&' */ - 055, 0155, 0, 0, 0163, 0141, 0152, 0051, /* ()*+,-./ */ - 077, 076, 074, 070, 060, 040, 041, 043, 047, 057, /* 0-9 */ - 0107, 0125, 0, 0061, 0, 0114, 0, /* :;<=>?@ */ - 006, 021, 025, 011, 002, 024, 013, 020, 004, /* A-I */ - 036, 015, 022, 007, 005, 017, 026, 033, 012, /* J-R */ - 010, 003, 014, 030, 016, 031, 035, 023, /* S-Z */ - 0, 0, 0, 0, 0154 /* [\]^_ */ -}; - -static inline unsigned char tomorse(char c) { - if (c >= 'a' && c <= 'z') - c = c - 'a' + 'A'; - if (c >= '"' && c <= '_') { - return morsetable[c - '"']; - } else - return 0; -} - -static inline unsigned long dit_len(struct morse_trig_data *morse_data) -{ - return MORSE_DIT_LEN*morse_data->delay; -} - -static inline unsigned long dah_len(struct morse_trig_data *morse_data) -{ - return MORSE_DAH_LEN*morse_data->delay; -} - -static inline unsigned long space_len(struct morse_trig_data *morse_data) -{ - return MORSE_SPACE_LEN*morse_data->delay; -} - -static void morse_timer_function(unsigned long data) -{ - struct led_classdev *led_cdev = (struct led_classdev *)data; - struct morse_trig_data *morse_data = led_cdev->trigger_data; - unsigned long brightness = LED_OFF; - unsigned long delay = 0; - - if (!morse_data->msg) - goto set_led; - - switch (morse_data->state) { - case MORSE_STATE_BLINK_START: - /* Starting a new blink. We have a valid code in morse. */ - delay = (morse_data->morse & 001) ? dah_len(morse_data): - dit_len(morse_data); - brightness = LED_FULL; - morse_data->state = MORSE_STATE_BLINK_STOP; - morse_data->morse >>= 1; - break; - case MORSE_STATE_BLINK_STOP: - /* Coming off of a blink. */ - morse_data->state = MORSE_STATE_BLINK_START; - - if (morse_data->morse > 1) { - /* Not done yet, just a one-dit pause. */ - delay = dit_len(morse_data); - break; - } - - /* Get a new char, figure out how much space. */ - /* First time through */ - if (!morse_data->msgpos) - morse_data->msgpos = (char *)morse_data->msg; - - if (!*morse_data->msgpos) { - /* Repeating */ - morse_data->msgpos = (char *)morse_data->msg; - delay = space_len(morse_data); - } else { - /* Inter-letter space */ - delay = dah_len(morse_data); - } - - if (!(morse_data->morse = tomorse(*morse_data->msgpos))) { - delay = space_len(morse_data); - /* And get us back here */ - morse_data->state = MORSE_STATE_BLINK_STOP; - } - morse_data->msgpos++; - break; - } - - mod_timer(&morse_data->timer, jiffies + msecs_to_jiffies(delay)); - -set_led: - led_set_brightness(led_cdev, brightness); -} - -static ssize_t _morse_delay_show(struct led_classdev *led_cdev, char *buf) -{ - struct morse_trig_data *morse_data = led_cdev->trigger_data; - - sprintf(buf, "%lu\n", morse_data->delay); - - return strlen(buf) + 1; -} - -static ssize_t _morse_delay_store(struct led_classdev *led_cdev, - const char *buf, size_t size) -{ - struct morse_trig_data *morse_data = led_cdev->trigger_data; - char *after; - unsigned long state = simple_strtoul(buf, &after, 10); - size_t count = after - buf; - int ret = -EINVAL; - - if (*after && isspace(*after)) - count++; - - if (count == size) { - morse_data->delay = state; - mod_timer(&morse_data->timer, jiffies + 1); - ret = count; - } - - return ret; -} - -static ssize_t _morse_msg_show(struct led_classdev *led_cdev, char *buf) -{ - struct morse_trig_data *morse_data = led_cdev->trigger_data; - - if (!morse_data->msg) - sprintf(buf, "<none>\n"); - else - sprintf(buf, "%s\n", morse_data->msg); - - return strlen(buf) + 1; -} - -static ssize_t _morse_msg_store(struct led_classdev *led_cdev, - const char *buf, size_t size) -{ - struct morse_trig_data *morse_data = led_cdev->trigger_data; - char *m; - - m = kmalloc(size, GFP_KERNEL); - if (!m) - return -ENOMEM; - - memcpy(m,buf,size); - m[size]='\0'; - - if (morse_data->msg) - kfree(morse_data->msg); - - morse_data->msg = m; - morse_data->msgpos = NULL; - morse_data->state = MORSE_STATE_BLINK_STOP; - - mod_timer(&morse_data->timer, jiffies + 1); - - return size; -} - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23) -static ssize_t morse_delay_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct led_classdev *led_cdev = dev_get_drvdata(dev); - - return _morse_delay_show(led_cdev, buf); -} - -static ssize_t morse_delay_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t size) -{ - struct led_classdev *led_cdev = dev_get_drvdata(dev); - - return _morse_delay_store(led_cdev, buf, size); -} - -static ssize_t morse_msg_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct led_classdev *led_cdev = dev_get_drvdata(dev); - - return _morse_msg_show(led_cdev, buf); -} - -static ssize_t morse_msg_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t size) -{ - struct led_classdev *led_cdev = dev_get_drvdata(dev); - - return _morse_msg_store(led_cdev, buf, size); -} - -static DEVICE_ATTR(delay, 0644, morse_delay_show, morse_delay_store); -static DEVICE_ATTR(message, 0644, morse_msg_show, morse_msg_store); - -#define led_device_create_file(leddev, attr) \ - device_create_file(leddev->dev, &dev_attr_ ## attr) -#define led_device_remove_file(leddev, attr) \ - device_remove_file(leddev->dev, &dev_attr_ ## attr) - -#else -static ssize_t morse_delay_show(struct class_device *dev, char *buf) -{ - struct led_classdev *led_cdev = class_get_devdata(dev); - - return _morse_delay_show(led_cdev, buf); -} - -static ssize_t morse_delay_store(struct class_device *dev, const char *buf, - size_t size) -{ - struct led_classdev *led_cdev = class_get_devdata(dev); - - return _morse_delay_store(led_cdev, buf, size); -} - -static ssize_t morse_msg_show(struct class_device *dev, char *buf) -{ - struct led_classdev *led_cdev = class_get_devdata(dev); - - return _morse_msg_show(led_cdev, buf); -} - -static ssize_t morse_msg_store(struct class_device *dev, const char *buf, - size_t size) -{ - struct led_classdev *led_cdev = class_get_devdata(dev); - - return _morse_msg_store(led_cdev, buf, size); -} - -static CLASS_DEVICE_ATTR(delay, 0644, morse_delay_show, morse_delay_store); -static CLASS_DEVICE_ATTR(message, 0644, morse_msg_show, morse_msg_store); - -#define led_device_create_file(leddev, attr) \ - class_device_create_file(leddev->class_dev, &class_device_attr_ ## attr) -#define led_device_remove_file(leddev, attr) \ - class_device_remove_file(leddev->class_dev, &class_device_attr_ ## attr) - -#endif - -static void morse_trig_activate(struct led_classdev *led_cdev) -{ - struct morse_trig_data *morse_data; - int rc; - - morse_data = kzalloc(sizeof(*morse_data), GFP_KERNEL); - if (!morse_data) - return; - - morse_data->delay = MORSE_DELAY_BASE; - init_timer(&morse_data->timer); - morse_data->timer.function = morse_timer_function; - morse_data->timer.data = (unsigned long)led_cdev; - - rc = led_device_create_file(led_cdev, delay); - if (rc) goto err; - - rc = led_device_create_file(led_cdev, message); - if (rc) goto err_delay; - - led_cdev->trigger_data = morse_data; - - return; - -err_delay: - led_device_remove_file(led_cdev, delay); -err: - kfree(morse_data); -} - -static void morse_trig_deactivate(struct led_classdev *led_cdev) -{ - struct morse_trig_data *morse_data = led_cdev->trigger_data; - - if (!morse_data) - return; - - led_device_remove_file(led_cdev, message); - led_device_remove_file(led_cdev, delay); - - del_timer_sync(&morse_data->timer); - if (morse_data->msg) - kfree(morse_data->msg); - - kfree(morse_data); -} - -static struct led_trigger morse_led_trigger = { - .name = "morse", - .activate = morse_trig_activate, - .deactivate = morse_trig_deactivate, -}; - -static int __init morse_trig_init(void) -{ - return led_trigger_register(&morse_led_trigger); -} - -static void __exit morse_trig_exit(void) -{ - led_trigger_unregister(&morse_led_trigger); -} - -module_init(morse_trig_init); -module_exit(morse_trig_exit); - -MODULE_AUTHOR("Gabor Juhos <juhosg at openwrt.org>"); -MODULE_DESCRIPTION("Morse LED trigger"); -MODULE_LICENSE("GPL"); diff --git a/target/linux/generic-2.6/files/drivers/leds/ledtrig-netdev.c b/target/linux/generic-2.6/files/drivers/leds/ledtrig-netdev.c deleted file mode 100644 index fac3571bdd..0000000000 --- a/target/linux/generic-2.6/files/drivers/leds/ledtrig-netdev.c +++ /dev/null @@ -1,451 +0,0 @@ -/* - * LED Kernel Netdev Trigger - * - * Toggles the LED to reflect the link and traffic state of a named net device - * - * Copyright 2007 Oliver Jowett <oliver@opencloud.com> - * - * Derived from ledtrig-timer.c which is: - * Copyright 2005-2006 Openedhand Ltd. - * Author: Richard Purdie <rpurdie@openedhand.com> - * - * 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/jiffies.h> -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/list.h> -#include <linux/spinlock.h> -#include <linux/device.h> -#include <linux/sysdev.h> -#include <linux/netdevice.h> -#include <linux/timer.h> -#include <linux/ctype.h> -#include <linux/leds.h> -#include <linux/version.h> - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) -#include <net/net_namespace.h> -#endif - -#include "leds.h" - -/* - * Configurable sysfs attributes: - * - * device_name - network device name to monitor - * - * interval - duration of LED blink, in milliseconds - * - * mode - either "none" (LED is off) or a space separated list of one or more of: - * link: LED's normal state reflects whether the link is up (has carrier) or not - * tx: LED blinks on transmitted data - * rx: LED blinks on receive data - * - * Some suggestions: - * - * Simple link status LED: - * $ echo netdev >someled/trigger - * $ echo eth0 >someled/device_name - * $ echo link >someled/mode - * - * Ethernet-style link/activity LED: - * $ echo netdev >someled/trigger - * $ echo eth0 >someled/device_name - * $ echo "link tx rx" >someled/mode - * - * Modem-style tx/rx LEDs: - * $ echo netdev >led1/trigger - * $ echo ppp0 >led1/device_name - * $ echo tx >led1/mode - * $ echo netdev >led2/trigger - * $ echo ppp0 >led2/device_name - * $ echo rx >led2/mode - * - */ - -#define MODE_LINK 1 -#define MODE_TX 2 -#define MODE_RX 4 - -struct led_netdev_data { - rwlock_t lock; - - struct timer_list timer; - struct notifier_block notifier; - - struct led_classdev *led_cdev; - struct net_device *net_dev; - - char device_name[IFNAMSIZ]; - unsigned interval; - unsigned mode; - unsigned link_up; - unsigned last_activity; -}; - -static void set_baseline_state(struct led_netdev_data *trigger_data) -{ - if ((trigger_data->mode & MODE_LINK) != 0 && trigger_data->link_up) - led_set_brightness(trigger_data->led_cdev, LED_FULL); - else - led_set_brightness(trigger_data->led_cdev, LED_OFF); - - if ((trigger_data->mode & (MODE_TX | MODE_RX)) != 0 && trigger_data->link_up) - mod_timer(&trigger_data->timer, jiffies + trigger_data->interval); - else - del_timer(&trigger_data->timer); -} - -static ssize_t led_device_name_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct led_classdev *led_cdev = dev_get_drvdata(dev); - struct led_netdev_data *trigger_data = led_cdev->trigger_data; - - read_lock(&trigger_data->lock); - sprintf(buf, "%s\n", trigger_data->device_name); - read_unlock(&trigger_data->lock); - - return strlen(buf) + 1; -} - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21) -extern struct net init_net; -#endif - -static ssize_t led_device_name_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t size) -{ - struct led_classdev *led_cdev = dev_get_drvdata(dev); - struct led_netdev_data *trigger_data = led_cdev->trigger_data; - - if (size < 0 || size >= IFNAMSIZ) - return -EINVAL; - - write_lock(&trigger_data->lock); - - strcpy(trigger_data->device_name, buf); - if (size > 0 && trigger_data->device_name[size-1] == '\n') - trigger_data->device_name[size-1] = 0; - - if (trigger_data->device_name[0] != 0) { - /* check for existing device to update from */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) - trigger_data->net_dev = dev_get_by_name(&init_net, trigger_data->device_name); -#else - trigger_data->net_dev = dev_get_by_name(trigger_data->device_name); -#endif - if (trigger_data->net_dev != NULL) - trigger_data->link_up = (dev_get_flags(trigger_data->net_dev) & IFF_LOWER_UP) != 0; - set_baseline_state(trigger_data); /* updates LEDs, may start timers */ - } - - write_unlock(&trigger_data->lock); - return size; -} - -static DEVICE_ATTR(device_name, 0644, led_device_name_show, led_device_name_store); - -static ssize_t led_mode_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct led_classdev *led_cdev = dev_get_drvdata(dev); - struct led_netdev_data *trigger_data = led_cdev->trigger_data; - - read_lock(&trigger_data->lock); - - if (trigger_data->mode == 0) { - strcpy(buf, "none\n"); - } else { - if (trigger_data->mode & MODE_LINK) - strcat(buf, "link "); - if (trigger_data->mode & MODE_TX) - strcat(buf, "tx "); - if (trigger_data->mode & MODE_RX) - strcat(buf, "rx "); - strcat(buf, "\n"); - } - - read_unlock(&trigger_data->lock); - - return strlen(buf)+1; -} - -static ssize_t led_mode_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t size) -{ - struct led_classdev *led_cdev = dev_get_drvdata(dev); - struct led_netdev_data *trigger_data = led_cdev->trigger_data; - char copybuf[1024]; - int new_mode = -1; - char *p, *token; - - /* take a copy since we don't want to trash the inbound buffer when using strsep */ - strncpy(copybuf, buf, sizeof(copybuf)); - copybuf[1023] = 0; - p = copybuf; - - while ((token = strsep(&p, " \t\n")) != NULL) { - if (!*token) - continue; - - if (new_mode == -1) - new_mode = 0; - - if (!strcmp(token, "none")) - new_mode = 0; - else if (!strcmp(token, "tx")) - new_mode |= MODE_TX; - else if (!strcmp(token, "rx")) - new_mode |= MODE_RX; - else if (!strcmp(token, "link")) - new_mode |= MODE_LINK; - else - return -EINVAL; - } - - if (new_mode == -1) - return -EINVAL; - - write_lock(&trigger_data->lock); - trigger_data->mode = new_mode; - set_baseline_state(trigger_data); - write_unlock(&trigger_data->lock); - - return size; -} - -static DEVICE_ATTR(mode, 0644, led_mode_show, led_mode_store); - -static ssize_t led_interval_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct led_classdev *led_cdev = dev_get_drvdata(dev); - struct led_netdev_data *trigger_data = led_cdev->trigger_data; - - read_lock(&trigger_data->lock); - sprintf(buf, "%u\n", jiffies_to_msecs(trigger_data->interval)); - read_unlock(&trigger_data->lock); - - return strlen(buf) + 1; -} - -static ssize_t led_interval_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t size) -{ - struct led_classdev *led_cdev = dev_get_drvdata(dev); - struct led_netdev_data *trigger_data = led_cdev->trigger_data; - int ret = -EINVAL; - char *after; - unsigned long value = simple_strtoul(buf, &after, 10); - size_t count = after - buf; - - if (*after && isspace(*after)) - count++; - - /* impose some basic bounds on the timer interval */ - if (count == size && value >= 5 && value <= 10000) { - write_lock(&trigger_data->lock); - trigger_data->interval = msecs_to_jiffies(value); - set_baseline_state(trigger_data); // resets timer - write_unlock(&trigger_data->lock); - ret = count; - } - - return ret; -} - -static DEVICE_ATTR(interval, 0644, led_interval_show, led_interval_store); - -static int netdev_trig_notify(struct notifier_block *nb, - unsigned long evt, - void *dv) -{ - struct net_device *dev = dv; - struct led_netdev_data *trigger_data = container_of(nb, struct led_netdev_data, notifier); - - if (evt != NETDEV_UP && evt != NETDEV_DOWN && evt != NETDEV_CHANGE && evt != NETDEV_REGISTER && evt != NETDEV_UNREGISTER) - return NOTIFY_DONE; - - write_lock(&trigger_data->lock); - - if (strcmp(dev->name, trigger_data->device_name)) - goto done; - - if (evt == NETDEV_REGISTER) { - if (trigger_data->net_dev != NULL) - dev_put(trigger_data->net_dev); - dev_hold(dev); - trigger_data->net_dev = dev; - trigger_data->link_up = 0; - goto done; - } - - if (evt == NETDEV_UNREGISTER && trigger_data->net_dev != NULL) { - dev_put(trigger_data->net_dev); - trigger_data->net_dev = NULL; - goto done; - } - - /* UP / DOWN / CHANGE */ - - trigger_data->link_up = (evt != NETDEV_DOWN && netif_carrier_ok(dev)); - set_baseline_state(trigger_data); - -done: - write_unlock(&trigger_data->lock); - return NOTIFY_DONE; -} - -/* here's the real work! */ -static void netdev_trig_timer(unsigned long arg) -{ - struct led_netdev_data *trigger_data = (struct led_netdev_data *)arg; - struct net_device_stats *dev_stats; - unsigned new_activity; - - write_lock(&trigger_data->lock); - - if (!trigger_data->link_up || !trigger_data->net_dev || (trigger_data->mode & (MODE_TX | MODE_RX)) == 0) { - /* we don't need to do timer work, just reflect link state. */ - led_set_brightness(trigger_data->led_cdev, ((trigger_data->mode & MODE_LINK) != 0 && trigger_data->link_up) ? LED_FULL : LED_OFF); - goto no_restart; - } - - dev_stats = trigger_data->net_dev->get_stats(trigger_data->net_dev); - new_activity = - ((trigger_data->mode & MODE_TX) ? dev_stats->tx_packets : 0) + - ((trigger_data->mode & MODE_RX) ? dev_stats->rx_packets : 0); - - if (trigger_data->mode & MODE_LINK) { - /* base state is ON (link present) */ - /* if there's no link, we don't get this far and the LED is off */ - - /* OFF -> ON always */ - /* ON -> OFF on activity */ - if (trigger_data->led_cdev->brightness == LED_OFF) { - led_set_brightness(trigger_data->led_cdev, LED_FULL); - } else if (trigger_data->last_activity != new_activity) { - led_set_brightness(trigger_data->led_cdev, LED_OFF); - } - } else { - /* base state is OFF */ - /* ON -> OFF always */ - /* OFF -> ON on activity */ - if (trigger_data->led_cdev->brightness == LED_FULL) { - led_set_brightness(trigger_data->led_cdev, LED_OFF); - } else if (trigger_data->last_activity != new_activity) { - led_set_brightness(trigger_data->led_cdev, LED_FULL); - } - } - - trigger_data->last_activity = new_activity; - mod_timer(&trigger_data->timer, jiffies + trigger_data->interval); - -no_restart: - write_unlock(&trigger_data->lock); -} - -static void netdev_trig_activate(struct led_classdev *led_cdev) -{ - struct led_netdev_data *trigger_data; - int rc; - - trigger_data = kzalloc(sizeof(struct led_netdev_data), GFP_KERNEL); - if (!trigger_data) - return; - - rwlock_init(&trigger_data->lock); - - trigger_data->notifier.notifier_call = netdev_trig_notify; - trigger_data->notifier.priority = 10; - - setup_timer(&trigger_data->timer, netdev_trig_timer, (unsigned long) trigger_data); - - trigger_data->led_cdev = led_cdev; - trigger_data->net_dev = NULL; - trigger_data->device_name[0] = 0; - - trigger_data->mode = 0; - trigger_data->interval = msecs_to_jiffies(50); - trigger_data->link_up = 0; - trigger_data->last_activity = 0; - - led_cdev->trigger_data = trigger_data; - - rc = device_create_file(led_cdev->dev, &dev_attr_device_name); - if (rc) - goto err_out; - rc = device_create_file(led_cdev->dev, &dev_attr_mode); - if (rc) - goto err_out_device_name; - rc = device_create_file(led_cdev->dev, &dev_attr_interval); - if (rc) - goto err_out_mode; - - register_netdevice_notifier(&trigger_data->notifier); - return; - -err_out_mode: - device_remove_file(led_cdev->dev, &dev_attr_mode); -err_out_device_name: - device_remove_file(led_cdev->dev, &dev_attr_device_name); -err_out: - led_cdev->trigger_data = NULL; - kfree(trigger_data); -} - -static void netdev_trig_deactivate(struct led_classdev *led_cdev) -{ - struct led_netdev_data *trigger_data = led_cdev->trigger_data; - - if (trigger_data) { - unregister_netdevice_notifier(&trigger_data->notifier); - - device_remove_file(led_cdev->dev, &dev_attr_device_name); - device_remove_file(led_cdev->dev, &dev_attr_mode); - device_remove_file(led_cdev->dev, &dev_attr_interval); - - write_lock(&trigger_data->lock); - - if (trigger_data->net_dev) { - dev_put(trigger_data->net_dev); - trigger_data->net_dev = NULL; - } - - write_unlock(&trigger_data->lock); - - del_timer_sync(&trigger_data->timer); - - kfree(trigger_data); - } -} - -static struct led_trigger netdev_led_trigger = { - .name = "netdev", - .activate = netdev_trig_activate, - .deactivate = netdev_trig_deactivate, -}; - -static int __init netdev_trig_init(void) -{ - return led_trigger_register(&netdev_led_trigger); -} - -static void __exit netdev_trig_exit(void) -{ - led_trigger_unregister(&netdev_led_trigger); -} - -module_init(netdev_trig_init); -module_exit(netdev_trig_exit); - -MODULE_AUTHOR("Oliver Jowett <oliver@opencloud.com>"); -MODULE_DESCRIPTION("Netdev LED trigger"); -MODULE_LICENSE("GPL"); |