diff mbox

[REVIEWv2,07/15] vb2: call buf_finish from __dqbuf

Message ID 1393332775-44067-8-git-send-email-hverkuil@xs4all.nl (mailing list archive)
State New, archived
Headers show

Commit Message

Hans Verkuil Feb. 25, 2014, 12:52 p.m. UTC
From: Hans Verkuil <hans.verkuil@cisco.com>

This ensures that it is also called from queue_cancel, which also calls
__dqbuf(). Without this change any time queue_cancel is called while
streaming the buf_finish op will not be called and any driver cleanup
will not happen.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Acked-by: Pawel Osciak <pawel@osciak.com>
---
 drivers/media/v4l2-core/videobuf2-core.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

Comments

Laurent Pinchart Feb. 27, 2014, 11:51 a.m. UTC | #1
Hi Hans,

On Tuesday 25 February 2014 13:52:47 Hans Verkuil wrote:
> From: Hans Verkuil <hans.verkuil@cisco.com>
> 
> This ensures that it is also called from queue_cancel, which also calls
> __dqbuf(). Without this change any time queue_cancel is called while
> streaming the buf_finish op will not be called and any driver cleanup
> will not happen.
> 
> Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
> Acked-by: Pawel Osciak <pawel@osciak.com>
> ---
>  drivers/media/v4l2-core/videobuf2-core.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/media/v4l2-core/videobuf2-core.c
> b/drivers/media/v4l2-core/videobuf2-core.c index 59bfd85..b5142e5 100644
> --- a/drivers/media/v4l2-core/videobuf2-core.c
> +++ b/drivers/media/v4l2-core/videobuf2-core.c
> @@ -1758,6 +1758,8 @@ static void __vb2_dqbuf(struct vb2_buffer *vb)
>  	if (vb->state == VB2_BUF_STATE_DEQUEUED)
>  		return;
> 
> +	call_vb_qop(vb, buf_finish, vb);
> +
>  	vb->state = VB2_BUF_STATE_DEQUEUED;
> 
>  	/* unmap DMABUF buffer */
> @@ -1783,8 +1785,6 @@ static int vb2_internal_dqbuf(struct vb2_queue *q,
> struct v4l2_buffer *b, bool n if (ret < 0)
>  		return ret;
> 
> -	call_vb_qop(vb, buf_finish, vb);
> -
>  	switch (vb->state) {
>  	case VB2_BUF_STATE_DONE:
>  		dprintk(3, "dqbuf: Returning done buffer\n");

This will cause an issue with the uvcvideo driver (and possibly others) if I'm 
not mistaken. To give a bit more context, we currently have the following code 
in vb2_internal_dqbuf.

        ret = call_qop(q, buf_finish, vb);
        if (ret) {
                dprintk(1, "dqbuf: buffer finish failed\n");
                return ret;
        }

        switch (vb->state) {
        case VB2_BUF_STATE_DONE:
                dprintk(3, "dqbuf: Returning done buffer\n");
                break;
        case VB2_BUF_STATE_ERROR:
                dprintk(3, "dqbuf: Returning done buffer with errors\n");
                break;
        default:
                dprintk(1, "dqbuf: Invalid buffer state\n");
                return -EINVAL;
        }

        /* Fill buffer information for the userspace */
        __fill_v4l2_buffer(vb, b);
        /* Remove from videobuf queue */
        list_del(&vb->queued_entry);
        /* go back to dequeued state */
        __vb2_dqbuf(vb);

You're thus effectively moving the buf_finish call from before 
__fill_v4l2_buffer() to after it. As the buf_finish operation in uvcvideo 
fills the vb2 timestamp, the timestamp copied to userspace will be wrong.

Other drivers may fill other vb2 fields that need to be copied to userspace as 
well. You should also double check that no driver modifies the vb2 state in 
the buf_finish operation. Expanding the buf_finish documentation to tell what 
drivers are allowed to do could be nice.
Hans Verkuil Feb. 27, 2014, 12:13 p.m. UTC | #2
On 02/27/14 12:51, Laurent Pinchart wrote:
> Hi Hans,
> 
> On Tuesday 25 February 2014 13:52:47 Hans Verkuil wrote:
>> From: Hans Verkuil <hans.verkuil@cisco.com>
>>
>> This ensures that it is also called from queue_cancel, which also calls
>> __dqbuf(). Without this change any time queue_cancel is called while
>> streaming the buf_finish op will not be called and any driver cleanup
>> will not happen.
>>
>> Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
>> Acked-by: Pawel Osciak <pawel@osciak.com>
>> ---
>>  drivers/media/v4l2-core/videobuf2-core.c | 4 ++--
>>  1 file changed, 2 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/media/v4l2-core/videobuf2-core.c
>> b/drivers/media/v4l2-core/videobuf2-core.c index 59bfd85..b5142e5 100644
>> --- a/drivers/media/v4l2-core/videobuf2-core.c
>> +++ b/drivers/media/v4l2-core/videobuf2-core.c
>> @@ -1758,6 +1758,8 @@ static void __vb2_dqbuf(struct vb2_buffer *vb)
>>  	if (vb->state == VB2_BUF_STATE_DEQUEUED)
>>  		return;
>>
>> +	call_vb_qop(vb, buf_finish, vb);
>> +
>>  	vb->state = VB2_BUF_STATE_DEQUEUED;
>>
>>  	/* unmap DMABUF buffer */
>> @@ -1783,8 +1785,6 @@ static int vb2_internal_dqbuf(struct vb2_queue *q,
>> struct v4l2_buffer *b, bool n if (ret < 0)
>>  		return ret;
>>
>> -	call_vb_qop(vb, buf_finish, vb);
>> -
>>  	switch (vb->state) {
>>  	case VB2_BUF_STATE_DONE:
>>  		dprintk(3, "dqbuf: Returning done buffer\n");
> 
> This will cause an issue with the uvcvideo driver (and possibly others) if I'm 
> not mistaken. To give a bit more context, we currently have the following code 
> in vb2_internal_dqbuf.
> 
>         ret = call_qop(q, buf_finish, vb);
>         if (ret) {
>                 dprintk(1, "dqbuf: buffer finish failed\n");
>                 return ret;
>         }
> 
>         switch (vb->state) {
>         case VB2_BUF_STATE_DONE:
>                 dprintk(3, "dqbuf: Returning done buffer\n");
>                 break;
>         case VB2_BUF_STATE_ERROR:
>                 dprintk(3, "dqbuf: Returning done buffer with errors\n");
>                 break;
>         default:
>                 dprintk(1, "dqbuf: Invalid buffer state\n");
>                 return -EINVAL;
>         }
> 
>         /* Fill buffer information for the userspace */
>         __fill_v4l2_buffer(vb, b);
>         /* Remove from videobuf queue */
>         list_del(&vb->queued_entry);
>         /* go back to dequeued state */
>         __vb2_dqbuf(vb);
> 
> You're thus effectively moving the buf_finish call from before 
> __fill_v4l2_buffer() to after it. As the buf_finish operation in uvcvideo 
> fills the vb2 timestamp, the timestamp copied to userspace will be wrong.

Ouch. Good catch. The solution is to move the __vb2_dqbuf() call to before
the __fill_v4l2_buffer call. But I should see if I can add some test for
this to vivi/v4l2-compliance as well since that should have been caught.

> Other drivers may fill other vb2 fields that need to be copied to userspace as 
> well. You should also double check that no driver modifies the vb2 state in 
> the buf_finish operation. Expanding the buf_finish documentation to tell what 
> drivers are allowed to do could be nice.

Good point.

Regards,

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

Patch

diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c
index 59bfd85..b5142e5 100644
--- a/drivers/media/v4l2-core/videobuf2-core.c
+++ b/drivers/media/v4l2-core/videobuf2-core.c
@@ -1758,6 +1758,8 @@  static void __vb2_dqbuf(struct vb2_buffer *vb)
 	if (vb->state == VB2_BUF_STATE_DEQUEUED)
 		return;
 
+	call_vb_qop(vb, buf_finish, vb);
+
 	vb->state = VB2_BUF_STATE_DEQUEUED;
 
 	/* unmap DMABUF buffer */
@@ -1783,8 +1785,6 @@  static int vb2_internal_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b, bool n
 	if (ret < 0)
 		return ret;
 
-	call_vb_qop(vb, buf_finish, vb);
-
 	switch (vb->state) {
 	case VB2_BUF_STATE_DONE:
 		dprintk(3, "dqbuf: Returning done buffer\n");