diff options
author | Sammy He <r62914@freescale.com> | 2011-07-28 19:50:31 +0800 |
---|---|---|
committer | Sammy He <r62914@freescale.com> | 2011-07-30 00:02:47 +0800 |
commit | 6d16069495c2f110bba4d4c311de1c02fceeccc2 (patch) | |
tree | c586ec59e87304d0a06aa5d8865370e2f9102c08 | |
parent | 5e31cce37c4e7f497bae0e74f62fd37eec3c82e4 (diff) |
ENGR00153830-2 vpu: Add VPU_IOC_REQ_VSHARE_MEM ioctl for shared memory
Add vmalloced memory for multi-instances shared memory, vpu lib
will call mmap for accessing the memory.
VPU_IOC_GET_SHARE_MEM ioctl is still reserved for some time since
vpu lib still uses it for mx5x now. Will remove it after mx5x changes
to this new added memory later.
Signed-off-by: Sammy He <r62914@freescale.com>
-rw-r--r-- | drivers/mxc/vpu/mxc_vpu.c | 63 |
1 files changed, 59 insertions, 4 deletions
diff --git a/drivers/mxc/vpu/mxc_vpu.c b/drivers/mxc/vpu/mxc_vpu.c index 7df033b2c149..41bd188ad109 100644 --- a/drivers/mxc/vpu/mxc_vpu.c +++ b/drivers/mxc/vpu/mxc_vpu.c @@ -37,7 +37,8 @@ #include <linux/io.h> #include <linux/slab.h> #include <linux/workqueue.h> - +#include <linux/sched.h> +#include <linux/vmalloc.h> #include <asm/sizes.h> #include <mach/clock.h> #include <mach/hardware.h> @@ -74,6 +75,7 @@ static struct vpu_mem_desc bitwork_mem = { 0 }; static struct vpu_mem_desc pic_para_mem = { 0 }; static struct vpu_mem_desc user_data_mem = { 0 }; static struct vpu_mem_desc share_mem = { 0 }; +static struct vpu_mem_desc vshare_mem = { 0 }; static void __iomem *vpu_base; static int vpu_irq; @@ -390,6 +392,36 @@ static int vpu_ioctl(struct inode *inode, struct file *filp, u_int cmd, spin_unlock(&vpu_lock); break; } + case VPU_IOC_REQ_VSHARE_MEM: + { + spin_lock(&vpu_lock); + if (vshare_mem.cpu_addr != 0) { + ret = copy_to_user((void __user *)arg, + &vshare_mem, + sizeof(struct vpu_mem_desc)); + spin_unlock(&vpu_lock); + break; + } else { + if (copy_from_user(&vshare_mem, + (struct vpu_mem_desc *)arg, + sizeof(struct + vpu_mem_desc))) { + spin_unlock(&vpu_lock); + return -EFAULT; + } + /* vmalloc shared memory if not allocated */ + if (!vshare_mem.cpu_addr) + vshare_mem.cpu_addr = + (unsigned long) + vmalloc_user(vshare_mem.size); + if (copy_to_user + ((void __user *)arg, &vshare_mem, + sizeof(struct vpu_mem_desc))) + ret = -EFAULT; + } + spin_unlock(&vpu_lock); + break; + } case VPU_IOC_GET_WORK_ADDR: { if (bitwork_mem.cpu_addr != 0) { @@ -447,6 +479,8 @@ static int vpu_release(struct inode *inode, struct file *filp) /* Free shared memory when vpu device is idle */ vpu_free_dma_buffer(&share_mem); share_mem.cpu_addr = 0; + vfree((void *)vshare_mem.cpu_addr); + vshare_mem.cpu_addr = 0; } spin_unlock(&vpu_lock); @@ -484,7 +518,7 @@ static int vpu_map_hwregs(struct file *fp, struct vm_area_struct *vm) * @brief memory map function of memory for vpu file operation * @return 0 on success or negative error code on error */ -static int vpu_map_mem(struct file *fp, struct vm_area_struct *vm) +static int vpu_map_dma_mem(struct file *fp, struct vm_area_struct *vm) { int request_size; request_size = vm->vm_end - vm->vm_start; @@ -501,14 +535,35 @@ static int vpu_map_mem(struct file *fp, struct vm_area_struct *vm) } +/* ! + * @brief memory map function of vmalloced share memory + * @return 0 on success or negative error code on error + */ +static int vpu_map_vshare_mem(struct file *fp, struct vm_area_struct *vm) +{ + int ret = -EINVAL; + + spin_lock(&vpu_lock); + ret = remap_vmalloc_range(vm, (void *)(vm->vm_pgoff << PAGE_SHIFT), 0); + vm->vm_flags |= VM_IO; + spin_unlock(&vpu_lock); + + return ret; +} /*! * @brief memory map interface for vpu file operation * @return 0 on success or negative error code on error */ static int vpu_mmap(struct file *fp, struct vm_area_struct *vm) { - if (vm->vm_pgoff) - return vpu_map_mem(fp, vm); + unsigned long offset; + + offset = vshare_mem.cpu_addr >> PAGE_SHIFT; + + if (vm->vm_pgoff && (vm->vm_pgoff == offset)) + return vpu_map_vshare_mem(fp, vm); + else if (vm->vm_pgoff) + return vpu_map_dma_mem(fp, vm); else return vpu_map_hwregs(fp, vm); } |