[PATCH 15/26] media: v4l2_subdev: Introduce default context
Jacopo Mondi
jacopo.mondi at ideasonboard.com
Thu Jul 17 03:45:41 PDT 2025
Introduce a default context for v4l2 subdvice.
Drivers ported to use multi-context support that used to work with a
non-context aware userspace (which doesn't call VIDIOC_SUBDEV_BIND_CONTEXT)
shall continue to work even if they are context aware.
Provide a default context in the v4l2 subdev and bind it to the media
device default context when the subdevice is fully registered by
providing a v4l2_subdev_registered() function.
Release the context when the subdevice gets unregistered by the core,
providing a v4l2_subdev_unregistered() helper.
Signed-off-by: Jacopo Mondi <jacopo.mondi at ideasonboard.com>
---
drivers/media/v4l2-core/v4l2-device.c | 11 +++-----
drivers/media/v4l2-core/v4l2-subdev.c | 50 +++++++++++++++++++++++++++++++++++
include/media/v4l2-subdev.h | 29 ++++++++++++++++++++
3 files changed, 83 insertions(+), 7 deletions(-)
diff --git a/drivers/media/v4l2-core/v4l2-device.c b/drivers/media/v4l2-core/v4l2-device.c
index 5e537454f5cd71b3c50a2a2864642f7d5548047b..bf3ebd77b7bb8b13c849a89d01e6d889e8a2e4fd 100644
--- a/drivers/media/v4l2-core/v4l2-device.c
+++ b/drivers/media/v4l2-core/v4l2-device.c
@@ -146,11 +146,9 @@ int __v4l2_device_register_subdev(struct v4l2_device *v4l2_dev,
}
#endif
- if (sd->internal_ops && sd->internal_ops->registered) {
- err = sd->internal_ops->registered(sd);
- if (err)
- goto error_unregister;
- }
+ err = v4l2_subdev_registered(sd);
+ if (err)
+ goto error_unregister;
sd->owner = module;
@@ -274,8 +272,7 @@ void v4l2_device_unregister_subdev(struct v4l2_subdev *sd)
list_del(&sd->list);
spin_unlock(&v4l2_dev->lock);
- if (sd->internal_ops && sd->internal_ops->unregistered)
- sd->internal_ops->unregistered(sd);
+ v4l2_subdev_unregistered(sd);
sd->v4l2_dev = NULL;
#if defined(CONFIG_MEDIA_CONTROLLER)
diff --git a/drivers/media/v4l2-core/v4l2-subdev.c b/drivers/media/v4l2-core/v4l2-subdev.c
index 300f84317623dd082a4cd2caec97057f972e82a3..438f51980e5ac0f092ba6b0a979a376133968ddf 100644
--- a/drivers/media/v4l2-core/v4l2-subdev.c
+++ b/drivers/media/v4l2-core/v4l2-subdev.c
@@ -1275,6 +1275,56 @@ const struct v4l2_file_operations v4l2_subdev_fops = {
.poll = subdev_poll,
};
+#ifdef CONFIG_MEDIA_CONTROLLER
+static int v4l2_subdev_register_default_context(struct v4l2_subdev *sd)
+{
+ struct media_device_context *mdev_context;
+
+ /* If the driver does not support contexts, return here. */
+ if (!sd->entity.ops || !sd->entity.ops->alloc_context ||
+ !sd->entity.ops->destroy_context)
+ return 0;
+
+ mdev_context = sd->entity.graph_obj.mdev->default_context;
+ return subdev_do_bind_context(sd, &sd->default_context, mdev_context);
+}
+#endif /* CONFIG_MEDIA_CONTROLLER */
+
+int v4l2_subdev_registered(struct v4l2_subdev *sd)
+{
+ int ret;
+
+#ifdef CONFIG_MEDIA_CONTROLLER
+ ret = v4l2_subdev_register_default_context(sd);
+ if (ret)
+ return ret;
+#endif /* CONFIG_MEDIA_CONTROLLER */
+
+ if (sd->internal_ops && sd->internal_ops->registered) {
+ ret = sd->internal_ops->registered(sd);
+ if (ret)
+ goto err_registered;
+ }
+
+ return 0;
+
+err_registered:
+ if (sd->default_context)
+ v4l2_subdev_context_put(sd->default_context);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(v4l2_subdev_registered);
+
+void v4l2_subdev_unregistered(struct v4l2_subdev *sd)
+{
+ if (sd->default_context)
+ v4l2_subdev_context_put(sd->default_context);
+
+ if (sd->internal_ops && sd->internal_ops->unregistered)
+ sd->internal_ops->unregistered(sd);
+}
+EXPORT_SYMBOL_GPL(v4l2_subdev_unregistered);
+
#ifdef CONFIG_MEDIA_CONTROLLER
int v4l2_subdev_get_fwnode_pad_1_to_1(struct media_entity *entity,
diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h
index 9d257b859acafb11cfe6976e906e7baabd0206f6..1fa42a9f322be0be44fc9308744f4f4ae0cf1606 100644
--- a/include/media/v4l2-subdev.h
+++ b/include/media/v4l2-subdev.h
@@ -1130,6 +1130,10 @@ struct v4l2_subdev_platform_data {
* @active_state: Active state for the subdev (NULL for subdevs tracking the
* state internally). Initialized by calling
* v4l2_subdev_init_finalize().
+ * @default_context: Default context for the subdev, allows to operate
+ * context-aware drivers with a context-unaware userspace.
+ * It is initialized when the subdev is registered in
+ * v4l2_subdev_registered().
* @enabled_pads: Bitmask of enabled pads used by v4l2_subdev_enable_streams()
* and v4l2_subdev_disable_streams() helper functions for
* fallback cases.
@@ -1182,6 +1186,7 @@ struct v4l2_subdev {
* doesn't support it.
*/
struct v4l2_subdev_state *active_state;
+ struct v4l2_subdev_context *default_context;
u64 enabled_pads;
bool s_stream_enabled;
};
@@ -1286,6 +1291,30 @@ static inline void *v4l2_get_subdev_hostdata(const struct v4l2_subdev *sd)
return sd->host_priv;
}
+/**
+ * v4l2_subdev_registered - Subdevice registered notification
+ *
+ * @sd: The subdevice that has been registered
+ *
+ * Notify that a subdevice has been registered by the core. This function wraps
+ * a call to sd->internal_ops->registered (if available) and instantiates the
+ * default v4l2 subdevice context.
+ *
+ * Returns 0 on success, a negative error code otherwise.
+ */
+int v4l2_subdev_registered(struct v4l2_subdev *sd);
+
+/**
+ * v4l2_subdev_unregistered - Subdevice unregistered notification
+ *
+ * @sd: The subdevice that has been unregistered
+ *
+ * Notify that a subdevice has been unregistered by the core. This function
+ * wraps a call to sd->internal_ops->unregistered (if available) and deletes
+ * the default v4l2 subdevice context.
+ */
+void v4l2_subdev_unregistered(struct v4l2_subdev *sd);
+
#ifdef CONFIG_MEDIA_CONTROLLER
/**
--
2.49.0
More information about the linux-arm-kernel
mailing list