From nobody Mon Oct 6 20:59:26 2025 Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7BF712BE024; Thu, 17 Jul 2025 10:46:04 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=213.167.242.64 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1752749166; cv=none; b=k+vKwy1FDaCODFnat8kuO/N9GK5MPLgx5hsqPqPON6ag4LfUcoypjcn1vqplQFOCkNJg2NQY+UB5jZ50LTDtRe0DsMOlzanI4EJbHnrKDYrW493i/9riVC49+TMRxeymNV8rhtYK+qFwpk3YJd9sApDVbRB6WbxjZB8JeRfXbxU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1752749166; c=relaxed/simple; bh=7I13wywrt99Sx2g/tHAlEPxkYo6PoehZ9YwsTffq1K4=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=AHEvOQsvxDjVXUkKRzZ0NV1FXpAkKiMd1XYv6M0z4yC3mF7qV9KIqISjBtN1Hsko2oim1rdhn/xilf11/Qvw4uR284suX7ReL60gHPwZ7oQLrXOC96b3Gf53YenM/G4HzKt/4+SzCWx5nmK/vveuksluAvwOD8ORmbFKA22sPsw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=ideasonboard.com; spf=pass smtp.mailfrom=ideasonboard.com; dkim=pass (1024-bit key) header.d=ideasonboard.com header.i=@ideasonboard.com header.b=t/XlmP8/; arc=none smtp.client-ip=213.167.242.64 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=ideasonboard.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=ideasonboard.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="t/XlmP8/" Received: from [192.168.0.172] (mob-5-90-140-254.net.vodafone.it [5.90.140.254]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 17A6721F5; Thu, 17 Jul 2025 12:45:23 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1752749125; bh=7I13wywrt99Sx2g/tHAlEPxkYo6PoehZ9YwsTffq1K4=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=t/XlmP8/X5RXCxwFsmf1/nSxWNBNsq8e9euPrc+fVLWEhiORcQD/1udMaug+br6ez AWiOcssX+z06OmeERZaiRbuLzEzPtkDjQZUZ88ab6/xG8XMy3rt68DT9My74IXvloF +Hl7NNPlSBsgFmbh3Y72+q/H4AMXjEFhVKZDfO4s= From: Jacopo Mondi Date: Thu, 17 Jul 2025 12:45:38 +0200 Subject: [PATCH 12/26] media: v4l2-subdev: Introduce v4l2 subdev context Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250717-multicontext-mainline-2025-v1-12-81ac18979c03@ideasonboard.com> References: <20250717-multicontext-mainline-2025-v1-0-81ac18979c03@ideasonboard.com> In-Reply-To: <20250717-multicontext-mainline-2025-v1-0-81ac18979c03@ideasonboard.com> To: Sakari Ailus , Laurent Pinchart , Tomi Valkeinen , Kieran Bingham , Nicolas Dufresne , Mauro Carvalho Chehab , Tomasz Figa , Marek Szyprowski , Raspberry Pi Kernel Maintenance , Florian Fainelli , Broadcom internal kernel review list , Hans Verkuil Cc: linux-kernel@vger.kernel.org, linux-media@vger.kernel.org, linux-rpi-kernel@lists.infradead.org, linux-arm-kernel@lists.infradead.org, Jacopo Mondi X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=8677; i=jacopo.mondi@ideasonboard.com; h=from:subject:message-id; bh=7I13wywrt99Sx2g/tHAlEPxkYo6PoehZ9YwsTffq1K4=; b=owEBbQKS/ZANAwAKAXI0Bo8WoVY8AcsmYgBoeNRQ8UB8+mF7gMnThRVJKgz7B8w/il6wiPY6O AMgv2ZUrh6JAjMEAAEKAB0WIQS1xD1IgJogio9YOMByNAaPFqFWPAUCaHjUUAAKCRByNAaPFqFW PDFcD/0etgZd6NlXIO9TufXayrKZfYsSFzxTtO9JnydgaM3udlm/IOAIggj9+M9nI5Y2XyxDhvs TUwyYiKCy9c1tGeZWWQBVqRrFZzFPaFzvxQhd0RCId4J+SHkBpcYXFKA5a/1hci37cMI3aGJSWf UvAGs+ilwBNcohu3IhSXCRgyr/JEOyrRdJuNhcy6XPeXxKaYDnXLw6FTxPUhLWFzXitNjDtrLA3 cxzFpLtMgeaQvpzjlJP0YCULQ7SKZMXutvrUTr8vReQabcOog6niSXgsRr14+cdxll+O6nGfpTw jp3ZSScspLTzn5bOBgPoXrroEsBnFv2hrZ7y3l+rYaHhHBUlT22dUuRAjHpnD/b5Ddg0lD+dXkP /T5aEqiFLM8fnFIUwW/9ppE4UtrTD+T3exjtGNH8wveQ7iN4DBz6u5FgnbmlTURPpawT7AGxi7e 8pklFf62glLv/JsKm1OzQyvDqZ5yMvrzufbNXAXBFHmCNatwW1doSsbDBcQ1HDjoKxBjEVevnvn WCDxVnEW/lS0feUxF3pJ2A9JTr9WxmONdHETs/k9aSTOTEtB2YEXednSpIGKKhvD9kmixGYFvvX nJ1lpNx/jWItJz3SXrgyAX9RRs7D74n23310B/ryVjqp+PeD4FqK4i8NGRjMd9H3Le4YRJUXgVa PGNLSbkxcdGzUUA== X-Developer-Key: i=jacopo.mondi@ideasonboard.com; a=openpgp; fpr=72392EDC88144A65C701EA9BA5826A2587AD026B 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 --- 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-cor= e/v4l2-subdev.c index 4fd25fea3b58477056729665706ddbacc436379c..7307f57439499c8d5360c89f492= 944828ac23973 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_entit= y *entity, } EXPORT_SYMBOL_GPL(v4l2_subdev_has_pad_interdep); =20 +struct v4l2_subdev_context * +v4l2_subdev_context_get(struct media_device_context *mdev_context, + struct v4l2_subdev *sd) +{ + struct media_entity *entity =3D &sd->entity; + struct media_entity_context *ctx =3D + media_device_get_entity_context(mdev_context, entity); + + if (!ctx) + 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..9d257b859acafb11cfe6976e906= e7baabd0206f6 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; }; =20 +/** + * 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 cont= ext, + * userspace is allowed to multiplex the usage of a subdevice devnode by o= pening + * it multiple times and by associating it with a media device context. Th= is + * 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 closi= ng 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 conte= xt, + * 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 associa= ted + * with a different file descriptor obtained by opening again the same sub= device + * 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_co= ntext + * instance as first member, and allocate the driver-specific structure si= ze 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 c= ontext + * - 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 *lin= k); bool v4l2_subdev_has_pad_interdep(struct media_entity *entity, unsigned int pad0, unsigned int pad1); =20 +/** + * 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 fun= ction + * are driver-specific implementations of the media_entity_ops.alloc_conte= xt() + * 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 functi= on 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 * --=20 2.49.0