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 > >