public inbox for linux-media@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 1/3] media: v4l2-mem2mem: Add a kref to the v4l2_m2m_dev structure
@ 2025-12-04  9:08 ming.qian
  2025-12-04  9:08 ` [PATCH v3 2/3] pmdomain: imx8m-blk-ctrl: Remove separate rst and clk mask for 8mq vpu ming.qian
                   ` (2 more replies)
  0 siblings, 3 replies; 10+ messages in thread
From: ming.qian @ 2025-12-04  9:08 UTC (permalink / raw)
  To: linux-media
  Cc: mchehab, hverkuil-cisco, nicolas, benjamin.gaignard, p.zabel,
	sebastian.fricke, shawnguo, ulf.hansson, s.hauer, kernel,
	festevam, linux-imx, l.stach, Frank.li, peng.fan, eagle.zhou, imx,
	linux-pm, linux-kernel, linux-arm-kernel

From: Nicolas Dufresne <nicolas.dufresne@collabora.com>

Adding a reference count to the v4l2_m2m_dev structure allow safely
sharing it across multiple hardware nodes. This can be used to prevent
running jobs concurrently on m2m cores that have some internal resource
sharing.

Signed-off-by: Nicolas Dufresne <nicolas.dufresne@collabora.com>
---
 drivers/media/v4l2-core/v4l2-mem2mem.c | 23 +++++++++++++++++++++++
 include/media/v4l2-mem2mem.h           | 21 +++++++++++++++++++++
 2 files changed, 44 insertions(+)

diff --git a/drivers/media/v4l2-core/v4l2-mem2mem.c b/drivers/media/v4l2-core/v4l2-mem2mem.c
index fec93c1a9231..ae0de54d4c3e 100644
--- a/drivers/media/v4l2-core/v4l2-mem2mem.c
+++ b/drivers/media/v4l2-core/v4l2-mem2mem.c
@@ -90,6 +90,7 @@ static const char * const m2m_entity_name[] = {
  * @job_work:		worker to run queued jobs.
  * @job_queue_flags:	flags of the queue status, %QUEUE_PAUSED.
  * @m2m_ops:		driver callbacks
+ * @kref:		device reference count
  */
 struct v4l2_m2m_dev {
 	struct v4l2_m2m_ctx	*curr_ctx;
@@ -109,6 +110,8 @@ struct v4l2_m2m_dev {
 	unsigned long		job_queue_flags;
 
 	const struct v4l2_m2m_ops *m2m_ops;
+
+	struct kref kref;
 };
 
 static struct v4l2_m2m_queue_ctx *get_queue_ctx(struct v4l2_m2m_ctx *m2m_ctx,
@@ -1200,6 +1203,7 @@ struct v4l2_m2m_dev *v4l2_m2m_init(const struct v4l2_m2m_ops *m2m_ops)
 	INIT_LIST_HEAD(&m2m_dev->job_queue);
 	spin_lock_init(&m2m_dev->job_spinlock);
 	INIT_WORK(&m2m_dev->job_work, v4l2_m2m_device_run_work);
+	kref_init(&m2m_dev->kref);
 
 	return m2m_dev;
 }
@@ -1211,6 +1215,25 @@ void v4l2_m2m_release(struct v4l2_m2m_dev *m2m_dev)
 }
 EXPORT_SYMBOL_GPL(v4l2_m2m_release);
 
+void v4l2_m2m_get(struct v4l2_m2m_dev *m2m_dev)
+{
+	kref_get(&m2m_dev->kref);
+}
+EXPORT_SYMBOL_GPL(v4l2_m2m_get);
+
+static void v4l2_m2m_release_from_kref(struct kref *kref)
+{
+	struct v4l2_m2m_dev *m2m_dev = container_of(kref, struct v4l2_m2m_dev, kref);
+
+	v4l2_m2m_release(m2m_dev);
+}
+
+void v4l2_m2m_put(struct v4l2_m2m_dev *m2m_dev)
+{
+	kref_put(&m2m_dev->kref, v4l2_m2m_release_from_kref);
+}
+EXPORT_SYMBOL_GPL(v4l2_m2m_put);
+
 struct v4l2_m2m_ctx *v4l2_m2m_ctx_init(struct v4l2_m2m_dev *m2m_dev,
 		void *drv_priv,
 		int (*queue_init)(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_vq))
diff --git a/include/media/v4l2-mem2mem.h b/include/media/v4l2-mem2mem.h
index bf6a09a04dcf..ca295c660c7f 100644
--- a/include/media/v4l2-mem2mem.h
+++ b/include/media/v4l2-mem2mem.h
@@ -547,6 +547,27 @@ v4l2_m2m_register_media_controller(struct v4l2_m2m_dev *m2m_dev,
  */
 void v4l2_m2m_release(struct v4l2_m2m_dev *m2m_dev);
 
+/**
+ * v4l2_m2m_get() - take a reference to the m2m_dev structure
+ *
+ * @m2m_dev: opaque pointer to the internal data to handle M2M context
+ *
+ * This is used to share the M2M device across multiple devices. This
+ * can be used to avoid scheduling two hardware nodes concurrently.
+ */
+void v4l2_m2m_get(struct v4l2_m2m_dev *m2m_dev);
+
+/**
+ * v4l2_m2m_put() - remove a reference to the m2m_dev structure
+ *
+ * @m2m_dev: opaque pointer to the internal data to handle M2M context
+ *
+ * Once the M2M device have no more references, v4l2_m2m_realse() will be
+ * called automatically. Users of this method should never call
+ * v4l2_m2m_release() directly. See v4l2_m2m_get() for more details.
+ */
+void v4l2_m2m_put(struct v4l2_m2m_dev *m2m_dev);
+
 /**
  * v4l2_m2m_ctx_init() - allocate and initialize a m2m context
  *
-- 
2.52.0


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v3 2/3] pmdomain: imx8m-blk-ctrl: Remove separate rst and clk mask for 8mq vpu
  2025-12-04  9:08 [PATCH v3 1/3] media: v4l2-mem2mem: Add a kref to the v4l2_m2m_dev structure ming.qian
@ 2025-12-04  9:08 ` ming.qian
  2025-12-04 17:24   ` Frank Li
  2025-12-04  9:08 ` [PATCH v3 3/3] media: verisilicon: Avoid G2 bus error while decoding H.264 and HEVC ming.qian
  2025-12-04 17:23 ` [PATCH v3 1/3] media: v4l2-mem2mem: Add a kref to the v4l2_m2m_dev structure Frank Li
  2 siblings, 1 reply; 10+ messages in thread
From: ming.qian @ 2025-12-04  9:08 UTC (permalink / raw)
  To: linux-media
  Cc: mchehab, hverkuil-cisco, nicolas, benjamin.gaignard, p.zabel,
	sebastian.fricke, shawnguo, ulf.hansson, s.hauer, kernel,
	festevam, linux-imx, l.stach, Frank.li, peng.fan, eagle.zhou, imx,
	linux-pm, linux-kernel, linux-arm-kernel

From: Ming Qian <ming.qian@oss.nxp.com>

For i.MX8MQ platform, the ADB in the VPUMIX domain has no separate reset
and clock enable bits, but is ungated and reset together with the VPUs.
So we can't reset G1 or G2 separately, it may led to the system hang.
Remove rst_mask and clk_mask of imx8mq_vpu_blk_ctl_domain_data.
Let imx8mq_vpu_power_notifier() do really vpu reset.

Fixes: 608d7c325e85 ("soc: imx: imx8m-blk-ctrl: add i.MX8MQ VPU blk-ctrl")
Signed-off-by: Ming Qian <ming.qian@oss.nxp.com>
Reviewed-by: Benjamin Gaignard <benjamin.gaignard@collabora.com>
Reviewed-by: Peng Fan <peng.fan@nxp.com>
---
v3
- Add some comments
v2
- Update commit message

 drivers/pmdomain/imx/imx8m-blk-ctrl.c | 11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/drivers/pmdomain/imx/imx8m-blk-ctrl.c b/drivers/pmdomain/imx/imx8m-blk-ctrl.c
index 5c83e5599f1e..74bf4936991d 100644
--- a/drivers/pmdomain/imx/imx8m-blk-ctrl.c
+++ b/drivers/pmdomain/imx/imx8m-blk-ctrl.c
@@ -846,22 +846,25 @@ static int imx8mq_vpu_power_notifier(struct notifier_block *nb,
 	return NOTIFY_OK;
 }
 
+/*
+ * For i.MX8MQ, the ADB in the VPUMIX domain has no separate reset and clock
+ * enable bits, but is ungated and reset together with the VPUs.
+ * Resetting G1 or G2 separately may led to system hang.
+ * Remove the rst_mask and clk_mask from the domain data of G1 and G2,
+ * Let imx8mq_vpu_power_notifier() do really vpu reset.
+ */
 static const struct imx8m_blk_ctrl_domain_data imx8mq_vpu_blk_ctl_domain_data[] = {
 	[IMX8MQ_VPUBLK_PD_G1] = {
 		.name = "vpublk-g1",
 		.clk_names = (const char *[]){ "g1", },
 		.num_clks = 1,
 		.gpc_name = "g1",
-		.rst_mask = BIT(1),
-		.clk_mask = BIT(1),
 	},
 	[IMX8MQ_VPUBLK_PD_G2] = {
 		.name = "vpublk-g2",
 		.clk_names = (const char *[]){ "g2", },
 		.num_clks = 1,
 		.gpc_name = "g2",
-		.rst_mask = BIT(0),
-		.clk_mask = BIT(0),
 	},
 };
 
-- 
2.52.0


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v3 3/3] media: verisilicon: Avoid G2 bus error while decoding H.264 and HEVC
  2025-12-04  9:08 [PATCH v3 1/3] media: v4l2-mem2mem: Add a kref to the v4l2_m2m_dev structure ming.qian
  2025-12-04  9:08 ` [PATCH v3 2/3] pmdomain: imx8m-blk-ctrl: Remove separate rst and clk mask for 8mq vpu ming.qian
@ 2025-12-04  9:08 ` ming.qian
  2025-12-04 17:34   ` Frank Li
  2025-12-04 17:23 ` [PATCH v3 1/3] media: v4l2-mem2mem: Add a kref to the v4l2_m2m_dev structure Frank Li
  2 siblings, 1 reply; 10+ messages in thread
From: ming.qian @ 2025-12-04  9:08 UTC (permalink / raw)
  To: linux-media
  Cc: mchehab, hverkuil-cisco, nicolas, benjamin.gaignard, p.zabel,
	sebastian.fricke, shawnguo, ulf.hansson, s.hauer, kernel,
	festevam, linux-imx, l.stach, Frank.li, peng.fan, eagle.zhou, imx,
	linux-pm, linux-kernel, linux-arm-kernel

From: Ming Qian <ming.qian@oss.nxp.com>

For the i.MX8MQ platform, there is a hardware limitation: the g1 VPU and
g2 VPU cannot decode simultaneously; otherwise, it will cause below bus
error and produce corrupted pictures, even potentially lead to system hang.

[  110.527986] hantro-vpu 38310000.video-codec: frame decode timed out.
[  110.583517] hantro-vpu 38310000.video-codec: bus error detected.

Therefore, it is necessary to ensure that g1 and g2 operate alternately.
This allows for successful multi-instance decoding of H.264 and HEVC.

To achieve this, we can have g1 and g2 share the same v4l2_m2m_dev, and
then the v4l2_m2m_dev can handle the scheduling.

Fixes: cb5dd5a0fa518 ("media: hantro: Introduce G2/HEVC decoder")
Co-developed-by: Nicolas Dufresne <nicolas.dufresne@collabora.com>
Signed-off-by: Nicolas Dufresne <nicolas.dufresne@collabora.com>
Signed-off-by: Ming Qian <ming.qian@oss.nxp.com>
---
v3
- Apply Nicolas's approach that use an array list to define the shared
  devices

v2
- Abandon the waiting approach.
- Switch to a shared v4l2_m2m_dev solution.

 drivers/media/platform/verisilicon/hantro.h   |  2 +
 .../media/platform/verisilicon/hantro_drv.c   | 42 +++++++++++++++++--
 .../media/platform/verisilicon/imx8m_vpu_hw.c |  8 ++++
 3 files changed, 49 insertions(+), 3 deletions(-)

diff --git a/drivers/media/platform/verisilicon/hantro.h b/drivers/media/platform/verisilicon/hantro.h
index e0fdc4535b2d..0353de154a1e 100644
--- a/drivers/media/platform/verisilicon/hantro.h
+++ b/drivers/media/platform/verisilicon/hantro.h
@@ -77,6 +77,7 @@ struct hantro_irq {
  * @double_buffer:		core needs double buffering
  * @legacy_regs:		core uses legacy register set
  * @late_postproc:		postproc must be set up at the end of the job
+ * @shared_devices:		an array of device ids that cannot run concurrently
  */
 struct hantro_variant {
 	unsigned int enc_offset;
@@ -101,6 +102,7 @@ struct hantro_variant {
 	unsigned int double_buffer : 1;
 	unsigned int legacy_regs : 1;
 	unsigned int late_postproc : 1;
+	const struct of_device_id *shared_devices;
 };
 
 /**
diff --git a/drivers/media/platform/verisilicon/hantro_drv.c b/drivers/media/platform/verisilicon/hantro_drv.c
index 60b95b5d8565..70160eaf3d15 100644
--- a/drivers/media/platform/verisilicon/hantro_drv.c
+++ b/drivers/media/platform/verisilicon/hantro_drv.c
@@ -13,6 +13,7 @@
 #include <linux/clk.h>
 #include <linux/module.h>
 #include <linux/of.h>
+#include <linux/of_platform.h>
 #include <linux/platform_device.h>
 #include <linux/pm.h>
 #include <linux/pm_runtime.h>
@@ -1035,6 +1036,41 @@ static int hantro_disable_multicore(struct hantro_dev *vpu)
 	return 0;
 }
 
+static struct v4l2_m2m_dev *hantro_get_v4l2_m2m_dev(struct hantro_dev *vpu)
+{
+	struct device_node *node;
+	struct hantro_dev *shared_vpu;
+
+	if (!vpu->variant || !vpu->variant->shared_devices)
+		goto init_new_m2m_dev;
+
+	for_each_matching_node(node, vpu->variant->shared_devices) {
+		struct platform_device *pdev;
+		struct v4l2_m2m_dev *m2m_dev;
+
+		pdev = of_find_device_by_node(node);
+		of_node_put(node);
+
+		if (!pdev)
+			continue;
+
+		shared_vpu = platform_get_drvdata(pdev);
+		if (IS_ERR_OR_NULL(shared_vpu) || shared_vpu == vpu) {
+			platform_device_put(pdev);
+			continue;
+		}
+
+		v4l2_m2m_get(shared_vpu->m2m_dev);
+		m2m_dev = shared_vpu->m2m_dev;
+		platform_device_put(pdev);
+
+		return m2m_dev;
+	}
+
+init_new_m2m_dev:
+	return v4l2_m2m_init(&vpu_m2m_ops);
+}
+
 static int hantro_probe(struct platform_device *pdev)
 {
 	const struct of_device_id *match;
@@ -1186,7 +1222,7 @@ static int hantro_probe(struct platform_device *pdev)
 	}
 	platform_set_drvdata(pdev, vpu);
 
-	vpu->m2m_dev = v4l2_m2m_init(&vpu_m2m_ops);
+	vpu->m2m_dev = hantro_get_v4l2_m2m_dev(vpu);
 	if (IS_ERR(vpu->m2m_dev)) {
 		v4l2_err(&vpu->v4l2_dev, "Failed to init mem2mem device\n");
 		ret = PTR_ERR(vpu->m2m_dev);
@@ -1225,7 +1261,7 @@ static int hantro_probe(struct platform_device *pdev)
 	hantro_remove_enc_func(vpu);
 err_m2m_rel:
 	media_device_cleanup(&vpu->mdev);
-	v4l2_m2m_release(vpu->m2m_dev);
+	v4l2_m2m_put(vpu->m2m_dev);
 err_v4l2_unreg:
 	v4l2_device_unregister(&vpu->v4l2_dev);
 err_clk_unprepare:
@@ -1248,7 +1284,7 @@ static void hantro_remove(struct platform_device *pdev)
 	hantro_remove_dec_func(vpu);
 	hantro_remove_enc_func(vpu);
 	media_device_cleanup(&vpu->mdev);
-	v4l2_m2m_release(vpu->m2m_dev);
+	v4l2_m2m_put(vpu->m2m_dev);
 	v4l2_device_unregister(&vpu->v4l2_dev);
 	clk_bulk_unprepare(vpu->variant->num_clocks, vpu->clocks);
 	reset_control_assert(vpu->resets);
diff --git a/drivers/media/platform/verisilicon/imx8m_vpu_hw.c b/drivers/media/platform/verisilicon/imx8m_vpu_hw.c
index 5be0e2e76882..6f8e43b7f157 100644
--- a/drivers/media/platform/verisilicon/imx8m_vpu_hw.c
+++ b/drivers/media/platform/verisilicon/imx8m_vpu_hw.c
@@ -343,6 +343,12 @@ const struct hantro_variant imx8mq_vpu_variant = {
 	.num_regs = ARRAY_SIZE(imx8mq_reg_names)
 };
 
+static const struct of_device_id imx8mq_vpu_shared_resources[] __initconst = {
+	{ .compatible = "nxp,imx8mq-vpu-g1", },
+	{ .compatible = "nxp,imx8mq-vpu-g2", },
+	{ /* sentinel */ }
+};
+
 const struct hantro_variant imx8mq_vpu_g1_variant = {
 	.dec_fmts = imx8m_vpu_dec_fmts,
 	.num_dec_fmts = ARRAY_SIZE(imx8m_vpu_dec_fmts),
@@ -356,6 +362,7 @@ const struct hantro_variant imx8mq_vpu_g1_variant = {
 	.num_irqs = ARRAY_SIZE(imx8mq_irqs),
 	.clk_names = imx8mq_g1_clk_names,
 	.num_clocks = ARRAY_SIZE(imx8mq_g1_clk_names),
+	.shared_devices = imx8mq_vpu_shared_resources,
 };
 
 const struct hantro_variant imx8mq_vpu_g2_variant = {
@@ -371,6 +378,7 @@ const struct hantro_variant imx8mq_vpu_g2_variant = {
 	.num_irqs = ARRAY_SIZE(imx8mq_g2_irqs),
 	.clk_names = imx8mq_g2_clk_names,
 	.num_clocks = ARRAY_SIZE(imx8mq_g2_clk_names),
+	.shared_devices = imx8mq_vpu_shared_resources,
 };
 
 const struct hantro_variant imx8mm_vpu_g1_variant = {
-- 
2.52.0


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [PATCH v3 1/3] media: v4l2-mem2mem: Add a kref to the v4l2_m2m_dev structure
  2025-12-04  9:08 [PATCH v3 1/3] media: v4l2-mem2mem: Add a kref to the v4l2_m2m_dev structure ming.qian
  2025-12-04  9:08 ` [PATCH v3 2/3] pmdomain: imx8m-blk-ctrl: Remove separate rst and clk mask for 8mq vpu ming.qian
  2025-12-04  9:08 ` [PATCH v3 3/3] media: verisilicon: Avoid G2 bus error while decoding H.264 and HEVC ming.qian
@ 2025-12-04 17:23 ` Frank Li
  2 siblings, 0 replies; 10+ messages in thread
From: Frank Li @ 2025-12-04 17:23 UTC (permalink / raw)
  To: ming.qian
  Cc: linux-media, mchehab, hverkuil-cisco, nicolas, benjamin.gaignard,
	p.zabel, sebastian.fricke, shawnguo, ulf.hansson, s.hauer, kernel,
	festevam, linux-imx, l.stach, peng.fan, eagle.zhou, imx, linux-pm,
	linux-kernel, linux-arm-kernel

On Thu, Dec 04, 2025 at 05:08:09PM +0800, ming.qian@oss.nxp.com wrote:
> From: Nicolas Dufresne <nicolas.dufresne@collabora.com>
>
> Adding a reference count to the v4l2_m2m_dev structure allow safely
> sharing it across multiple hardware nodes. This can be used to prevent
> running jobs concurrently on m2m cores that have some internal resource
> sharing.
>
> Signed-off-by: Nicolas Dufresne <nicolas.dufresne@collabora.com>

Also need your s-o-b, or just said refer to other thread if it already
posted.

Frank
> ---
>  drivers/media/v4l2-core/v4l2-mem2mem.c | 23 +++++++++++++++++++++++
>  include/media/v4l2-mem2mem.h           | 21 +++++++++++++++++++++
>  2 files changed, 44 insertions(+)
>
> diff --git a/drivers/media/v4l2-core/v4l2-mem2mem.c b/drivers/media/v4l2-core/v4l2-mem2mem.c
> index fec93c1a9231..ae0de54d4c3e 100644
> --- a/drivers/media/v4l2-core/v4l2-mem2mem.c
> +++ b/drivers/media/v4l2-core/v4l2-mem2mem.c
> @@ -90,6 +90,7 @@ static const char * const m2m_entity_name[] = {
>   * @job_work:		worker to run queued jobs.
>   * @job_queue_flags:	flags of the queue status, %QUEUE_PAUSED.
>   * @m2m_ops:		driver callbacks
> + * @kref:		device reference count
>   */
>  struct v4l2_m2m_dev {
>  	struct v4l2_m2m_ctx	*curr_ctx;
> @@ -109,6 +110,8 @@ struct v4l2_m2m_dev {
>  	unsigned long		job_queue_flags;
>
>  	const struct v4l2_m2m_ops *m2m_ops;
> +
> +	struct kref kref;
>  };
>
>  static struct v4l2_m2m_queue_ctx *get_queue_ctx(struct v4l2_m2m_ctx *m2m_ctx,
> @@ -1200,6 +1203,7 @@ struct v4l2_m2m_dev *v4l2_m2m_init(const struct v4l2_m2m_ops *m2m_ops)
>  	INIT_LIST_HEAD(&m2m_dev->job_queue);
>  	spin_lock_init(&m2m_dev->job_spinlock);
>  	INIT_WORK(&m2m_dev->job_work, v4l2_m2m_device_run_work);
> +	kref_init(&m2m_dev->kref);
>
>  	return m2m_dev;
>  }
> @@ -1211,6 +1215,25 @@ void v4l2_m2m_release(struct v4l2_m2m_dev *m2m_dev)
>  }
>  EXPORT_SYMBOL_GPL(v4l2_m2m_release);
>
> +void v4l2_m2m_get(struct v4l2_m2m_dev *m2m_dev)
> +{
> +	kref_get(&m2m_dev->kref);
> +}
> +EXPORT_SYMBOL_GPL(v4l2_m2m_get);
> +
> +static void v4l2_m2m_release_from_kref(struct kref *kref)
> +{
> +	struct v4l2_m2m_dev *m2m_dev = container_of(kref, struct v4l2_m2m_dev, kref);
> +
> +	v4l2_m2m_release(m2m_dev);
> +}
> +
> +void v4l2_m2m_put(struct v4l2_m2m_dev *m2m_dev)
> +{
> +	kref_put(&m2m_dev->kref, v4l2_m2m_release_from_kref);
> +}
> +EXPORT_SYMBOL_GPL(v4l2_m2m_put);
> +
>  struct v4l2_m2m_ctx *v4l2_m2m_ctx_init(struct v4l2_m2m_dev *m2m_dev,
>  		void *drv_priv,
>  		int (*queue_init)(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_vq))
> diff --git a/include/media/v4l2-mem2mem.h b/include/media/v4l2-mem2mem.h
> index bf6a09a04dcf..ca295c660c7f 100644
> --- a/include/media/v4l2-mem2mem.h
> +++ b/include/media/v4l2-mem2mem.h
> @@ -547,6 +547,27 @@ v4l2_m2m_register_media_controller(struct v4l2_m2m_dev *m2m_dev,
>   */
>  void v4l2_m2m_release(struct v4l2_m2m_dev *m2m_dev);
>
> +/**
> + * v4l2_m2m_get() - take a reference to the m2m_dev structure
> + *
> + * @m2m_dev: opaque pointer to the internal data to handle M2M context
> + *
> + * This is used to share the M2M device across multiple devices. This
> + * can be used to avoid scheduling two hardware nodes concurrently.
> + */
> +void v4l2_m2m_get(struct v4l2_m2m_dev *m2m_dev);
> +
> +/**
> + * v4l2_m2m_put() - remove a reference to the m2m_dev structure
> + *
> + * @m2m_dev: opaque pointer to the internal data to handle M2M context
> + *
> + * Once the M2M device have no more references, v4l2_m2m_realse() will be
> + * called automatically. Users of this method should never call
> + * v4l2_m2m_release() directly. See v4l2_m2m_get() for more details.
> + */
> +void v4l2_m2m_put(struct v4l2_m2m_dev *m2m_dev);
> +
>  /**
>   * v4l2_m2m_ctx_init() - allocate and initialize a m2m context
>   *
> --
> 2.52.0
>

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v3 2/3] pmdomain: imx8m-blk-ctrl: Remove separate rst and clk mask for 8mq vpu
  2025-12-04  9:08 ` [PATCH v3 2/3] pmdomain: imx8m-blk-ctrl: Remove separate rst and clk mask for 8mq vpu ming.qian
@ 2025-12-04 17:24   ` Frank Li
  0 siblings, 0 replies; 10+ messages in thread
From: Frank Li @ 2025-12-04 17:24 UTC (permalink / raw)
  To: ming.qian
  Cc: linux-media, mchehab, hverkuil-cisco, nicolas, benjamin.gaignard,
	p.zabel, sebastian.fricke, shawnguo, ulf.hansson, s.hauer, kernel,
	festevam, linux-imx, l.stach, peng.fan, eagle.zhou, imx, linux-pm,
	linux-kernel, linux-arm-kernel

On Thu, Dec 04, 2025 at 05:08:10PM +0800, ming.qian@oss.nxp.com wrote:
> From: Ming Qian <ming.qian@oss.nxp.com>
>
> For i.MX8MQ platform, the ADB in the VPUMIX domain has no separate reset
> and clock enable bits, but is ungated and reset together with the VPUs.
> So we can't reset G1 or G2 separately, it may led to the system hang.
> Remove rst_mask and clk_mask of imx8mq_vpu_blk_ctl_domain_data.
> Let imx8mq_vpu_power_notifier() do really vpu reset.
>
> Fixes: 608d7c325e85 ("soc: imx: imx8m-blk-ctrl: add i.MX8MQ VPU blk-ctrl")
> Signed-off-by: Ming Qian <ming.qian@oss.nxp.com>
> Reviewed-by: Benjamin Gaignard <benjamin.gaignard@collabora.com>
> Reviewed-by: Peng Fan <peng.fan@nxp.com>

Reviewed-by: Frank Li <Frank.Li@nxp.com>

> ---
> v3
> - Add some comments
> v2
> - Update commit message
>
>  drivers/pmdomain/imx/imx8m-blk-ctrl.c | 11 +++++++----
>  1 file changed, 7 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/pmdomain/imx/imx8m-blk-ctrl.c b/drivers/pmdomain/imx/imx8m-blk-ctrl.c
> index 5c83e5599f1e..74bf4936991d 100644
> --- a/drivers/pmdomain/imx/imx8m-blk-ctrl.c
> +++ b/drivers/pmdomain/imx/imx8m-blk-ctrl.c
> @@ -846,22 +846,25 @@ static int imx8mq_vpu_power_notifier(struct notifier_block *nb,
>  	return NOTIFY_OK;
>  }
>
> +/*
> + * For i.MX8MQ, the ADB in the VPUMIX domain has no separate reset and clock
> + * enable bits, but is ungated and reset together with the VPUs.
> + * Resetting G1 or G2 separately may led to system hang.
> + * Remove the rst_mask and clk_mask from the domain data of G1 and G2,
> + * Let imx8mq_vpu_power_notifier() do really vpu reset.
> + */
>  static const struct imx8m_blk_ctrl_domain_data imx8mq_vpu_blk_ctl_domain_data[] = {
>  	[IMX8MQ_VPUBLK_PD_G1] = {
>  		.name = "vpublk-g1",
>  		.clk_names = (const char *[]){ "g1", },
>  		.num_clks = 1,
>  		.gpc_name = "g1",
> -		.rst_mask = BIT(1),
> -		.clk_mask = BIT(1),
>  	},
>  	[IMX8MQ_VPUBLK_PD_G2] = {
>  		.name = "vpublk-g2",
>  		.clk_names = (const char *[]){ "g2", },
>  		.num_clks = 1,
>  		.gpc_name = "g2",
> -		.rst_mask = BIT(0),
> -		.clk_mask = BIT(0),
>  	},
>  };
>
> --
> 2.52.0
>

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v3 3/3] media: verisilicon: Avoid G2 bus error while decoding H.264 and HEVC
  2025-12-04  9:08 ` [PATCH v3 3/3] media: verisilicon: Avoid G2 bus error while decoding H.264 and HEVC ming.qian
@ 2025-12-04 17:34   ` Frank Li
  2025-12-04 18:15     ` Nicolas Dufresne
  0 siblings, 1 reply; 10+ messages in thread
From: Frank Li @ 2025-12-04 17:34 UTC (permalink / raw)
  To: ming.qian
  Cc: linux-media, mchehab, hverkuil-cisco, nicolas, benjamin.gaignard,
	p.zabel, sebastian.fricke, shawnguo, ulf.hansson, s.hauer, kernel,
	festevam, linux-imx, l.stach, peng.fan, eagle.zhou, imx, linux-pm,
	linux-kernel, linux-arm-kernel

On Thu, Dec 04, 2025 at 05:08:11PM +0800, ming.qian@oss.nxp.com wrote:
> From: Ming Qian <ming.qian@oss.nxp.com>
>
> For the i.MX8MQ platform, there is a hardware limitation: the g1 VPU and
> g2 VPU cannot decode simultaneously; otherwise, it will cause below bus
> error and produce corrupted pictures, even potentially lead to system hang.
>
> [  110.527986] hantro-vpu 38310000.video-codec: frame decode timed out.
> [  110.583517] hantro-vpu 38310000.video-codec: bus error detected.
>
> Therefore, it is necessary to ensure that g1 and g2 operate alternately.
> This allows for successful multi-instance decoding of H.264 and HEVC.
>
> To achieve this, we can have g1 and g2 share the same v4l2_m2m_dev, and
> then the v4l2_m2m_dev can handle the scheduling.

To achieve this, g1 and g2 share the same v4l2_m2m_dev, ...

>
> Fixes: cb5dd5a0fa518 ("media: hantro: Introduce G2/HEVC decoder")
> Co-developed-by: Nicolas Dufresne <nicolas.dufresne@collabora.com>
> Signed-off-by: Nicolas Dufresne <nicolas.dufresne@collabora.com>
> Signed-off-by: Ming Qian <ming.qian@oss.nxp.com>
> ---
> v3
> - Apply Nicolas's approach that use an array list to define the shared
>   devices
>
> v2
> - Abandon the waiting approach.
> - Switch to a shared v4l2_m2m_dev solution.
>
>  drivers/media/platform/verisilicon/hantro.h   |  2 +
>  .../media/platform/verisilicon/hantro_drv.c   | 42 +++++++++++++++++--
>  .../media/platform/verisilicon/imx8m_vpu_hw.c |  8 ++++
>  3 files changed, 49 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/media/platform/verisilicon/hantro.h b/drivers/media/platform/verisilicon/hantro.h
> index e0fdc4535b2d..0353de154a1e 100644
> --- a/drivers/media/platform/verisilicon/hantro.h
> +++ b/drivers/media/platform/verisilicon/hantro.h
> @@ -77,6 +77,7 @@ struct hantro_irq {
>   * @double_buffer:		core needs double buffering
>   * @legacy_regs:		core uses legacy register set
>   * @late_postproc:		postproc must be set up at the end of the job
> + * @shared_devices:		an array of device ids that cannot run concurrently
>   */
>  struct hantro_variant {
>  	unsigned int enc_offset;
> @@ -101,6 +102,7 @@ struct hantro_variant {
>  	unsigned int double_buffer : 1;
>  	unsigned int legacy_regs : 1;
>  	unsigned int late_postproc : 1;
> +	const struct of_device_id *shared_devices;
>  };
>
>  /**
> diff --git a/drivers/media/platform/verisilicon/hantro_drv.c b/drivers/media/platform/verisilicon/hantro_drv.c
> index 60b95b5d8565..70160eaf3d15 100644
> --- a/drivers/media/platform/verisilicon/hantro_drv.c
> +++ b/drivers/media/platform/verisilicon/hantro_drv.c
> @@ -13,6 +13,7 @@
>  #include <linux/clk.h>
>  #include <linux/module.h>
>  #include <linux/of.h>
> +#include <linux/of_platform.h>
>  #include <linux/platform_device.h>
>  #include <linux/pm.h>
>  #include <linux/pm_runtime.h>
> @@ -1035,6 +1036,41 @@ static int hantro_disable_multicore(struct hantro_dev *vpu)
>  	return 0;
>  }
>
> +static struct v4l2_m2m_dev *hantro_get_v4l2_m2m_dev(struct hantro_dev *vpu)
> +{
> +	struct device_node *node;
> +	struct hantro_dev *shared_vpu;
> +
> +	if (!vpu->variant || !vpu->variant->shared_devices)
> +		goto init_new_m2m_dev;

I found only use shared_devices here, how to  ensure that g1 and g2 operate
alternately by using shared_devices?

Frank

> +
> +	for_each_matching_node(node, vpu->variant->shared_devices) {
> +		struct platform_device *pdev;
> +		struct v4l2_m2m_dev *m2m_dev;
> +
> +		pdev = of_find_device_by_node(node);
> +		of_node_put(node);
> +
> +		if (!pdev)
> +			continue;
> +
> +		shared_vpu = platform_get_drvdata(pdev);
> +		if (IS_ERR_OR_NULL(shared_vpu) || shared_vpu == vpu) {
> +			platform_device_put(pdev);
> +			continue;
> +		}
> +
> +		v4l2_m2m_get(shared_vpu->m2m_dev);
> +		m2m_dev = shared_vpu->m2m_dev;
> +		platform_device_put(pdev);
> +
> +		return m2m_dev;
> +	}
> +
> +init_new_m2m_dev:
> +	return v4l2_m2m_init(&vpu_m2m_ops);
> +}
> +
>  static int hantro_probe(struct platform_device *pdev)
>  {
>  	const struct of_device_id *match;
> @@ -1186,7 +1222,7 @@ static int hantro_probe(struct platform_device *pdev)
>  	}
>  	platform_set_drvdata(pdev, vpu);
>
> -	vpu->m2m_dev = v4l2_m2m_init(&vpu_m2m_ops);
> +	vpu->m2m_dev = hantro_get_v4l2_m2m_dev(vpu);
>  	if (IS_ERR(vpu->m2m_dev)) {
>  		v4l2_err(&vpu->v4l2_dev, "Failed to init mem2mem device\n");
>  		ret = PTR_ERR(vpu->m2m_dev);
> @@ -1225,7 +1261,7 @@ static int hantro_probe(struct platform_device *pdev)
>  	hantro_remove_enc_func(vpu);
>  err_m2m_rel:
>  	media_device_cleanup(&vpu->mdev);
> -	v4l2_m2m_release(vpu->m2m_dev);
> +	v4l2_m2m_put(vpu->m2m_dev);
>  err_v4l2_unreg:
>  	v4l2_device_unregister(&vpu->v4l2_dev);
>  err_clk_unprepare:
> @@ -1248,7 +1284,7 @@ static void hantro_remove(struct platform_device *pdev)
>  	hantro_remove_dec_func(vpu);
>  	hantro_remove_enc_func(vpu);
>  	media_device_cleanup(&vpu->mdev);
> -	v4l2_m2m_release(vpu->m2m_dev);
> +	v4l2_m2m_put(vpu->m2m_dev);
>  	v4l2_device_unregister(&vpu->v4l2_dev);
>  	clk_bulk_unprepare(vpu->variant->num_clocks, vpu->clocks);
>  	reset_control_assert(vpu->resets);
> diff --git a/drivers/media/platform/verisilicon/imx8m_vpu_hw.c b/drivers/media/platform/verisilicon/imx8m_vpu_hw.c
> index 5be0e2e76882..6f8e43b7f157 100644
> --- a/drivers/media/platform/verisilicon/imx8m_vpu_hw.c
> +++ b/drivers/media/platform/verisilicon/imx8m_vpu_hw.c
> @@ -343,6 +343,12 @@ const struct hantro_variant imx8mq_vpu_variant = {
>  	.num_regs = ARRAY_SIZE(imx8mq_reg_names)
>  };
>
> +static const struct of_device_id imx8mq_vpu_shared_resources[] __initconst = {
> +	{ .compatible = "nxp,imx8mq-vpu-g1", },
> +	{ .compatible = "nxp,imx8mq-vpu-g2", },
> +	{ /* sentinel */ }
> +};
> +
>  const struct hantro_variant imx8mq_vpu_g1_variant = {
>  	.dec_fmts = imx8m_vpu_dec_fmts,
>  	.num_dec_fmts = ARRAY_SIZE(imx8m_vpu_dec_fmts),
> @@ -356,6 +362,7 @@ const struct hantro_variant imx8mq_vpu_g1_variant = {
>  	.num_irqs = ARRAY_SIZE(imx8mq_irqs),
>  	.clk_names = imx8mq_g1_clk_names,
>  	.num_clocks = ARRAY_SIZE(imx8mq_g1_clk_names),
> +	.shared_devices = imx8mq_vpu_shared_resources,
>  };
>
>  const struct hantro_variant imx8mq_vpu_g2_variant = {
> @@ -371,6 +378,7 @@ const struct hantro_variant imx8mq_vpu_g2_variant = {
>  	.num_irqs = ARRAY_SIZE(imx8mq_g2_irqs),
>  	.clk_names = imx8mq_g2_clk_names,
>  	.num_clocks = ARRAY_SIZE(imx8mq_g2_clk_names),
> +	.shared_devices = imx8mq_vpu_shared_resources,
>  };
>
>  const struct hantro_variant imx8mm_vpu_g1_variant = {
> --
> 2.52.0
>

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v3 3/3] media: verisilicon: Avoid G2 bus error while decoding H.264 and HEVC
  2025-12-04 17:34   ` Frank Li
@ 2025-12-04 18:15     ` Nicolas Dufresne
  2025-12-04 22:57       ` Frank Li
  0 siblings, 1 reply; 10+ messages in thread
From: Nicolas Dufresne @ 2025-12-04 18:15 UTC (permalink / raw)
  To: Frank Li, ming.qian
  Cc: linux-media, mchehab, hverkuil-cisco, benjamin.gaignard, p.zabel,
	sebastian.fricke, shawnguo, ulf.hansson, s.hauer, kernel,
	festevam, linux-imx, l.stach, peng.fan, eagle.zhou, imx, linux-pm,
	linux-kernel, linux-arm-kernel

[-- Attachment #1: Type: text/plain, Size: 1034 bytes --]

Hi Frank,

Le jeudi 04 décembre 2025 à 12:34 -0500, Frank Li a écrit :
> > +static struct v4l2_m2m_dev *hantro_get_v4l2_m2m_dev(struct hantro_dev *vpu)
> > +{
> > +	struct device_node *node;
> > +	struct hantro_dev *shared_vpu;
> > +
> > +	if (!vpu->variant || !vpu->variant->shared_devices)
> > +		goto init_new_m2m_dev;
> 
> I found only use shared_devices here, how to  ensure that g1 and g2 operate
> alternately by using shared_devices?

shared_devices is an array of of_device_id we match against. All the matching
devices will share the same v4l2_m2m_dev (aka m2m scheduler). Typically, both
cores will be schedule as one. This achieve what alternate operations without
active polling or blocking locks/mutex.

For this platform, we only matched against the compatible for simplicity, since
we know there is only one of each type. I've suggested this method to Ming,
since it will make it really easy to apply such a quirk if other hardware have
problems or design constraints.

regards,
Nicolas

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v3 3/3] media: verisilicon: Avoid G2 bus error while decoding H.264 and HEVC
  2025-12-04 18:15     ` Nicolas Dufresne
@ 2025-12-04 22:57       ` Frank Li
  2025-12-05  0:05         ` Nicolas Dufresne
  0 siblings, 1 reply; 10+ messages in thread
From: Frank Li @ 2025-12-04 22:57 UTC (permalink / raw)
  To: Nicolas Dufresne
  Cc: ming.qian, linux-media, mchehab, hverkuil-cisco,
	benjamin.gaignard, p.zabel, sebastian.fricke, shawnguo,
	ulf.hansson, s.hauer, kernel, festevam, linux-imx, l.stach,
	peng.fan, eagle.zhou, imx, linux-pm, linux-kernel,
	linux-arm-kernel

On Thu, Dec 04, 2025 at 01:15:35PM -0500, Nicolas Dufresne wrote:
> Hi Frank,
>
> Le jeudi 04 décembre 2025 à 12:34 -0500, Frank Li a écrit :
> > > +static struct v4l2_m2m_dev *hantro_get_v4l2_m2m_dev(struct hantro_dev *vpu)
> > > +{
> > > +	struct device_node *node;
> > > +	struct hantro_dev *shared_vpu;
> > > +
> > > +	if (!vpu->variant || !vpu->variant->shared_devices)
> > > +		goto init_new_m2m_dev;
> >
> > I found only use shared_devices here, how to  ensure that g1 and g2 operate
> > alternately by using shared_devices?
>
> shared_devices is an array of of_device_id we match against. All the matching
> devices will share the same v4l2_m2m_dev (aka m2m scheduler). Typically, both
> cores will be schedule as one. This achieve what alternate operations without
> active polling or blocking locks/mutex.

Okay, but this code require shared_devices==NULL's device probe firstly.
generally not order guaranteed, if there are not depentance at DT.

Does VPU always probe before g1/g2?

and if there are two VPU instances, what's happen?

Frank

>
> For this platform, we only matched against the compatible for simplicity, since
> we know there is only one of each type. I've suggested this method to Ming,
> since it will make it really easy to apply such a quirk if other hardware have
> problems or design constraints.
>
> regards,
> Nicolas



^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v3 3/3] media: verisilicon: Avoid G2 bus error while decoding H.264 and HEVC
  2025-12-04 22:57       ` Frank Li
@ 2025-12-05  0:05         ` Nicolas Dufresne
  2025-12-05 15:07           ` Frank Li
  0 siblings, 1 reply; 10+ messages in thread
From: Nicolas Dufresne @ 2025-12-05  0:05 UTC (permalink / raw)
  To: Frank Li
  Cc: ming.qian, linux-media, mchehab, hverkuil-cisco,
	benjamin.gaignard, p.zabel, sebastian.fricke, shawnguo,
	ulf.hansson, s.hauer, kernel, festevam, linux-imx, l.stach,
	peng.fan, eagle.zhou, imx, linux-pm, linux-kernel,
	linux-arm-kernel

[-- Attachment #1: Type: text/plain, Size: 2457 bytes --]

Le jeudi 04 décembre 2025 à 17:57 -0500, Frank Li a écrit :
> On Thu, Dec 04, 2025 at 01:15:35PM -0500, Nicolas Dufresne wrote:
> > Hi Frank,
> > 
> > Le jeudi 04 décembre 2025 à 12:34 -0500, Frank Li a écrit :
> > > > +static struct v4l2_m2m_dev *hantro_get_v4l2_m2m_dev(struct hantro_dev *vpu)
> > > > +{
> > > > +	struct device_node *node;
> > > > +	struct hantro_dev *shared_vpu;
> > > > +
> > > > +	if (!vpu->variant || !vpu->variant->shared_devices)
> > > > +		goto init_new_m2m_dev;
> > > 
> > > I found only use shared_devices here, how to  ensure that g1 and g2 operate
> > > alternately by using shared_devices?
> > 
> > shared_devices is an array of of_device_id we match against. All the matching
> > devices will share the same v4l2_m2m_dev (aka m2m scheduler). Typically, both
> > cores will be schedule as one. This achieve what alternate operations without
> > active polling or blocking locks/mutex.
> 
> Okay, but this code require shared_devices==NULL's device probe firstly.
> generally not order guaranteed, if there are not depentance at DT.

shared_devices is a constant array that is set inside the variant. It is
normally NULL, except for the imx8mq SoC, for which its always set.

> 
> Does VPU always probe before g1/g2?
> 
> and if there are two VPU instances, what's happen?

Since there is two VPU, g1 and g2, we will enter this loop:

> +	for_each_matching_node(node, vpu->variant->shared_devices) {

On imx8mq, this will match twice.

> +		struct platform_device *pdev;
> +		struct v4l2_m2m_dev *m2m_dev;
> +
> +		pdev = of_find_device_by_node(node);
> +		of_node_put(node);
> +
> +		if (!pdev)
> +			continue;

If the match does not have a device yet (not probe yet), we skip.

> +
> +		shared_vpu = platform_get_drvdata(pdev);
> +		if (IS_ERR_OR_NULL(shared_vpu) || shared_vpu == vpu) {
> +			platform_device_put(pdev);
> +			continue;
> +		}

If its the current VPU, we also skip.

> +
> +		v4l2_m2m_get(shared_vpu->m2m_dev);
> +		m2m_dev = shared_vpu->m2m_dev;
> +		platform_device_put(pdev);

Finally, if the other VPU was initialized, we ref the v4l2_m2m_dev. We will then
create m2m_ctx from it which will cause the two VPU to be scheduled one after
the other.

> +
> +		return m2m_dev;
> +	}

> +
> +init_new_m2m_dev:
> +	return v4l2_m2m_init(&vpu_m2m_ops);

Otherwhise we create a fresh one.

Does it make sense now ?

Nicolas

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v3 3/3] media: verisilicon: Avoid G2 bus error while decoding H.264 and HEVC
  2025-12-05  0:05         ` Nicolas Dufresne
@ 2025-12-05 15:07           ` Frank Li
  0 siblings, 0 replies; 10+ messages in thread
From: Frank Li @ 2025-12-05 15:07 UTC (permalink / raw)
  To: Nicolas Dufresne
  Cc: ming.qian, linux-media, mchehab, hverkuil-cisco,
	benjamin.gaignard, p.zabel, sebastian.fricke, shawnguo,
	ulf.hansson, s.hauer, kernel, festevam, linux-imx, l.stach,
	peng.fan, eagle.zhou, imx, linux-pm, linux-kernel,
	linux-arm-kernel

On Thu, Dec 04, 2025 at 07:05:01PM -0500, Nicolas Dufresne wrote:
> Le jeudi 04 décembre 2025 à 17:57 -0500, Frank Li a écrit :
> > On Thu, Dec 04, 2025 at 01:15:35PM -0500, Nicolas Dufresne wrote:
> > > Hi Frank,
> > >
> > > Le jeudi 04 décembre 2025 à 12:34 -0500, Frank Li a écrit :
> > > > > +static struct v4l2_m2m_dev *hantro_get_v4l2_m2m_dev(struct hantro_dev *vpu)
> > > > > +{
> > > > > +	struct device_node *node;
> > > > > +	struct hantro_dev *shared_vpu;
> > > > > +
> > > > > +	if (!vpu->variant || !vpu->variant->shared_devices)
> > > > > +		goto init_new_m2m_dev;
> > > >
> > > > I found only use shared_devices here, how to  ensure that g1 and g2 operate
> > > > alternately by using shared_devices?
> > >
> > > shared_devices is an array of of_device_id we match against. All the matching
> > > devices will share the same v4l2_m2m_dev (aka m2m scheduler). Typically, both
> > > cores will be schedule as one. This achieve what alternate operations without
> > > active polling or blocking locks/mutex.
> >
> > Okay, but this code require shared_devices==NULL's device probe firstly.
> > generally not order guaranteed, if there are not depentance at DT.
>
> shared_devices is a constant array that is set inside the variant. It is
> normally NULL, except for the imx8mq SoC, for which its always set.
>
> >
> > Does VPU always probe before g1/g2?
> >
> > and if there are two VPU instances, what's happen?
>
> Since there is two VPU, g1 and g2, we will enter this loop:
>
> > +	for_each_matching_node(node, vpu->variant->shared_devices) {
>
> On imx8mq, this will match twice.
>
> > +		struct platform_device *pdev;
> > +		struct v4l2_m2m_dev *m2m_dev;
> > +
> > +		pdev = of_find_device_by_node(node);
> > +		of_node_put(node);
> > +
> > +		if (!pdev)
> > +			continue;
>
> If the match does not have a device yet (not probe yet), we skip.
>
> > +
> > +		shared_vpu = platform_get_drvdata(pdev);
> > +		if (IS_ERR_OR_NULL(shared_vpu) || shared_vpu == vpu) {
> > +			platform_device_put(pdev);
> > +			continue;
> > +		}
>
> If its the current VPU, we also skip.
>
> > +
> > +		v4l2_m2m_get(shared_vpu->m2m_dev);
> > +		m2m_dev = shared_vpu->m2m_dev;
> > +		platform_device_put(pdev);
>
> Finally, if the other VPU was initialized, we ref the v4l2_m2m_dev. We will then
> create m2m_ctx from it which will cause the two VPU to be scheduled one after
> the other.
>
> > +
> > +		return m2m_dev;
> > +	}
>
> > +
> > +init_new_m2m_dev:
> > +	return v4l2_m2m_init(&vpu_m2m_ops);
>
> Otherwhise we create a fresh one.
>
> Does it make sense now ?

Yes, thanks for detial explain.

Frank

>
> Nicolas



^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2025-12-05 15:07 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-12-04  9:08 [PATCH v3 1/3] media: v4l2-mem2mem: Add a kref to the v4l2_m2m_dev structure ming.qian
2025-12-04  9:08 ` [PATCH v3 2/3] pmdomain: imx8m-blk-ctrl: Remove separate rst and clk mask for 8mq vpu ming.qian
2025-12-04 17:24   ` Frank Li
2025-12-04  9:08 ` [PATCH v3 3/3] media: verisilicon: Avoid G2 bus error while decoding H.264 and HEVC ming.qian
2025-12-04 17:34   ` Frank Li
2025-12-04 18:15     ` Nicolas Dufresne
2025-12-04 22:57       ` Frank Li
2025-12-05  0:05         ` Nicolas Dufresne
2025-12-05 15:07           ` Frank Li
2025-12-04 17:23 ` [PATCH v3 1/3] media: v4l2-mem2mem: Add a kref to the v4l2_m2m_dev structure Frank Li

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox