in uio.c [762:816]
static int uio_mmap(struct file *filep, struct vm_area_struct *vma)
{
struct uio_listener *listener = filep->private_data;
struct uio_device *idev = listener->dev;
int mi;
unsigned long requested_pages, actual_pages;
int ret = 0;
if (vma->vm_end < vma->vm_start)
return -EINVAL;
vma->vm_private_data = idev;
mutex_lock(&idev->info_lock);
if (!idev->info) {
ret = -EINVAL;
goto out;
}
mi = uio_find_mem_index(vma);
if (mi < 0) {
ret = -EINVAL;
goto out;
}
requested_pages = vma_pages(vma);
actual_pages = ((idev->info->mem[mi].addr & ~PAGE_MASK)
+ idev->info->mem[mi].size + PAGE_SIZE -1) >> PAGE_SHIFT;
if (requested_pages > actual_pages) {
ret = -EINVAL;
goto out;
}
if (idev->info->mmap) {
ret = idev->info->mmap(idev->info, vma);
goto out;
}
switch (idev->info->mem[mi].memtype) {
case UIO_MEM_IOVA:
case UIO_MEM_PHYS:
ret = uio_mmap_physical(vma);
break;
case UIO_MEM_LOGICAL:
case UIO_MEM_VIRTUAL:
ret = uio_mmap_logical(vma);
break;
default:
ret = -EINVAL;
}
out:
mutex_unlock(&idev->info_lock);
return ret;
}