diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/mxc/vpu/mxc_vpu.c | 57 |
1 files changed, 57 insertions, 0 deletions
diff --git a/drivers/mxc/vpu/mxc_vpu.c b/drivers/mxc/vpu/mxc_vpu.c index c3235dfb361e..4574208fefb8 100644 --- a/drivers/mxc/vpu/mxc_vpu.c +++ b/drivers/mxc/vpu/mxc_vpu.c @@ -39,6 +39,12 @@ #include <linux/workqueue.h> #include <linux/sched.h> #include <linux/vmalloc.h> +#include <linux/page-flags.h> +#include <linux/mm_types.h> +#include <linux/types.h> +#include <linux/memblock.h> +#include <linux/memory.h> +#include <asm/page.h> #include <asm/sizes.h> #include <mach/clock.h> #include <mach/hardware.h> @@ -84,6 +90,7 @@ static struct vpu_mem_desc vshare_mem = { 0 }; static void __iomem *vpu_base; static int vpu_ipi_irq; static u32 phy_vpu_base_addr; +static phys_addr_t top_address_DRAM; static struct mxc_vpu_platform_data *vpu_plat; /* IRAM setting */ @@ -218,6 +225,24 @@ static irqreturn_t vpu_jpu_irq_handler(int irq, void *dev_id) #endif /*! + * @brief check phy memory prepare to pass to vpu is valid or not, we + * already address some issue that if pass a wrong address to vpu + * (like virtual address), system will hang. + * + * @return true return is a valid phy memory address, false return not. + */ +bool vpu_is_valid_phy_memory(u32 vaddr, u32 paddr, u32 size) +{ + if (virt_addr_valid((void *)vaddr) && is_vmalloc_addr((void *)vaddr)) + return false; + + if (paddr > top_address_DRAM) + return false; + + return true; +} + +/*! * @brief open function for vpu file operation * * @return 0 on success or negative error code on error @@ -466,6 +491,34 @@ static long vpu_ioctl(struct file *filp, u_int cmd, break; case VPU_IOC_PHYMEM_DUMP: break; + case VPU_IOC_PHYMEM_CHECK: + { + struct vpu_mem_desc check_memory; + ret = copy_from_user(&check_memory, + (void __user *)arg, + sizeof(struct vpu_mem_desc)); + if (ret != 0) { + printk(KERN_ERR "copy from user failure:%d\n", ret); + ret = -EFAULT; + break; + } + check_memory.virt_uaddr = (u32)__va(check_memory.phy_addr); + ret = vpu_is_valid_phy_memory((u32)check_memory.virt_uaddr, + (u32)check_memory.phy_addr, + check_memory.size); + pr_debug("vpu: memory phy:0x%x va:0x%x %s phy memory\n", + check_memory.phy_addr, check_memory.virt_uaddr, + (ret ? "is" : "isn't")); + /* borrow .size to pass back the result. */ + check_memory.size = ret; + ret = copy_to_user((void __user *)arg, &check_memory, + sizeof(struct vpu_mem_desc)); + if (ret) { + ret = -EFAULT; + break; + } + break; + } default: { printk(KERN_ERR "No such IOCTL, cmd is %d\n", cmd); @@ -844,6 +897,10 @@ static int __init vpu_init(void) init_waitqueue_head(&vpu_queue); + + memblock_analyze(); + top_address_DRAM = memblock_end_of_DRAM_with_reserved(); + return ret; } |