All of lore.kernel.org
 help / color / mirror / Atom feed
From: Detlev Casanova <detlev.casanova@collabora.com>
To: Jacob Chen <jacob-chen@iotwrt.com>,
	Ezequiel Garcia <ezequiel@vanguardiasur.com.ar>,
	Mauro Carvalho Chehab <mchehab@kernel.org>,
	Heiko Stuebner <heiko@sntech.de>,
	Philipp Zabel <p.zabel@pengutronix.de>,
	linux-rockchip@lists.infradead.org
Cc: linux-media@vger.kernel.org, linux-rockchip@lists.infradead.org,
	linux-arm-kernel@lists.infradead.org,
	linux-kernel@vger.kernel.org, kernel@pengutronix.de,
	"Michael Tretter" <m.tretter@pengutronix.de>,
	"Sven Püschel" <s.pueschel@pengutronix.de>
Subject: Re: [PATCH 05/17] media: v4l2-mem2mem: support running multiple jobs in parallel
Date: Mon, 10 Aug 2026 11:39:32 -0400	[thread overview]
Message-ID: <f1RqEsL3T-SFEBZFuL9s-A@collabora.com> (raw)
In-Reply-To: <20260606-spu-rga3multicore-v1-5-3ec2b15675f7@pengutronix.de>

Hi Sven !

On Friday, 5 June 2026 18:06:51 EDT Sven Püschel wrote:
> Add support for running multiple jobs in parallel for SoCs containing
> multiple identical devices. An example is the Rockchip RK3588 SoC,
> which contains two identical RGA3 devices. Therefore it is desirable to
> have the kernel schedule the work across all available devices and only
> expose one video device to the userspace.
> 
> Previously the curr_ctx member of a v4l2_m2m_dev was used to track the
> currently running context. But the currently running context will always
> be at the top of the job_queue. As the TRANS_RUNNING flag can be used to
> check if the queue head is already running, the curr_ctx member can be
> completely dropped
> 
> To avoid queueing too many parallel jobs, the
> v4l2_m2m_set_max_parallel_jobs method is added. It allows a driver
> to set the number of parallel jobs and avoids calling device_run when
> the given number of jobs is already running. This is set to 1 by default
> to prevent parallel job runs. Drivers with the need and support for
> scheduling jobs can adjust this value accordingly.
> 
> Note that this change doesn't allow a context to be used multiple times
> in parallel. So a single stream won't be able to utilize multiple devices
> at once, but N streams can utilize up to N devices. This is caused by the
> fact that a context is not added multiple times to the job_list and also
> holds the job_flags to distinguish if it's currently running.
> 
> Signed-off-by: Sven Püschel <s.pueschel@pengutronix.de>
> ---
>  drivers/media/v4l2-core/v4l2-mem2mem.c | 89
> ++++++++++++++++++++++------------ include/media/v4l2-mem2mem.h           |
>  3 ++
>  2 files changed, 62 insertions(+), 30 deletions(-)
> 
> diff --git a/drivers/media/v4l2-core/v4l2-mem2mem.c
> b/drivers/media/v4l2-core/v4l2-mem2mem.c index a65cbb124cfe0..14ac9c85803d1
> 100644
> --- a/drivers/media/v4l2-core/v4l2-mem2mem.c
> +++ b/drivers/media/v4l2-core/v4l2-mem2mem.c
> @@ -84,16 +84,15 @@ static const char * const m2m_entity_name[] = {
>   *			v4l2_m2m_unregister_media_controller().
>   * @intf_devnode:	&struct media_intf devnode pointer with the interface
>   *			with controls the M2M device.
> - * @curr_ctx:		currently running instance
>   * @job_queue:		instances queued to run
>   * @job_spinlock:	protects job_queue
>   * @job_work:		worker to run queued jobs.
>   * @job_queue_flags:	flags of the queue status, %QUEUE_PAUSED.
> + * @max_parallel_jobs:	max job_queue instances number marked as running
>   * @m2m_ops:		driver callbacks
>   * @kref:		device reference count
>   */
>  struct v4l2_m2m_dev {
> -	struct v4l2_m2m_ctx	*curr_ctx;
>  #ifdef CONFIG_MEDIA_CONTROLLER
>  	struct media_entity	*source;
>  	struct media_pad	source_pad;
> @@ -108,6 +107,7 @@ struct v4l2_m2m_dev {
>  	spinlock_t		job_spinlock;
>  	struct work_struct	job_work;
>  	unsigned long		job_queue_flags;
> +	u32			max_parallel_jobs;
> 
>  	const struct v4l2_m2m_ops *m2m_ops;
> 
> @@ -123,6 +123,12 @@ static struct v4l2_m2m_queue_ctx *get_queue_ctx(struct
> v4l2_m2m_ctx *m2m_ctx, return &m2m_ctx->cap_q_ctx;
>  }
> 
> +void v4l2_m2m_set_max_parallel_jobs(struct v4l2_m2m_dev *m2m_dev,
> +				    u32 max_parallel_jobs)
> +{
> +	m2m_dev->max_parallel_jobs = max_parallel_jobs;
> +}

This needs to be exported so that drivers can use it even when compiled as 
modules.
+EXPORT_SYMBOL(v4l2_m2m_set_max_parallel_jobs);

> +
>  struct vb2_queue *v4l2_m2m_get_vq(struct v4l2_m2m_ctx *m2m_ctx,
>  				       enum v4l2_buf_type type)
>  {
> @@ -229,14 +235,22 @@ EXPORT_SYMBOL_GPL(v4l2_m2m_buf_remove_by_idx);
>  void *v4l2_m2m_get_curr_priv(struct v4l2_m2m_dev *m2m_dev)
>  {
>  	unsigned long flags;
> -	void *ret = NULL;
> +	struct v4l2_m2m_ctx *first_ctx;
> 
>  	spin_lock_irqsave(&m2m_dev->job_spinlock, flags);
> -	if (m2m_dev->curr_ctx)
> -		ret = m2m_dev->curr_ctx->priv;
> +	if (list_empty(&m2m_dev->job_queue)) {
> +		spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags);
> +		return NULL;
> +	}
> +
> +	first_ctx = list_first_entry(&m2m_dev->job_queue,
> +				     struct v4l2_m2m_ctx, queue);
>  	spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags);
> 
> -	return ret;
> +	if (first_ctx->job_flags & TRANS_RUNNING)
> +		return first_ctx->priv;
> +	else
> +		return NULL;
>  }
>  EXPORT_SYMBOL(v4l2_m2m_get_curr_priv);
> 
> @@ -252,13 +266,11 @@ EXPORT_SYMBOL(v4l2_m2m_get_curr_priv);
>  static void v4l2_m2m_try_run(struct v4l2_m2m_dev *m2m_dev)
>  {
>  	unsigned long flags;
> +	struct v4l2_m2m_ctx *ctx;
> +	struct v4l2_m2m_ctx *chosen_ctx = NULL;
> +	u32 running_jobs = 0;
> 
>  	spin_lock_irqsave(&m2m_dev->job_spinlock, flags);
> -	if (NULL != m2m_dev->curr_ctx) {
> -		spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags);
> -		dprintk("Another instance is running, won't run 
now\n");
> -		return;
> -	}
> 
>  	if (list_empty(&m2m_dev->job_queue)) {
>  		spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags);
> @@ -272,13 +284,30 @@ static void v4l2_m2m_try_run(struct v4l2_m2m_dev
> *m2m_dev) return;
>  	}
> 
> -	m2m_dev->curr_ctx = list_first_entry(&m2m_dev->job_queue,
> -				   struct v4l2_m2m_ctx, queue);
> -	m2m_dev->curr_ctx->job_flags |= TRANS_RUNNING;
> +	list_for_each_entry(ctx, &m2m_dev->job_queue, queue) {
> +		if (!(ctx->job_flags & TRANS_RUNNING)) {
> +			chosen_ctx = ctx;
> +			break;
> +		}
> +
> +		running_jobs++;
> +	}
> +	if (running_jobs >= m2m_dev->max_parallel_jobs) {
> +		spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags);
> +		dprintk("Maximum number of parallel jobs reached\n");
> +		return;
> +	}
> +	if (!chosen_ctx) {
> +		spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags);
> +		dprintk("All jobs already running\n");
> +		return;
> +	}
> +
> +	chosen_ctx->job_flags |= TRANS_RUNNING;
>  	spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags);
> 
> -	dprintk("Running job on m2m_ctx: %p\n", m2m_dev->curr_ctx);
> -	m2m_dev->m2m_ops->device_run(m2m_dev->curr_ctx->priv);
> +	dprintk("Running job on m2m_ctx: %p\n", chosen_ctx);
> +	m2m_dev->m2m_ops->device_run(chosen_ctx->priv);
>  }
> 
>  /*
> @@ -469,15 +498,14 @@ static void v4l2_m2m_schedule_next_job(struct
> v4l2_m2m_dev *m2m_dev, static bool _v4l2_m2m_job_finish(struct v4l2_m2m_dev
> *m2m_dev,
>  				 struct v4l2_m2m_ctx *m2m_ctx)
>  {
> -	if (!m2m_dev->curr_ctx || m2m_dev->curr_ctx != m2m_ctx) {
> +	if (!m2m_ctx || !(m2m_ctx->job_flags & TRANS_RUNNING)) {
>  		dprintk("Called by an instance not currently 
running\n");
>  		return false;
>  	}
> 
> -	list_del(&m2m_dev->curr_ctx->queue);
> -	m2m_dev->curr_ctx->job_flags &= ~(TRANS_QUEUED | TRANS_RUNNING);
> -	wake_up(&m2m_dev->curr_ctx->finished);
> -	m2m_dev->curr_ctx = NULL;
> +	list_del(&m2m_ctx->queue);
> +	m2m_ctx->job_flags &= ~(TRANS_QUEUED | TRANS_RUNNING);
> +	wake_up(&m2m_ctx->finished);
>  	return true;
>  }
> 
> @@ -544,16 +572,19 @@ EXPORT_SYMBOL(v4l2_m2m_buf_done_and_job_finish);
>  void v4l2_m2m_suspend(struct v4l2_m2m_dev *m2m_dev)
>  {
>  	unsigned long flags;
> -	struct v4l2_m2m_ctx *curr_ctx;
> +	struct v4l2_m2m_ctx *ctx;
> +	struct v4l2_m2m_ctx *ctx_safe;
> 
>  	spin_lock_irqsave(&m2m_dev->job_spinlock, flags);
>  	m2m_dev->job_queue_flags |= QUEUE_PAUSED;
> -	curr_ctx = m2m_dev->curr_ctx;
>  	spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags);
> 
> -	if (curr_ctx)
> -		wait_event(curr_ctx->finished,
> -			   !(curr_ctx->job_flags & TRANS_RUNNING));
> +	list_for_each_entry_safe(ctx, ctx_safe, &m2m_dev->job_queue, queue) 
{
> +		if (!(ctx->job_flags & TRANS_RUNNING))
> +			break;
> +
> +		wait_event(ctx->finished, !(ctx->job_flags & 
TRANS_RUNNING));
> +	}
>  }
>  EXPORT_SYMBOL(v4l2_m2m_suspend);
> 
> @@ -896,10 +927,8 @@ int v4l2_m2m_streamoff(struct file *file, struct
> v4l2_m2m_ctx *m2m_ctx, q_ctx->num_rdy = 0;
>  	spin_unlock_irqrestore(&q_ctx->rdy_spinlock, flags);
> 
> -	if (m2m_dev->curr_ctx == m2m_ctx) {
> -		m2m_dev->curr_ctx = NULL;
> +	if (m2m_ctx->job_flags & TRANS_RUNNING)
>  		wake_up(&m2m_ctx->finished);
> -	}
>  	spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags_job);
> 
>  	return 0;
> @@ -1194,12 +1223,12 @@ struct v4l2_m2m_dev *v4l2_m2m_init(const struct
> v4l2_m2m_ops *m2m_ops) if (!m2m_dev)
>  		return ERR_PTR(-ENOMEM);
> 
> -	m2m_dev->curr_ctx = NULL;
>  	m2m_dev->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);
> +	m2m_dev->max_parallel_jobs = 1;
> 
>  	return m2m_dev;
>  }
> diff --git a/include/media/v4l2-mem2mem.h b/include/media/v4l2-mem2mem.h
> index 31de25d792b98..e6177d0eaf637 100644
> --- a/include/media/v4l2-mem2mem.h
> +++ b/include/media/v4l2-mem2mem.h
> @@ -594,6 +594,9 @@ static inline void v4l2_m2m_set_dst_buffered(struct
> v4l2_m2m_ctx *m2m_ctx, m2m_ctx->cap_q_ctx.buffered = buffered;
>  }
> 
> +void v4l2_m2m_set_max_parallel_jobs(struct v4l2_m2m_dev *m2m_dev,
> +				    u32 max_parallel_jobs);
> +
>  /**
>   * v4l2_m2m_ctx_release() - release m2m context
>   *





_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip

WARNING: multiple messages have this Message-ID (diff)
From: Detlev Casanova <detlev.casanova@collabora.com>
To: Jacob Chen <jacob-chen@iotwrt.com>,
	Ezequiel Garcia <ezequiel@vanguardiasur.com.ar>,
	Mauro Carvalho Chehab <mchehab@kernel.org>,
	Heiko Stuebner <heiko@sntech.de>,
	Philipp Zabel <p.zabel@pengutronix.de>,
	linux-rockchip@lists.infradead.org
Cc: linux-media@vger.kernel.org, linux-rockchip@lists.infradead.org,
	linux-arm-kernel@lists.infradead.org,
	linux-kernel@vger.kernel.org, kernel@pengutronix.de,
	"Michael Tretter" <m.tretter@pengutronix.de>,
	"Sven Püschel" <s.pueschel@pengutronix.de>
Subject: Re: [PATCH 05/17] media: v4l2-mem2mem: support running multiple jobs in parallel
Date: Mon, 10 Aug 2026 11:39:32 -0400	[thread overview]
Message-ID: <f1RqEsL3T-SFEBZFuL9s-A@collabora.com> (raw)
In-Reply-To: <20260606-spu-rga3multicore-v1-5-3ec2b15675f7@pengutronix.de>

Hi Sven !

On Friday, 5 June 2026 18:06:51 EDT Sven Püschel wrote:
> Add support for running multiple jobs in parallel for SoCs containing
> multiple identical devices. An example is the Rockchip RK3588 SoC,
> which contains two identical RGA3 devices. Therefore it is desirable to
> have the kernel schedule the work across all available devices and only
> expose one video device to the userspace.
> 
> Previously the curr_ctx member of a v4l2_m2m_dev was used to track the
> currently running context. But the currently running context will always
> be at the top of the job_queue. As the TRANS_RUNNING flag can be used to
> check if the queue head is already running, the curr_ctx member can be
> completely dropped
> 
> To avoid queueing too many parallel jobs, the
> v4l2_m2m_set_max_parallel_jobs method is added. It allows a driver
> to set the number of parallel jobs and avoids calling device_run when
> the given number of jobs is already running. This is set to 1 by default
> to prevent parallel job runs. Drivers with the need and support for
> scheduling jobs can adjust this value accordingly.
> 
> Note that this change doesn't allow a context to be used multiple times
> in parallel. So a single stream won't be able to utilize multiple devices
> at once, but N streams can utilize up to N devices. This is caused by the
> fact that a context is not added multiple times to the job_list and also
> holds the job_flags to distinguish if it's currently running.
> 
> Signed-off-by: Sven Püschel <s.pueschel@pengutronix.de>
> ---
>  drivers/media/v4l2-core/v4l2-mem2mem.c | 89
> ++++++++++++++++++++++------------ include/media/v4l2-mem2mem.h           |
>  3 ++
>  2 files changed, 62 insertions(+), 30 deletions(-)
> 
> diff --git a/drivers/media/v4l2-core/v4l2-mem2mem.c
> b/drivers/media/v4l2-core/v4l2-mem2mem.c index a65cbb124cfe0..14ac9c85803d1
> 100644
> --- a/drivers/media/v4l2-core/v4l2-mem2mem.c
> +++ b/drivers/media/v4l2-core/v4l2-mem2mem.c
> @@ -84,16 +84,15 @@ static const char * const m2m_entity_name[] = {
>   *			v4l2_m2m_unregister_media_controller().
>   * @intf_devnode:	&struct media_intf devnode pointer with the interface
>   *			with controls the M2M device.
> - * @curr_ctx:		currently running instance
>   * @job_queue:		instances queued to run
>   * @job_spinlock:	protects job_queue
>   * @job_work:		worker to run queued jobs.
>   * @job_queue_flags:	flags of the queue status, %QUEUE_PAUSED.
> + * @max_parallel_jobs:	max job_queue instances number marked as running
>   * @m2m_ops:		driver callbacks
>   * @kref:		device reference count
>   */
>  struct v4l2_m2m_dev {
> -	struct v4l2_m2m_ctx	*curr_ctx;
>  #ifdef CONFIG_MEDIA_CONTROLLER
>  	struct media_entity	*source;
>  	struct media_pad	source_pad;
> @@ -108,6 +107,7 @@ struct v4l2_m2m_dev {
>  	spinlock_t		job_spinlock;
>  	struct work_struct	job_work;
>  	unsigned long		job_queue_flags;
> +	u32			max_parallel_jobs;
> 
>  	const struct v4l2_m2m_ops *m2m_ops;
> 
> @@ -123,6 +123,12 @@ static struct v4l2_m2m_queue_ctx *get_queue_ctx(struct
> v4l2_m2m_ctx *m2m_ctx, return &m2m_ctx->cap_q_ctx;
>  }
> 
> +void v4l2_m2m_set_max_parallel_jobs(struct v4l2_m2m_dev *m2m_dev,
> +				    u32 max_parallel_jobs)
> +{
> +	m2m_dev->max_parallel_jobs = max_parallel_jobs;
> +}

This needs to be exported so that drivers can use it even when compiled as 
modules.
+EXPORT_SYMBOL(v4l2_m2m_set_max_parallel_jobs);

> +
>  struct vb2_queue *v4l2_m2m_get_vq(struct v4l2_m2m_ctx *m2m_ctx,
>  				       enum v4l2_buf_type type)
>  {
> @@ -229,14 +235,22 @@ EXPORT_SYMBOL_GPL(v4l2_m2m_buf_remove_by_idx);
>  void *v4l2_m2m_get_curr_priv(struct v4l2_m2m_dev *m2m_dev)
>  {
>  	unsigned long flags;
> -	void *ret = NULL;
> +	struct v4l2_m2m_ctx *first_ctx;
> 
>  	spin_lock_irqsave(&m2m_dev->job_spinlock, flags);
> -	if (m2m_dev->curr_ctx)
> -		ret = m2m_dev->curr_ctx->priv;
> +	if (list_empty(&m2m_dev->job_queue)) {
> +		spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags);
> +		return NULL;
> +	}
> +
> +	first_ctx = list_first_entry(&m2m_dev->job_queue,
> +				     struct v4l2_m2m_ctx, queue);
>  	spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags);
> 
> -	return ret;
> +	if (first_ctx->job_flags & TRANS_RUNNING)
> +		return first_ctx->priv;
> +	else
> +		return NULL;
>  }
>  EXPORT_SYMBOL(v4l2_m2m_get_curr_priv);
> 
> @@ -252,13 +266,11 @@ EXPORT_SYMBOL(v4l2_m2m_get_curr_priv);
>  static void v4l2_m2m_try_run(struct v4l2_m2m_dev *m2m_dev)
>  {
>  	unsigned long flags;
> +	struct v4l2_m2m_ctx *ctx;
> +	struct v4l2_m2m_ctx *chosen_ctx = NULL;
> +	u32 running_jobs = 0;
> 
>  	spin_lock_irqsave(&m2m_dev->job_spinlock, flags);
> -	if (NULL != m2m_dev->curr_ctx) {
> -		spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags);
> -		dprintk("Another instance is running, won't run 
now\n");
> -		return;
> -	}
> 
>  	if (list_empty(&m2m_dev->job_queue)) {
>  		spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags);
> @@ -272,13 +284,30 @@ static void v4l2_m2m_try_run(struct v4l2_m2m_dev
> *m2m_dev) return;
>  	}
> 
> -	m2m_dev->curr_ctx = list_first_entry(&m2m_dev->job_queue,
> -				   struct v4l2_m2m_ctx, queue);
> -	m2m_dev->curr_ctx->job_flags |= TRANS_RUNNING;
> +	list_for_each_entry(ctx, &m2m_dev->job_queue, queue) {
> +		if (!(ctx->job_flags & TRANS_RUNNING)) {
> +			chosen_ctx = ctx;
> +			break;
> +		}
> +
> +		running_jobs++;
> +	}
> +	if (running_jobs >= m2m_dev->max_parallel_jobs) {
> +		spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags);
> +		dprintk("Maximum number of parallel jobs reached\n");
> +		return;
> +	}
> +	if (!chosen_ctx) {
> +		spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags);
> +		dprintk("All jobs already running\n");
> +		return;
> +	}
> +
> +	chosen_ctx->job_flags |= TRANS_RUNNING;
>  	spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags);
> 
> -	dprintk("Running job on m2m_ctx: %p\n", m2m_dev->curr_ctx);
> -	m2m_dev->m2m_ops->device_run(m2m_dev->curr_ctx->priv);
> +	dprintk("Running job on m2m_ctx: %p\n", chosen_ctx);
> +	m2m_dev->m2m_ops->device_run(chosen_ctx->priv);
>  }
> 
>  /*
> @@ -469,15 +498,14 @@ static void v4l2_m2m_schedule_next_job(struct
> v4l2_m2m_dev *m2m_dev, static bool _v4l2_m2m_job_finish(struct v4l2_m2m_dev
> *m2m_dev,
>  				 struct v4l2_m2m_ctx *m2m_ctx)
>  {
> -	if (!m2m_dev->curr_ctx || m2m_dev->curr_ctx != m2m_ctx) {
> +	if (!m2m_ctx || !(m2m_ctx->job_flags & TRANS_RUNNING)) {
>  		dprintk("Called by an instance not currently 
running\n");
>  		return false;
>  	}
> 
> -	list_del(&m2m_dev->curr_ctx->queue);
> -	m2m_dev->curr_ctx->job_flags &= ~(TRANS_QUEUED | TRANS_RUNNING);
> -	wake_up(&m2m_dev->curr_ctx->finished);
> -	m2m_dev->curr_ctx = NULL;
> +	list_del(&m2m_ctx->queue);
> +	m2m_ctx->job_flags &= ~(TRANS_QUEUED | TRANS_RUNNING);
> +	wake_up(&m2m_ctx->finished);
>  	return true;
>  }
> 
> @@ -544,16 +572,19 @@ EXPORT_SYMBOL(v4l2_m2m_buf_done_and_job_finish);
>  void v4l2_m2m_suspend(struct v4l2_m2m_dev *m2m_dev)
>  {
>  	unsigned long flags;
> -	struct v4l2_m2m_ctx *curr_ctx;
> +	struct v4l2_m2m_ctx *ctx;
> +	struct v4l2_m2m_ctx *ctx_safe;
> 
>  	spin_lock_irqsave(&m2m_dev->job_spinlock, flags);
>  	m2m_dev->job_queue_flags |= QUEUE_PAUSED;
> -	curr_ctx = m2m_dev->curr_ctx;
>  	spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags);
> 
> -	if (curr_ctx)
> -		wait_event(curr_ctx->finished,
> -			   !(curr_ctx->job_flags & TRANS_RUNNING));
> +	list_for_each_entry_safe(ctx, ctx_safe, &m2m_dev->job_queue, queue) 
{
> +		if (!(ctx->job_flags & TRANS_RUNNING))
> +			break;
> +
> +		wait_event(ctx->finished, !(ctx->job_flags & 
TRANS_RUNNING));
> +	}
>  }
>  EXPORT_SYMBOL(v4l2_m2m_suspend);
> 
> @@ -896,10 +927,8 @@ int v4l2_m2m_streamoff(struct file *file, struct
> v4l2_m2m_ctx *m2m_ctx, q_ctx->num_rdy = 0;
>  	spin_unlock_irqrestore(&q_ctx->rdy_spinlock, flags);
> 
> -	if (m2m_dev->curr_ctx == m2m_ctx) {
> -		m2m_dev->curr_ctx = NULL;
> +	if (m2m_ctx->job_flags & TRANS_RUNNING)
>  		wake_up(&m2m_ctx->finished);
> -	}
>  	spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags_job);
> 
>  	return 0;
> @@ -1194,12 +1223,12 @@ struct v4l2_m2m_dev *v4l2_m2m_init(const struct
> v4l2_m2m_ops *m2m_ops) if (!m2m_dev)
>  		return ERR_PTR(-ENOMEM);
> 
> -	m2m_dev->curr_ctx = NULL;
>  	m2m_dev->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);
> +	m2m_dev->max_parallel_jobs = 1;
> 
>  	return m2m_dev;
>  }
> diff --git a/include/media/v4l2-mem2mem.h b/include/media/v4l2-mem2mem.h
> index 31de25d792b98..e6177d0eaf637 100644
> --- a/include/media/v4l2-mem2mem.h
> +++ b/include/media/v4l2-mem2mem.h
> @@ -594,6 +594,9 @@ static inline void v4l2_m2m_set_dst_buffered(struct
> v4l2_m2m_ctx *m2m_ctx, m2m_ctx->cap_q_ctx.buffered = buffered;
>  }
> 
> +void v4l2_m2m_set_max_parallel_jobs(struct v4l2_m2m_dev *m2m_dev,
> +				    u32 max_parallel_jobs);
> +
>  /**
>   * v4l2_m2m_ctx_release() - release m2m context
>   *





  parent reply	other threads:[~2026-08-10 15:39 UTC|newest]

Thread overview: 60+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-06-05 22:06 [PATCH 00/17] media: rockchip: rga: Add multi-core support Sven Püschel
2026-06-05 22:06 ` Sven Püschel
2026-06-05 22:06 ` [PATCH 01/17] media: rockchip: rga: zero cmdbuf in shared code Sven Püschel
2026-06-05 22:06   ` Sven Püschel
2026-06-05 22:20   ` sashiko-bot
2026-06-05 22:06 ` [PATCH 02/17] media: rockchip: rga: add comment about pixel alignment for YUV formats Sven Püschel
2026-06-05 22:06   ` Sven Püschel
2026-06-05 22:06 ` [PATCH 03/17] media: rockchip: rga: move early return into if condition in vidioc_enum_fmt Sven Püschel
2026-06-05 22:06   ` Sven Püschel
2026-06-05 22:06 ` [PATCH 04/17] media: rockchip: rga: removed unused regmap member Sven Püschel
2026-06-05 22:06   ` Sven Püschel
2026-06-05 22:06 ` [PATCH 05/17] media: v4l2-mem2mem: support running multiple jobs in parallel Sven Püschel
2026-06-05 22:06   ` Sven Püschel
2026-06-05 22:18   ` sashiko-bot
2026-07-10 21:18   ` Nicolas Dufresne
2026-07-10 21:18     ` Nicolas Dufresne
2026-07-15  9:44     ` Sven Püschel
2026-07-15  9:44       ` Sven Püschel
2026-08-10 15:44       ` Detlev Casanova
2026-08-10 15:44         ` Detlev Casanova
2026-08-10 15:39   ` Detlev Casanova [this message]
2026-08-10 15:39     ` Detlev Casanova
2026-06-05 22:06 ` [PATCH 06/17] media: rockchip: rga: move power handling to device_run Sven Püschel
2026-06-05 22:06   ` Sven Püschel
2026-06-05 22:22   ` sashiko-bot
2026-06-05 22:06 ` [PATCH 07/17] media: rockchip: rga: adjust get_version to return the version Sven Püschel
2026-06-05 22:06   ` Sven Püschel
2026-06-05 22:06 ` [PATCH 08/17] media: rockchip: rga: add rga_core structure Sven Püschel
2026-06-05 22:06   ` Sven Püschel
2026-06-05 22:22   ` sashiko-bot
2026-07-10 21:03     ` Nicolas Dufresne
2026-06-05 22:06 ` [PATCH 09/17] media: rockchip: rga: use components to manage multiple cores Sven Püschel
2026-06-05 22:06   ` Sven Püschel
2026-06-05 22:24   ` sashiko-bot
2026-06-05 22:06 ` [PATCH 10/17] media: rockchip: rga: move rockchip_rga allocation to master probe Sven Püschel
2026-06-05 22:06   ` Sven Püschel
2026-06-05 22:23   ` sashiko-bot
2026-06-05 22:06 ` [PATCH 11/17] media: rockchip: rga: move video device to the master Sven Püschel
2026-06-05 22:06   ` Sven Püschel
2026-06-05 22:21   ` sashiko-bot
2026-06-05 22:06 ` [PATCH 12/17] media: rockchip: rga: move core initialization from bind to probe Sven Püschel
2026-06-05 22:06   ` Sven Püschel
2026-06-05 22:20   ` sashiko-bot
2026-07-10 21:05     ` Nicolas Dufresne
2026-06-05 22:06 ` [PATCH 13/17] media: rockchip: rga: bind all cores to the master Sven Püschel
2026-06-05 22:06   ` Sven Püschel
2026-06-05 22:23   ` sashiko-bot
2026-07-10 21:06   ` Nicolas Dufresne
2026-07-10 21:06     ` Nicolas Dufresne
2026-06-05 22:07 ` [PATCH 14/17] media: rockchip: rga: put all cores into first core iommu domain Sven Püschel
2026-06-05 22:07   ` Sven Püschel
2026-06-05 22:23   ` sashiko-bot
2026-06-05 22:07 ` [PATCH 15/17] media: rockchip: rga: schedule jobs to multiple cores Sven Püschel
2026-06-05 22:07   ` Sven Püschel
2026-06-05 22:25   ` sashiko-bot
2026-06-05 22:07 ` [PATCH 16/17] arm64: dts: rockchip: add rga3 dt nodes to rk3588 Sven Püschel
2026-06-05 22:07   ` Sven Püschel
2026-06-05 22:07 ` [PATCH 17/17] iommu/rockchip: disable fetch dte time limit Sven Püschel
2026-06-05 22:07   ` Sven Püschel
2026-06-05 22:26   ` sashiko-bot

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=f1RqEsL3T-SFEBZFuL9s-A@collabora.com \
    --to=detlev.casanova@collabora.com \
    --cc=ezequiel@vanguardiasur.com.ar \
    --cc=heiko@sntech.de \
    --cc=jacob-chen@iotwrt.com \
    --cc=kernel@pengutronix.de \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-media@vger.kernel.org \
    --cc=linux-rockchip@lists.infradead.org \
    --cc=m.tretter@pengutronix.de \
    --cc=mchehab@kernel.org \
    --cc=p.zabel@pengutronix.de \
    --cc=s.pueschel@pengutronix.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.