diff mbox series

[v6,03/14] videobuf2: handle V4L2 buffer cache flags

Message ID 20200514160153.3646-4-sergey.senozhatsky@gmail.com (mailing list archive)
State New, archived
Headers show
Series Implement V4L2_BUF_FLAG_NO_CACHE_* flags | expand

Commit Message

Sergey Senozhatsky May 14, 2020, 4:01 p.m. UTC
From: Sergey Senozhatsky <senozhatsky@chromium.org>

Set video buffer cache management flags corresponding to V4L2 cache
flags.

Both ->prepare() and ->finish() cache management hints should be
passed during this stage (buffer preparation), because there is
no other way for user-space to tell V4L2 to avoid ->finish() cache
flush.

Signed-off-by: Sergey Senozhatsky <senozhatsky@chromium.org>
---
 .../media/common/videobuf2/videobuf2-v4l2.c   | 48 +++++++++++++++++++
 include/media/videobuf2-core.h                | 11 +++++
 2 files changed, 59 insertions(+)

Comments

Hans Verkuil June 2, 2020, 9:51 a.m. UTC | #1
Hi Sergey,

While doing final testing for this patch series (together with the v4l-utils patch)
I found one remaining issue:

On 14/05/2020 18:01, Sergey Senozhatsky wrote:
> From: Sergey Senozhatsky <senozhatsky@chromium.org>
> 
> Set video buffer cache management flags corresponding to V4L2 cache
> flags.
> 
> Both ->prepare() and ->finish() cache management hints should be
> passed during this stage (buffer preparation), because there is
> no other way for user-space to tell V4L2 to avoid ->finish() cache
> flush.
> 
> Signed-off-by: Sergey Senozhatsky <senozhatsky@chromium.org>
> ---
>  .../media/common/videobuf2/videobuf2-v4l2.c   | 48 +++++++++++++++++++
>  include/media/videobuf2-core.h                | 11 +++++
>  2 files changed, 59 insertions(+)
> 
> diff --git a/drivers/media/common/videobuf2/videobuf2-v4l2.c b/drivers/media/common/videobuf2/videobuf2-v4l2.c
> index eb5d5db96552..f13851212cc8 100644
> --- a/drivers/media/common/videobuf2/videobuf2-v4l2.c
> +++ b/drivers/media/common/videobuf2/videobuf2-v4l2.c
> @@ -337,6 +337,53 @@ static int vb2_fill_vb2_v4l2_buffer(struct vb2_buffer *vb, struct v4l2_buffer *b
>  	return 0;
>  }
>  
> +static void set_buffer_cache_hints(struct vb2_queue *q,
> +				   struct vb2_buffer *vb,
> +				   struct v4l2_buffer *b)
> +{
> +	/*
> +	 * DMA exporter should take care of cache syncs, so we can avoid
> +	 * explicit ->prepare()/->finish() syncs. For other ->memory types
> +	 * we always need ->prepare() or/and ->finish() cache sync.
> +	 */
> +	if (q->memory == VB2_MEMORY_DMABUF) {
> +		vb->need_cache_sync_on_finish = 0;
> +		vb->need_cache_sync_on_prepare = 0;
> +		return;
> +	}
> +
> +	/*
> +	 * Cache sync/invalidation flags are set by default in order to
> +	 * preserve existing behaviour for old apps/drivers.
> +	 */
> +	vb->need_cache_sync_on_prepare = 1;
> +	vb->need_cache_sync_on_finish = 1;
> +
> +	if (!vb2_queue_allows_cache_hints(q)) {
> +		/*
> +		 * Clear buffer cache flags if queue does not support user
> +		 * space hints. That's to indicate to userspace that these
> +		 * flags won't work.
> +		 */
> +		b->flags &= ~V4L2_BUF_FLAG_NO_CACHE_INVALIDATE;
> +		b->flags &= ~V4L2_BUF_FLAG_NO_CACHE_CLEAN;
> +		return;
> +	}

These two flags need to be cleared for VB2_MEMORY_DMABUF as well in the test above.
This bug is causing v4l2-compliance failures (use the test-media script in contrib/test
in v4l-utils: 'sudo test-media vim2m').

It's enough to post a v6.1 for this patch, everything else is fine.

Regards,

	Hans

> +
> +	/*
> +	 * ->finish() cache sync can be avoided when queue direction is
> +	 * TO_DEVICE.
> +	 */
> +	if (q->dma_dir == DMA_TO_DEVICE)
> +		vb->need_cache_sync_on_finish = 0;
> +
> +	if (b->flags & V4L2_BUF_FLAG_NO_CACHE_INVALIDATE)
> +		vb->need_cache_sync_on_finish = 0;
> +
> +	if (b->flags & V4L2_BUF_FLAG_NO_CACHE_CLEAN)
> +		vb->need_cache_sync_on_prepare = 0;
> +}
> +
>  static int vb2_queue_or_prepare_buf(struct vb2_queue *q, struct media_device *mdev,
>  				    struct v4l2_buffer *b, bool is_prepare,
>  				    struct media_request **p_req)
> @@ -381,6 +428,7 @@ static int vb2_queue_or_prepare_buf(struct vb2_queue *q, struct media_device *md
>  	}
>  
>  	if (!vb->prepared) {
> +		set_buffer_cache_hints(q, vb, b);
>  		/* Copy relevant information provided by the userspace */
>  		memset(vbuf->planes, 0,
>  		       sizeof(vbuf->planes[0]) * vb->num_planes);
> diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
> index 7f39d9fffc8c..ccc5c498d3e3 100644
> --- a/include/media/videobuf2-core.h
> +++ b/include/media/videobuf2-core.h
> @@ -635,6 +635,17 @@ struct vb2_queue {
>  #endif
>  };
>  
> +/**
> + * vb2_queue_allows_cache_hints() - Return true if the queue allows cache
> + * and memory consistency hints.
> + *
> + * @q:		pointer to &struct vb2_queue with videobuf2 queue
> + */
> +static inline bool vb2_queue_allows_cache_hints(struct vb2_queue *q)
> +{
> +	return q->allow_cache_hints && q->memory == VB2_MEMORY_MMAP;
> +}
> +
>  /**
>   * vb2_plane_vaddr() - Return a kernel virtual address of a given plane.
>   * @vb:		pointer to &struct vb2_buffer to which the plane in
>
Sergey Senozhatsky June 2, 2020, 10:18 a.m. UTC | #2
Hi Hans,

On (20/06/02 11:51), Hans Verkuil wrote:
> Hi Sergey,
> 
> While doing final testing for this patch series (together with the v4l-utils patch)
> I found one remaining issue:

Thanks for the report.

> > +static void set_buffer_cache_hints(struct vb2_queue *q,
> > +				   struct vb2_buffer *vb,
> > +				   struct v4l2_buffer *b)
> > +{
> > +	/*
> > +	 * DMA exporter should take care of cache syncs, so we can avoid
> > +	 * explicit ->prepare()/->finish() syncs. For other ->memory types
> > +	 * we always need ->prepare() or/and ->finish() cache sync.
> > +	 */
> > +	if (q->memory == VB2_MEMORY_DMABUF) {
> > +		vb->need_cache_sync_on_finish = 0;
> > +		vb->need_cache_sync_on_prepare = 0;
> > +		return;
> > +	}
> > +
> > +	/*
> > +	 * Cache sync/invalidation flags are set by default in order to
> > +	 * preserve existing behaviour for old apps/drivers.
> > +	 */
> > +	vb->need_cache_sync_on_prepare = 1;
> > +	vb->need_cache_sync_on_finish = 1;
> > +
> > +	if (!vb2_queue_allows_cache_hints(q)) {
> > +		/*
> > +		 * Clear buffer cache flags if queue does not support user
> > +		 * space hints. That's to indicate to userspace that these
> > +		 * flags won't work.
> > +		 */
> > +		b->flags &= ~V4L2_BUF_FLAG_NO_CACHE_INVALIDATE;
> > +		b->flags &= ~V4L2_BUF_FLAG_NO_CACHE_CLEAN;
> > +		return;
> > +	}
> 
> These two flags need to be cleared for VB2_MEMORY_DMABUF as well in the test above.
> This bug is causing v4l2-compliance failures (use the test-media script in contrib/test
> in v4l-utils: 'sudo test-media vim2m').

Sorry, Hans, do you suggest to have something like this:

	if (q->memory == VB2_MEMORY_DMABUF) {
		vb->need_cache_sync_on_finish = 0;
		vb->need_cache_sync_on_prepare = 0;
		b->flags &= ~V4L2_BUF_FLAG_NO_CACHE_INVALIDATE;
		b->flags &= ~V4L2_BUF_FLAG_NO_CACHE_CLEAN;
		return;
	}

I didn't clear the ->flags there because we clear the vb flush/sync
flags: ->need_cache_sync_on_finish/prepare are zeros for DMABUF memory
type. Which is equivalent to passing V4L2_BUF_FLAG_NO_CACHE_INVALIDATE
V4L2_BUF_FLAG_NO_CACHE_CLEAN. IOW we would clearing both "vb's do cache
sync" and request's "do not cache sync".

> It's enough to post a v6.1 for this patch, everything else is fine.

Thanks!

	-ss
Hans Verkuil June 2, 2020, 10:27 a.m. UTC | #3
On 02/06/2020 12:18, Sergey Senozhatsky wrote:
> Hi Hans,
> 
> On (20/06/02 11:51), Hans Verkuil wrote:
>> Hi Sergey,
>>
>> While doing final testing for this patch series (together with the v4l-utils patch)
>> I found one remaining issue:
> 
> Thanks for the report.
> 
>>> +static void set_buffer_cache_hints(struct vb2_queue *q,
>>> +				   struct vb2_buffer *vb,
>>> +				   struct v4l2_buffer *b)
>>> +{
>>> +	/*
>>> +	 * DMA exporter should take care of cache syncs, so we can avoid
>>> +	 * explicit ->prepare()/->finish() syncs. For other ->memory types
>>> +	 * we always need ->prepare() or/and ->finish() cache sync.
>>> +	 */
>>> +	if (q->memory == VB2_MEMORY_DMABUF) {
>>> +		vb->need_cache_sync_on_finish = 0;
>>> +		vb->need_cache_sync_on_prepare = 0;
>>> +		return;
>>> +	}
>>> +
>>> +	/*
>>> +	 * Cache sync/invalidation flags are set by default in order to
>>> +	 * preserve existing behaviour for old apps/drivers.
>>> +	 */
>>> +	vb->need_cache_sync_on_prepare = 1;
>>> +	vb->need_cache_sync_on_finish = 1;
>>> +
>>> +	if (!vb2_queue_allows_cache_hints(q)) {
>>> +		/*
>>> +		 * Clear buffer cache flags if queue does not support user
>>> +		 * space hints. That's to indicate to userspace that these
>>> +		 * flags won't work.
>>> +		 */
>>> +		b->flags &= ~V4L2_BUF_FLAG_NO_CACHE_INVALIDATE;
>>> +		b->flags &= ~V4L2_BUF_FLAG_NO_CACHE_CLEAN;
>>> +		return;
>>> +	}
>>
>> These two flags need to be cleared for VB2_MEMORY_DMABUF as well in the test above.
>> This bug is causing v4l2-compliance failures (use the test-media script in contrib/test
>> in v4l-utils: 'sudo test-media vim2m').
> 
> Sorry, Hans, do you suggest to have something like this:
> 
> 	if (q->memory == VB2_MEMORY_DMABUF) {
> 		vb->need_cache_sync_on_finish = 0;
> 		vb->need_cache_sync_on_prepare = 0;
> 		b->flags &= ~V4L2_BUF_FLAG_NO_CACHE_INVALIDATE;
> 		b->flags &= ~V4L2_BUF_FLAG_NO_CACHE_CLEAN;
> 		return;
> 	}
> 
> I didn't clear the ->flags there because we clear the vb flush/sync
> flags: ->need_cache_sync_on_finish/prepare are zeros for DMABUF memory
> type. Which is equivalent to passing V4L2_BUF_FLAG_NO_CACHE_INVALIDATE
> V4L2_BUF_FLAG_NO_CACHE_CLEAN. IOW we would clearing both "vb's do cache
> sync" and request's "do not cache sync".

Ah, yes. In that case the v4l-utils patch is likely wrong. Can you take a
look at that patch?

In any case, *something* is wrong.

Regards,

	Hans

> 
>> It's enough to post a v6.1 for this patch, everything else is fine.
> 
> Thanks!
> 
> 	-ss
>
Sergey Senozhatsky June 2, 2020, 12:10 p.m. UTC | #4
On (20/06/02 12:27), Hans Verkuil wrote:
[..]
> > Sorry, Hans, do you suggest to have something like this:
> > 
> > 	if (q->memory == VB2_MEMORY_DMABUF) {
> > 		vb->need_cache_sync_on_finish = 0;
> > 		vb->need_cache_sync_on_prepare = 0;
> > 		b->flags &= ~V4L2_BUF_FLAG_NO_CACHE_INVALIDATE;
> > 		b->flags &= ~V4L2_BUF_FLAG_NO_CACHE_CLEAN;
> > 		return;
> > 	}
> > 
> > I didn't clear the ->flags there because we clear the vb flush/sync
> > flags: ->need_cache_sync_on_finish/prepare are zeros for DMABUF memory
> > type. Which is equivalent to passing V4L2_BUF_FLAG_NO_CACHE_INVALIDATE
> > V4L2_BUF_FLAG_NO_CACHE_CLEAN. IOW we would clearing both "vb's do cache
> > sync" and request's "do not cache sync".
> 
> Ah, yes. In that case the v4l-utils patch is likely wrong.
> Can you take a look at that patch?

Hans, are we talking about "v4l2-utils: test cache_hints for MMAP queues"
patch? I can take a look, yes.

	-ss
Hans Verkuil June 2, 2020, 12:21 p.m. UTC | #5
On 02/06/2020 14:10, Sergey Senozhatsky wrote:
> On (20/06/02 12:27), Hans Verkuil wrote:
> [..]
>>> Sorry, Hans, do you suggest to have something like this:
>>>
>>> 	if (q->memory == VB2_MEMORY_DMABUF) {
>>> 		vb->need_cache_sync_on_finish = 0;
>>> 		vb->need_cache_sync_on_prepare = 0;
>>> 		b->flags &= ~V4L2_BUF_FLAG_NO_CACHE_INVALIDATE;
>>> 		b->flags &= ~V4L2_BUF_FLAG_NO_CACHE_CLEAN;
>>> 		return;
>>> 	}
>>>
>>> I didn't clear the ->flags there because we clear the vb flush/sync
>>> flags: ->need_cache_sync_on_finish/prepare are zeros for DMABUF memory
>>> type. Which is equivalent to passing V4L2_BUF_FLAG_NO_CACHE_INVALIDATE
>>> V4L2_BUF_FLAG_NO_CACHE_CLEAN. IOW we would clearing both "vb's do cache
>>> sync" and request's "do not cache sync".
>>
>> Ah, yes. In that case the v4l-utils patch is likely wrong.
>> Can you take a look at that patch?
> 
> Hans, are we talking about "v4l2-utils: test cache_hints for MMAP queues"
> patch? I can take a look, yes.

Yes, that's the one.

	Hans
Tomasz Figa June 2, 2020, 12:22 p.m. UTC | #6
Hi Hans,

On Tue, Jun 2, 2020 at 11:51 AM Hans Verkuil <hverkuil@xs4all.nl> wrote:
>
> Hi Sergey,
>
> While doing final testing for this patch series (together with the v4l-utils patch)
> I found one remaining issue:
>
> On 14/05/2020 18:01, Sergey Senozhatsky wrote:
> > From: Sergey Senozhatsky <senozhatsky@chromium.org>
> >
> > Set video buffer cache management flags corresponding to V4L2 cache
> > flags.
> >
> > Both ->prepare() and ->finish() cache management hints should be
> > passed during this stage (buffer preparation), because there is
> > no other way for user-space to tell V4L2 to avoid ->finish() cache
> > flush.
> >
> > Signed-off-by: Sergey Senozhatsky <senozhatsky@chromium.org>
> > ---
> >  .../media/common/videobuf2/videobuf2-v4l2.c   | 48 +++++++++++++++++++
> >  include/media/videobuf2-core.h                | 11 +++++
> >  2 files changed, 59 insertions(+)
> >
> > diff --git a/drivers/media/common/videobuf2/videobuf2-v4l2.c b/drivers/media/common/videobuf2/videobuf2-v4l2.c
> > index eb5d5db96552..f13851212cc8 100644
> > --- a/drivers/media/common/videobuf2/videobuf2-v4l2.c
> > +++ b/drivers/media/common/videobuf2/videobuf2-v4l2.c
> > @@ -337,6 +337,53 @@ static int vb2_fill_vb2_v4l2_buffer(struct vb2_buffer *vb, struct v4l2_buffer *b
> >       return 0;
> >  }
> >
> > +static void set_buffer_cache_hints(struct vb2_queue *q,
> > +                                struct vb2_buffer *vb,
> > +                                struct v4l2_buffer *b)
> > +{
> > +     /*
> > +      * DMA exporter should take care of cache syncs, so we can avoid
> > +      * explicit ->prepare()/->finish() syncs. For other ->memory types
> > +      * we always need ->prepare() or/and ->finish() cache sync.
> > +      */
> > +     if (q->memory == VB2_MEMORY_DMABUF) {
> > +             vb->need_cache_sync_on_finish = 0;
> > +             vb->need_cache_sync_on_prepare = 0;
> > +             return;
> > +     }
> > +
> > +     /*
> > +      * Cache sync/invalidation flags are set by default in order to
> > +      * preserve existing behaviour for old apps/drivers.
> > +      */
> > +     vb->need_cache_sync_on_prepare = 1;
> > +     vb->need_cache_sync_on_finish = 1;
> > +
> > +     if (!vb2_queue_allows_cache_hints(q)) {
> > +             /*
> > +              * Clear buffer cache flags if queue does not support user
> > +              * space hints. That's to indicate to userspace that these
> > +              * flags won't work.
> > +              */
> > +             b->flags &= ~V4L2_BUF_FLAG_NO_CACHE_INVALIDATE;
> > +             b->flags &= ~V4L2_BUF_FLAG_NO_CACHE_CLEAN;
> > +             return;
> > +     }
>
> These two flags need to be cleared for VB2_MEMORY_DMABUF as well in the test above.
> This bug is causing v4l2-compliance failures (use the test-media script in contrib/test
> in v4l-utils: 'sudo test-media vim2m').

Would you be able to paste the failures, so that we know that we
reproduce the same problems? Thanks!

Best regards,
Tomasz

>
> It's enough to post a v6.1 for this patch, everything else is fine.
>
> Regards,
>
>         Hans
>
> > +
> > +     /*
> > +      * ->finish() cache sync can be avoided when queue direction is
> > +      * TO_DEVICE.
> > +      */
> > +     if (q->dma_dir == DMA_TO_DEVICE)
> > +             vb->need_cache_sync_on_finish = 0;
> > +
> > +     if (b->flags & V4L2_BUF_FLAG_NO_CACHE_INVALIDATE)
> > +             vb->need_cache_sync_on_finish = 0;
> > +
> > +     if (b->flags & V4L2_BUF_FLAG_NO_CACHE_CLEAN)
> > +             vb->need_cache_sync_on_prepare = 0;
> > +}
> > +
> >  static int vb2_queue_or_prepare_buf(struct vb2_queue *q, struct media_device *mdev,
> >                                   struct v4l2_buffer *b, bool is_prepare,
> >                                   struct media_request **p_req)
> > @@ -381,6 +428,7 @@ static int vb2_queue_or_prepare_buf(struct vb2_queue *q, struct media_device *md
> >       }
> >
> >       if (!vb->prepared) {
> > +             set_buffer_cache_hints(q, vb, b);
> >               /* Copy relevant information provided by the userspace */
> >               memset(vbuf->planes, 0,
> >                      sizeof(vbuf->planes[0]) * vb->num_planes);
> > diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
> > index 7f39d9fffc8c..ccc5c498d3e3 100644
> > --- a/include/media/videobuf2-core.h
> > +++ b/include/media/videobuf2-core.h
> > @@ -635,6 +635,17 @@ struct vb2_queue {
> >  #endif
> >  };
> >
> > +/**
> > + * vb2_queue_allows_cache_hints() - Return true if the queue allows cache
> > + * and memory consistency hints.
> > + *
> > + * @q:               pointer to &struct vb2_queue with videobuf2 queue
> > + */
> > +static inline bool vb2_queue_allows_cache_hints(struct vb2_queue *q)
> > +{
> > +     return q->allow_cache_hints && q->memory == VB2_MEMORY_MMAP;
> > +}
> > +
> >  /**
> >   * vb2_plane_vaddr() - Return a kernel virtual address of a given plane.
> >   * @vb:              pointer to &struct vb2_buffer to which the plane in
> >
>
Hans Verkuil June 2, 2020, 12:24 p.m. UTC | #7
On 02/06/2020 14:22, Tomasz Figa wrote:
> Hi Hans,
> 
> On Tue, Jun 2, 2020 at 11:51 AM Hans Verkuil <hverkuil@xs4all.nl> wrote:
>>
>> Hi Sergey,
>>
>> While doing final testing for this patch series (together with the v4l-utils patch)
>> I found one remaining issue:
>>
>> On 14/05/2020 18:01, Sergey Senozhatsky wrote:
>>> From: Sergey Senozhatsky <senozhatsky@chromium.org>
>>>
>>> Set video buffer cache management flags corresponding to V4L2 cache
>>> flags.
>>>
>>> Both ->prepare() and ->finish() cache management hints should be
>>> passed during this stage (buffer preparation), because there is
>>> no other way for user-space to tell V4L2 to avoid ->finish() cache
>>> flush.
>>>
>>> Signed-off-by: Sergey Senozhatsky <senozhatsky@chromium.org>
>>> ---
>>>  .../media/common/videobuf2/videobuf2-v4l2.c   | 48 +++++++++++++++++++
>>>  include/media/videobuf2-core.h                | 11 +++++
>>>  2 files changed, 59 insertions(+)
>>>
>>> diff --git a/drivers/media/common/videobuf2/videobuf2-v4l2.c b/drivers/media/common/videobuf2/videobuf2-v4l2.c
>>> index eb5d5db96552..f13851212cc8 100644
>>> --- a/drivers/media/common/videobuf2/videobuf2-v4l2.c
>>> +++ b/drivers/media/common/videobuf2/videobuf2-v4l2.c
>>> @@ -337,6 +337,53 @@ static int vb2_fill_vb2_v4l2_buffer(struct vb2_buffer *vb, struct v4l2_buffer *b
>>>       return 0;
>>>  }
>>>
>>> +static void set_buffer_cache_hints(struct vb2_queue *q,
>>> +                                struct vb2_buffer *vb,
>>> +                                struct v4l2_buffer *b)
>>> +{
>>> +     /*
>>> +      * DMA exporter should take care of cache syncs, so we can avoid
>>> +      * explicit ->prepare()/->finish() syncs. For other ->memory types
>>> +      * we always need ->prepare() or/and ->finish() cache sync.
>>> +      */
>>> +     if (q->memory == VB2_MEMORY_DMABUF) {
>>> +             vb->need_cache_sync_on_finish = 0;
>>> +             vb->need_cache_sync_on_prepare = 0;
>>> +             return;
>>> +     }
>>> +
>>> +     /*
>>> +      * Cache sync/invalidation flags are set by default in order to
>>> +      * preserve existing behaviour for old apps/drivers.
>>> +      */
>>> +     vb->need_cache_sync_on_prepare = 1;
>>> +     vb->need_cache_sync_on_finish = 1;
>>> +
>>> +     if (!vb2_queue_allows_cache_hints(q)) {
>>> +             /*
>>> +              * Clear buffer cache flags if queue does not support user
>>> +              * space hints. That's to indicate to userspace that these
>>> +              * flags won't work.
>>> +              */
>>> +             b->flags &= ~V4L2_BUF_FLAG_NO_CACHE_INVALIDATE;
>>> +             b->flags &= ~V4L2_BUF_FLAG_NO_CACHE_CLEAN;
>>> +             return;
>>> +     }
>>
>> These two flags need to be cleared for VB2_MEMORY_DMABUF as well in the test above.
>> This bug is causing v4l2-compliance failures (use the test-media script in contrib/test
>> in v4l-utils: 'sudo test-media vim2m').
> 
> Would you be able to paste the failures, so that we know that we
> reproduce the same problems? Thanks!

For vim2m (but looks the same for vivid/vimc/vicodec):

Streaming ioctls:
        test read/write: OK (Not Supported)
        test blocking wait: OK
        Video Capture: Captured 8 buffers
        test MMAP (no poll): OK
        Video Capture: Captured 8 buffers
        test MMAP (select): OK
        Video Capture: Captured 8 buffers
        test MMAP (epoll): OK
        Video Capture: Captured 8 buffers
        test USERPTR (no poll): OK
        Video Capture: Captured 8 buffers
        test USERPTR (select): OK
                fail: v4l2-test-buffers.cpp(1874): flags & V4L2_BUF_FLAG_NO_CACHE_INVALIDATE
                fail: v4l2-test-buffers.cpp(1937): setupDmaBuf(expbuf_node, node, q, exp_q)
        test DMABUF (no poll): FAIL
                fail: v4l2-test-buffers.cpp(1874): flags & V4L2_BUF_FLAG_NO_CACHE_INVALIDATE
                fail: v4l2-test-buffers.cpp(1937): setupDmaBuf(expbuf_node, node, q, exp_q)
        test DMABUF (select): FAIL

Regards,

	Hans


> 
> Best regards,
> Tomasz
> 
>>
>> It's enough to post a v6.1 for this patch, everything else is fine.
>>
>> Regards,
>>
>>         Hans
>>
>>> +
>>> +     /*
>>> +      * ->finish() cache sync can be avoided when queue direction is
>>> +      * TO_DEVICE.
>>> +      */
>>> +     if (q->dma_dir == DMA_TO_DEVICE)
>>> +             vb->need_cache_sync_on_finish = 0;
>>> +
>>> +     if (b->flags & V4L2_BUF_FLAG_NO_CACHE_INVALIDATE)
>>> +             vb->need_cache_sync_on_finish = 0;
>>> +
>>> +     if (b->flags & V4L2_BUF_FLAG_NO_CACHE_CLEAN)
>>> +             vb->need_cache_sync_on_prepare = 0;
>>> +}
>>> +
>>>  static int vb2_queue_or_prepare_buf(struct vb2_queue *q, struct media_device *mdev,
>>>                                   struct v4l2_buffer *b, bool is_prepare,
>>>                                   struct media_request **p_req)
>>> @@ -381,6 +428,7 @@ static int vb2_queue_or_prepare_buf(struct vb2_queue *q, struct media_device *md
>>>       }
>>>
>>>       if (!vb->prepared) {
>>> +             set_buffer_cache_hints(q, vb, b);
>>>               /* Copy relevant information provided by the userspace */
>>>               memset(vbuf->planes, 0,
>>>                      sizeof(vbuf->planes[0]) * vb->num_planes);
>>> diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
>>> index 7f39d9fffc8c..ccc5c498d3e3 100644
>>> --- a/include/media/videobuf2-core.h
>>> +++ b/include/media/videobuf2-core.h
>>> @@ -635,6 +635,17 @@ struct vb2_queue {
>>>  #endif
>>>  };
>>>
>>> +/**
>>> + * vb2_queue_allows_cache_hints() - Return true if the queue allows cache
>>> + * and memory consistency hints.
>>> + *
>>> + * @q:               pointer to &struct vb2_queue with videobuf2 queue
>>> + */
>>> +static inline bool vb2_queue_allows_cache_hints(struct vb2_queue *q)
>>> +{
>>> +     return q->allow_cache_hints && q->memory == VB2_MEMORY_MMAP;
>>> +}
>>> +
>>>  /**
>>>   * vb2_plane_vaddr() - Return a kernel virtual address of a given plane.
>>>   * @vb:              pointer to &struct vb2_buffer to which the plane in
>>>
>>
Sergey Senozhatsky June 4, 2020, 4:36 a.m. UTC | #8
On (20/06/02 14:24), Hans Verkuil wrote:
[..]
> For vim2m (but looks the same for vivid/vimc/vicodec):
> 
> Streaming ioctls:
>         test read/write: OK (Not Supported)
>         test blocking wait: OK
>         Video Capture: Captured 8 buffers
>         test MMAP (no poll): OK
>         Video Capture: Captured 8 buffers
>         test MMAP (select): OK
>         Video Capture: Captured 8 buffers
>         test MMAP (epoll): OK
>         Video Capture: Captured 8 buffers
>         test USERPTR (no poll): OK
>         Video Capture: Captured 8 buffers
>         test USERPTR (select): OK
>                 fail: v4l2-test-buffers.cpp(1874): flags & V4L2_BUF_FLAG_NO_CACHE_INVALIDATE
>                 fail: v4l2-test-buffers.cpp(1937): setupDmaBuf(expbuf_node, node, q, exp_q)
>         test DMABUF (no poll): FAIL
>                 fail: v4l2-test-buffers.cpp(1874): flags & V4L2_BUF_FLAG_NO_CACHE_INVALIDATE
>                 fail: v4l2-test-buffers.cpp(1937): setupDmaBuf(expbuf_node, node, q, exp_q)
>         test DMABUF (select): FAIL

This helps. I'm probably "holding v4l2-compliance wrong", but I have
never seen that assertion triggering. The fix should be easy enough

---

diff --git a/utils/v4l2-compliance/v4l2-test-buffers.cpp b/utils/v4l2-compliance/v4l2-test-buffers.cpp
index 79b74e96..1ee12f96 100644
--- a/utils/v4l2-compliance/v4l2-test-buffers.cpp
+++ b/utils/v4l2-compliance/v4l2-test-buffers.cpp
@@ -1871,8 +1871,8 @@ static int setupDmaBuf(struct node *expbuf_node, struct node *node,
 				fail_on_test(!buf.g_bytesused(p));
 		}
 		flags = buf.g_flags();
-		fail_on_test(flags & V4L2_BUF_FLAG_NO_CACHE_INVALIDATE);
-		fail_on_test(flags & V4L2_BUF_FLAG_NO_CACHE_CLEAN);
+		fail_on_test(!(flags & V4L2_BUF_FLAG_NO_CACHE_INVALIDATE));
+		fail_on_test(!(flags & V4L2_BUF_FLAG_NO_CACHE_CLEAN));
 		fail_on_test(flags & V4L2_BUF_FLAG_DONE);
 		fail_on_test(buf.querybuf(node, i));
 		fail_on_test(buf.check(q, Queued, i));
diff mbox series

Patch

diff --git a/drivers/media/common/videobuf2/videobuf2-v4l2.c b/drivers/media/common/videobuf2/videobuf2-v4l2.c
index eb5d5db96552..f13851212cc8 100644
--- a/drivers/media/common/videobuf2/videobuf2-v4l2.c
+++ b/drivers/media/common/videobuf2/videobuf2-v4l2.c
@@ -337,6 +337,53 @@  static int vb2_fill_vb2_v4l2_buffer(struct vb2_buffer *vb, struct v4l2_buffer *b
 	return 0;
 }
 
+static void set_buffer_cache_hints(struct vb2_queue *q,
+				   struct vb2_buffer *vb,
+				   struct v4l2_buffer *b)
+{
+	/*
+	 * DMA exporter should take care of cache syncs, so we can avoid
+	 * explicit ->prepare()/->finish() syncs. For other ->memory types
+	 * we always need ->prepare() or/and ->finish() cache sync.
+	 */
+	if (q->memory == VB2_MEMORY_DMABUF) {
+		vb->need_cache_sync_on_finish = 0;
+		vb->need_cache_sync_on_prepare = 0;
+		return;
+	}
+
+	/*
+	 * Cache sync/invalidation flags are set by default in order to
+	 * preserve existing behaviour for old apps/drivers.
+	 */
+	vb->need_cache_sync_on_prepare = 1;
+	vb->need_cache_sync_on_finish = 1;
+
+	if (!vb2_queue_allows_cache_hints(q)) {
+		/*
+		 * Clear buffer cache flags if queue does not support user
+		 * space hints. That's to indicate to userspace that these
+		 * flags won't work.
+		 */
+		b->flags &= ~V4L2_BUF_FLAG_NO_CACHE_INVALIDATE;
+		b->flags &= ~V4L2_BUF_FLAG_NO_CACHE_CLEAN;
+		return;
+	}
+
+	/*
+	 * ->finish() cache sync can be avoided when queue direction is
+	 * TO_DEVICE.
+	 */
+	if (q->dma_dir == DMA_TO_DEVICE)
+		vb->need_cache_sync_on_finish = 0;
+
+	if (b->flags & V4L2_BUF_FLAG_NO_CACHE_INVALIDATE)
+		vb->need_cache_sync_on_finish = 0;
+
+	if (b->flags & V4L2_BUF_FLAG_NO_CACHE_CLEAN)
+		vb->need_cache_sync_on_prepare = 0;
+}
+
 static int vb2_queue_or_prepare_buf(struct vb2_queue *q, struct media_device *mdev,
 				    struct v4l2_buffer *b, bool is_prepare,
 				    struct media_request **p_req)
@@ -381,6 +428,7 @@  static int vb2_queue_or_prepare_buf(struct vb2_queue *q, struct media_device *md
 	}
 
 	if (!vb->prepared) {
+		set_buffer_cache_hints(q, vb, b);
 		/* Copy relevant information provided by the userspace */
 		memset(vbuf->planes, 0,
 		       sizeof(vbuf->planes[0]) * vb->num_planes);
diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
index 7f39d9fffc8c..ccc5c498d3e3 100644
--- a/include/media/videobuf2-core.h
+++ b/include/media/videobuf2-core.h
@@ -635,6 +635,17 @@  struct vb2_queue {
 #endif
 };
 
+/**
+ * vb2_queue_allows_cache_hints() - Return true if the queue allows cache
+ * and memory consistency hints.
+ *
+ * @q:		pointer to &struct vb2_queue with videobuf2 queue
+ */
+static inline bool vb2_queue_allows_cache_hints(struct vb2_queue *q)
+{
+	return q->allow_cache_hints && q->memory == VB2_MEMORY_MMAP;
+}
+
 /**
  * vb2_plane_vaddr() - Return a kernel virtual address of a given plane.
  * @vb:		pointer to &struct vb2_buffer to which the plane in