From: Alexey Dobriyan Note: looks like accesses to "registered_fb" are done without any exclusion so there're none in new proc code, too. This should be fixed in separate patch. Signed-off-by: Alexey Dobriyan Cc: "Antonino A. Daplas" Signed-off-by: Andrew Morton --- drivers/video/fbmem.c | 61 ++++++++++++++++++++++++++++------------ 1 file changed, 43 insertions(+), 18 deletions(-) diff -puN drivers/video/fbmem.c~fb-convert-proc-fb-to-seq_file-interface drivers/video/fbmem.c --- a/drivers/video/fbmem.c~fb-convert-proc-fb-to-seq_file-interface +++ a/drivers/video/fbmem.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #ifdef CONFIG_KMOD #include @@ -632,27 +633,51 @@ int fb_prepare_logo(struct fb_info *info int fb_show_logo(struct fb_info *info, int rotate) { return 0; } #endif /* CONFIG_LOGO */ -static int fbmem_read_proc(char *buf, char **start, off_t offset, - int len, int *eof, void *private) +static void * fb_seq_start(struct seq_file *m, loff_t *pos) { - struct fb_info **fi; - int clen; + return (*pos < FB_MAX) ? pos : NULL; +} - clen = 0; - for (fi = registered_fb; fi < ®istered_fb[FB_MAX] && clen < 4000; - fi++) - if (*fi) - clen += sprintf(buf + clen, "%d %s\n", - (*fi)->node, - (*fi)->fix.id); - *start = buf + offset; - if (clen > offset) - clen -= offset; - else - clen = 0; - return clen < len ? clen : len; +static void * fb_seq_next(struct seq_file *m, void *v, loff_t *pos) +{ + (*pos)++; + return (*pos < FB_MAX) ? pos : NULL; +} + +static void fb_seq_stop(struct seq_file *m, void *v) +{ +} + +static int fb_seq_show(struct seq_file *m, void *v) +{ + int i = *(loff_t *)v; + struct fb_info *fi = registered_fb[i]; + + if (fi) + seq_printf(m, "%d %s\n", fi->node, fi->fix.id); + return 0; } +static const struct seq_operations proc_fb_seq_ops = { + .start = fb_seq_start, + .next = fb_seq_next, + .stop = fb_seq_stop, + .show = fb_seq_show, +}; + +static int proc_fb_open(struct inode *inode, struct file *file) +{ + return seq_open(file, &proc_fb_seq_ops); +} + +static const struct file_operations fb_proc_fops = { + .owner = THIS_MODULE, + .open = proc_fb_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release, +}; + static ssize_t fb_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { @@ -1533,7 +1558,7 @@ void fb_set_suspend(struct fb_info *info static int __init fbmem_init(void) { - create_proc_read_entry("fb", 0, NULL, fbmem_read_proc, NULL); + proc_create("fb", 0, NULL, &fb_proc_fops); if (register_chrdev(FB_MAJOR,"fb",&fb_fops)) printk("unable to get major %d for fb devs\n", FB_MAJOR); _