/**
 * __vb2_buf_mem_alloc() - allocate video memory for the given buffer
 */
static int __vb2_buf_mem_alloc(struct vb2_buffer *vb,
				unsigned long *plane_sizes)
{
	struct vb2_queue *q = vb->vb2_queue;
	void *mem_priv;
	int plane;

	/* Allocate memory for all planes in this buffer */
	for (plane = 0; plane < vb->num_planes; ++plane) {
		mem_priv = call_memop(q, plane, alloc, q->alloc_ctx[plane],
					plane_sizes[plane]);
		if (IS_ERR_OR_NULL(mem_priv))
			goto free;

		/* Associate allocator private data with this plane */
		vb->planes[plane].mem_priv = mem_priv;
		vb->v4l2_planes[plane].length = plane_sizes[plane];
	}

	return 0;
free:
	/* Free already allocated memory if one of the allocations failed */
	for (; plane > 0; --plane)
		call_memop(q, plane, put, vb->planes[plane - 1].mem_priv);

	return -ENOMEM;
}
Beispiel #2
0
static int __vb2_buf_mem_alloc(struct vb2_buffer *vb,
				unsigned long *plane_sizes)
{
	struct vb2_queue *q = vb->vb2_queue;
	void *mem_priv;
	int plane;

	
	for (plane = 0; plane < vb->num_planes; ++plane) {
		mem_priv = call_memop(q, plane, alloc, q->alloc_ctx[plane],
					plane_sizes[plane]);
		if (IS_ERR_OR_NULL(mem_priv))
			goto free;

		
		vb->planes[plane].mem_priv = mem_priv;
		vb->v4l2_planes[plane].length = plane_sizes[plane];
	}

	return 0;
free:
	
	for (; plane > 0; --plane)
		call_memop(q, plane, put, vb->planes[plane - 1].mem_priv);

	return -ENOMEM;
}
/**
 * vb2_plane_cookie() - Return allocator specific cookie for the given plane
 * @vb:		vb2_buffer to which the plane in question belongs to
 * @plane_no:	plane number for which the cookie is to be returned
 *
 * This function returns an allocator specific cookie for a given plane if
 * available, NULL otherwise. The allocator should provide some simple static
 * inline function, which would convert this cookie to the allocator specific
 * type that can be used directly by the driver to access the buffer. This can
 * be for example physical address, pointer to scatter list or IOMMU mapping.
 */
void *vb2_plane_cookie(struct vb2_buffer *vb, unsigned int plane_no)
{
	struct vb2_queue *q = vb->vb2_queue;

	if (plane_no > vb->num_planes)
		return NULL;

	return call_memop(q, plane_no, cookie, vb->planes[plane_no].mem_priv);
}
/**
 * __vb2_buf_mem_free() - free memory of the given buffer
 */
static void __vb2_buf_mem_free(struct vb2_buffer *vb)
{
	struct vb2_queue *q = vb->vb2_queue;
	unsigned int plane;

	for (plane = 0; plane < vb->num_planes; ++plane) {
		call_memop(q, plane, put, vb->planes[plane].mem_priv);
		vb->planes[plane].mem_priv = NULL;
		dprintk(3, "Freed plane %d of buffer %d\n",
				plane, vb->v4l2_buf.index);
	}
}
/**
 * __vb2_buf_userptr_put() - release userspace memory associated with
 * a USERPTR buffer
 */
static void __vb2_buf_userptr_put(struct vb2_buffer *vb)
{
	struct vb2_queue *q = vb->vb2_queue;
	unsigned int plane;

	for (plane = 0; plane < vb->num_planes; ++plane) {
		void *mem_priv = vb->planes[plane].mem_priv;

		if (mem_priv) {
			call_memop(q, plane, put_userptr, mem_priv);
			vb->planes[plane].mem_priv = NULL;
		}
	}
}
Beispiel #6
0
static bool __buffers_in_use(struct vb2_queue *q)
{
	unsigned int buffer, plane;
	struct vb2_buffer *vb;

	for (buffer = 0; buffer < q->num_buffers; ++buffer) {
		vb = q->bufs[buffer];
		for (plane = 0; plane < vb->num_planes; ++plane) {
			if (call_memop(q, plane, num_users,
					vb->planes[plane].mem_priv) > 1)
				return true;
		}
	}

	return false;
}
/**
 * __buffers_in_use() - return true if any buffers on the queue are in use and
 * the queue cannot be freed (by the means of REQBUFS(0)) call
 */
static bool __buffers_in_use(struct vb2_queue *q)
{
	unsigned int buffer, plane;
	struct vb2_buffer *vb;

	for (buffer = 0; buffer < q->num_buffers; ++buffer) {
		vb = q->bufs[buffer];
		for (plane = 0; plane < vb->num_planes; ++plane) {
			/*
			 * If num_users() has not been provided, call_memop
			 * will return 0, apparently nobody cares about this
			 * case anyway. If num_users() returns more than 1,
			 * we are not the only user of the plane's memory.
			 */
			if (call_memop(q, plane, num_users,
					vb->planes[plane].mem_priv) > 1)
				return true;
		}
	}

	return false;
}
/**
 * __qbuf_userptr() - handle qbuf of a USERPTR buffer
 */
static int __qbuf_userptr(struct vb2_buffer *vb, struct v4l2_buffer *b)
{
	struct v4l2_plane planes[VIDEO_MAX_PLANES];
	struct vb2_queue *q = vb->vb2_queue;
	void *mem_priv;
	unsigned int plane;
	int ret;
	int write = !V4L2_TYPE_IS_OUTPUT(q->type);

	/* Verify and copy relevant information provided by the userspace */
	ret = __fill_vb2_buffer(vb, b, planes);
	if (ret)
		return ret;

	for (plane = 0; plane < vb->num_planes; ++plane) {
		/* Skip the plane if already verified */
		if (vb->v4l2_planes[plane].m.userptr == planes[plane].m.userptr
		    && vb->v4l2_planes[plane].length == planes[plane].length)
			continue;

		dprintk(3, "qbuf: userspace address for plane %d changed, "
				"reacquiring memory\n", plane);

		/* Release previously acquired memory if present */
		if (vb->planes[plane].mem_priv)
			call_memop(q, plane, put_userptr,
					vb->planes[plane].mem_priv);

		vb->planes[plane].mem_priv = NULL;

		/* Acquire each plane's memory */
		if (q->mem_ops->get_userptr) {
			mem_priv = q->mem_ops->get_userptr(q->alloc_ctx[plane],
							planes[plane].m.userptr,
							planes[plane].length,
							write);
			if (IS_ERR(mem_priv)) {
				dprintk(1, "qbuf: failed acquiring userspace "
						"memory for plane %d\n", plane);
				ret = PTR_ERR(mem_priv);
				goto err;
			}
			vb->planes[plane].mem_priv = mem_priv;
		}
	}

	/*
	 * Call driver-specific initialization on the newly acquired buffer,
	 * if provided.
	 */
	ret = call_qop(q, buf_init, vb);
	if (ret) {
		dprintk(1, "qbuf: buffer initialization failed\n");
		goto err;
	}

	/*
	 * Now that everything is in order, copy relevant information
	 * provided by userspace.
	 */
	for (plane = 0; plane < vb->num_planes; ++plane)
		vb->v4l2_planes[plane] = planes[plane];

	return 0;
err:
	/* In case of errors, release planes that were already acquired */
	for (; plane > 0; --plane) {
		call_memop(q, plane, put_userptr,
				vb->planes[plane - 1].mem_priv);
		vb->planes[plane - 1].mem_priv = NULL;
	}

	return ret;
}
Beispiel #9
0
static int __qbuf_userptr(struct vb2_buffer *vb, struct v4l2_buffer *b)
{
	struct v4l2_plane planes[VIDEO_MAX_PLANES];
	struct vb2_queue *q = vb->vb2_queue;
	void *mem_priv;
	unsigned int plane;
	int ret;
	int write = !V4L2_TYPE_IS_OUTPUT(q->type);

	
	ret = __fill_vb2_buffer(vb, b, planes);
	if (ret)
		return ret;

	for (plane = 0; plane < vb->num_planes; ++plane) {
		
		if (vb->v4l2_planes[plane].m.userptr == planes[plane].m.userptr
		    && vb->v4l2_planes[plane].length == planes[plane].length)
			continue;

		dprintk(3, "qbuf: userspace address for plane %d changed, "
				"reacquiring memory\n", plane);

		
		if (vb->planes[plane].mem_priv)
			call_memop(q, plane, put_userptr,
					vb->planes[plane].mem_priv);

		vb->planes[plane].mem_priv = NULL;

		
		if (q->mem_ops->get_userptr) {
			mem_priv = q->mem_ops->get_userptr(q->alloc_ctx[plane],
							planes[plane].m.userptr,
							planes[plane].length,
							write);
			if (IS_ERR(mem_priv)) {
				dprintk(1, "qbuf: failed acquiring userspace "
						"memory for plane %d\n", plane);
				ret = PTR_ERR(mem_priv);
				goto err;
			}
			vb->planes[plane].mem_priv = mem_priv;
		}
	}

	ret = call_qop(q, buf_init, vb);
	if (ret) {
		dprintk(1, "qbuf: buffer initialization failed\n");
		goto err;
	}

	for (plane = 0; plane < vb->num_planes; ++plane)
		vb->v4l2_planes[plane] = planes[plane];

	return 0;
err:
	
	for (plane = 0; plane < vb->num_planes; ++plane) {
		if (vb->planes[plane].mem_priv)
			call_memop(q, plane, put_userptr,
				   vb->planes[plane].mem_priv);
		vb->planes[plane].mem_priv = NULL;
		vb->v4l2_planes[plane].m.userptr = 0;
		vb->v4l2_planes[plane].length = 0;
	}

	return ret;
}