in devices/rio_mport_cdev.c [2193:2250]
static int mport_cdev_mmap(struct file *filp, struct vm_area_struct *vma)
{
struct mport_cdev_priv *priv = filp->private_data;
struct mport_dev *md;
size_t size = vma->vm_end - vma->vm_start;
dma_addr_t baddr;
unsigned long offset;
int found = 0, ret;
struct rio_mport_mapping *map;
rmcd_debug(MMAP, "0x%x bytes at offset 0x%lx",
(unsigned int)size, vma->vm_pgoff);
md = priv->md;
baddr = ((dma_addr_t)vma->vm_pgoff << PAGE_SHIFT);
mutex_lock(&md->buf_mutex);
list_for_each_entry(map, &md->mappings, node) {
if (baddr >= map->phys_addr &&
baddr < (map->phys_addr + map->size)) {
found = 1;
break;
}
}
mutex_unlock(&md->buf_mutex);
if (!found)
return -ENOMEM;
offset = baddr - map->phys_addr;
if (size + offset > map->size)
return -EINVAL;
vma->vm_pgoff = offset >> PAGE_SHIFT;
rmcd_debug(MMAP, "MMAP adjusted offset = 0x%lx", vma->vm_pgoff);
if (map->dir == MAP_INBOUND || map->dir == MAP_DMA)
ret = dma_mmap_coherent(md->mport->dev.parent, vma,
map->virt_addr, map->phys_addr, map->size);
else if (map->dir == MAP_OUTBOUND) {
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
ret = vm_iomap_memory(vma, map->phys_addr, map->size);
} else {
rmcd_error("Attempt to mmap unsupported mapping type");
ret = -EIO;
}
if (!ret) {
vma->vm_private_data = map;
vma->vm_ops = &vm_ops;
mport_mm_open(vma);
} else {
rmcd_error("MMAP exit with err=%d", ret);
}
return ret;
}