On 6/25/19 4:11 PM, Michael Tretter wrote:
> When reaching the end of stream, V4L2 m2m clients may expect the
> V4L2_EOS_EVENT. Although the V4L2_EOS_EVENT is deprecated behavior,
> drivers must signal that event before dequeuing the buffer that has the
> V4L2_BUF_FLAG_LAST flag set.
> 
> If a driver queues the V4L2_EOS_EVENT event and returns the buffer after
> the check for events but before the check for buffers, vb2_m2m_poll()
> will signal that the buffer with V4L2_BUF_FLAG_LAST can be read but not
> that the V4L2_EOS_EVENT is available.
> 
> Split the check for buffers into a separate function and check for
> available buffers before checking for events. This ensures that if
> vb2_m2m_poll() signals POLLIN | POLLRDNORM for the V4L2_BUF_FLAG_LAST
> buffer, it signals POLLPRI for the V4L2_EOS_EVENT, too.
> 
> Signed-off-by: Michael Tretter <m.tret...@pengutronix.de>
> ---
>  drivers/media/v4l2-core/v4l2-mem2mem.c | 47 +++++++++++++++-----------
>  1 file changed, 27 insertions(+), 20 deletions(-)
> 
> diff --git a/drivers/media/v4l2-core/v4l2-mem2mem.c 
> b/drivers/media/v4l2-core/v4l2-mem2mem.c
> index 4f5176702937..f18fdce31d6f 100644
> --- a/drivers/media/v4l2-core/v4l2-mem2mem.c
> +++ b/drivers/media/v4l2-core/v4l2-mem2mem.c
> @@ -603,11 +603,10 @@ int v4l2_m2m_streamoff(struct file *file, struct 
> v4l2_m2m_ctx *m2m_ctx,
>  }
>  EXPORT_SYMBOL_GPL(v4l2_m2m_streamoff);
>  
> -__poll_t v4l2_m2m_poll(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
> -                        struct poll_table_struct *wait)
> +static __poll_t __v4l2_m2m_poll(struct file *file,
> +                             struct v4l2_m2m_ctx *m2m_ctx,
> +                             struct poll_table_struct *wait)

I agree with the patch, except for this function name.

How about: v4l2_m2m_poll_for_data() or something along those lines?

Regards,

        Hans

>  {
> -     struct video_device *vfd = video_devdata(file);
> -     __poll_t req_events = poll_requested_events(wait);
>       struct vb2_queue *src_q, *dst_q;
>       struct vb2_buffer *src_vb = NULL, *dst_vb = NULL;
>       __poll_t rc = 0;
> @@ -619,16 +618,6 @@ __poll_t v4l2_m2m_poll(struct file *file, struct 
> v4l2_m2m_ctx *m2m_ctx,
>       poll_wait(file, &src_q->done_wq, wait);
>       poll_wait(file, &dst_q->done_wq, wait);
>  
> -     if (test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags)) {
> -             struct v4l2_fh *fh = file->private_data;
> -
> -             poll_wait(file, &fh->wait, wait);
> -             if (v4l2_event_pending(fh))
> -                     rc = EPOLLPRI;
> -             if (!(req_events & (EPOLLOUT | EPOLLWRNORM | EPOLLIN | 
> EPOLLRDNORM)))
> -                     return rc;
> -     }
> -
>       /*
>        * There has to be at least one buffer queued on each queued_list, which
>        * means either in driver already or waiting for driver to claim it
> @@ -637,10 +626,8 @@ __poll_t v4l2_m2m_poll(struct file *file, struct 
> v4l2_m2m_ctx *m2m_ctx,
>       if ((!src_q->streaming || src_q->error ||
>            list_empty(&src_q->queued_list)) &&
>           (!dst_q->streaming || dst_q->error ||
> -          list_empty(&dst_q->queued_list))) {
> -             rc |= EPOLLERR;
> -             goto end;
> -     }
> +          list_empty(&dst_q->queued_list)))
> +             return EPOLLERR;
>  
>       spin_lock_irqsave(&dst_q->done_lock, flags);
>       if (list_empty(&dst_q->done_list)) {
> @@ -650,7 +637,7 @@ __poll_t v4l2_m2m_poll(struct file *file, struct 
> v4l2_m2m_ctx *m2m_ctx,
>                */
>               if (dst_q->last_buffer_dequeued) {
>                       spin_unlock_irqrestore(&dst_q->done_lock, flags);
> -                     return rc | EPOLLIN | EPOLLRDNORM;
> +                     return EPOLLIN | EPOLLRDNORM;
>               }
>       }
>       spin_unlock_irqrestore(&dst_q->done_lock, flags);
> @@ -673,7 +660,27 @@ __poll_t v4l2_m2m_poll(struct file *file, struct 
> v4l2_m2m_ctx *m2m_ctx,
>               rc |= EPOLLIN | EPOLLRDNORM;
>       spin_unlock_irqrestore(&dst_q->done_lock, flags);
>  
> -end:
> +     return rc;
> +}
> +
> +__poll_t v4l2_m2m_poll(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
> +                        struct poll_table_struct *wait)
> +{
> +     struct video_device *vfd = video_devdata(file);
> +     __poll_t req_events = poll_requested_events(wait);
> +     __poll_t rc = 0;
> +
> +     if (req_events & (EPOLLOUT | EPOLLWRNORM | EPOLLIN | EPOLLRDNORM))
> +             rc = __v4l2_m2m_poll(file, m2m_ctx, wait);
> +
> +     if (test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags)) {
> +             struct v4l2_fh *fh = file->private_data;
> +
> +             poll_wait(file, &fh->wait, wait);
> +             if (v4l2_event_pending(fh))
> +                     rc |= EPOLLPRI;
> +     }
> +
>       return rc;
>  }
>  EXPORT_SYMBOL_GPL(v4l2_m2m_poll);
> 

Reply via email to