From nobody Mon Oct 6 20:59:27 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 198FD29DB7F; Thu, 17 Jul 2025 10:45:54 +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=1752749156; cv=none; b=GkHdO99/oRJE+S23W1cDbm1dUFOeUHEEYXkODmZHDsCG53GQaB+Wz9y9Nup+c9kFwwcUQqLkD/MAwm4tw7hqon9qhvTphFOpZFhbBe9I2QCjYFGKRvBsvhuw6sLhjtSwXQa4u8yRjl8CC+aQmm94TgV6JrFmYINFuoSoVXwIxt4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1752749156; c=relaxed/simple; bh=8R73HPaz5pGFoxscWZIYsH9YWq0Ywb87x5bejY/EFeM=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=QHyp/xz8M4R+lxygFeyM8kBI0919U3RgeYmDxW+zj3FOEbpiaF1TztxkN0PiLfCITEjufZDXOo8pjQUUE1X+iAYzpty9vbAEWpkGRSYvzuVewEbs4uSGlj2BTImw7LkxI5VbtQI2d1BlkpBHvYYFKCiNczuUMFc2lV9nzDYwIrI= 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=SOiHuxq8; 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="SOiHuxq8" 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 C93F3198D; Thu, 17 Jul 2025 12:45:13 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1752749115; bh=8R73HPaz5pGFoxscWZIYsH9YWq0Ywb87x5bejY/EFeM=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=SOiHuxq8bdNt7SUOg01x5EwIA3zPLzESlFTgWYrVGjEHsxAno2JVpff/lYDXyYxvn WCggyMJgoWJlyzBLV1qU7pt3DxqyFpOP9ZJoF8o9RwzG+mcQIuu9WkLjtfNN2wZeLC oIBVD8zOmfZjdx9WqMGJG5648ji+ca0iXpNxNG5k= From: Jacopo Mondi Date: Thu, 17 Jul 2025 12:45:32 +0200 Subject: [PATCH 06/26] 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: <20250717-multicontext-mainline-2025-v1-6-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=8477; i=jacopo.mondi@ideasonboard.com; h=from:subject:message-id; bh=8R73HPaz5pGFoxscWZIYsH9YWq0Ywb87x5bejY/EFeM=; b=owEBbQKS/ZANAwAKAXI0Bo8WoVY8AcsmYgBoeNRPuxlgrQbLEhBMUC26EnJg5sMetl7FSM+mi 8Q1kKPMoYqJAjMEAAEKAB0WIQS1xD1IgJogio9YOMByNAaPFqFWPAUCaHjUTwAKCRByNAaPFqFW PNIjD/0fEqn9SDhgeerqLoTAs2HwXZnGao1NsXkGYyUmaguuhhDcaMETK1sZeSWBDURKkRGij0X WXrWQpEbohjIBjGAObAiOae4/zPpcHEvZCq1P3knfpKdDleAyOMCRkpXgkN9Zbrm/22PMa+zqv8 jj+g+jdoqDnyOt2f7WqVMiDzlJRTq6KucXNeio3Rwk9QPA+Perj1a5U6niBrZqUPe0Y0SEFzRty zxrmQQCaVJXcRy9pMIyqofajGgIrMrXDhrRmGn5nMc9QAu4+oTQwX6zJxgAxlekt08KD9L6Ioqc 5HkpMu/QtEF1RkZmLbvsV7E7M5qHxGeDd6et4W4wW35Ciw1LNjDWsD/xMHmZ9Kf+thPEZzdIGVV j2S3fIJunNWw9nYffnWXm9Q3Su+++kv19zSWanLxPw0zHG7d/xvYSX2BhSbAwQzD/LJnNptXcny Y4rs5Ls77K3DuVoybPh9FYdak+5m7uU6AjrBPnnH3ugsztxXkRRXwaG73oK3RjY3PHiuJO28L0e ouc9VzJspHZ32CXbyPDzGHYMQvDdmlZCaO8/QS9q+L/cvqu6a9PrJCvRfiFPF6+gB+DkCSkHvc9 6tTshdadZ/WX6c9BF0XLpWfj2SGOV+vLD1AlAjTcbwd8CZ8mpTRzifPz4nJv+KFt9KV0QKN+KPh mZKXBqwSo2SPv2A== 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 | 64 ++++++++++++++++++++++++++++++++= ++++ include/media/v4l2-ioctl.h | 7 ++++ include/uapi/linux/videodev2.h | 11 +++++++ 5 files changed, 93 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..bade64cc62b66dd6237ccd5338a= a6dd8ab00ef8c 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,61 @@ static int v4l_overlay(const struct v4l2_ioctl_ops *= ops, return ops->vidioc_overlay(file, fh, *(unsigned int *)arg); } =20 +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; +} + static int v4l_reqbufs(const struct v4l2_ioctl_ops *ops, struct file *file, void *fh, void *arg) { @@ -2998,6 +3061,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