Re: [RFT PATCH v3 5/6] uvcvideo: queue: Support asynchronous buffer handling

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

 



Hi Kieran

I think your v4 doesn't take the review comments below into account.

On Wednesday, 17 January 2018 01:45:33 EEST Laurent Pinchart wrote:
> On Friday, 12 January 2018 11:19:26 EET Kieran Bingham wrote:
> > The buffer queue interface currently operates sequentially, processing
> > buffers after they have fully completed.
> > 
> > In preparation for supporting parallel tasks operating on the buffers,
> > we will need to support buffers being processed on multiple CPUs.
> > 
> > Adapt the uvc_queue_next_buffer() such that a reference count tracks the
> > active use of the buffer, returning the buffer to the VB2 stack at
> > completion.
> > 
> > Signed-off-by: Kieran Bingham <kieran.bingham@xxxxxxxxxxxxxxxx>
> > ---
> > 
> >  drivers/media/usb/uvc/uvc_queue.c | 61 ++++++++++++++++++++++++++------
> >  drivers/media/usb/uvc/uvcvideo.h  |  4 ++-
> >  2 files changed, 54 insertions(+), 11 deletions(-)
> > 
> > diff --git a/drivers/media/usb/uvc/uvc_queue.c
> > b/drivers/media/usb/uvc/uvc_queue.c index ddac4d89a291..5a9987e547d3
> > 100644
> > --- a/drivers/media/usb/uvc/uvc_queue.c
> > +++ b/drivers/media/usb/uvc/uvc_queue.c
> > @@ -131,6 +131,7 @@ static void uvc_buffer_queue(struct vb2_buffer *vb)
> > 
> >  	spin_lock_irqsave(&queue->irqlock, flags);
> >  	if (likely(!(queue->flags & UVC_QUEUE_DISCONNECTED))) {
> > 
> > +		kref_init(&buf->ref);
> > 
> >  		list_add_tail(&buf->queue, &queue->irqqueue);
> >  	
> >  	} else {
> >  	
> >  		/* If the device is disconnected return the buffer to userspace
> > 
> > @@ -424,28 +425,66 @@ struct uvc_buffer
> > *uvc_queue_get_current_buffer(struct uvc_video_queue *queue) return
> > nextbuf;
> > 
> >  }
> > 
> > -struct uvc_buffer *uvc_queue_next_buffer(struct uvc_video_queue *queue,
> > +/*
> > + * uvc_queue_requeue: Requeue a buffer on our internal irqqueue
> > + *
> > + * Reuse a buffer through our internal queue without the need to
> > 'prepare'
> > + * The buffer will be returned to userspace through the uvc_buffer_queue
> > call if
> > + * the device has been disconnected

Additionally, periods are messing at the end of sentences.

> > + */
> > +static void uvc_queue_requeue(struct uvc_video_queue *queue,
> > 
> >  		struct uvc_buffer *buf)
> >  
> >  {
> > 
> > -	struct uvc_buffer *nextbuf;
> > -	unsigned long flags;
> > +	buf->error = 0;
> > +	buf->state = UVC_BUF_STATE_QUEUED;
> > +	buf->bytesused = 0;
> > +	vb2_set_plane_payload(&buf->buf.vb2_buf, 0, 0);
> > +
> > +	uvc_buffer_queue(&buf->buf.vb2_buf);
> > +}
> 
> You could have inlined this in uvc_queue_buffer_complete(), but the above
> documentation is useful, so I'm fine if you prefer keeping it as a separate
> function. Maybe you could call it uvc_queue_buffer_requeue() to be
> consistent with the other functions ?
> 
> > +static void uvc_queue_buffer_complete(struct kref *ref)
> > +{
> > +	struct uvc_buffer *buf = container_of(ref, struct uvc_buffer, ref);
> > +	struct vb2_buffer *vb = &buf->buf.vb2_buf;
> > +	struct uvc_video_queue *queue = vb2_get_drv_priv(vb->vb2_queue);
> > 
> >  	if ((queue->flags & UVC_QUEUE_DROP_CORRUPTED) && buf->error) {
> > 
> > -		buf->error = 0;
> > -		buf->state = UVC_BUF_STATE_QUEUED;
> > -		buf->bytesused = 0;
> > -		vb2_set_plane_payload(&buf->buf.vb2_buf, 0, 0);
> > -		return buf;
> > +		uvc_queue_requeue(queue, buf);
> > +		return;
> 
> This changes the behaviour of the driver. Currently when an erroneous buffer
> is encountered, it will be immediately reused. With this patch applied it
> will be pushed to the back of the queue for later reuse. This will result
> in buffers being reordered, possibly causing issues later when we'll
> implement fences support (or possibly even today).
> 
> I think the whole drop corrupted buffers mechanism was a bad idea in the
> first place and I'd like to remove it at some point, buffers in the error
> state should be handled by applications. However, until that's done, I
> wonder whether it would be possible to keep the current order. I
> unfortunately don't see an easy option to do so at the moment, but maybe
> you would. Otherwise I suppose we'll have to leave it as is.
> 
> I'm tempted to flip the driver to not drop corrupted buffers by default.
> I've done so on my computer, I'll see if I run into any issue. It could be
> useful if you could set the nodrop parameter to 1 on your systems too when
> performing tests.
> 
> >  	}
> > 
> > +	buf->state = buf->error ? UVC_BUF_STATE_ERROR : UVC_BUF_STATE_DONE;
> > +	vb2_set_plane_payload(&buf->buf.vb2_buf, 0, buf->bytesused);
> > +	vb2_buffer_done(&buf->buf.vb2_buf, VB2_BUF_STATE_DONE);
> > +}
> > +
> > +/*
> > + * Release a reference on the buffer. Complete the buffer when the last
> > + * reference is released
> > + */
> > +void uvc_queue_buffer_release(struct uvc_buffer *buf)
> > +{
> > +	kref_put(&buf->ref, uvc_queue_buffer_complete);
> > +}
> > +
> > +/*
> > + * Remove this buffer from the queue. Lifetime will persist while async
> > actions
> > + * are still running (if any), and uvc_queue_buffer_release will give the
> > buffer
> > + * back to VB2 when all users have completed.
> > + */
> > +struct uvc_buffer *uvc_queue_next_buffer(struct uvc_video_queue *queue,
> > +		struct uvc_buffer *buf)
> > +{
> > +	struct uvc_buffer *nextbuf;
> > +	unsigned long flags;
> > +
> > 
> >  	spin_lock_irqsave(&queue->irqlock, flags);
> >  	list_del(&buf->queue);
> >  	nextbuf = __uvc_queue_get_current_buffer(queue);
> >  	spin_unlock_irqrestore(&queue->irqlock, flags);
> > 
> > -	buf->state = buf->error ? UVC_BUF_STATE_ERROR : UVC_BUF_STATE_DONE;
> > -	vb2_set_plane_payload(&buf->buf.vb2_buf, 0, buf->bytesused);
> > -	vb2_buffer_done(&buf->buf.vb2_buf, VB2_BUF_STATE_DONE);
> > +	uvc_queue_buffer_release(buf);
> > 
> >  	return nextbuf;
> >  
> >  }
> > 
> > diff --git a/drivers/media/usb/uvc/uvcvideo.h
> > b/drivers/media/usb/uvc/uvcvideo.h index 5caa1f4de3cb..6a18dbfc3e5b 100644
> > --- a/drivers/media/usb/uvc/uvcvideo.h
> > +++ b/drivers/media/usb/uvc/uvcvideo.h
> > @@ -404,6 +404,9 @@ struct uvc_buffer {
> > 
> >  	unsigned int bytesused;
> >  	
> >  	u32 pts;
> > 
> > +
> > +	/* asynchronous buffer handling */
> 
> Please capitalize the first word to match other comments in the driver.
> 
> > +	struct kref ref;
> > 
> >  };
> >  
> >  #define UVC_QUEUE_DISCONNECTED		(1 << 0)
> > 
> > @@ -696,6 +699,7 @@ extern struct uvc_buffer *
> > 
> >  		uvc_queue_get_current_buffer(struct uvc_video_queue *queue);
> >  
> >  extern struct uvc_buffer *uvc_queue_next_buffer(struct uvc_video_queue
> > 
> > *queue, struct uvc_buffer *buf);
> > +extern void uvc_queue_buffer_release(struct uvc_buffer *buf);
> 
> No need for the extern keyboard. I'll submit a patch to drop it for all
> functions.
> 
> >  extern int uvc_queue_mmap(struct uvc_video_queue *queue,
> >  
> >  		struct vm_area_struct *vma);
> >  
> >  extern unsigned int uvc_queue_poll(struct uvc_video_queue *queue,

-- 
Regards,

Laurent Pinchart






[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