Add debugfs entries for device activity trigger. Three entries are created under /sys/kernel/debug/ledtrig-dev when the driver gets loaded. These are: devices - cat'ing will produce a list of currently registered devices in <major>:<minor> format, a line for each device. register - echo'ing <major>:<minor> will create a trigger for this device trigger - echo'ing <major>:<minor> will fire a trigger for this device Signed-off-by: Maciek Borzecki <maciek.borzecki@xxxxxxxxx> --- drivers/leds/trigger/ledtrig-device.c | 113 +++++++++++++++++++++++++++++++++- 1 file changed, 111 insertions(+), 2 deletions(-) diff --git a/drivers/leds/trigger/ledtrig-device.c b/drivers/leds/trigger/ledtrig-device.c index dbb8d7d2b4a0258149c581a040c416d412d9ceeb..6814db5e34d76974ae095d2e1c8f1f2e23dea79e 100644 --- a/drivers/leds/trigger/ledtrig-device.c +++ b/drivers/leds/trigger/ledtrig-device.c @@ -16,15 +16,18 @@ #include <linux/list.h> #include <linux/rwsem.h> #include <linux/kdev_t.h> +#include <linux/fs.h> +#include <linux/debugfs.h> +#include <linux/seq_file.h> #define BLINK_DELAY 30 static unsigned long blink_delay = BLINK_DELAY; static DECLARE_RWSEM(devs_list_lock); static LIST_HEAD(devs_list); +static struct dentry *debug_root; #define MAX_NAME_LEN 20 - struct ledtrig_dev_data { char name[MAX_NAME_LEN]; dev_t dev; @@ -114,8 +117,11 @@ void ledtrig_dev_add(dev_t dev) /* register with led triggers */ led_trigger_register_simple(new_dev_trig->name, &new_dev_trig->trig); - else + else { + pr_warn("device %u:%u already registered\n", + MAJOR(dev), MINOR(dev)); kfree(new_dev_trig); + } } EXPORT_SYMBOL(ledtrig_dev_add); @@ -167,13 +173,116 @@ static void ledtrig_dev_remove_all(void) up_write(&devs_list_lock); } +static int ledtrig_dev_devices_show(struct seq_file *s, void *unused) +{ + struct ledtrig_dev_data *dev_trig; + + down_read(&devs_list_lock); + list_for_each_entry(dev_trig, &devs_list, node) { + seq_printf(s, "%u:%u\n", MAJOR(dev_trig->dev), + MINOR(dev_trig->dev)); + } + up_read(&devs_list_lock); + return 0; +} + +static int ledtrig_dev_devices_open(struct inode *inode, struct file *file) +{ + return single_open(file, ledtrig_dev_devices_show, + &inode->i_private); +} + +static const struct file_operations debug_devices_ops = { + .owner = THIS_MODULE, + .open = ledtrig_dev_devices_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release +}; + +static int get_dev_from_user(const char __user *buf, size_t size, + dev_t *dev) +{ + unsigned int major; + unsigned int minor; + int ret; + + WARN_ON(dev == NULL); + if (dev == NULL) + return -EINVAL; + + ret = sscanf(buf, "%u:%u", &major, &minor); + if (ret < 2) + return -EINVAL; + + *dev = MKDEV(major, minor); + return 0; +} + +static ssize_t ledtrig_dev_register_write(struct file *filp, + const char __user *buf, + size_t size, loff_t *off) +{ + dev_t dev; + int ret; + + ret = get_dev_from_user(buf, size, &dev); + if (ret < 0) + return ret; + + pr_debug("got device %u:%u\n", MAJOR(dev), MINOR(dev)); + ledtrig_dev_add(dev); + + return size; +} + +static const struct file_operations debug_register_ops = { + .owner = THIS_MODULE, + .write = ledtrig_dev_register_write, +}; + +static ssize_t ledtrig_dev_trigger_write(struct file *filp, + const char __user *buf, + size_t size, loff_t *off) +{ + dev_t dev; + int ret; + + ret = get_dev_from_user(buf, size, &dev); + if (ret < 0) + return ret; + + pr_debug("trigger device %u:%u\n", MAJOR(dev), MINOR(dev)); + ledtrig_dev_activity(dev); + + return size; +} + +static const struct file_operations debug_trigger_ops = { + .owner = THIS_MODULE, + .write = ledtrig_dev_trigger_write, +}; + static int __init ledtrig_dev_init(void) { + debug_root = debugfs_create_dir("ledtrig-dev", NULL); + + if (debug_root) { + debugfs_create_file("devices", 0444, debug_root, NULL, + &debug_devices_ops); + debugfs_create_file("register", 0200, debug_root, NULL, + &debug_register_ops); + debugfs_create_file("trigger", 0200, debug_root, NULL, + &debug_trigger_ops); + } + return 0; } static void __exit ledtrig_dev_exit(void) { + debugfs_remove_recursive(debug_root); + ledtrig_dev_remove_all(); } -- 2.5.3 -- To unsubscribe from this list: send the line "unsubscribe linux-doc" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html