X-Git-Url: http://pilppa.org/gitweb/?a=blobdiff_plain;f=drivers%2Fchar%2Fmem.c;h=e67eef4867ba02c8af26652b811b290057bf959e;hb=4f911d64e04a44c47985be30f978fb3c2efcee0c;hp=e97c32ceb7962b745d3ea6d164a353f930686c74;hpb=e82ca04387dd6c98722f5f48235089839fd04268;p=linux-2.6-omap-h63xx.git diff --git a/drivers/char/mem.c b/drivers/char/mem.c index e97c32ceb79..cc9a9d0df97 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c @@ -18,7 +18,6 @@ #include #include #include -#include #include #include #include @@ -26,6 +25,7 @@ #include #include #include +#include #include #include @@ -95,7 +95,7 @@ static inline int valid_phys_addr_range(unsigned long addr, size_t count) return 1; } -static inline int valid_mmap_phys_addr_range(unsigned long addr, size_t size) +static inline int valid_mmap_phys_addr_range(unsigned long pfn, size_t size) { return 1; } @@ -238,13 +238,42 @@ 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 << PAGE_SHIFT; +} + +/* 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; - if (!valid_mmap_phys_addr_range(vma->vm_pgoff << PAGE_SHIFT, size)) + 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__) +#ifdef CONFIG_DEVPORT static ssize_t read_port(struct file * file, char __user * buf, size_t count, loff_t *ppos) { @@ -616,7 +645,8 @@ static inline size_t read_zero_pagealigned(char __user * buf, size_t size) count = size; zap_page_range(vma, addr, count, NULL); - zeromap_page_range(vma, addr, count, PAGE_COPY); + if (zeromap_page_range(vma, addr, count, PAGE_COPY)) + break; size -= count; buf += count; @@ -683,11 +713,14 @@ out: static int mmap_zero(struct file * file, struct vm_area_struct * vma) { + int err; + if (vma->vm_flags & VM_SHARED) return shmem_zero_setup(vma); - if (zeromap_page_range(vma, vma->vm_start, vma->vm_end - vma->vm_start, vma->vm_page_prot)) - return -EAGAIN; - return 0; + err = zeromap_page_range(vma, vma->vm_start, + vma->vm_end - vma->vm_start, vma->vm_page_prot); + BUG_ON(err == -EEXIST); + return err; } #else /* CONFIG_MMU */ static ssize_t read_zero(struct file * file, char * buf, @@ -744,7 +777,7 @@ static loff_t memory_lseek(struct file * file, loff_t offset, int orig) { loff_t ret; - mutex_lock(&file->f_dentry->d_inode->i_mutex); + mutex_lock(&file->f_path.dentry->d_inode->i_mutex); switch (orig) { case 0: file->f_pos = offset; @@ -759,7 +792,7 @@ static loff_t memory_lseek(struct file * file, loff_t offset, int orig) default: ret = -EINVAL; } - mutex_unlock(&file->f_dentry->d_inode->i_mutex); + mutex_unlock(&file->f_path.dentry->d_inode->i_mutex); return ret; } @@ -782,6 +815,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 +824,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 +834,7 @@ static const struct file_operations null_fops = { .splice_write = splice_write_null, }; -#if defined(CONFIG_ISA) || !defined(__mc68000__) +#ifdef CONFIG_DEVPORT static const struct file_operations port_fops = { .llseek = memory_lseek, .read = read_port, @@ -815,6 +850,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 +901,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__) +#ifdef CONFIG_DEVPORT case 4: filp->f_op = &port_fops; break; @@ -916,7 +959,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__) +#ifdef CONFIG_DEVPORT {4, "port", S_IRUSR | S_IWUSR | S_IRGRP, &port_fops}, #endif {5, "zero", S_IRUGO | S_IWUGO, &zero_fops}, @@ -940,10 +983,10 @@ static int __init chr_dev_init(void) mem_class = class_create(THIS_MODULE, "mem"); for (i = 0; i < ARRAY_SIZE(devlist); i++) - class_device_create(mem_class, NULL, - MKDEV(MEM_MAJOR, devlist[i].minor), - NULL, devlist[i].name); - + device_create(mem_class, NULL, + MKDEV(MEM_MAJOR, devlist[i].minor), + devlist[i].name); + return 0; }