mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH 0/2] drm/atomic-helper: Support atomic flush with an optional kthread worker
@ 2025-10-31 10:21 Liu Ying
  2025-10-31 10:21 ` [PATCH 1/2] " Liu Ying
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Liu Ying @ 2025-10-31 10:21 UTC (permalink / raw)
  To: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
	David Airlie, Simona Vetter, Shawn Guo, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam
  Cc: dri-devel, linux-kernel, imx, linux-arm-kernel, Liu Ying

Hi,

As drm_atomic_helper_commit_planes() calls atomic_flush for CRTCs
sequentially and a driver's atomic_flush callback could be blocking,
the performance for flushing multiple CRTCs in a single atomic commit
could be low, like page flip for multiple CRTCs.  A real case is imx8-dc,
which supports two CRTCs and does atomic_flush in a blocking way, i.e.,
waits for a done event for loading shadow registers.

To resolve that, introduce an optional kthread worker to conduct
flush in drm_atomic_helper_commit_planes(), so that flush can run in
parallel for multiple CRTCs.

Drivers should call drmm_crtc_flush_worker_init() to initialize the
kthread worker if they want to use it.

Patch 1 adds the optional kthread worker support.
Patch 2 makes imx8-dc use the kthread worker.

Let me know your thoughts.  Thanks.

Signed-off-by: Liu Ying <victor.liu@nxp.com>
---
Liu Ying (2):
      drm/atomic-helper: Support atomic flush with an optional kthread worker
      drm/imx: dc-crtc: Use flush worker

 drivers/gpu/drm/drm_atomic_helper.c | 27 ++++++++++++++++-
 drivers/gpu/drm/drm_crtc.c          | 59 +++++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/imx/dc/dc-crtc.c    |  9 +++++-
 include/drm/drm_crtc.h              | 45 ++++++++++++++++++++++++++++
 4 files changed, 138 insertions(+), 2 deletions(-)
---
base-commit: dcb6fa37fd7bc9c3d2b066329b0d27dedf8becaa
change-id: 20251031-drm-crtc-flush-worker-0aac27acf40f

Best regards,
-- 
Liu Ying <victor.liu@nxp.com>


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

* [PATCH 1/2] drm/atomic-helper: Support atomic flush with an optional kthread worker
  2025-10-31 10:21 [PATCH 0/2] drm/atomic-helper: Support atomic flush with an optional kthread worker Liu Ying
@ 2025-10-31 10:21 ` Liu Ying
  2025-10-31 10:21 ` [PATCH 2/2] drm/imx: dc-crtc: Use flush worker Liu Ying
  2025-12-08  7:38 ` [PATCH 0/2] drm/atomic-helper: Support atomic flush with an optional kthread worker Liu Ying
  2 siblings, 0 replies; 4+ messages in thread
From: Liu Ying @ 2025-10-31 10:21 UTC (permalink / raw)
  To: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
	David Airlie, Simona Vetter, Shawn Guo, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam
  Cc: dri-devel, linux-kernel, imx, linux-arm-kernel, Liu Ying

Atomic flush could be blocking and hence potential low performance
when flushing for multiple CRTCs sequentially with
drm_atomic_helper_commit_planes(), e.g., page flip for multiple
CRTCs in a single atomic commit.  A real case is imx8-dc, where
atomic flush contains shadow load register trigger and waiting for
the shadow load done event as required by i.MX8 display controller
IP specification.  Add an optional kthread worker to conduct atomic
flush in drm_atomic_helper_commit_planes() so that multiple CRTCs
could be flushed in parallel for better performance.

Drivers should call drmm_crtc_flush_worker_init() to initialize the
kthread worker if they want to use it.

Signed-off-by: Liu Ying <victor.liu@nxp.com>
---
 drivers/gpu/drm/drm_atomic_helper.c | 27 ++++++++++++++++-
 drivers/gpu/drm/drm_crtc.c          | 59 +++++++++++++++++++++++++++++++++++++
 include/drm/drm_crtc.h              | 45 ++++++++++++++++++++++++++++
 3 files changed, 130 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
index d5ebe6ea0acbc5a08aef7fa41ecb9ed5d8fa8e80..e976facba8fc55fb8634d3d87686cd2e1c3fd31c 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -27,6 +27,7 @@
 
 #include <linux/export.h>
 #include <linux/dma-fence.h>
+#include <linux/kthread.h>
 #include <linux/ktime.h>
 
 #include <drm/drm_atomic.h>
@@ -2977,7 +2978,31 @@ void drm_atomic_helper_commit_planes(struct drm_device *dev,
 		if (active_only && !new_crtc_state->active)
 			continue;
 
-		funcs->atomic_flush(crtc, state);
+		if (crtc->flush_worker) {
+			crtc->flush_work.state = state;
+			kthread_queue_work(crtc->flush_worker, &crtc->flush_work.base);
+		} else {
+			funcs->atomic_flush(crtc, state);
+		}
+	}
+
+	/*
+	 * Iterate over all CRTCs again, to make sure flush works have finished
+	 * execution if needed.
+	 */
+	for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
+		const struct drm_crtc_helper_funcs *funcs;
+
+		funcs = crtc->helper_private;
+
+		if (!funcs || !funcs->atomic_flush)
+			continue;
+
+		if (active_only && !new_crtc_state->active)
+			continue;
+
+		if (crtc->flush_worker)
+			kthread_flush_work(&crtc->flush_work.base);
 	}
 
 	/*
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 46655339003db2a1b43441434839e26f61d79b4e..dad4182d2bb893a3e015cf0573df2c410c5ee226 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -30,7 +30,9 @@
  *      Jesse Barnes <jesse.barnes@intel.com>
  */
 #include <linux/ctype.h>
+#include <linux/kthread.h>
 #include <linux/list.h>
+#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/export.h>
 #include <linux/dma-fence.h>
@@ -41,6 +43,7 @@
 #include <drm/drm_fourcc.h>
 #include <drm/drm_framebuffer.h>
 #include <drm/drm_managed.h>
+#include <drm/drm_modeset_helper_vtables.h>
 #include <drm/drm_modeset_lock.h>
 #include <drm/drm_atomic.h>
 #include <drm/drm_auth.h>
@@ -440,6 +443,62 @@ int drmm_crtc_init_with_planes(struct drm_device *dev, struct drm_crtc *crtc,
 }
 EXPORT_SYMBOL(drmm_crtc_init_with_planes);
 
+static void drm_crtc_flush_work(struct kthread_work *work)
+{
+	struct drm_crtc_flush_work *flush_work = to_drm_crtc_flush_work(work);
+	struct drm_crtc *crtc = flush_work->crtc;
+	const struct drm_crtc_helper_funcs *funcs = crtc->helper_private;
+
+	if (funcs && funcs->atomic_flush)
+		funcs->atomic_flush(crtc, flush_work->state);
+}
+
+static void drmm_crtc_flush_worker_cleanup(struct drm_device *dev, void *ptr)
+{
+	struct drm_crtc *crtc = ptr;
+
+	kthread_destroy_worker(crtc->flush_worker);
+}
+
+/**
+ * drmm_crtc_flush_worker_init - Initialize a worker to conduct CRTC flush
+ * @dev: DRM device
+ * @crtc: CRTC object to be flushed
+ *
+ * Create a &kthread_worker used for executing flush works for the CRTC.
+ * Initialize a work item to be queued to the created &kthread_worker.
+ *
+ * Cleanup is automatically handled through registering
+ * drmm_crtc_flush_worker_cleanup() with drmm_add_action_or_reset().
+ *
+ * Returns:
+ * Zero on success, error code on failure.
+ */
+int drmm_crtc_flush_worker_init(struct drm_device *dev, struct drm_crtc *crtc)
+{
+	struct kthread_worker *flush_worker;
+	int ret;
+
+	flush_worker = kthread_create_worker(0, "card%d-crtc%u-flush",
+					     dev->primary->index, crtc->index);
+	if (IS_ERR(flush_worker))
+		return PTR_ERR(flush_worker);
+
+	crtc->flush_worker = flush_worker;
+
+	sched_set_fifo(flush_worker->task);
+
+	ret = drmm_add_action_or_reset(dev, drmm_crtc_flush_worker_cleanup, crtc);
+	if (ret)
+		return ret;
+
+	crtc->flush_work.crtc = crtc;
+	kthread_init_work(&crtc->flush_work.base, drm_crtc_flush_work);
+
+	return 0;
+}
+EXPORT_SYMBOL(drmm_crtc_flush_worker_init);
+
 void *__drmm_crtc_alloc_with_planes(struct drm_device *dev,
 				    size_t size, size_t offset,
 				    struct drm_plane *primary,
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index caa56e039da2a748cf40ebf45b37158acda439d9..62e98d714bbb4d1a948cc7c17bafbe587490b081 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -25,6 +25,7 @@
 #ifndef __DRM_CRTC_H__
 #define __DRM_CRTC_H__
 
+#include <linux/kthread.h>
 #include <linux/spinlock.h>
 #include <linux/types.h>
 #include <drm/drm_modeset_lock.h>
@@ -923,6 +924,34 @@ struct drm_crtc_funcs {
 				     bool in_vblank_irq);
 };
 
+/**
+ * struct drm_crtc_flush_work - flush work for CRTC
+ *
+ * See also:
+ * drmm_crtc_flush_worker_init()
+ */
+struct drm_crtc_flush_work {
+	/**
+	 * @base: The base &kthread_work item which will be executed by
+	 * &drm_crtc.flush_worker. Drivers should not interact with this
+	 * directly, but instead rely on drmm_crtc_flush_worker_init() to
+	 * initialize this.
+	 */
+	struct kthread_work base;
+	/** @crtc: CRTC to be flushed */
+	struct drm_crtc *crtc;
+	/** @state: pointer to global drm_atomic_state to be flushed */
+	struct drm_atomic_state *state;
+};
+
+/**
+ * to_drm_crtc_flush_work - Retrieve &drm_crtc_flush_work instance from a
+ * &kthread_work
+ * @_work: The &kthread_work embedded inside a &drm_crtc_flush_work
+ */
+#define to_drm_crtc_flush_work(_work) \
+	container_of((_work), struct drm_crtc_flush_work, base)
+
 /**
  * struct drm_crtc - central CRTC control structure
  *
@@ -1175,6 +1204,20 @@ struct drm_crtc {
 	 * Initialized via drm_self_refresh_helper_init().
 	 */
 	struct drm_self_refresh_data *self_refresh_data;
+
+	/**
+	 * @flush_worker:
+	 *
+	 * The &kthread_worker used for executing flush works.
+	 */
+	struct kthread_worker *flush_worker;
+
+	/**
+	 * @flush_work:
+	 *
+	 * Flush work to be executed by @flush_worker.
+	 */
+	struct drm_crtc_flush_work flush_work;
 };
 
 /**
@@ -1220,6 +1263,8 @@ int drmm_crtc_init_with_planes(struct drm_device *dev,
 			       const struct drm_crtc_funcs *funcs,
 			       const char *name, ...);
 
+int drmm_crtc_flush_worker_init(struct drm_device *dev, struct drm_crtc *crtc);
+
 void drm_crtc_cleanup(struct drm_crtc *crtc);
 
 __printf(7, 8)

-- 
2.34.1


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

* [PATCH 2/2] drm/imx: dc-crtc: Use flush worker
  2025-10-31 10:21 [PATCH 0/2] drm/atomic-helper: Support atomic flush with an optional kthread worker Liu Ying
  2025-10-31 10:21 ` [PATCH 1/2] " Liu Ying
@ 2025-10-31 10:21 ` Liu Ying
  2025-12-08  7:38 ` [PATCH 0/2] drm/atomic-helper: Support atomic flush with an optional kthread worker Liu Ying
  2 siblings, 0 replies; 4+ messages in thread
From: Liu Ying @ 2025-10-31 10:21 UTC (permalink / raw)
  To: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
	David Airlie, Simona Vetter, Shawn Guo, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam
  Cc: dri-devel, linux-kernel, imx, linux-arm-kernel, Liu Ying

As dc_crtc_atomic_flush() is blocking due to waiting for shadow load
done event, page flip performance could be low when atomic flush for
two CRTCs are conducted sequentially by drm_atomic_helper_commit_planes()
with a single atomic commit.  So, call drmm_crtc_flush_worker_init()
from dc_crtc_init() to initialize a flush worker for each CRTC so that
atomic flush can run in parallel by drm_atomic_helper_commit_planes()
for multiple CRTCs to achieve better page flip performance.

Signed-off-by: Liu Ying <victor.liu@nxp.com>
---
 drivers/gpu/drm/imx/dc/dc-crtc.c | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/imx/dc/dc-crtc.c b/drivers/gpu/drm/imx/dc/dc-crtc.c
index 31d3a982deaf7a0390937285c9d5d00100323181..fb1049a09296a3ecaad8d1430d818fd6e2f25a54 100644
--- a/drivers/gpu/drm/imx/dc/dc-crtc.c
+++ b/drivers/gpu/drm/imx/dc/dc-crtc.c
@@ -540,8 +540,15 @@ int dc_crtc_init(struct dc_drm_device *dc_drm, int crtc_index)
 
 	ret = drm_crtc_init_with_planes(drm, &dc_crtc->base, &dc_primary->base,
 					NULL, &dc_crtc_funcs, NULL);
-	if (ret)
+	if (ret) {
 		dev_err(de->dev, "failed to add CRTC: %d\n", ret);
+		return ret;
+	}
+
+	ret = drmm_crtc_flush_worker_init(drm, &dc_crtc->base);
+	if (ret)
+		dev_err(de->dev,
+			"failed to initialize flush worker for CRTC: %d\n", ret);
 
 	return ret;
 }

-- 
2.34.1


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

* Re: [PATCH 0/2] drm/atomic-helper: Support atomic flush with an optional kthread worker
  2025-10-31 10:21 [PATCH 0/2] drm/atomic-helper: Support atomic flush with an optional kthread worker Liu Ying
  2025-10-31 10:21 ` [PATCH 1/2] " Liu Ying
  2025-10-31 10:21 ` [PATCH 2/2] drm/imx: dc-crtc: Use flush worker Liu Ying
@ 2025-12-08  7:38 ` Liu Ying
  2 siblings, 0 replies; 4+ messages in thread
From: Liu Ying @ 2025-12-08  7:38 UTC (permalink / raw)
  To: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
	David Airlie, Simona Vetter, Shawn Guo, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam
  Cc: dri-devel, linux-kernel, imx, linux-arm-kernel

On 10/31/2025, Liu Ying wrote:
> Hi,
> 
> As drm_atomic_helper_commit_planes() calls atomic_flush for CRTCs
> sequentially and a driver's atomic_flush callback could be blocking,
> the performance for flushing multiple CRTCs in a single atomic commit
> could be low, like page flip for multiple CRTCs.  A real case is imx8-dc,
> which supports two CRTCs and does atomic_flush in a blocking way, i.e.,
> waits for a done event for loading shadow registers.
> 
> To resolve that, introduce an optional kthread worker to conduct
> flush in drm_atomic_helper_commit_planes(), so that flush can run in
> parallel for multiple CRTCs.
> 
> Drivers should call drmm_crtc_flush_worker_init() to initialize the
> kthread worker if they want to use it.
> 
> Patch 1 adds the optional kthread worker support.
> Patch 2 makes imx8-dc use the kthread worker.
> 
> Let me know your thoughts.  Thanks.

Gentle ping for review.

> 
> Signed-off-by: Liu Ying <victor.liu@nxp.com>
> ---
> Liu Ying (2):
>       drm/atomic-helper: Support atomic flush with an optional kthread worker
>       drm/imx: dc-crtc: Use flush worker
> 
>  drivers/gpu/drm/drm_atomic_helper.c | 27 ++++++++++++++++-
>  drivers/gpu/drm/drm_crtc.c          | 59 +++++++++++++++++++++++++++++++++++++
>  drivers/gpu/drm/imx/dc/dc-crtc.c    |  9 +++++-
>  include/drm/drm_crtc.h              | 45 ++++++++++++++++++++++++++++
>  4 files changed, 138 insertions(+), 2 deletions(-)
> ---
> base-commit: dcb6fa37fd7bc9c3d2b066329b0d27dedf8becaa
> change-id: 20251031-drm-crtc-flush-worker-0aac27acf40f
> 
> Best regards,

-- 
Regards,
Liu Ying

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

end of thread, other threads:[~2025-12-08  7:37 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-10-31 10:21 [PATCH 0/2] drm/atomic-helper: Support atomic flush with an optional kthread worker Liu Ying
2025-10-31 10:21 ` [PATCH 1/2] " Liu Ying
2025-10-31 10:21 ` [PATCH 2/2] drm/imx: dc-crtc: Use flush worker Liu Ying
2025-12-08  7:38 ` [PATCH 0/2] drm/atomic-helper: Support atomic flush with an optional kthread worker Liu Ying

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

all inboxes | Powered by JetHome®