Introduce the media device and video device default contexts. Drivers ported to use multi-context support that used to work with a non-context aware userspace (which doesn't call VIDIOC_BIND_CONTEXT) shall continue to work even if they are context aware. Provide a default context in the media device and in the video device structures and let drivers allocate and release them with the newly introduced operations. Bind the video device default context to the default context of the media device associated with the v4l2_dev. Signed-off-by: Jacopo Mondi <jacopo.mondi@xxxxxxxxxxxxxxxx> --- drivers/media/mc/mc-device.c | 11 ++++++++ drivers/media/v4l2-core/v4l2-dev.c | 43 +++++++++++++++++++++++++++++- include/media/media-device.h | 5 ++++ include/media/v4l2-dev.h | 1 + 4 files changed, 59 insertions(+), 1 deletion(-) diff --git a/drivers/media/mc/mc-device.c b/drivers/media/mc/mc-device.c index 1b24d5e74ffb..b4ebe30c21aa 100644 --- a/drivers/media/mc/mc-device.c +++ b/drivers/media/mc/mc-device.c @@ -828,6 +828,16 @@ void media_device_init(struct media_device *mdev) media_set_bus_info(mdev->bus_info, sizeof(mdev->bus_info), mdev->dev); + mdev->default_context = NULL; + if (mdev->ops && + mdev->ops->alloc_context && mdev->ops->destroy_context) { + if (mdev->ops->alloc_context(mdev, &mdev->default_context)) { + dev_err(mdev->dev, + "Failed to initialize media device default context\n"); + return; + } + } + dev_dbg(mdev->dev, "Media device initialized\n"); } EXPORT_SYMBOL_GPL(media_device_init); @@ -836,6 +846,7 @@ void media_device_cleanup(struct media_device *mdev) { WARN_ON(mdev->ops && mdev->ops->release); __media_device_release(mdev); + media_device_context_put(mdev->default_context); media_device_put(mdev); } EXPORT_SYMBOL_GPL(media_device_cleanup); diff --git a/drivers/media/v4l2-core/v4l2-dev.c b/drivers/media/v4l2-core/v4l2-dev.c index 41719b009c1e..73462191fd17 100644 --- a/drivers/media/v4l2-core/v4l2-dev.c +++ b/drivers/media/v4l2-core/v4l2-dev.c @@ -31,6 +31,8 @@ #include <media/v4l2-ioctl.h> #include <media/v4l2-event.h> +#include <media/media-device.h> + #define VIDEO_NUM_DEVICES 256 #define VIDEO_NAME "video4linux" @@ -221,6 +223,12 @@ static void v4l2_device_release(struct device *cd) media_device_put(mdev); #endif + /* Release default context. */ +#ifdef CONFIG_MEDIA_CONTROLLER + video_device_context_put(vdev->default_context); +#endif + vdev->default_context = NULL; + /* Release video_device and perform other cleanups as needed. */ vdev->release(vdev); @@ -1096,7 +1104,36 @@ int __video_register_device(struct video_device *vdev, /* Part 5: Register the entity. */ ret = video_register_media_controller(vdev); - /* Part 6: Activate this minor. The char device can now be used. */ + /* + * Part 6: Complete the video device registration by initializing the + * default context. The defaul context serves for context-aware driver + * to operate with a non-context-aware userspace that never creates + * new contexts. If the video device driver is not context aware, it + * will never implement 'context_ops' and will never use the default + * context. + */ + vdev->default_context = NULL; +#ifdef CONFIG_MEDIA_CONTROLLER + if (vdev->entity.ops && vdev->entity.ops->alloc_context && + vdev->entity.ops->destroy_context) { + ret = vdev->entity.ops->alloc_context(&vdev->entity, + (struct media_entity_context **) + &vdev->default_context); + if (ret) { + pr_err("%s: default context alloc failed\n", __func__); + goto cleanup; + } + + ret = media_device_bind_context(vdev->v4l2_dev->mdev->default_context, + &vdev->default_context->base); + if (ret) { + pr_err("%s: default context bind failed\n", __func__); + goto cleanup; + } + } +#endif + + /* Part 7: Activate this minor. The char device can now be used. */ set_bit(V4L2_FL_REGISTERED, &vdev->flags); mutex_unlock(&videodev_lock); @@ -1104,6 +1141,10 @@ int __video_register_device(struct video_device *vdev, cleanup: mutex_lock(&videodev_lock); +#ifdef CONFIG_MEDIA_CONTROLLER + video_device_context_put(vdev->default_context); +#endif + vdev->default_context = NULL; if (vdev->cdev) cdev_del(vdev->cdev); video_devices[vdev->minor] = NULL; diff --git a/include/media/media-device.h b/include/media/media-device.h index a73f650f122f..74c0a2e1f003 100644 --- a/include/media/media-device.h +++ b/include/media/media-device.h @@ -185,6 +185,9 @@ struct media_device_ops { * @fh_list: List of file handles in the media device * (struct media_device_fh.mdev_list). * @fh_list_lock: Serialise access to fh_list list. + * @default_context: The default video device context. Used by drivers that + * support multi-context operation when operated by a + * non-context aware userspace. * * This structure represents an abstract high-level media device. It allows easy * access to entities and provides basic media device-level support. The @@ -261,6 +264,8 @@ struct media_device { struct list_head fh_list; spinlock_t fh_list_lock; + + struct media_device_context *default_context; }; /* We don't need to include usb.h here */ diff --git a/include/media/v4l2-dev.h b/include/media/v4l2-dev.h index d538f0f32d6d..b79b14e36a2a 100644 --- a/include/media/v4l2-dev.h +++ b/include/media/v4l2-dev.h @@ -282,6 +282,7 @@ struct video_device { struct vb2_queue *queue; + struct video_device_context *default_context; struct v4l2_prio_state *prio; /* device info */ -- 2.46.0