media: v4l2-mem2mem: reorder checks in v4l2_m2m_poll()
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.tretter@pengutronix.de> Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl> [hverkuil-cisco@xs4all.nl: fix checkpatch alignment warning] Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
This commit is contained in:
parent
8d86a15649
commit
7708065f5d
@ -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_for_data(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);
|
||||
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_for_data(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);
|
||||
|
Loading…
Reference in New Issue
Block a user