}
EXPORT_SYMBOL_GPL(vb2_wait_for_all_buffers);
+/**
+ * __vb2_dqbuf() - bring back the buffer to the DEQUEUED state
+ */
+static void __vb2_dqbuf(struct vb2_buffer *vb)
+{
+ struct vb2_queue *q = vb->vb2_queue;
+ unsigned int i;
+
+ /* nothing to do if the buffer is already dequeued */
+ if (vb->state == VB2_BUF_STATE_DEQUEUED)
+ return;
+
+ vb->state = VB2_BUF_STATE_DEQUEUED;
+
+ /* unmap DMABUF buffer
+ * TODO: this unpins the buffer(dma_buf_unmap_attachment()).. but
+ * really we want to do this just after DMA, not when the
+ * buffer is dequeued..
+ */
+ if (q->memory == V4L2_MEMORY_DMABUF) {
+ for (i = 0; i < vb->num_planes; ++i) {
+ if (!vb->planes[i].dbuf_mapped)
+ continue;
+ call_memop(q, unmap_dmabuf, vb->planes[i].mem_priv);
+ vb->planes[i].dbuf_mapped = 0;
+ }
+ }
+}
+
/**
* vb2_dqbuf() - Dequeue a buffer to the userspace
* @q: videobuf2 queue
return ret;
}
- /* TODO: this unpins the buffer(dma_buf_unmap_attachment()).. but
- * really we want to do this just after DMA, not when the
- * buffer is dequeued..
- */
- if (q->memory == V4L2_MEMORY_DMABUF) {
- unsigned int i;
-
- for (i = 0; i < vb->num_planes; ++i) {
- call_memop(q, unmap_dmabuf, vb->planes[i].mem_priv);
- vb->planes[i].dbuf_mapped = 0;
- }
- }
-
switch (vb->state) {
case VB2_BUF_STATE_DONE:
dprintk(3, "dqbuf: Returning done buffer\n");
__fill_v4l2_buffer(vb, b);
/* Remove from videobuf queue */
list_del(&vb->queued_entry);
+ /* go back to dequeued state */
+ __vb2_dqbuf(vb);
dprintk(1, "dqbuf of buffer %d, with state %d\n",
vb->v4l2_buf.index, vb->state);
- vb->state = VB2_BUF_STATE_DEQUEUED;
return 0;
}
EXPORT_SYMBOL_GPL(vb2_dqbuf);
* Reinitialize all buffers for next use.
*/
for (i = 0; i < q->num_buffers; ++i)
- q->bufs[i]->state = VB2_BUF_STATE_DEQUEUED;
+ __vb2_dqbuf(q->bufs[i]);
}
/**
}
EXPORT_SYMBOL_GPL(vb2_streamoff);
-/**
- * __find_plane_by_offset() - find plane associated with the given offset off
- */
-static int __find_plane_by_offset(struct vb2_queue *q, unsigned long off,
- unsigned int *_buffer, unsigned int *_plane)
-{
- struct vb2_buffer *vb;
- unsigned int buffer, plane;
-
- /*
- * Go over all buffers and their planes, comparing the given offset
- * with an offset assigned to each plane. If a match is found,
- * return its buffer and plane numbers.
- */
- for (buffer = 0; buffer < q->num_buffers; ++buffer) {
- vb = q->bufs[buffer];
-
- for (plane = 0; plane < vb->num_planes; ++plane) {
- if (vb->v4l2_planes[plane].m.mem_offset == off) {
- *_buffer = buffer;
- *_plane = plane;
- return 0;
- }
- }
- }
-
- return -EINVAL;
-}
-
/**
* vb2_expbuf() - Export a buffer as a file descriptor
* @q: videobuf2 queue
{
struct vb2_buffer *vb = NULL;
struct vb2_plane *vb_plane;
- unsigned int buffer, plane;
int ret;
struct dma_buf *dbuf;
/*
* Find the plane corresponding to the offset passed by userspace.
*/
- ret = __find_plane_by_offset(q, eb->mem_offset, &buffer, &plane);
- if (ret) {
- dprintk(1, "invalid offset %u\n", eb->mem_offset);
- return ret;
+ if (eb->type != q->type) {
+ dprintk(1, "invalid type %u\n", eb->type);
+ return -EINVAL;
}
-
- vb = q->bufs[buffer];
- vb_plane = &vb->planes[plane];
+ if (eb->index >= q->num_buffers) {
+ dprintk(1, "invalid buffer %u\n", eb->index);
+ return -EINVAL;
+ }
+ vb = q->bufs[eb->index];
+ if (eb->plane >= vb->num_planes) {
+ dprintk(1, "invalid plane %u\n", eb->plane);
+ return -EINVAL;
+ }
+ vb_plane = &vb->planes[eb->plane];
dbuf = call_memop(q, get_dmabuf, vb_plane->mem_priv);
if (IS_ERR_OR_NULL(dbuf)) {
dprintk(1, "Failed to export buffer %d, plane %d\n",
- buffer, plane);
+ eb->index, eb->plane);
return -EINVAL;
}
ret = dma_buf_fd(dbuf, eb->flags);
if (ret < 0) {
dprintk(3, "buffer %d, plane %d failed to export (%d)\n",
- buffer, plane, ret);
+ eb->index, eb->plane, ret);
dma_buf_put(dbuf);
return ret;
}
dprintk(3, "buffer %d, plane %d exported as %d descriptor\n",
- buffer, plane, ret);
+ eb->index, eb->plane, ret);
eb->fd = ret;
return 0;
}
EXPORT_SYMBOL_GPL(vb2_expbuf);
+/**
+ * __find_plane_by_offset() - find plane associated with the given offset off
+ */
+static int __find_plane_by_offset(struct vb2_queue *q, unsigned long off,
+ unsigned int *_buffer, unsigned int *_plane)
+{
+ struct vb2_buffer *vb;
+ unsigned int buffer, plane;
+
+ /*
+ * Go over all buffers and their planes, comparing the given offset
+ * with an offset assigned to each plane. If a match is found,
+ * return its buffer and plane numbers.
+ */
+ for (buffer = 0; buffer < q->num_buffers; ++buffer) {
+ vb = q->bufs[buffer];
+
+ for (plane = 0; plane < vb->num_planes; ++plane) {
+ if (vb->v4l2_planes[plane].m.mem_offset == off) {
+ *_buffer = buffer;
+ *_plane = plane;
+ return 0;
+ }
+ }
+ }
+
+ return -EINVAL;
+}
+
/**
* vb2_mmap() - map video buffers into application address space
* @q: videobuf2 queue