From nobody Mon Oct 6 06:42:59 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 843022E427B; Thu, 24 Jul 2025 14:10:42 +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=1753366244; cv=none; b=N40FF0MNCUVCicY74d7gs+UplHgbN6bzlsMq2htVbDiMN90HwbxtRifYXZ4wTg9q60u2IoYzgt78P6KBa7pDoVSsBb+YWjiM/w3NNPnOBXyDAYBWJwmPAIzbEVsfjr7xB01+m+RhCo3tSM5D+aDeoMVjhHob6Frnv6s0MgsqYzM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753366244; c=relaxed/simple; bh=y6CtFSygCTQezYgM+DYFcUUx7oApPhfpK3+h4WXc9Ak=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=MFzqLMz/4heK4HtAOMjSgbdSPc2tWZZfZcwSeDPLhTHokJtPgJNN+Asfe85hk84VtNPAj7JsouXgUGa/eDspC/lHazGJT3DTwVUZZjghdJkR12S8igXn7qxdDTD0t4o1Krb8+CyigLi81as6IgoXwd5GF4Ms7ObIudaTN+Haum8= 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=kbLncd37; 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="kbLncd37" Received: from [192.168.1.76] (unknown [IPv6:2001:b07:6462:5de2:520d:d7a3:63ca:99e8]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 448871ACF; Thu, 24 Jul 2025 16:09:54 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1753366195; bh=y6CtFSygCTQezYgM+DYFcUUx7oApPhfpK3+h4WXc9Ak=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=kbLncd37uM6slkchMwKMFoa5Z+rme7cALBL/gmeJPvzlOC9u6V32nK4u3NdvORqC+ QCCSBLEOKBiMlHeB6tb+aEe91YybJMTCrRRgMjxG1qWBBGfR76tZLOtkdBykjJ9cyd TV5aIuX4T5Hjyjiu3L47i/pS7YwNI89GBuSOhgeo= From: Jacopo Mondi Date: Thu, 24 Jul 2025 16:10:13 +0200 Subject: [PATCH v2 06/27] media: v4l2-ioctl: Introduce VIDIOC_BIND_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: <20250724-multicontext-mainline-2025-v2-6-c9b316773486@ideasonboard.com> References: <20250724-multicontext-mainline-2025-v2-0-c9b316773486@ideasonboard.com> In-Reply-To: <20250724-multicontext-mainline-2025-v2-0-c9b316773486@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=8696; i=jacopo.mondi@ideasonboard.com; h=from:subject:message-id; bh=y6CtFSygCTQezYgM+DYFcUUx7oApPhfpK3+h4WXc9Ak=; b=owEBbQKS/ZANAwAKAXI0Bo8WoVY8AcsmYgBogj7OCMocGJg4McaY1eSfSvbZPdFRvvqXYBeuy 1Sht/lP79eJAjMEAAEKAB0WIQS1xD1IgJogio9YOMByNAaPFqFWPAUCaII+zgAKCRByNAaPFqFW PJVOD/0XAYjLtUFbG6lCv0mocUmp2jzA8aHY3WAyxy1LGEk0h23LFl7Ldw9t8Rtb1IWe1sR1Xey dJxntT81RpS+p+B06GzDswCgy0hyCKYYJBNyxwhCBPp/nBphdDgucoRfW8lLADNl13RfH8I/jL0 8Fq/mml98a+AsKmHxYw50yO6OhAIlhJtATpf3a8cwRSCOcoQEwHWV87nvd9MlllkoTm8lukh+Z9 owkWKDjDvfO0snm9gJsF/2P1aKgLjL+i2bCdCFpUpppbTrr727E6J6/YooWPi+0TZXUdEZueFtt w9fnf/SWhXEH+Ind9BUVG3RbmwPjDYfw8KEj+VrAKmJiHW01DrRqiWQwSSXW+l3E5fWk62TvunK Ifix0dCR+QBcvMxdkNmvZgRms+ZEmP5LVHCUF19Wcv057eUQFXR3kVh5h/IT2jSWVA1iJ9uP/ds JqbJmkA3SdDSU+sZjRnfjQIEhSeMbWD3wxBZiCOZmiRCcQo31sZQgh9xxt25Od3SnP9JsF26xDS B1S63mJl77am4UvDFs4Y6ggYAcMcEke9zPK3JytIAJo+hdy1wcKUEAkcl0vPj370wIYPq5S0sDo SQ2ei4DrQLOYiBSRyYQBJbnes93h24sC22BNbRyRCF9RqsFQTlgX9O+sylKf1GymZD5joDOW3N4 3aLqtYbXhM9+Eyg== X-Developer-Key: i=jacopo.mondi@ideasonboard.com; a=openpgp; fpr=72392EDC88144A65C701EA9BA5826A2587AD026B Introduce a new ioctl in V4L2 to allocate a video device context and associate it with a media device context. The ioctl is valid only if support for MEDIA_CONTROLLER is compiled in as it calls into the entity ops to let driver allocate a new context and binds the newly created context with the media context associated with the file descriptor provided by userspace as the new ioctl argument. The newly allocated video context is then stored in the v4l2-fh that represent the open file handle on which the ioctl has been called. Signed-off-by: Jacopo Mondi --- drivers/media/v4l2-core/v4l2-dev.c | 10 +++++ drivers/media/v4l2-core/v4l2-fh.c | 1 + drivers/media/v4l2-core/v4l2-ioctl.c | 72 ++++++++++++++++++++++++++++++++= ++++ include/media/v4l2-ioctl.h | 7 ++++ include/uapi/linux/videodev2.h | 11 ++++++ 5 files changed, 101 insertions(+) diff --git a/drivers/media/v4l2-core/v4l2-dev.c b/drivers/media/v4l2-core/v= 4l2-dev.c index c83c37843c9e7beb899a4b2bd176273c3dec381b..bc6502b4ce21cc0ad53136e1637= d1c926e31dd89 100644 --- a/drivers/media/v4l2-core/v4l2-dev.c +++ b/drivers/media/v4l2-core/v4l2-dev.c @@ -606,6 +606,10 @@ static void determine_valid_ioctls(struct video_device= *vdev) __set_bit(_IOC_NR(VIDIOC_ENUM_FREQ_BANDS), valid_ioctls); =20 if (is_vid) { +#ifdef CONFIG_MEDIA_CONTROLLER + __set_bit(_IOC_NR(VIDIOC_BIND_CONTEXT), valid_ioctls); +#endif + /* video specific ioctls */ if ((is_rx && (ops->vidioc_enum_fmt_vid_cap || ops->vidioc_enum_fmt_vid_overlay)) || @@ -661,12 +665,18 @@ static void determine_valid_ioctls(struct video_devic= e *vdev) SET_VALID_IOCTL(ops, VIDIOC_G_FMT, vidioc_g_fmt_meta_cap); SET_VALID_IOCTL(ops, VIDIOC_S_FMT, vidioc_s_fmt_meta_cap); SET_VALID_IOCTL(ops, VIDIOC_TRY_FMT, vidioc_try_fmt_meta_cap); +#ifdef CONFIG_MEDIA_CONTROLLER + __set_bit(_IOC_NR(VIDIOC_BIND_CONTEXT), valid_ioctls); +#endif } else if (is_meta && is_tx) { /* metadata output specific ioctls */ SET_VALID_IOCTL(ops, VIDIOC_ENUM_FMT, vidioc_enum_fmt_meta_out); SET_VALID_IOCTL(ops, VIDIOC_G_FMT, vidioc_g_fmt_meta_out); SET_VALID_IOCTL(ops, VIDIOC_S_FMT, vidioc_s_fmt_meta_out); SET_VALID_IOCTL(ops, VIDIOC_TRY_FMT, vidioc_try_fmt_meta_out); +#ifdef CONFIG_MEDIA_CONTROLLER + __set_bit(_IOC_NR(VIDIOC_BIND_CONTEXT), valid_ioctls); +#endif } if (is_vbi) { /* vbi specific ioctls */ diff --git a/drivers/media/v4l2-core/v4l2-fh.c b/drivers/media/v4l2-core/v4= l2-fh.c index 90eec79ee995a2d214590beeacc91b9f8f33236d..f7af444d2344541ccae1eae230b= 39d4cbc47f6bd 100644 --- a/drivers/media/v4l2-core/v4l2-fh.c +++ b/drivers/media/v4l2-core/v4l2-fh.c @@ -93,6 +93,7 @@ int v4l2_fh_release(struct file *filp) struct v4l2_fh *fh =3D filp->private_data; =20 if (fh) { + video_device_context_put(fh->context); v4l2_fh_del(fh); v4l2_fh_exit(fh); kfree(fh); diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core= /v4l2-ioctl.c index 46da373066f4ec786b87ef18b8372abee621332f..ff80a3d9a9fe66753d8c9bc8353= 5f6ad5288c3ec 100644 --- a/drivers/media/v4l2-core/v4l2-ioctl.c +++ b/drivers/media/v4l2-core/v4l2-ioctl.c @@ -9,6 +9,7 @@ */ =20 #include +#include #include #include #include @@ -350,6 +351,13 @@ static void v4l_print_format(const void *arg, bool wri= te_only) } } =20 +static void v4l_print_context(const void *arg, bool write_only) +{ + const struct v4l2_context *c =3D arg; + + pr_cont("context=3D%u\n", c->context_fd); +} + static void v4l_print_framebuffer(const void *arg, bool write_only) { const struct v4l2_framebuffer *p =3D arg; @@ -2151,6 +2159,69 @@ static int v4l_overlay(const struct v4l2_ioctl_ops *= ops, return ops->vidioc_overlay(file, fh, *(unsigned int *)arg); } =20 +#if defined(CONFIG_MEDIA_CONTROLLER) +static int v4l_bind_context(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) +{ + struct video_device *vdev =3D video_devdata(file); + struct media_device_context *mdev_context; + struct v4l2_fh *vfh =3D + test_bit(V4L2_FL_USES_V4L2_FH, &vdev->flags) ? fh : NULL; + struct v4l2_context *c =3D arg; + int ret; + + /* + * TODO: do not __set_bit(_IOC_NR(VIDIOC_BIND_CONTEXT), valid_ioctls) + * if V4L2_FL_USES_V4L2_FH isn't set or the driver does not implement + * alloc_context and destroy_context. + */ + if (!vfh) + return -ENOTTY; + + if (!vdev->entity.ops || !vdev->entity.ops->alloc_context || + !vdev->entity.ops->destroy_context) + return -ENOTTY; + + mdev_context =3D media_device_context_get_from_fd(c->context_fd); + if (!mdev_context) + return -EINVAL; + + /* Let the driver allocate the per-file handle context. */ + ret =3D vdev->entity.ops->alloc_context(&vdev->entity, + (struct media_entity_context **) + &vfh->context); + if (ret) + goto err_put_mdev_context; + + /* + * Bind the newly created video device context to the media device + * context identified by the file descriptor. + */ + ret =3D media_device_bind_context(mdev_context, + (struct media_entity_context *) + vfh->context); + if (ret) + goto err_put_context; + + media_device_context_put(mdev_context); + + return 0; + +err_put_context: + video_device_context_put(vfh->context); +err_put_mdev_context: + media_device_context_put(mdev_context); + + return ret; +} +#else +static int v4l_bind_context(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) +{ + return 0; +} +#endif /* CONFIG_MEDIA_CONTROLLER */ + static int v4l_reqbufs(const struct v4l2_ioctl_ops *ops, struct file *file, void *fh, void *arg) { @@ -2998,6 +3069,7 @@ static const struct v4l2_ioctl_info v4l2_ioctls[] =3D= { IOCTL_INFO(VIDIOC_DBG_G_CHIP_INFO, v4l_dbg_g_chip_info, v4l_print_dbg_chi= p_info, INFO_FL_CLEAR(v4l2_dbg_chip_info, match)), IOCTL_INFO(VIDIOC_QUERY_EXT_CTRL, v4l_query_ext_ctrl, v4l_print_query_ext= _ctrl, INFO_FL_CTRL | INFO_FL_CLEAR(v4l2_query_ext_ctrl, id)), IOCTL_INFO(VIDIOC_REMOVE_BUFS, v4l_remove_bufs, v4l_print_remove_buffers,= INFO_FL_PRIO | INFO_FL_QUEUE | INFO_FL_CLEAR(v4l2_remove_buffers, type)), + IOCTL_INFO(VIDIOC_BIND_CONTEXT, v4l_bind_context, v4l_print_context, 0), }; #define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls) =20 diff --git a/include/media/v4l2-ioctl.h b/include/media/v4l2-ioctl.h index 82695c3a300a73219f262fb556ed61a8f09d273e..6d9edfd9ca912972ad15acdc070= 14dee1ed36ab6 100644 --- a/include/media/v4l2-ioctl.h +++ b/include/media/v4l2-ioctl.h @@ -18,6 +18,7 @@ #include =20 struct v4l2_fh; +struct video_device_context; =20 /** * struct v4l2_ioctl_ops - describe operations for each V4L2 ioctl @@ -149,6 +150,8 @@ struct v4l2_fh; * :ref:`VIDIOC_TRY_FMT ` ioctl logic for metadata capture * @vidioc_try_fmt_meta_out: pointer to the function that implements * :ref:`VIDIOC_TRY_FMT ` ioctl logic for metadata output + * @vidioc_bind_context: pointer to the function that implements + * :ref:`VIDIOC_BIND_CONTEXT ` ioctl * @vidioc_reqbufs: pointer to the function that implements * :ref:`VIDIOC_REQBUFS ` ioctl * @vidioc_querybuf: pointer to the function that implements @@ -402,6 +405,10 @@ struct v4l2_ioctl_ops { int (*vidioc_try_fmt_meta_out)(struct file *file, void *fh, struct v4l2_format *f); =20 + /* Context handlers */ + int (*vidioc_bind_context)(struct file *file, void *fh, + struct video_device_context *c); + /* Buffer handlers */ int (*vidioc_reqbufs)(struct file *file, void *fh, struct v4l2_requestbuffers *b); diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h index 3dd9fa45dde1066d52a68581625a39e7ec92c9b7..0b9aa89e2479620dbbaa54f1aad= ff7aaa7a3d0f7 100644 --- a/include/uapi/linux/videodev2.h +++ b/include/uapi/linux/videodev2.h @@ -1057,6 +1057,14 @@ struct v4l2_jpegcompression { * always use APP0 */ }; =20 +/* + * V I D E O D E V I C E C O N T E X T + */ + +struct v4l2_context { + __u32 context_fd; +}; + /* * M E M O R Y - M A P P I N G B U F F E R S */ @@ -2818,6 +2826,9 @@ struct v4l2_remove_buffers { #define VIDIOC_REMOVE_BUFS _IOWR('V', 104, struct v4l2_remove_buffers) =20 =20 +/* Context handling */ +#define VIDIOC_BIND_CONTEXT _IOW('V', 105, struct v4l2_context) + /* Reminder: when adding new ioctls please add support for them to drivers/media/v4l2-core/v4l2-compat-ioctl32.c as well! */ =20 --=20 2.49.0