RE: [PATCH 1/7] v4l: add videobuf2 Video for Linux 2 driver framework

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi~ Marek.
Some comments in here.

Saturday, November 20, 2010 12:56 AM Marek Szyprowski wrote : 
> To: linux-media@xxxxxxxxxxxxxxx
> Cc: m.szyprowski@xxxxxxxxxxx; pawel@xxxxxxxxxx; kyungmin.park@xxxxxxxxxxx
> Subject: [PATCH 1/7] v4l: add videobuf2 Video for Linux 2 driver framework
> 
> From: Pawel Osciak <p.osciak@xxxxxxxxxxx>
> 
> Videobuf2 is a Video for Linux 2 API-compatible driver framework for
> multimedia devices. It acts as an intermediate layer between userspace
> applications and device drivers. It also provides low-level, modular
> memory management functions for drivers.
> 
> Videobuf2 eases driver development, reduces drivers' code size and aids in
> proper and consistent implementation of V4L2 API in drivers.
> 
> Videobuf2 memory management backend is fully modular. This allows custom
> memory management routines for devices and platforms with non-standard
> memory management requirements to be plugged in, without changing the
> high-level buffer management functions and API.
> 
> The framework provides:
> - implementations of streaming I/O V4L2 ioctls and file operations
> - high-level video buffer, video queue and state management functions
> - video buffer memory allocation and management
> 
> Signed-off-by: Pawel Osciak <p.osciak@xxxxxxxxxxx>
> Signed-off-by: Marek Szyprowski <m.szyprowski@xxxxxxxxxxx>
> Signed-off-by: Kyungmin Park <kyungmin.park@xxxxxxxxxxx>
> CC: Pawel Osciak <pawel@xxxxxxxxxx>
> ---
>  drivers/media/video/Kconfig          |    3 +
>  drivers/media/video/Makefile         |    2 +
>  drivers/media/video/videobuf2-core.c | 1435
> ++++++++++++++++++++++++++++++++++
>  include/media/videobuf2-core.h       |  376 +++++++++
>  4 files changed, 1816 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/media/video/videobuf2-core.c
>  create mode 100644 include/media/videobuf2-core.h
> 
> diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
> index ac16e81..fef6a14 100644
> --- a/drivers/media/video/Kconfig
> +++ b/drivers/media/video/Kconfig
> @@ -49,6 +49,9 @@ config V4L2_MEM2MEM_DEV
>  	tristate
>  	depends on VIDEOBUF_GEN
> 
> +config VIDEOBUF2_CORE
> +	tristate
> +
>  #
>  # Multimedia Video device configuration
>  #
> diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile
> index af79d47..77c4f85 100644
> --- a/drivers/media/video/Makefile
> +++ b/drivers/media/video/Makefile
> @@ -114,6 +114,8 @@ obj-$(CONFIG_VIDEOBUF_VMALLOC) += videobuf-vmalloc.o
>  obj-$(CONFIG_VIDEOBUF_DVB) += videobuf-dvb.o
>  obj-$(CONFIG_VIDEO_BTCX)  += btcx-risc.o
> 
> +obj-$(CONFIG_VIDEOBUF2_CORE)		+= videobuf2-core.o
> +
>  obj-$(CONFIG_V4L2_MEM2MEM_DEV) += v4l2-mem2mem.o
> 
>  obj-$(CONFIG_VIDEO_M32R_AR_M64278) += arv.o
> diff --git a/drivers/media/video/videobuf2-core.c
> b/drivers/media/video/videobuf2-core.c
> new file mode 100644
> index 0000000..828803f
> --- /dev/null
> +++ b/drivers/media/video/videobuf2-core.c
> @@ -0,0 +1,1435 @@
> +/*
> + * videobuf2-core.c - V4L2 driver helper framework
> + *
> + * Copyright (C) 2010 Samsung Electronics
> + *
> + * Author: Pawel Osciak <p.osciak@xxxxxxxxxxx>
> + *	   Marek Szyprowski <m.szyprowski@xxxxxxxxxxx>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation.
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/mm.h>
> +#include <linux/module.h>
> +#include <linux/slab.h>
> +#include <linux/sched.h>
> +#include <linux/err.h>
> +#include <linux/poll.h>
> +
> +#include <media/videobuf2-core.h>
> +
> +static int debug;
> +module_param(debug, int, 0644);
> +
> +#define dprintk(level, fmt, arg...)					\
> +	do {								\
> +		if (debug >= level)					\
> +			printk(KERN_DEBUG "vb2: " fmt, ## arg);		\
> +	} while (0)
> +
> +#define mem_ops(q, plane) ((q)->alloc_ctx[plane]->mem_ops)
> +
> +#define call_memop(q, plane, op, args...)				\
> +	((mem_ops(q, plane)->op) ?					\
> +		(mem_ops(q, plane)->op(args)) : 0)
> +
> +#define call_qop(q, op, args...)					\
> +	(((q)->ops->op) ? ((q)->ops->op(args)) : 0)
> +

snip

> +/**
> + * __vb2_wait_for_done_vb() - wait for a buffer to become available
> + * for dequeuing
> + *
> + * Will sleep if required for nonblocking == false.
> + */
> +static int __vb2_wait_for_done_vb(struct vb2_queue *q, int nonblocking)
> +{
> +checks:
> +	if (!q->streaming) {
> +		dprintk(1, "Streaming off, will not wait for buffers\n");
> +		return -EINVAL;
> +	}
> +
> +	/*
> +	 * Buffers may be added to vb_done_list without holding the
> driver's
> +	 * lock, but removal is performed only while holding both driver's
> +	 * lock and the vb_done_lock spinlock. Thus we can be sure that as
> +	 * long as we hold lock, the list will remain not empty if this
> +	 * check succeeds.
> +	 */
> +	if (list_empty(&q->done_list)) {
> +		int retval;
> +		if (nonblocking) {
> +			dprintk(1, "Nonblocking and no buffers to dequeue, "
> +					"will not wait\n");
> +			return -EAGAIN;
> +		}
> +
> +		/*
> +		 * We are streaming and nonblocking, wait for another buffer
> to
> +		 * become ready or for streamoff. Driver's lock is released
> to
> +		 * allow streamoff or qbuf to be called while waiting.
> +		 */
> +		call_qop(q, unlock, q);
> +
> +		/*
> +		 * Although the mutex is released here, we will be
> reevaluating
> +		 * both conditions again after reacquiring it.
> +		 */
> +		dprintk(3, "Will sleep waiting for buffers\n");
> +		retval = wait_event_interruptible(q->done_wq,
> +				!list_empty(&q->done_list) || !q->streaming);

How about use wait_event_timeout() or other wait functions?
If h/w or sub-device(e.g camera sensor module) does not operating due to 
any reason, then maybe fall into blocking state forever.

> +		call_qop(q, lock, q);
> +
> +		if (retval)
> +			return -EINTR;
> +
> +		goto checks;
> +	}
> +	return 0;
> +}
> +

snip

> +int vb2_queue_init(struct vb2_queue *q, const struct vb2_ops *ops,
> +			const struct vb2_alloc_ctx *alloc_ctx,
> +			enum v4l2_buf_type type, void *drv_priv)
> +{
> +	unsigned int i;
> +
> +	BUG_ON(!q);
> +	BUG_ON(!ops);
> +	BUG_ON(!ops->queue_negotiate);
> +	BUG_ON(!ops->plane_setup);
> +	BUG_ON(!ops->buf_queue);
> +
> +	BUG_ON(!alloc_ctx);
> +	BUG_ON(!alloc_ctx->mem_ops);
> +
> +	memset(q, 0, sizeof *q);
> +	q->ops = ops;
> +
> +	for (i = 0; i < VIDEO_MAX_PLANES; ++i)
> +		q->alloc_ctx[i] = alloc_ctx;

According to my understanding, the alloc_ctx means that 
each plane per buffer use each allocator.
for example, 
It is possible alloc_ctx[0] use CMA, alloc_ctx[1] use DMA-coherent allocator.

How to set in these case? 
I think you don't control about it like above for-loop.

> +
> +	q->type = type;
> +	q->drv_priv = drv_priv;
> +
> +	INIT_LIST_HEAD(&q->queued_list);
> +	INIT_LIST_HEAD(&q->done_list);
> +	spin_lock_init(&q->done_lock);
> +	init_waitqueue_head(&q->done_wq);
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL_GPL(vb2_queue_init);

snip

> +
> +struct vb2_queue;
> +
> +/**
> + * struct vb2_buffer - represents a video buffer
> + * @v4l2_buf:		struct v4l2_buffer associated with this buffer;
> can
> + *			be read by the driver and relevant entries can be
> + *			changed by the driver in case of CAPTURE types
> + *			(such as timestamp)
> + * @v4l2_planes:	struct v4l2_planes associated with this buffer; can
> + *			be read by the driver and relevant entries can be
> + *			changed by the driver in case of CAPTURE types
> + *			(such as bytesused); NOTE that even for single-planar
> + *			types, the v4l2_planes[0] struct should be used
> + *			instead of v4l2_buf for filling bytesused - drivers
> + *			should use the vb2_set_plane_payload() function for
> that
> + * @vb2_queue:		the queue to which this driver belongs
> + * @drv_entry:		list entry to be used by driver for storing the
> buffer

Outdated comment. VB2 doesn't use this field any longer.

>From now on,
driver will use own buffer that is included vb2_buffer, right?
I wonder why remove drv_entry field in struct vb2_buffer?


> + * @num_planes:		number of planes in the buffer
> + *			on an internal driver queue
> + * @state:		current buffer state; do not change
> + * @queued_entry:	entry on the queued buffers list, which holds all
> + *			buffers queued from userspace
> + * @done_entry:		entry on the list that stores all buffers ready
> to
> + *			be dequeued to userspace
> + * @planes:		private per-plane information; do not change
> + * @num_planes_mapped:	number of mapped planes; do not change
> + */

snip

> +/**
> + * struct vb2_queue - a videobuf queue
> + *
> + * @type:	current queue type
> + * @memory:	current memory type used
> + * @drv_priv:	driver private data, passed on vb2_queue_init
> + * @bufs:	videobuf buffer structures
> + * @num_buffers: number of allocated/used buffers
> + * @vb_lock:	for ioctl handler and queue state changes synchronization
> + * @queued_list: list of buffers currently queued from userspace
> + * @done_list:	list of buffers ready to be dequeued to userspace
> + * @done_lock:	lock to protect done_list list
> + * @done_wq:	waitqueue for processes waiting for buffers ready to be
> dequeued
> + * @ops:	driver-specific callbacks
> + * @alloc_ctx:	memory type/allocator-specific callbacks
> + * @streaming:	current streaming state
> + * @userptr_supported: true if queue supports USERPTR types
> + * @mmap_supported: true if queue supports MMAP types
> + */
> +struct vb2_queue {
> +	enum v4l2_buf_type		type;
> +	enum v4l2_memory		memory;
> +	void				*drv_priv;
> +
> +/* private: internal use only */
> +	struct vb2_buffer		*bufs[VIDEO_MAX_FRAME];
> +	unsigned int			num_buffers;
> +
> +	struct list_head		queued_list;
> +
> +	struct list_head		done_list;
> +	spinlock_t			done_lock;
> +	wait_queue_head_t		done_wq;
> +
> +	const struct vb2_ops		*ops;
> +	const struct vb2_alloc_ctx	*alloc_ctx[VIDEO_MAX_PLANES];
> +
> +	int				streaming:1;
> +	int				userptr_supported:1;
> +	int				mmap_supported:1;
> +};

As you know, VIDIOC_REQBUFS is checking I/O support or not.
Memory mapping(or user pointer) I/O is not supported the ioctl 
returns an EINVAL error code.
Therefore, two kinds of variables(userptr_supported, mmap_supported) 
to use vb2_queue, right?

But, there's no usage anywhere.
Why donât you initialize in vb2_queue_init() when  is called from driver?
and check this variables in vb2_reqbufs().


--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Input]     [Video for Linux]     [Gstreamer Embedded]     [Mplayer Users]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]
  Powered by Linux