示例#1
0
static void *msm_vb2_mem_ops_alloc(void *alloc_ctx, unsigned long size)
{
    struct videobuf2_contig_pmem *mem;
    unsigned int flags = 0;
    long rc;
    mem = kzalloc(sizeof(*mem), GFP_KERNEL);
    if (!mem)
        return ERR_PTR(-ENOMEM);

    mem->magic = MAGIC_PMEM;
    mem->size =  PAGE_ALIGN(size);
    mem->alloc_ctx = alloc_ctx;
    mem->is_userptr = 0;
    mem->phyaddr = msm_mem_allocate(mem);
    if (!mem->phyaddr) {
        pr_err("%s : pmem memory allocation failed\n", __func__);
        kfree(mem);
        return ERR_PTR(-ENOMEM);
    }
    flags = MSM_SUBSYSTEM_MAP_IOVA;
    mem->subsys_id = MSM_SUBSYSTEM_CAMERA;
    mem->msm_buffer = msm_subsystem_map_buffer(mem->phyaddr, mem->size,
                      flags, &(mem->subsys_id), 1);
    if (IS_ERR((void *)mem->msm_buffer)) {
        pr_err("%s: msm_subsystem_map_buffer failed\n", __func__);
        rc = PTR_ERR((void *)mem->msm_buffer);
        msm_mem_free(mem);
        kfree(mem);
        return ERR_PTR(-ENOMEM);
    }
    mem->mapped_phyaddr = mem->msm_buffer->iova[0];
    return mem;
}
static void msm_vb2_mem_ops_put(void *buf_priv)
{
	struct videobuf2_contig_pmem *mem = buf_priv;
	if (!mem->is_userptr) {
		D("%s Freeing memory ", __func__);
		msm_mem_free(mem);
	}
	kfree(mem);
}
示例#3
0
static void msm_vb2_mem_ops_put(void *buf_priv)
{
    struct videobuf2_contig_pmem *mem = buf_priv;
    if (!mem->is_userptr) {
        D("%s Freeing memory ", __func__);
        if (msm_subsystem_unmap_buffer(mem->msm_buffer) < 0)
            D("%s unmapped memory\n", __func__);
        msm_mem_free(mem);
    }
    kfree(mem);
}
示例#4
0
static void videobuf_vm_close(struct vm_area_struct *vma)
{
	struct videobuf_mapping *map = vma->vm_private_data;
	struct videobuf_queue *q = map->q;
	int i, rc;

	D("vm_close %p [count=%u,vma=%08lx-%08lx]\n",
		map, map->count, vma->vm_start, vma->vm_end);

	map->count--;
	if (0 == map->count) {
		struct videobuf_contig_pmem *mem;

		D("munmap %p q=%p\n", map, q);
		mutex_lock(&q->vb_lock);

		/* We need first to cancel streams, before unmapping */
		if (q->streaming)
			videobuf_queue_cancel(q);

		for (i = 0; i < VIDEO_MAX_FRAME; i++) {
			if (NULL == q->bufs[i])
				continue;

			if (q->bufs[i]->map != map)
				continue;

			mem = q->bufs[i]->priv;
			if (mem) {
				/* This callback is called only if kernel has
				 * allocated memory and this memory is mmapped.
				 * In this case, memory should be freed,
				 * in order to do memory unmap.
				 */

				MAGIC_CHECK(mem->magic, MAGIC_PMEM);

				/* vfree is not atomic - can't be
				 called with IRQ's disabled
				 */
				D("buf[%d] freeing physical %d\n",
					i, mem->phyaddr);

				rc = msm_mem_free(mem->phyaddr);
				if (rc < 0)
					D("%s: Invalid memory location\n",
								__func__);
				else {
					mem->phyaddr = 0;
				}
			}

			q->bufs[i]->map   = NULL;
			q->bufs[i]->baddr = 0;
		}

		kfree(map);

		mutex_unlock(&q->vb_lock);

		/* deallocate the q->bufs[i] structure not a good solution
		 as it will result in unnecessary iterations but right now
		 this looks like the only cleaner way  */
		videobuf_mmap_free(q);
	}
}
示例#5
0
static int __videobuf_mmap_mapper(struct videobuf_queue *q,
		struct videobuf_buffer *buf,
		struct vm_area_struct *vma)
{
	struct videobuf_contig_pmem *mem;
	struct videobuf_mapping *map;
	int retval;
	unsigned long size;

	D("%s\n", __func__);

	/* create mapping + update buffer list */
	map = kzalloc(sizeof(struct videobuf_mapping), GFP_KERNEL);
	if (!map) {
		pr_err("%s: kzalloc failed.\n", __func__);
		return -ENOMEM;
	}

	buf->map = map;
	map->q = q;

	buf->baddr = vma->vm_start;

	mem = buf->priv;
	D("mem = 0x%x\n", (u32)mem);
	D("buf = 0x%x\n", (u32)buf);
	BUG_ON(!mem);
	MAGIC_CHECK(mem->magic, MAGIC_PMEM);

	mem->size = PAGE_ALIGN(buf->bsize);
	mem->y_off = 0;
	mem->cbcr_off = (buf->bsize)*2/3;
	if (buf->i >= 0 && buf->i <= 3)
		mem->buffer_type = OUTPUT_TYPE_P;
	else
		mem->buffer_type = OUTPUT_TYPE_V;

	buf->bsize = mem->size;
	mem->phyaddr = msm_mem_allocate(mem->size);

	if (IS_ERR((void *)mem->phyaddr)) {
		pr_err("%s : pmem memory allocation failed\n", __func__);
		goto error;
	}

	/* Try to remap memory */
	size = vma->vm_end - vma->vm_start;
	size = (size < mem->size) ? size : mem->size;

	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
	retval = remap_pfn_range(vma, vma->vm_start,
		mem->phyaddr >> PAGE_SHIFT,
		size, vma->vm_page_prot);
	if (retval) {
		pr_err("mmap: remap failed with error %d. ", retval);
		retval = msm_mem_free(mem->phyaddr);
		if (retval < 0)
			printk(KERN_ERR "%s: Invalid memory location\n",
								__func__);
		else {
			mem->phyaddr = 0;
		}
		goto error;
	}

	vma->vm_ops          = &videobuf_vm_ops;
	vma->vm_flags       |= VM_DONTEXPAND;
	vma->vm_private_data = map;

	D("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:
	kfree(map);
	return -ENOMEM;
}