summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSammy He <r62914@freescale.com>2011-07-28 19:50:31 +0800
committerSammy He <r62914@freescale.com>2011-07-30 00:02:47 +0800
commit6d16069495c2f110bba4d4c311de1c02fceeccc2 (patch)
treec586ec59e87304d0a06aa5d8865370e2f9102c08
parent5e31cce37c4e7f497bae0e74f62fd37eec3c82e4 (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.c63
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);
}