diff options
Diffstat (limited to 'drivers/char/mem.c')
-rw-r--r-- | drivers/char/mem.c | 47 |
1 files changed, 43 insertions, 4 deletions
diff --git a/drivers/char/mem.c b/drivers/char/mem.c index 917b2040266..6511012cbdc 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c @@ -238,6 +238,32 @@ static pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn, } #endif +#ifndef CONFIG_MMU +static unsigned long get_unmapped_area_mem(struct file *file, + unsigned long addr, + unsigned long len, + unsigned long pgoff, + unsigned long flags) +{ + if (!valid_mmap_phys_addr_range(pgoff, len)) + return (unsigned long) -EINVAL; + return pgoff; +} + +/* can't do an in-place private mapping if there's no MMU */ +static inline int private_mapping_ok(struct vm_area_struct *vma) +{ + return vma->vm_flags & VM_MAYSHARE; +} +#else +#define get_unmapped_area_mem NULL + +static inline int private_mapping_ok(struct vm_area_struct *vma) +{ + return 1; +} +#endif + static int mmap_mem(struct file * file, struct vm_area_struct * vma) { size_t size = vma->vm_end - vma->vm_start; @@ -245,6 +271,9 @@ static int mmap_mem(struct file * file, struct vm_area_struct * vma) if (!valid_mmap_phys_addr_range(vma->vm_pgoff, size)) return -EINVAL; + if (!private_mapping_ok(vma)) + return -ENOSYS; + vma->vm_page_prot = phys_mem_access_prot(file, vma->vm_pgoff, size, vma->vm_page_prot); @@ -522,7 +551,7 @@ static ssize_t write_kmem(struct file * file, const char __user * buf, return virtr + wrote; } -#if defined(CONFIG_ISA) || !defined(__mc68000__) +#if (defined(CONFIG_ISA) || defined(CONFIG_PCI)) && !defined(__mc68000__) static ssize_t read_port(struct file * file, char __user * buf, size_t count, loff_t *ppos) { @@ -782,6 +811,7 @@ static const struct file_operations mem_fops = { .write = write_mem, .mmap = mmap_mem, .open = open_mem, + .get_unmapped_area = get_unmapped_area_mem, }; static const struct file_operations kmem_fops = { @@ -790,6 +820,7 @@ static const struct file_operations kmem_fops = { .write = write_kmem, .mmap = mmap_kmem, .open = open_kmem, + .get_unmapped_area = get_unmapped_area_mem, }; static const struct file_operations null_fops = { @@ -799,7 +830,7 @@ static const struct file_operations null_fops = { .splice_write = splice_write_null, }; -#if defined(CONFIG_ISA) || !defined(__mc68000__) +#if (defined(CONFIG_ISA) || defined(CONFIG_PCI)) && !defined(__mc68000__) static const struct file_operations port_fops = { .llseek = memory_lseek, .read = read_port, @@ -815,6 +846,10 @@ static const struct file_operations zero_fops = { .mmap = mmap_zero, }; +/* + * capabilities for /dev/zero + * - permits private mappings, "copies" are taken of the source of zeros + */ static struct backing_dev_info zero_bdi = { .capabilities = BDI_CAP_MAP_COPY, }; @@ -862,14 +897,18 @@ static int memory_open(struct inode * inode, struct file * filp) switch (iminor(inode)) { case 1: filp->f_op = &mem_fops; + filp->f_mapping->backing_dev_info = + &directly_mappable_cdev_bdi; break; case 2: filp->f_op = &kmem_fops; + filp->f_mapping->backing_dev_info = + &directly_mappable_cdev_bdi; break; case 3: filp->f_op = &null_fops; break; -#if defined(CONFIG_ISA) || !defined(__mc68000__) +#if (defined(CONFIG_ISA) || defined(CONFIG_PCI)) && !defined(__mc68000__) case 4: filp->f_op = &port_fops; break; @@ -916,7 +955,7 @@ static const struct { {1, "mem", S_IRUSR | S_IWUSR | S_IRGRP, &mem_fops}, {2, "kmem", S_IRUSR | S_IWUSR | S_IRGRP, &kmem_fops}, {3, "null", S_IRUGO | S_IWUGO, &null_fops}, -#if defined(CONFIG_ISA) || !defined(__mc68000__) +#if (defined(CONFIG_ISA) || defined(CONFIG_PCI)) && !defined(__mc68000__) {4, "port", S_IRUSR | S_IWUSR | S_IRGRP, &port_fops}, #endif {5, "zero", S_IRUGO | S_IWUGO, &zero_fops}, |