diff options
Diffstat (limited to 'package/kernel/broadcom-diag/src/diag.c')
-rw-r--r-- | package/kernel/broadcom-diag/src/diag.c | 240 |
1 files changed, 121 insertions, 119 deletions
diff --git a/package/kernel/broadcom-diag/src/diag.c b/package/kernel/broadcom-diag/src/diag.c index ace44cce55..c87ca97458 100644 --- a/package/kernel/broadcom-diag/src/diag.c +++ b/package/kernel/broadcom-diag/src/diag.c @@ -45,9 +45,6 @@ static unsigned int gpiomask = 0; module_param(gpiomask, int, 0644); extern char *nvram_get(char *str); - -static void register_leds(struct led_t *l); -static void unregister_leds(struct led_t *l); static void led_flash(unsigned long dummy); static struct platform_t platform; @@ -56,8 +53,20 @@ static struct timer_list led_timer = TIMER_INITIALIZER(&led_flash, 0, 0); static struct proc_dir_entry *diag, *leds; -static struct prochandler_t proc_model = { .type = PROC_MODEL }; -static struct prochandler_t proc_gpiomask = { .type = PROC_GPIOMASK }; +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,9,0) +static inline struct inode *file_inode(struct file *f) +{ + return f->f_path.dentry->d_inode; +} +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) +static inline void *PDE_DATA(const struct inode *inode) +{ + return PDE(inode)->data; +} +#endif + enum { /* Linksys */ @@ -1586,122 +1595,65 @@ static void led_flash(unsigned long dummy) { } } -static ssize_t diag_proc_read(struct file *file, char *buf, size_t count, loff_t *ppos) +static int diag_led_show(struct seq_file *m, void *v) { - struct proc_dir_entry *dent = PDE(file->f_dentry->d_inode); - char *page; - int len = 0; - - if ((page = kmalloc(1024, GFP_KERNEL)) == NULL) - return -ENOBUFS; - - if (dent->data != NULL) { - struct prochandler_t *handler = (struct prochandler_t *) dent->data; - switch (handler->type) { - case PROC_LED: { - struct led_t * led = (struct led_t *) handler->ptr; - u8 p = (led->polarity == NORMAL ? 0 : 1); - if (led->flash) { - len = sprintf(page, "f\n"); - } else if ((led->gpio & GPIO_TYPE_MASK) != GPIO_TYPE_NORMAL) { - len = sprintf(page, "%d\n", ((led->state ^ p) ? 1 : 0)); - } else { - u32 in = (bcm47xx_gpio_in(~0) & led->gpio ? 1 : 0); - len = sprintf(page, "%d\n", ((in ^ p) ? 1 : 0)); - } - break; - } - case PROC_MODEL: - len = sprintf(page, "%s\n", platform.name); - break; - case PROC_GPIOMASK: - len = sprintf(page, "0x%04x\n", gpiomask); - break; - } - } - len += 1; + struct led_t * led = m->private; - if (*ppos < len) { - len = min_t(int, len - *ppos, count); - if (copy_to_user(buf, (page + *ppos), len)) { - kfree(page); - return -EFAULT; - } - *ppos += len; + u8 p = (led->polarity == NORMAL ? 0 : 1); + if (led->flash) { + return seq_printf(m, "f\n"); + } else if ((led->gpio & GPIO_TYPE_MASK) != GPIO_TYPE_NORMAL) { + return seq_printf(m, "%d\n", ((led->state ^ p) ? 1 : 0)); } else { - len = 0; + u32 in = (bcm47xx_gpio_in(~0) & led->gpio ? 1 : 0); + return seq_printf(m, "%d\n", ((in ^ p) ? 1 : 0)); } - - kfree(page); - return len; } +static int diag_led_open(struct inode *inode, struct file *file) +{ + return single_open(file, diag_led_show, PDE_DATA(inode)); +} -static ssize_t diag_proc_write(struct file *file, const char *buf, size_t count, loff_t *ppos) +static ssize_t diag_led_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { - struct proc_dir_entry *dent = PDE(file->f_dentry->d_inode); - char *page; - int ret = -EINVAL; + struct led_t *led = PDE_DATA(file_inode(file)); + char cmd[5]; + size_t len; + int p; - if ((page = kmalloc(count + 1, GFP_KERNEL)) == NULL) - return -ENOBUFS; + len = min(count, sizeof(cmd) - 1); + if (copy_from_user(cmd, buf, len)) + return -EFAULT; - if (copy_from_user(page, buf, count)) { - kfree(page); - return -EINVAL; - } - page[count] = 0; - - if (dent->data != NULL) { - struct prochandler_t *handler = (struct prochandler_t *) dent->data; - switch (handler->type) { - case PROC_LED: { - struct led_t *led = (struct led_t *) handler->ptr; - int p = (led->polarity == NORMAL ? 0 : 1); - - if (page[0] == 'f') { - led->flash = 1; - led_flash(0); - } else { - led->flash = 0; - if ((led->gpio & GPIO_TYPE_MASK) == GPIO_TYPE_EXTIF) { - led->state = p ^ ((page[0] == '1') ? 1 : 0); - set_led_extif(led); - } else if ((led->gpio & GPIO_TYPE_MASK) == GPIO_TYPE_SHIFT) { - led->state = p ^ ((page[0] == '1') ? 1 : 0); - set_led_shift(led); - } else { - bcm47xx_gpio_outen(led->gpio, led->gpio); - bcm47xx_gpio_control(led->gpio, 0); - bcm47xx_gpio_out(led->gpio, ((p ^ (page[0] == '1')) ? led->gpio : 0)); - } - } - break; - } - case PROC_GPIOMASK: - gpiomask = simple_strtoul(page, NULL, 0); - - if (platform.buttons) { - unregister_buttons(platform.buttons); - register_buttons(platform.buttons); - } - - if (platform.leds) { - unregister_leds(platform.leds); - register_leds(platform.leds); - } - break; + cmd[len] = 0; + + p = (led->polarity == NORMAL ? 0 : 1); + if (cmd[0] == 'f') { + led->flash = 1; + led_flash(0); + } else { + led->flash = 0; + if ((led->gpio & GPIO_TYPE_MASK) == GPIO_TYPE_EXTIF) { + led->state = p ^ ((cmd[0] == '1') ? 1 : 0); + set_led_extif(led); + } else if ((led->gpio & GPIO_TYPE_MASK) == GPIO_TYPE_SHIFT) { + led->state = p ^ ((cmd[0] == '1') ? 1 : 0); + set_led_shift(led); + } else { + bcm47xx_gpio_outen(led->gpio, led->gpio); + bcm47xx_gpio_control(led->gpio, 0); + bcm47xx_gpio_out(led->gpio, ((p ^ (cmd[0] == '1')) ? led->gpio : 0)); } - ret = count; } - - kfree(page); - return ret; + return count; } -static struct file_operations diag_proc_fops = { - read: diag_proc_read, - write: diag_proc_write +static const struct file_operations diag_led_fops = { + .open = diag_led_open, + .read = seq_read, + .llseek = seq_lseek, + .write = diag_led_write }; static void register_leds(struct led_t *l) @@ -1740,12 +1692,7 @@ static void register_leds(struct led_t *l) if (l->polarity == INPUT) continue; - if ((p = create_proc_entry(l->name, S_IRUSR, leds))) { - l->proc.type = PROC_LED; - l->proc.ptr = l; - p->data = (void *) &l->proc; - p->proc_fops = &diag_proc_fops; - } + p = proc_create_data(l->name, S_IRUSR, leds, &diag_led_fops, l); } bcm47xx_gpio_outen(mask, oe_mask); @@ -1762,6 +1709,58 @@ static void unregister_leds(struct led_t *l) remove_proc_entry("led", diag); } +static int diag_model_show(struct seq_file *m, void *v) +{ + return seq_printf(m, "%s\n", platform.name); +} + +static int diag_model_open(struct inode *inode, struct file *file) +{ + return single_open(file, diag_model_show, PDE_DATA(inode)); +} + +static const struct file_operations diag_model_fops = { + .open = diag_model_open, + .read = seq_read, + .llseek = seq_lseek +}; + +static int diag_gpiomask_show(struct seq_file *m, void *v) +{ + return seq_printf(m, "0x%04x\n", gpiomask); +} + +static int diag_gpiomask_open(struct inode *inode, struct file *file) +{ + return single_open(file, diag_gpiomask_show, PDE_DATA(inode)); +} + +static ssize_t diag_gpiomask_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) +{ + int err = kstrtouint_from_user(buf, count, 0, &gpiomask); + if (err) + return err; + + if (platform.buttons) { + unregister_buttons(platform.buttons); + register_buttons(platform.buttons); + } + + if (platform.leds) { + unregister_leds(platform.leds); + register_leds(platform.leds); + } + + return count; +} + +static const struct file_operations diag_gpiomask_fops = { + .open = diag_gpiomask_open, + .read = seq_read, + .llseek = seq_lseek, + .write = diag_gpiomask_write +}; + static int __init diag_init(void) { static struct proc_dir_entry *p; @@ -1784,14 +1783,17 @@ static int __init diag_init(void) return -EINVAL; } - if ((p = create_proc_entry("model", S_IRUSR, diag))) { - p->data = (void *) &proc_model; - p->proc_fops = &diag_proc_fops; + p = proc_create("model", S_IRUSR, diag, &diag_model_fops); + if (!p) { + remove_proc_entry("diag", NULL); + return -EINVAL; } - if ((p = create_proc_entry("gpiomask", S_IRUSR | S_IWUSR, diag))) { - p->data = (void *) &proc_gpiomask; - p->proc_fops = &diag_proc_fops; + p = proc_create("gpiomask", S_IRUSR | S_IWUSR, diag, &diag_gpiomask_fops); + if (!p) { + remove_proc_entry("model", diag); + remove_proc_entry("diag", NULL); + return -EINVAL; } if (platform.buttons) |