static int ion_kernel_mapper_map_user(struct ion_mapper *mapper, struct ion_buffer *buffer, struct vm_area_struct *vma, struct ion_mapping *mapping) { int ret; switch (buffer->heap->type) { case ION_HEAP_KMALLOC: { unsigned long pfn = __phys_to_pfn(virt_to_phys(buffer->priv)); ret = remap_pfn_range(vma, vma->vm_start, pfn + vma->vm_pgoff, vma->vm_end - vma->vm_start, vma->vm_page_prot); break; } case ION_HEAP_VMALLOC: ret = remap_vmalloc_range(vma, buffer->priv, vma->vm_pgoff); break; default: pr_err("%s: attempting to map unsupported heap to userspace\n", __func__); return -EINVAL; } return ret; }
static int vb2_vmalloc_mmap(void *buf_priv, struct vm_area_struct *vma) { struct vb2_vmalloc_buf *buf = buf_priv; int ret; if (!buf) { pr_err("No memory to map\n"); return -EINVAL; } ret = remap_vmalloc_range(vma, buf->vaddr, 0); if (ret) { pr_err("Remapping vmalloc memory, error: %d\n", ret); return ret; } /* * Make sure that vm_areas for 2 buffers won't be merged together */ vma->vm_flags |= VM_DONTEXPAND; /* * Use common vm_area operations to track buffer refcount. */ vma->vm_private_data = &buf->handler; vma->vm_ops = &vb2_common_vm_ops; vma->vm_ops->open(vma); return 0; }
static int __videobuf_mmap_mapper(struct videobuf_queue *q, struct videobuf_buffer *buf, struct vm_area_struct *vma) { struct videobuf_vmalloc_memory *mem; struct videobuf_mapping *map; int retval, pages; dprintk(1, "%s\n", __func__); /* create mapping + update buffer list */ map = kzalloc(sizeof(struct videobuf_mapping), GFP_KERNEL); if (NULL == map) return -ENOMEM; buf->map = map; map->start = vma->vm_start; map->end = vma->vm_end; map->q = q; buf->baddr = vma->vm_start; mem = buf->priv; BUG_ON(!mem); MAGIC_CHECK(mem->magic, MAGIC_VMAL_MEM); pages = PAGE_ALIGN(vma->vm_end - vma->vm_start); mem->vmalloc = vmalloc_user(pages); if (!mem->vmalloc) { printk(KERN_ERR "vmalloc (%d pages) failed\n", pages); goto error; } dprintk(1, "vmalloc is at addr %p (%d pages)\n", mem->vmalloc, pages); /* Try to remap memory */ retval = remap_vmalloc_range(vma, mem->vmalloc, 0); if (retval < 0) { printk(KERN_ERR "mmap: remap failed with error %d. ", retval); vfree(mem->vmalloc); goto error; } vma->vm_ops = &videobuf_vm_ops; vma->vm_flags |= VM_DONTEXPAND | VM_RESERVED; vma->vm_private_data = map; dprintk(1, "mmap %p: q=%p %08lx-%08lx (%lx) pgoff %08lx buf %d\n", map, q, vma->vm_start, vma->vm_end, (long int)buf->bsize, vma->vm_pgoff, buf->i); videobuf_vm_open(vma); return 0; error: mem = NULL; kfree(map); return -ENOMEM; }
/* runs when user space wants to mmap the file */ static int flowtab_mmap(struct file *filep, struct vm_area_struct *vma) { struct flowtab_info *info = filep->private_data; if (remap_vmalloc_range(vma, info->map->pairs, 0)) { pr_warning("remap_vmalloc_range failed\n"); return -EAGAIN; } return 0; }
int ion_system_heap_map_user(struct ion_heap *heap, struct ion_buffer *buffer, struct vm_area_struct *vma, unsigned long flags) { if (ION_IS_CACHED(flags)) return remap_vmalloc_range(vma, buffer->priv_virt, vma->vm_pgoff); else { pr_err("%s: cannot map system heap uncached\n", __func__); return -EINVAL; } }
static int ion_mm_heap_map_user(struct ion_heap *heap, struct ion_buffer *buffer, struct vm_area_struct *vma) { int ret; ion_mm_buffer_info* pBufferInfo = (ion_mm_buffer_info*) buffer->priv_virt; ION_FUNC_ENTER; if ((!pBufferInfo) || (!pBufferInfo->pVA)) { printk("[ion_mm_heap_map_user]: Error. Invalid buffer.\n"); return -EFAULT; } ret = remap_vmalloc_range(vma, pBufferInfo->pVA, vma->vm_pgoff); ION_FUNC_LEAVE; return ret; }
static int __videobuf_iolock(struct videobuf_queue *q, struct videobuf_buffer *vb, struct v4l2_framebuffer *fbuf) { struct videobuf_vmalloc_memory *mem = vb->priv; int pages; BUG_ON(!mem); MAGIC_CHECK(mem->magic, MAGIC_VMAL_MEM); switch (vb->memory) { case V4L2_MEMORY_MMAP: dprintk(1, "%s memory method MMAP\n", __func__); /* All handling should be done by __videobuf_mmap_mapper() */ if (!mem->vaddr) { printk(KERN_ERR "memory is not alloced/mmapped.\n"); return -EINVAL; } break; case V4L2_MEMORY_USERPTR: pages = PAGE_ALIGN(vb->size); dprintk(1, "%s memory method USERPTR\n", __func__); if (vb->baddr) { printk(KERN_ERR "USERPTR is currently not supported\n"); return -EINVAL; } /* The only USERPTR currently supported is the one needed for * read() method. */ mem->vaddr = vmalloc_user(pages); if (!mem->vaddr) { printk(KERN_ERR "vmalloc (%d pages) failed\n", pages); return -ENOMEM; } dprintk(1, "vmalloc is at addr %p (%d pages)\n", mem->vaddr, pages); #if 0 int rc; /* Kernel userptr is used also by read() method. In this case, there's no need to remap, since data will be copied to user */ if (!vb->baddr) return 0; /* FIXME: to properly support USERPTR, remap should occur. The code below won't work, since mem->vma = NULL */ /* Try to remap memory */ rc = remap_vmalloc_range(mem->vma, (void *)vb->baddr, 0); if (rc < 0) { printk(KERN_ERR "mmap: remap failed with error %d", rc); return -ENOMEM; } #endif break; case V4L2_MEMORY_OVERLAY: default: dprintk(1, "%s memory method OVERLAY/unknown\n", __func__); /* Currently, doesn't support V4L2_MEMORY_OVERLAY */ printk(KERN_ERR "Memory method currently unsupported.\n"); return -EINVAL; } return 0; }
static int __videobuf_iolock(struct videobuf_queue *q, struct videobuf_buffer *vb, struct v4l2_framebuffer *fbuf) { struct videobuf_vmalloc_memory *mem = vb->priv; int pages; BUG_ON(!mem); MAGIC_CHECK(mem->magic, MAGIC_VMAL_MEM); switch (vb->memory) { case V4L2_MEMORY_MMAP: dprintk(1, "%s memory method MMAP\n", __func__); if (!mem->vaddr) { printk(KERN_ERR "memory is not alloced/mmapped.\n"); return -EINVAL; } break; case V4L2_MEMORY_USERPTR: pages = PAGE_ALIGN(vb->size); dprintk(1, "%s memory method USERPTR\n", __func__); if (vb->baddr) { printk(KERN_ERR "USERPTR is currently not supported\n"); return -EINVAL; } mem->vaddr = vmalloc_user(pages); if (!mem->vaddr) { printk(KERN_ERR "vmalloc (%d pages) failed\n", pages); return -ENOMEM; } dprintk(1, "vmalloc is at addr %p (%d pages)\n", mem->vaddr, pages); #if 0 int rc; if (!vb->baddr) return 0; rc = remap_vmalloc_range(mem->vma, (void *)vb->baddr, 0); if (rc < 0) { printk(KERN_ERR "mmap: remap failed with error %d", rc); return -ENOMEM; } #endif break; case V4L2_MEMORY_OVERLAY: default: dprintk(1, "%s memory method OVERLAY/unknown\n", __func__); printk(KERN_ERR "Memory method currently unsupported.\n"); return -EINVAL; } return 0; }
static int __videobuf_mmap_mapper(struct videobuf_queue *q, struct vm_area_struct *vma) { struct videobuf_vmalloc_memory *mem; struct videobuf_mapping *map; unsigned int first; int retval, pages; unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; dprintk(1, "%s\n", __func__); if (!(vma->vm_flags & VM_WRITE) || !(vma->vm_flags & VM_SHARED)) return -EINVAL; /* look for first buffer to map */ for (first = 0; first < VIDEO_MAX_FRAME; first++) { if (NULL == q->bufs[first]) continue; if (V4L2_MEMORY_MMAP != q->bufs[first]->memory) continue; if (q->bufs[first]->boff == offset) break; } if (VIDEO_MAX_FRAME == first) { dprintk(1,"mmap app bug: offset invalid [offset=0x%lx]\n", (vma->vm_pgoff << PAGE_SHIFT)); return -EINVAL; } /* create mapping + update buffer list */ map = kzalloc(sizeof(struct videobuf_mapping), GFP_KERNEL); if (NULL == map) return -ENOMEM; q->bufs[first]->map = map; map->start = vma->vm_start; map->end = vma->vm_end; map->q = q; q->bufs[first]->baddr = vma->vm_start; mem = q->bufs[first]->priv; BUG_ON(!mem); MAGIC_CHECK(mem->magic, MAGIC_VMAL_MEM); pages = PAGE_ALIGN(vma->vm_end - vma->vm_start); mem->vmalloc = vmalloc_user(pages); if (!mem->vmalloc) { printk(KERN_ERR "vmalloc (%d pages) failed\n", pages); goto error; } dprintk(1, "vmalloc is at addr %p (%d pages)\n", mem->vmalloc, pages); /* Try to remap memory */ retval = remap_vmalloc_range(vma, mem->vmalloc, 0); if (retval < 0) { printk(KERN_ERR "mmap: remap failed with error %d. ", retval); vfree(mem->vmalloc); goto error; } vma->vm_ops = &videobuf_vm_ops; vma->vm_flags |= VM_DONTEXPAND | VM_RESERVED; vma->vm_private_data = map; dprintk(1,"mmap %p: q=%p %08lx-%08lx (%lx) pgoff %08lx buf %d\n", map, q, vma->vm_start, vma->vm_end, (long int) q->bufs[first]->bsize, vma->vm_pgoff, first); videobuf_vm_open(vma); return 0; error: mem = NULL; kfree(map); return -ENOMEM; }
* maintenance necessary to support an uncached mapping */ BUG_ON(kaddr); vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); } if (!kaddr) { for (i = 0; i < nr_pages; i++) { err = vm_insert_mixed(vma, vma->vm_start + (i << PAGE_SHIFT), page_array[i + start_off] >> PAGE_SHIFT); WARN_ON(err); if (err) break; } } else { /* vmalloc remaping is easy... */ err = remap_vmalloc_range(vma, kaddr, 0); WARN_ON(err); } if (err) { kfree(map); goto out; } map->uaddr = (void *)vma->vm_start; map->nr_pages = nr_pages; map->page_off = start_off; map->private = vma; if ( (reg->flags & KBASE_REG_ZONE_MASK) == KBASE_REG_ZONE_TMEM) {
int ion_system_heap_map_user(struct ion_heap *heap, struct ion_buffer *buffer, struct vm_area_struct *vma) { return remap_vmalloc_range(vma, buffer->priv_virt, vma->vm_pgoff); }