|
@@ -13,6 +13,7 @@
|
|
|
#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>
|
|
@@ -107,12 +108,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 +785,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,6 +846,10 @@ 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)
|