diff options
Diffstat (limited to 'drivers/mtd/mtdchar.c')
-rw-r--r-- | drivers/mtd/mtdchar.c | 111 |
1 files changed, 69 insertions, 42 deletions
diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c index e9ec59e9a566..763d3f0a1f42 100644 --- a/drivers/mtd/mtdchar.c +++ b/drivers/mtd/mtdchar.c @@ -13,39 +13,13 @@ #include <linux/slab.h> #include <linux/sched.h> #include <linux/smp_lock.h> +#include <linux/backing-dev.h> #include <linux/mtd/mtd.h> #include <linux/mtd/compatmac.h> #include <asm/uaccess.h> -static struct class *mtd_class; - -static void mtd_notify_add(struct mtd_info* mtd) -{ - if (!mtd) - return; - - device_create(mtd_class, NULL, MKDEV(MTD_CHAR_MAJOR, mtd->index*2), - NULL, "mtd%d", mtd->index); - - device_create(mtd_class, NULL, MKDEV(MTD_CHAR_MAJOR, mtd->index*2+1), - NULL, "mtd%dro", mtd->index); -} - -static void mtd_notify_remove(struct mtd_info* mtd) -{ - if (!mtd) - return; - - device_destroy(mtd_class, MKDEV(MTD_CHAR_MAJOR, mtd->index*2)); - device_destroy(mtd_class, MKDEV(MTD_CHAR_MAJOR, mtd->index*2+1)); -} - -static struct mtd_notifier notifier = { - .add = mtd_notify_add, - .remove = mtd_notify_remove, -}; /* * Data structure to hold the pointer to the mtd device as well @@ -107,12 +81,15 @@ static int mtd_open(struct inode *inode, struct file *file) goto out; } - if (MTD_ABSENT == mtd->type) { + if (mtd->type == MTD_ABSENT) { put_mtd_device(mtd); ret = -ENODEV; goto out; } + if (mtd->backing_dev_info) + file->f_mapping->backing_dev_info = mtd->backing_dev_info; + /* You can't open it RW if it's not a writeable device */ if ((file->f_mode & FMODE_WRITE) && !(mtd->flags & MTD_WRITEABLE)) { put_mtd_device(mtd); @@ -781,6 +758,59 @@ static int mtd_ioctl(struct inode *inode, struct file *file, return ret; } /* memory_ioctl */ +/* + * try to determine where a shared mapping can be made + * - only supported for NOMMU at the moment (MMU can't doesn't copy private + * mappings) + */ +#ifndef CONFIG_MMU +static unsigned long mtd_get_unmapped_area(struct file *file, + unsigned long addr, + unsigned long len, + unsigned long pgoff, + unsigned long flags) +{ + struct mtd_file_info *mfi = file->private_data; + struct mtd_info *mtd = mfi->mtd; + + if (mtd->get_unmapped_area) { + unsigned long offset; + + if (addr != 0) + return (unsigned long) -EINVAL; + + if (len > mtd->size || pgoff >= (mtd->size >> PAGE_SHIFT)) + return (unsigned long) -EINVAL; + + offset = pgoff << PAGE_SHIFT; + if (offset > mtd->size - len) + return (unsigned long) -EINVAL; + + return mtd->get_unmapped_area(mtd, len, offset, flags); + } + + /* can't map directly */ + return (unsigned long) -ENOSYS; +} +#endif + +/* + * set up a mapping for shared memory segments + */ +static int mtd_mmap(struct file *file, struct vm_area_struct *vma) +{ +#ifdef CONFIG_MMU + struct mtd_file_info *mfi = file->private_data; + struct mtd_info *mtd = mfi->mtd; + + if (mtd->type == MTD_RAM || mtd->type == MTD_ROM) + return 0; + return -ENOSYS; +#else + return vma->vm_flags & VM_SHARED ? 0 : -ENOSYS; +#endif +} + static const struct file_operations mtd_fops = { .owner = THIS_MODULE, .llseek = mtd_lseek, @@ -789,39 +819,36 @@ static const struct file_operations mtd_fops = { .ioctl = mtd_ioctl, .open = mtd_open, .release = mtd_close, + .mmap = mtd_mmap, +#ifndef CONFIG_MMU + .get_unmapped_area = mtd_get_unmapped_area, +#endif }; static int __init init_mtdchar(void) { - if (register_chrdev(MTD_CHAR_MAJOR, "mtd", &mtd_fops)) { + int status; + + status = register_chrdev(MTD_CHAR_MAJOR, "mtd", &mtd_fops); + if (status < 0) { printk(KERN_NOTICE "Can't allocate major number %d for Memory Technology Devices.\n", MTD_CHAR_MAJOR); - return -EAGAIN; } - mtd_class = class_create(THIS_MODULE, "mtd"); - - if (IS_ERR(mtd_class)) { - printk(KERN_ERR "Error creating mtd class.\n"); - unregister_chrdev(MTD_CHAR_MAJOR, "mtd"); - return PTR_ERR(mtd_class); - } - - register_mtd_user(¬ifier); - return 0; + return status; } static void __exit cleanup_mtdchar(void) { - unregister_mtd_user(¬ifier); - class_destroy(mtd_class); unregister_chrdev(MTD_CHAR_MAJOR, "mtd"); } module_init(init_mtdchar); module_exit(cleanup_mtdchar); +MODULE_ALIAS_CHARDEV_MAJOR(MTD_CHAR_MAJOR); MODULE_LICENSE("GPL"); MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>"); MODULE_DESCRIPTION("Direct character-device access to MTD devices"); +MODULE_ALIAS_CHARDEV_MAJOR(MTD_CHAR_MAJOR); |