RE: [PATCH V4 1/2] usb: gadget/uvc: Port UVC webcam gadget to use videobuf2 framework

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

 



Hi Laurent,


> -----Original Message-----
> From: Laurent Pinchart [mailto:laurent.pinchart@xxxxxxxxxxxxxxxx]
> Sent: Wednesday, March 27, 2013 11:25 PM
> To: Bhupesh SHARMA
> Cc: linux-usb@xxxxxxxxxxxxxxx; balbi@xxxxxx; bhupesh.linux@xxxxxxxxx;
> mgr@xxxxxxxxxxxxxx; gang.chen@xxxxxxxxxxx; tipecaml@xxxxxxxxx
> Subject: Re: [PATCH V4 1/2] usb: gadget/uvc: Port UVC webcam gadget to
> use videobuf2 framework
> 
> Hi Bhupesh,
> 
> Thanks for the patch. Please see below for a couple of small comments.
> 
> On Thursday 21 March 2013 13:56:08 Bhupesh Sharma wrote:
> > This patch reworks the videobuffer management logic present in the UVC
> > webcam gadget and ports it to use the "more apt" videobuf2 framework
> > for video buffer management.
> >
> > To support routing video data captured from a real V4L2 video capture
> > device with a "zero copy" operation on videobuffers (as they pass from
> > the V4L2 domain to UVC domain via a user-space application), we need
> > to support USER_PTR IO method at the UVC gadget side.
> >
> > So the V4L2 capture device driver can still continue to use MMAP IO
> > method and now the user-space application can just pass a pointer to
> > the video buffers being dequeued from the V4L2 device side while
> > queueing them at the UVC gadget end. This ensures that we have a "zero-
> copy"
> > design as the videobuffers pass from the V4L2 capture device to the
> > UVC gadget.
> >
> > Note that there will still be a need to apply UVC specific payload
> > headers on top of each UVC payload data, which will still require a
> > copy operation to be performed in the 'encode' routines of the UVC
> gadget.
> >
> > This patch also addresses one issue found out while porting the UVC
> > gadget to videobuf2 framework:
> > 	- In case the usb requests queued by the gadget get completed
> > 	  with a status of -ESHUTDOWN (disconnected from host),
> > 	  the queue of videobuf2 should be cancelled to ensure that the
> > 	  application space daemon is not left in a state waiting for
> > 	  a vb2 to be successfully absorbed at the USB side.
> >
> > Signed-off-by: Bhupesh Sharma <bhupesh.sharma@xxxxxx>
> > ---
> >  drivers/usb/gadget/Kconfig     |    1 +
> >  drivers/usb/gadget/uvc_queue.c |  533 ++++++++++++-----------------------
> --
> >  drivers/usb/gadget/uvc_queue.h |   25 +--
> >  drivers/usb/gadget/uvc_v4l2.c  |   37 +--
> >  drivers/usb/gadget/uvc_video.c |   17 +-
> >  5 files changed, 188 insertions(+), 425 deletions(-)
> 
> [snip]
> 
> > diff --git a/drivers/usb/gadget/uvc_queue.c
> > b/drivers/usb/gadget/uvc_queue.c index 104ae9c..3f5eeae 100644
> > --- a/drivers/usb/gadget/uvc_queue.c
> > +++ b/drivers/usb/gadget/uvc_queue.c
> 
> [snip]
> 
> > +static int uvc_queue_init(struct uvc_video_queue *queue,
> > +			  enum v4l2_buf_type type)
> >  {
> > +	int ret;
> >
> > +	queue->queue.type = type;
> > +	queue->queue.io_modes = VB2_MMAP | VB2_USERPTR;
> > +	queue->queue.drv_priv = queue;
> > +	queue->queue.buf_struct_size = sizeof(struct uvc_buffer);
> > +	queue->queue.ops = &uvc_queue_qops;
> > +	queue->queue.mem_ops = &vb2_vmalloc_memops;
> > +	ret = vb2_queue_init(&queue->queue);
> > +	if (ret)
> > +		return ret;
> >
> > +	mutex_init(&queue->mutex);
> > +	spin_lock_init(&queue->irqlock);
> > +	INIT_LIST_HEAD(&queue->irqqueue);
> 
> I think you should initialize queue->flags to 0 here.
> 
> >
> > +	return 0;
> >  }
> 
> [snip]
> 
> > +static int uvc_queue_buffer(struct uvc_video_queue *queue,
> > +			    struct v4l2_buffer *buf)
> >  {
> > +	int ret;
> > +
> > +	mutex_lock(&queue->mutex);
> > +	ret = vb2_qbuf(&queue->queue, buf);
> > +	ret = (queue->flags & UVC_QUEUE_PAUSED) != 0;
> > +	queue->flags &= ~UVC_QUEUE_PAUSED;
> 
> Access to the queue flags need to be protected by the irqlock spinlock here
> (in addition to the queue mutex).
> 
> > +	mutex_unlock(&queue->mutex);
> >
> > +	return ret;
> >  }
> 
> [snip]
> 
> > @@ -516,26 +283,32 @@ static void uvc_queue_cancel(struct
> > uvc_video_queue *queue, int disconnect) */  static int
> > uvc_queue_enable(struct uvc_video_queue *queue, int enable)  {
> > -	unsigned int i;
> > +	unsigned long flags;
> >  	int ret = 0;
> >
> >  	mutex_lock(&queue->mutex);
> >  	if (enable) {
> > -		if (uvc_queue_streaming(queue)) {
> > -			ret = -EBUSY;
> > +		ret = vb2_streamon(&queue->queue, queue->queue.type);
> > +		if (ret < 0)
> >  			goto done;
> > -		}
> > -		queue->sequence = 0;
> 
> Shouldn't you keep this line ?
> 
> > -		queue->flags |= UVC_QUEUE_STREAMING;
> > +
> >  		queue->buf_used = 0;
> >  	} else {
> > -		uvc_queue_cancel(queue, 0);
> > -		INIT_LIST_HEAD(&queue->mainqueue);
> > +		ret = vb2_streamoff(&queue->queue, queue->queue.type);
> > +		if (ret < 0)
> > +			goto done;
> >
> > -		for (i = 0; i < queue->count; ++i)
> > -			queue->buffer[i].state = UVC_BUF_STATE_IDLE;
> > +		spin_lock_irqsave(&queue->irqlock, flags);
> > +		INIT_LIST_HEAD(&queue->irqqueue);
> >
> > -		queue->flags &= ~UVC_QUEUE_STREAMING;
> > +		/*
> > +		 * FIXME: We need to clear the DISCONNECTED flag to ensure
> that
> > +		 * applications will be able to queue buffers for the next
> > +		 * streaming run. However, clearing it here doesn't guarantee
> > +		 * that the device will be reconnected in the meantime.
> > +		 */
> > +		queue->flags &= ~UVC_QUEUE_DISCONNECTED;
> > +		spin_unlock_irqrestore(&queue->irqlock, flags);
> >  	}
> >
> >  done:
> 
> [snip]
> 
> > diff --git a/drivers/usb/gadget/uvc_queue.h
> > b/drivers/usb/gadget/uvc_queue.h index 1812a8e..47ad0b8 100644
> > --- a/drivers/usb/gadget/uvc_queue.h
> > +++ b/drivers/usb/gadget/uvc_queue.h
> 
> [snip]
> 
> > @@ -25,14 +26,13 @@ enum uvc_buffer_state {  };
> >
> >  struct uvc_buffer {
> > -	unsigned long vma_use_count;
> > -	struct list_head stream;
> > -
> > -	/* Touched by interrupt handler. */
> > -	struct v4l2_buffer buf;
> > +	struct vb2_buffer buf;
> >  	struct list_head queue;
> > -	wait_queue_head_t wait;
> > +
> >  	enum uvc_buffer_state state;
> > +	void *mem;
> > +	unsigned int length;
> > +	unsigned int bytesused;
> >  };
> >
> >  #define UVC_QUEUE_STREAMING		(1 << 0)
> 
> You can remove the UVC_QUEUE_STREAMIN flag, it's not used anymore.
> 
> > @@ -41,26 +41,21 @@ struct uvc_buffer {
> >  #define UVC_QUEUE_PAUSED		(1 << 3)
> >
> >  struct uvc_video_queue {
> > -	enum v4l2_buf_type type;
> > +	struct vb2_queue queue;
> > +	struct mutex mutex;	/* Protects queue */
> >
> > -	void *mem;
> >  	unsigned int flags;
> >  	__u32 sequence;
> >
> > -	unsigned int count;
> > -	unsigned int buf_size;
> >  	unsigned int buf_used;
> > -	struct uvc_buffer buffer[UVC_MAX_VIDEO_BUFFERS];
> > -	struct mutex mutex;	/* protects buffers and mainqueue */
> > -	spinlock_t irqlock;	/* protects irqqueue */
> >
> > -	struct list_head mainqueue;
> > +	spinlock_t irqlock;	/* Protects irqqueue */
> 
> The comment is incorrect, it should be "Protects flags and irqqueue" (it's my
> fault, but let's fix it :-)).
> 
> >  	struct list_head irqqueue;
> >  };
> >
> >  static inline int uvc_queue_streaming(struct uvc_video_queue *queue)
> > {
> > -	return queue->flags & UVC_QUEUE_STREAMING;
> > +	return vb2_is_streaming(&queue->queue);
> >  }
> >
> >  #endif /* __KERNEL__ */
> 
> [snip]
> 
> --

All comments accepted.  I will send out V5 shortly.

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




[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux