Re: [PATCH v2 12/27] media: v4l2-subdev: Introduce v4l2 subdev context

John Cox <[email protected]>
Newsgroups org.kernel.vger.linux-media,org.infradead.lists.linux-arm-kernel,org.kernel.vger.linux-kernel
Message-ID <CAFyCYyOPESG6TJaUBdWE28BRxwems_EQsvhMP08LbN8D=sYAWw@mail.gmail.com>
> Introduce a new type in v4l2 subdev that represents a v4l2 subdevice
> contex. It extends 'struct media_entity_context' and is intended to be
> extended by drivers that can store driver-specific information
> in their derived types.
>
> Signed-off-by: Jacopo Mondi <[email protected]>
> ---
>  drivers/media/v4l2-core/v4l2-subdev.c |  39 +++++++++++
>  include/media/v4l2-subdev.h           | 126 ++++++++++++++++++++++++++++++++++
>  2 files changed, 165 insertions(+)
>
> diff --git a/drivers/media/v4l2-core/v4l2-subdev.c b/drivers/media/v4l2-core/v4l2-subdev.c
> index 4fd25fea3b58477056729665706ddbacc436379c..7307f57439499c8d5360c89f492944828ac23973 100644
> --- a/drivers/media/v4l2-core/v4l2-subdev.c
> +++ b/drivers/media/v4l2-core/v4l2-subdev.c
> @@ -1577,6 +1577,45 @@ bool v4l2_subdev_has_pad_interdep(struct media_entity *entity,
>  }
>  EXPORT_SYMBOL_GPL(v4l2_subdev_has_pad_interdep);
>
> +struct v4l2_subdev_context *
> +v4l2_subdev_context_get(struct media_device_context *mdev_context,
> +                       struct v4l2_subdev *sd)
> +{
> +       struct media_entity *entity = &sd->entity;
> +       struct media_entity_context *ctx =
> +                media_device_get_entity_context(mdev_context, entity);
> +
> +       if (!ctx)
This needs to be "if (IS_ERR_OR_NULL(ctx))" as media_device_get_entity_context()
can return an error pointer.

Regards

John Cox

> +               return NULL;
> +
> +       return container_of(ctx, struct v4l2_subdev_context, base);
> +}
> +EXPORT_SYMBOL_GPL(v4l2_subdev_context_get);
> +
> +void v4l2_subdev_context_put(struct v4l2_subdev_context *ctx)
> +{
> +       if (!ctx)
> +               return;
> +
> +       media_entity_context_put(&ctx->base);
> +}
> +EXPORT_SYMBOL_GPL(v4l2_subdev_context_put);
> +
> +int v4l2_subdev_init_context(struct v4l2_subdev *sd,
> +                            struct v4l2_subdev_context *context)
> +{
> +       media_entity_init_context(&sd->entity, &context->base);
> +
> +       return 0;
> +}
> +EXPORT_SYMBOL_GPL(v4l2_subdev_init_context);
> +
> +void v4l2_subdev_cleanup_context(struct v4l2_subdev_context *context)
> +{
> +       media_entity_cleanup_context(&context->base);
> +}
> +EXPORT_SYMBOL_GPL(v4l2_subdev_cleanup_context);
> +
>  struct v4l2_subdev_state *
>  __v4l2_subdev_state_alloc(struct v4l2_subdev *sd, const char *lock_name,
>                           struct lock_class_key *lock_key)
> diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h
> index 5dcf4065708f32e7d3b5da003771810d5f7973b8..9d257b859acafb11cfe6976e906e7baabd0206f6 100644
> --- a/include/media/v4l2-subdev.h
> +++ b/include/media/v4l2-subdev.h
> @@ -757,6 +757,78 @@ struct v4l2_subdev_state {
>         struct v4l2_subdev_stream_configs stream_configs;
>  };
>
> +/**
> + * struct v4l2_subdev_context - The v4l2 subdevice context
> + * @base: The media entity context base class member
> + * @state: The subdevice state associated with this context
> + *
> + * This structure represents an isolated execution context of a subdevice.
> + * This type 'derives' the base 'struct media_entity_context' type which
> + * implements refcounting on our behalf and allows instances of this type to be
> + * linked in the media_device_context contexts list.
> + *
> + * The subdevice context stores the subdev state in a per-file handle context,
> + * userspace is allowed to multiplex the usage of a subdevice devnode by opening
> + * it multiple times and by associating it with a media device context. This
> + * operation is called 'bounding' and is performed using the
> + * VIDIOC_SUBDEV_BIND_CONTEXT ioctl.
> + *
> + * A subdevice context is created and stored in the v4l2_fh file handle
> + * associated with an open file descriptor when a subdevice is 'bound' to a
> + * media device context. The 'bounding' operation realizes a permanent
> + * association valid until the subdevice context is released.
> + *
> + * A subdevice can be bound to the same media device context once only.
> + * Trying to bind the same subdevice to the same media device context a
> + * second time, without releasing the already established context by closing the
> + * bound file descriptor first, will result in an error.
> + *
> + * To create a subdevice context userspace shall use the
> + * VIDIOC_SUBDEV_BIND_CONTEXT ioctl that creates the subdevice context and
> + * uniquely associates it with a media device file descriptor.
> + *
> + * Once a subdevice file descriptor has been bound to a media device context,
> + * all the operations performed on the subdevice file descriptor will be
> + * directed on the just created subdevice context. This means, in example, that
> + * the subdevice state and configuration is isolated from the ones associated
> + * with a different file descriptor obtained by opening again the same subdevice
> + * devnode but bound to a different media device context.
> + *
> + * Drivers that implement multiplexing support have to provide a valid
> + * implementation of the context-related operations in the media entity
> + * operations.
> + *
> + * Drivers are allowed to sub-class the v4l2_subdevice_context structure by
> + * defining a driver-specific type which embeds a struct v4l2_subdevice_context
> + * instance as first member, and allocate the driver-specific structure size in
> + * their implementation of the `alloc_context` operation.
> + *
> + * Subdevice contexts are ref-counted by embedding an instance of 'struct
> + * media_entity_context' and are freed once all the references to it are
> + * released.
> + *
> + * A subdevice context ref-count is increased when:
> + * - The context is created by bounding a video device to a media device context
> + * - The media pipeline it is part of starts streaming
> + * A subdevice context ref-count is decreased when:
> + * - The associated file handle is closed
> + * - The media pipeline it is part of stops streaming
> + *
> + * The ref-count is increased by a call to v4l2_subdev_context_get() and is
> + * reponsibility of the caller to decrease the reference count with a call to
> + * v4l2_subdev_context_put().
> + */
> +struct v4l2_subdev_context {
> +       struct media_entity_context base;
> +       /*
> +        * TODO: active_state should most likely be changed from a pointer to an
> +        * embedded field. For the time being it's kept as a pointer to more
> +        * easily catch uses of active_state in the cases where the driver
> +        * doesn't support it.
> +        */
> +       struct v4l2_subdev_state *state;
> +};
> +
>  /**
>   * struct v4l2_subdev_pad_ops - v4l2-subdev pad level operations
>   *
> @@ -1152,6 +1224,7 @@ struct v4l2_subdev_fh {
>         struct module *owner;
>  #if defined(CONFIG_VIDEO_V4L2_SUBDEV_API)
>         struct v4l2_subdev_state *state;
> +       struct v4l2_subdev_context *context;
>         u64 client_caps;
>  #endif
>  };
> @@ -1285,6 +1358,59 @@ int v4l2_subdev_link_validate(struct media_link *link);
>  bool v4l2_subdev_has_pad_interdep(struct media_entity *entity,
>                                   unsigned int pad0, unsigned int pad1);
>
> +/**
> + * v4l2_subdev_context_get - Helper to get a v4l2 subdev context from a
> + *                          media device context
> + *
> + * @mdev_context: The media device context
> + * @sd: The V4L2 subdevice the context refers to
> + *
> + * Helper function that wraps media_device_get_entity_context() and returns
> + * the v4l2 subdevice context associated with a subdevice in a media device
> + * context.
> + *
> + * The reference count of the returned v4l2 subdevice context is increased.
> + * Callers of this function are required to decrease the reference count of
> + * the context reference with a call to v4l2_subdev_context_put().
> + */
> +struct v4l2_subdev_context *
> +v4l2_subdev_context_get(struct media_device_context *mdev_context,
> +                       struct v4l2_subdev *sd);
> +
> +/**
> + * v4l2_subdev_context_put - Helper to decrease a v4l2 subdevice context
> + *                          reference count
> + *
> + * @ctx: The v4l2 subdevice context to put
> + */
> +void v4l2_subdev_context_put(struct v4l2_subdev_context *ctx);
> +
> +/**
> + * v4l2_subdev_init_context - Initialize the v4l2 subdevice context
> + *
> + * @sd: The subdevice the context belongs to
> + * @ctx: The context to initialize
> + *
> + * Initialize the v4l2 subdevice context. The intended callers of this function
> + * are driver-specific implementations of the media_entity_ops.alloc_context()
> + * function that allocates their driver specific types that derive from
> + * struct v4l2_subdev_context.
> + */
> +int v4l2_subdev_init_context(struct v4l2_subdev *sd,
> +                            struct v4l2_subdev_context *ctx);
> +
> +/**
> + * v4l2_subdev_cleanup_context - Cleanup the v4l2 subdevice context
> + *
> + * @ctx: The context to cleanup.
> + *
> + * Cleanup the v4l2 subdevice context. The intended callers of this function are
> + * driver specific implementation of the media_entity_ops.destroy_context()
> + * function before releasing the memory previously allocated by
> + * media_entity_ops.alloc_context().
> + */
> +void v4l2_subdev_cleanup_context(struct v4l2_subdev_context *ctx);
> +
>  /**
>   * __v4l2_subdev_state_alloc - allocate v4l2_subdev_state
>   *
>
> --
> 2.49.0
>
>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.