diff options
Diffstat (limited to 'drivers/staging/tidspbridge/rmgr/drv_interface.c')
-rw-r--r-- | drivers/staging/tidspbridge/rmgr/drv_interface.c | 33 |
1 files changed, 28 insertions, 5 deletions
diff --git a/drivers/staging/tidspbridge/rmgr/drv_interface.c b/drivers/staging/tidspbridge/rmgr/drv_interface.c index 56e355b3e7fa..74d31dabe832 100644 --- a/drivers/staging/tidspbridge/rmgr/drv_interface.c +++ b/drivers/staging/tidspbridge/rmgr/drv_interface.c @@ -23,7 +23,6 @@ #include <linux/pm.h> #include <linux/module.h> #include <linux/device.h> -#include <linux/init.h> #include <linux/moduleparam.h> #include <linux/cdev.h> @@ -258,6 +257,8 @@ err: /* This function maps kernel space memory to user space memory. */ static int bridge_mmap(struct file *filp, struct vm_area_struct *vma) { + unsigned long base_pgoff; + int status; struct omap_dsp_platform_data *pdata = omap_dspbridge_dev->dev.platform_data; @@ -269,9 +270,31 @@ static int bridge_mmap(struct file *filp, struct vm_area_struct *vma) vma->vm_start, vma->vm_end, vma->vm_page_prot, vma->vm_flags); - return vm_iomap_memory(vma, - pdata->phys_mempool_base, - pdata->phys_mempool_size); + /* + * vm_iomap_memory() expects vma->vm_pgoff to be expressed as an offset + * from the start of the physical memory pool, but we're called with + * a pfn (physical page number) stored there instead. + * + * To avoid duplicating lots of tricky overflow checking logic, + * temporarily convert vma->vm_pgoff to the offset vm_iomap_memory() + * expects, but restore the original value once the mapping has been + * created. + */ + base_pgoff = pdata->phys_mempool_base >> PAGE_SHIFT; + + if (vma->vm_pgoff < base_pgoff) + return -EINVAL; + + vma->vm_pgoff -= base_pgoff; + + status = vm_iomap_memory(vma, + pdata->phys_mempool_base, + pdata->phys_mempool_size); + + /* Restore the original value of vma->vm_pgoff */ + vma->vm_pgoff += base_pgoff; + + return status; } static const struct file_operations bridge_fops = { @@ -566,7 +589,7 @@ func_cont: class_destroy(bridge_class); } - return 0; + return status; } #ifdef CONFIG_PM |