diff options
author | David Howells <dhowells@redhat.com> | 2009-02-12 05:40:00 -0500 |
---|---|---|
committer | David Woodhouse <David.Woodhouse@intel.com> | 2009-03-24 05:00:19 -0400 |
commit | 402d326519c1a4859c527702383f4e60f606ef52 (patch) | |
tree | beb302d56d7671d372ae73f2664feed2a5b1226d /drivers/mtd/mtdchar.c | |
parent | 9ce969082e490d0a5a81862b364337c93dc3482a (diff) |
NOMMU: Present backing device capabilities for MTD chardevs
Present backing device capabilities for MTD character device files to allow
NOMMU mmap to do direct mapping where possible.
Signed-off-by: David Howells <dhowells@redhat.com>
Tested-by: Bernd Schmidt <bernd.schmidt@analog.com>
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
Diffstat (limited to 'drivers/mtd/mtdchar.c')
-rw-r--r-- | drivers/mtd/mtdchar.c | 63 |
1 files changed, 62 insertions, 1 deletions
diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c index 2c8a16f49ca..f478f1fc394 100644 --- a/drivers/mtd/mtdchar.c +++ b/drivers/mtd/mtdchar.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/slab.h> | 13 | #include <linux/slab.h> |
14 | #include <linux/sched.h> | 14 | #include <linux/sched.h> |
15 | #include <linux/smp_lock.h> | 15 | #include <linux/smp_lock.h> |
16 | #include <linux/backing-dev.h> | ||
16 | 17 | ||
17 | #include <linux/mtd/mtd.h> | 18 | #include <linux/mtd/mtd.h> |
18 | #include <linux/mtd/compatmac.h> | 19 | #include <linux/mtd/compatmac.h> |
@@ -107,12 +108,15 @@ static int mtd_open(struct inode *inode, struct file *file) | |||
107 | goto out; | 108 | goto out; |
108 | } | 109 | } |
109 | 110 | ||
110 | if (MTD_ABSENT == mtd->type) { | 111 | if (mtd->type == MTD_ABSENT) { |
111 | put_mtd_device(mtd); | 112 | put_mtd_device(mtd); |
112 | ret = -ENODEV; | 113 | ret = -ENODEV; |
113 | goto out; | 114 | goto out; |
114 | } | 115 | } |
115 | 116 | ||
117 | if (mtd->backing_dev_info) | ||
118 | file->f_mapping->backing_dev_info = mtd->backing_dev_info; | ||
119 | |||
116 | /* You can't open it RW if it's not a writeable device */ | 120 | /* You can't open it RW if it's not a writeable device */ |
117 | if ((file->f_mode & FMODE_WRITE) && !(mtd->flags & MTD_WRITEABLE)) { | 121 | if ((file->f_mode & FMODE_WRITE) && !(mtd->flags & MTD_WRITEABLE)) { |
118 | put_mtd_device(mtd); | 122 | put_mtd_device(mtd); |
@@ -781,6 +785,59 @@ static int mtd_ioctl(struct inode *inode, struct file *file, | |||
781 | return ret; | 785 | return ret; |
782 | } /* memory_ioctl */ | 786 | } /* memory_ioctl */ |
783 | 787 | ||
788 | /* | ||
789 | * try to determine where a shared mapping can be made | ||
790 | * - only supported for NOMMU at the moment (MMU can't doesn't copy private | ||
791 | * mappings) | ||
792 | */ | ||
793 | #ifndef CONFIG_MMU | ||
794 | static unsigned long mtd_get_unmapped_area(struct file *file, | ||
795 | unsigned long addr, | ||
796 | unsigned long len, | ||
797 | unsigned long pgoff, | ||
798 | unsigned long flags) | ||
799 | { | ||
800 | struct mtd_file_info *mfi = file->private_data; | ||
801 | struct mtd_info *mtd = mfi->mtd; | ||
802 | |||
803 | if (mtd->get_unmapped_area) { | ||
804 | unsigned long offset; | ||
805 | |||
806 | if (addr != 0) | ||
807 | return (unsigned long) -EINVAL; | ||
808 | |||
809 | if (len > mtd->size || pgoff >= (mtd->size >> PAGE_SHIFT)) | ||
810 | return (unsigned long) -EINVAL; | ||
811 | |||
812 | offset = pgoff << PAGE_SHIFT; | ||
813 | if (offset > mtd->size - len) | ||
814 | return (unsigned long) -EINVAL; | ||
815 | |||
816 | return mtd->get_unmapped_area(mtd, len, offset, flags); | ||
817 | } | ||
818 | |||
819 | /* can't map directly */ | ||
820 | return (unsigned long) -ENOSYS; | ||
821 | } | ||
822 | #endif | ||
823 | |||
824 | /* | ||
825 | * set up a mapping for shared memory segments | ||
826 | */ | ||
827 | static int mtd_mmap(struct file *file, struct vm_area_struct *vma) | ||
828 | { | ||
829 | #ifdef CONFIG_MMU | ||
830 | struct mtd_file_info *mfi = file->private_data; | ||
831 | struct mtd_info *mtd = mfi->mtd; | ||
832 | |||
833 | if (mtd->type == MTD_RAM || mtd->type == MTD_ROM) | ||
834 | return 0; | ||
835 | return -ENOSYS; | ||
836 | #else | ||
837 | return vma->vm_flags & VM_SHARED ? 0 : -ENOSYS; | ||
838 | #endif | ||
839 | } | ||
840 | |||
784 | static const struct file_operations mtd_fops = { | 841 | static const struct file_operations mtd_fops = { |
785 | .owner = THIS_MODULE, | 842 | .owner = THIS_MODULE, |
786 | .llseek = mtd_lseek, | 843 | .llseek = mtd_lseek, |
@@ -789,6 +846,10 @@ static const struct file_operations mtd_fops = { | |||
789 | .ioctl = mtd_ioctl, | 846 | .ioctl = mtd_ioctl, |
790 | .open = mtd_open, | 847 | .open = mtd_open, |
791 | .release = mtd_close, | 848 | .release = mtd_close, |
849 | .mmap = mtd_mmap, | ||
850 | #ifndef CONFIG_MMU | ||
851 | .get_unmapped_area = mtd_get_unmapped_area, | ||
852 | #endif | ||
792 | }; | 853 | }; |
793 | 854 | ||
794 | static int __init init_mtdchar(void) | 855 | static int __init init_mtdchar(void) |