[PATCH v2 11/27] media: videobuf2-v4l2: Support vb2_queue embedded in a context

John Cox jc at kynesim.co.uk
Thu Aug 20 09:31:31 PDT 2026


> Support device drivers that implement multi-context operations in the
> videobuf2 core by providing an helper to retrieve the vb2_queue from
> the context associated with an open file handle. If no context is
> associated with a file handle, retrieve it from the video device
> default context, created by the core for multi-context aware drivers.
>
> Fall-back to use the vb2_queue from the video_device to support existing
> drivers which are not context aware.
>
> Signed-off-by: Jacopo Mondi <jacopo.mondi at ideasonboard.com>
> ---
>  drivers/media/common/videobuf2/videobuf2-v4l2.c | 139 +++++++++++++++---------
>  1 file changed, 88 insertions(+), 51 deletions(-)
>
> diff --git a/drivers/media/common/videobuf2/videobuf2-v4l2.c b/drivers/media/common/videobuf2/videobuf2-v4l2.c
> index 1cd26faee50338aefeb670c6865da7c2d43f44d3..ad7892551f54c5abc7db7641bb8fb89d77b1337f 100644
> --- a/drivers/media/common/videobuf2/videobuf2-v4l2.c
> +++ b/drivers/media/common/videobuf2/videobuf2-v4l2.c
> @@ -998,23 +998,46 @@ EXPORT_SYMBOL_GPL(vb2_poll);
>   * and so they simplify the driver code.
>   */
>
> +/*
> + * Helper to get the vb2 queue either from:
> + * 1) The video context bound to the open file handle
> + * 2) The default context for context-aware drivers if userspace has not bound
> + *    a context to the file handle
> + * 3) From the video device for non-context aware drivers
> + */
> +static struct vb2_queue *get_vb2_queue(struct file *file,
> +                                      struct video_device *vdev)
> +{
> +#if defined(CONFIG_MEDIA_CONTROLLER)
> +       struct video_device_context *ctx =
> +                               video_device_context_from_file(file, vdev);
> +
> +       return ctx ? &ctx->queue
> +                  : vdev->default_context ? &vdev->default_context->queue
> +                  : vdev->queue;
> +#else
> +       return vdev->queue;
> +#endif /* CONFIG_MEDIA_CONTROLLER */
> +}
> +
>  /* vb2 ioctl helpers */
>
>  int vb2_ioctl_remove_bufs(struct file *file, void *priv,
>                           struct v4l2_remove_buffers *d)
>  {
>         struct video_device *vdev = video_devdata(file);
> +       struct vb2_queue *q = get_vb2_queue(file, vdev);
>
> -       if (vdev->queue->type != d->type)
> +       if (q->type != d->type)
>                 return -EINVAL;
>
>         if (d->count == 0)
>                 return 0;
>
> -       if (vb2_queue_is_busy(vdev->queue, file))
> +       if (vb2_queue_is_busy(q, file))
>                 return -EBUSY;
>
> -       return vb2_core_remove_bufs(vdev->queue, d->index, d->count);
> +       return vb2_core_remove_bufs(q, d->index, d->count);
>  }
>  EXPORT_SYMBOL_GPL(vb2_ioctl_remove_bufs);
>
> @@ -1022,21 +1045,21 @@ int vb2_ioctl_reqbufs(struct file *file, void *priv,
>                           struct v4l2_requestbuffers *p)
>  {
>         struct video_device *vdev = video_devdata(file);
> -       int res = vb2_verify_memory_type(vdev->queue, p->memory, p->type);
> +       struct vb2_queue *q = get_vb2_queue(file, vdev);
> +       int res = vb2_verify_memory_type(q, p->memory, p->type);
>         u32 flags = p->flags;
>
> -       vb2_set_flags_and_caps(vdev->queue, p->memory, &flags,
> -                              &p->capabilities, NULL);
> +       vb2_set_flags_and_caps(q, p->memory, &flags, &p->capabilities, NULL);
>         p->flags = flags;
>         if (res)
>                 return res;
> -       if (vb2_queue_is_busy(vdev->queue, file))
> +       if (vb2_queue_is_busy(q, file))
>                 return -EBUSY;
> -       res = vb2_core_reqbufs(vdev->queue, p->memory, p->flags, &p->count);
> +       res = vb2_core_reqbufs(q, p->memory, p->flags, &p->count);
>         /* If count == 0, then the owner has released all buffers and he
>            is no longer owner of the queue. Otherwise we have a new owner. */
>         if (res == 0)
> -               vdev->queue->owner = p->count ? file->private_data : NULL;
> +               q->owner = p->count ? file->private_data : NULL;
>         return res;
>  }
>  EXPORT_SYMBOL_GPL(vb2_ioctl_reqbufs);
> @@ -1045,11 +1068,12 @@ int vb2_ioctl_create_bufs(struct file *file, void *priv,
>                           struct v4l2_create_buffers *p)
>  {
>         struct video_device *vdev = video_devdata(file);
> -       int res = vb2_verify_memory_type(vdev->queue, p->memory, p->format.type);
> +       struct vb2_queue *q = get_vb2_queue(file, vdev);
> +       int res = vb2_verify_memory_type(q, p->memory, p->format.type);
>
> -       p->index = vb2_get_num_buffers(vdev->queue);
> -       vb2_set_flags_and_caps(vdev->queue, p->memory, &p->flags,
> -                              &p->capabilities, &p->max_num_buffers);
> +       p->index = vb2_get_num_buffers(q);
> +       vb2_set_flags_and_caps(q, p->memory, &p->flags, &p->capabilities,
> +                              &p->max_num_buffers);
>         /*
>          * If count == 0, then just check if memory and type are valid.
>          * Any -EBUSY result from vb2_verify_memory_type can be mapped to 0.
> @@ -1058,12 +1082,12 @@ int vb2_ioctl_create_bufs(struct file *file, void *priv,
>                 return res != -EBUSY ? res : 0;
>         if (res)
>                 return res;
> -       if (vb2_queue_is_busy(vdev->queue, file))
> +       if (vb2_queue_is_busy(q, file))
>                 return -EBUSY;
>
> -       res = vb2_create_bufs(vdev->queue, p);
> +       res = vb2_create_bufs(q, p);
>         if (res == 0)
> -               vdev->queue->owner = file->private_data;
> +               q->owner = file->private_data;
>         return res;
>  }
>  EXPORT_SYMBOL_GPL(vb2_ioctl_create_bufs);
> @@ -1072,69 +1096,76 @@ int vb2_ioctl_prepare_buf(struct file *file, void *priv,
>                           struct v4l2_buffer *p)
>  {
>         struct video_device *vdev = video_devdata(file);
> +       struct vb2_queue *q = get_vb2_queue(file, vdev);
>
> -       if (vb2_queue_is_busy(vdev->queue, file))
> +       if (vb2_queue_is_busy(q, file))
>                 return -EBUSY;
> -       return vb2_prepare_buf(vdev->queue, vdev->v4l2_dev->mdev, p);
> +       return vb2_prepare_buf(q, vdev->v4l2_dev->mdev, p);
>  }
>  EXPORT_SYMBOL_GPL(vb2_ioctl_prepare_buf);
>
>  int vb2_ioctl_querybuf(struct file *file, void *priv, struct v4l2_buffer *p)
>  {
>         struct video_device *vdev = video_devdata(file);
> +       struct vb2_queue *q = get_vb2_queue(file, vdev);
>
>         /* No need to call vb2_queue_is_busy(), anyone can query buffers. */
> -       return vb2_querybuf(vdev->queue, p);
> +       return vb2_querybuf(q, p);
>  }
>  EXPORT_SYMBOL_GPL(vb2_ioctl_querybuf);
>
>  int vb2_ioctl_qbuf(struct file *file, void *priv, struct v4l2_buffer *p)
>  {
>         struct video_device *vdev = video_devdata(file);
> +       struct vb2_queue *q = get_vb2_queue(file, vdev);
>
> -       if (vb2_queue_is_busy(vdev->queue, file))
> +       if (vb2_queue_is_busy(q, file))
>                 return -EBUSY;
> -       return vb2_qbuf(vdev->queue, vdev->v4l2_dev->mdev, p);
> +       return vb2_qbuf(q, vdev->v4l2_dev->mdev, p);
>  }
>  EXPORT_SYMBOL_GPL(vb2_ioctl_qbuf);
>
>  int vb2_ioctl_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p)
>  {
>         struct video_device *vdev = video_devdata(file);
> +       struct vb2_queue *q = get_vb2_queue(file, vdev);
>
> -       if (vb2_queue_is_busy(vdev->queue, file))
> +       if (vb2_queue_is_busy(q, file))
>                 return -EBUSY;
> -       return vb2_dqbuf(vdev->queue, p, file->f_flags & O_NONBLOCK);
> +       return vb2_dqbuf(q, p, file->f_flags & O_NONBLOCK);
>  }
>  EXPORT_SYMBOL_GPL(vb2_ioctl_dqbuf);
>
>  int vb2_ioctl_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
>  {
>         struct video_device *vdev = video_devdata(file);
> +       struct vb2_queue *q = get_vb2_queue(file, vdev);
>
> -       if (vb2_queue_is_busy(vdev->queue, file))
> +       if (vb2_queue_is_busy(q, file))
>                 return -EBUSY;
> -       return vb2_streamon(vdev->queue, i);
> +       return vb2_streamon(q, i);
>  }
>  EXPORT_SYMBOL_GPL(vb2_ioctl_streamon);
>
>  int vb2_ioctl_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
>  {
>         struct video_device *vdev = video_devdata(file);
> +       struct vb2_queue *q = get_vb2_queue(file, vdev);
>
> -       if (vb2_queue_is_busy(vdev->queue, file))
> +       if (vb2_queue_is_busy(q, file))
>                 return -EBUSY;
> -       return vb2_streamoff(vdev->queue, i);
> +       return vb2_streamoff(q, i);
>  }
>  EXPORT_SYMBOL_GPL(vb2_ioctl_streamoff);
>
>  int vb2_ioctl_expbuf(struct file *file, void *priv, struct v4l2_exportbuffer *p)
>  {
>         struct video_device *vdev = video_devdata(file);
> +       struct vb2_queue *q = get_vb2_queue(file, vdev);
>
> -       if (vb2_queue_is_busy(vdev->queue, file))
> +       if (vb2_queue_is_busy(q, file))
>                 return -EBUSY;
> -       return vb2_expbuf(vdev->queue, p);
> +       return vb2_expbuf(q, p);
>  }
>  EXPORT_SYMBOL_GPL(vb2_ioctl_expbuf);
>
> @@ -1143,20 +1174,22 @@ EXPORT_SYMBOL_GPL(vb2_ioctl_expbuf);
>  int vb2_fop_mmap(struct file *file, struct vm_area_struct *vma)
>  {
>         struct video_device *vdev = video_devdata(file);
> +       struct vb2_queue *q = get_vb2_queue(file, vdev);
>
> -       return vb2_mmap(vdev->queue, vma);
> +       return vb2_mmap(q, vma);
>  }
>  EXPORT_SYMBOL_GPL(vb2_fop_mmap);
>
>  int _vb2_fop_release(struct file *file, struct mutex *lock)
>  {
>         struct video_device *vdev = video_devdata(file);
> +       struct vb2_queue *q = get_vb2_queue(file, vdev);
>
>         if (lock)
>                 mutex_lock(lock);
> -       if (!vdev->queue->owner || file->private_data == vdev->queue->owner) {
> -               vb2_queue_release(vdev->queue);
> -               vdev->queue->owner = NULL;
> +       if (!q->owner || file->private_data == q->owner) {
> +               vb2_queue_release(q);
> +               q->owner = NULL;
>         }
>         if (lock)
>                 mutex_unlock(lock);
> @@ -1167,7 +1200,8 @@ EXPORT_SYMBOL_GPL(_vb2_fop_release);
>  int vb2_fop_release(struct file *file)
>  {
>         struct video_device *vdev = video_devdata(file);
> -       struct mutex *lock = vdev->queue->lock ? vdev->queue->lock : vdev->lock;
> +       struct vb2_queue *q = get_vb2_queue(file, vdev);
> +       struct mutex *lock = q->lock ? q->lock : vdev->lock;
>
>         return _vb2_fop_release(file, lock);
>  }
> @@ -1177,19 +1211,20 @@ ssize_t vb2_fop_write(struct file *file, const char __user *buf,
>                 size_t count, loff_t *ppos)
>  {
>         struct video_device *vdev = video_devdata(file);
> -       struct mutex *lock = vdev->queue->lock ? vdev->queue->lock : vdev->lock;
> +       struct vb2_queue *q = get_vb2_queue(file, vdev);
> +       struct mutex *lock = q->lock ? q->lock : vdev->lock;
>         int err = -EBUSY;
>
> -       if (!(vdev->queue->io_modes & VB2_WRITE))
> +       if (!(q->io_modes & VB2_WRITE))
>                 return -EINVAL;
>         if (lock && mutex_lock_interruptible(lock))
>                 return -ERESTARTSYS;
> -       if (vb2_queue_is_busy(vdev->queue, file))
> +       if (vb2_queue_is_busy(q, file))
>                 goto exit;
> -       err = vb2_write(vdev->queue, buf, count, ppos,
> -                      file->f_flags & O_NONBLOCK);
> -       if (vdev->queue->fileio)
> -               vdev->queue->owner = file->private_data;
> +       err = vb2_write(q, buf, count, ppos,
> +                       file->f_flags & O_NONBLOCK);
> +       if (q->fileio)
> +               q->owner = file->private_data;
>  exit:
>         if (lock)
>                 mutex_unlock(lock);
> @@ -1201,20 +1236,21 @@ ssize_t vb2_fop_read(struct file *file, char __user *buf,
>                 size_t count, loff_t *ppos)
>  {
>         struct video_device *vdev = video_devdata(file);
> -       struct mutex *lock = vdev->queue->lock ? vdev->queue->lock : vdev->lock;
> +       struct vb2_queue *q = get_vb2_queue(file, vdev);
> +       struct mutex *lock = q->lock ? q->lock : vdev->lock;
>         int err = -EBUSY;
>
> -       if (!(vdev->queue->io_modes & VB2_READ))
> +       if (!(q->io_modes & VB2_READ))
>                 return -EINVAL;
>         if (lock && mutex_lock_interruptible(lock))
>                 return -ERESTARTSYS;
> -       if (vb2_queue_is_busy(vdev->queue, file))
> +       if (vb2_queue_is_busy(q, file))
>                 goto exit;
> -       vdev->queue->owner = file->private_data;
> -       err = vb2_read(vdev->queue, buf, count, ppos,
> +       q->owner = file->private_data;
> +       err = vb2_read(q, buf, count, ppos,
>                        file->f_flags & O_NONBLOCK);
> -       if (!vdev->queue->fileio)
> -               vdev->queue->owner = NULL;
> +       if (!q->fileio)
> +               q->owner = NULL;
>  exit:
>         if (lock)
>                 mutex_unlock(lock);
> @@ -1225,7 +1261,7 @@ EXPORT_SYMBOL_GPL(vb2_fop_read);
>  __poll_t vb2_fop_poll(struct file *file, poll_table *wait)
>  {
>         struct video_device *vdev = video_devdata(file);
> -       struct vb2_queue *q = vdev->queue;
> +       struct vb2_queue *q = get_vb2_queue(file, vdev);
>         struct mutex *lock = q->lock ? q->lock : vdev->lock;
>         __poll_t res;
>         void *fileio;
> @@ -1241,7 +1277,7 @@ __poll_t vb2_fop_poll(struct file *file, poll_table *wait)
>
>         fileio = q->fileio;
>
> -       res = vb2_poll(vdev->queue, file, wait);
> +       res = vb2_poll(q, file, wait);
>
>         /* If fileio was started, then we have a new queue owner. */
>         if (!fileio && q->fileio)
> @@ -1257,8 +1293,9 @@ unsigned long vb2_fop_get_unmapped_area(struct file *file, unsigned long addr,
>                 unsigned long len, unsigned long pgoff, unsigned long flags)
>  {
>         struct video_device *vdev = video_devdata(file);
> +       struct vb2_queue *q = get_vb2_queue(file, vdev);
>
> -       return vb2_get_unmapped_area(vdev->queue, addr, len, pgoff, flags);
> +       return vb2_get_unmapped_area(q, addr, len, pgoff, flags);
>  }
>  EXPORT_SYMBOL_GPL(vb2_fop_get_unmapped_area);
>  #endif

You need similar logic in v4l2-ioctl.c to retrieve the correct queue from
a video_device and v4l2_fh so v4l2_ioctl_get_lock retrieves the correct
lock.

Regards

John Cox



More information about the linux-arm-kernel mailing list