All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH RFC 0/8] drm: Add DRM_MODE_ATOMIC_RESET flag
@ 2026-07-08 16:08 Maxime Ripard
  2026-07-08 16:08 ` [PATCH RFC 1/8] drm/atomic: colorop: Rename state to state_to_destroy Maxime Ripard
                   ` (9 more replies)
  0 siblings, 10 replies; 15+ messages in thread
From: Maxime Ripard @ 2026-07-08 16:08 UTC (permalink / raw)
  To: Maarten Lankhorst, Thomas Zimmermann, David Airlie, Simona Vetter
  Cc: Daniel Stone, Harry Wentland, Jonas Ådahl,
	Michel Dänzer, Pekka Paalanen, Sebastian Wick, Simon Ser,
	Victoria Brekenfeld, Xaver Hugl, dri-devel, linux-kernel,
	Maxime Ripard

Hi,

Userspace currently has no atomic way to bring a display pipeline back
to a pristine state. A compositor that wants to start from a known
baseline must explicitly set every property on every KMS object to its
default value, which requires tracking which properties exist and what
their defaults are. This is fragile and must be updated every time a
new property is added to the kernel.

This series introduces a new DRM_MODE_ATOMIC_RESET flag for the
atomic ioctl. When set, the kernel fills the commit with default
states for all KMS objects before applying the properties supplied in
the request. Properties not explicitly included remain at their
defaults (CRTCs inactive, planes disabled, connectors unbound, and so
on). This allows userspace to describe the desired end state
declaratively, without having to care about the current state or the
full set of properties.

The first patch is a small cleanup aligning __drm_colorops_state with
the naming convention used by the other atomic state tracking
structures.

Patches 2 through 6 extract the state insertion logic from each
drm_atomic_get_*_state() function into standalone helpers. This is
needed because the new fill_with_defaults path creates states through
atomic_create_state() rather than atomic_duplicate_state(), so it
cannot go through the existing drm_atomic_get_*_state() functions.

Patch 7 adds drm_atomic_commit_fill_with_defaults(), which uses those
helpers to populate a commit with pristine states for every object in
the device.

Patch 8 wires it all up by adding DRM_MODE_ATOMIC_RESET to the atomic
ioctl.

Open question: should DRM_MODE_ATOMIC_RESET require
DRM_MODE_ATOMIC_ALLOW_MODESET? A full state reset will change CRTC
active states, which is effectively a modeset. Without requiring it,
a reset could pass flag validation but fail later at atomic_check in
a confusing way.

This series is untested and relies on all drivers implementing the
atomic_create_state hook, which is not yet the case. The conversion
is actively in progress but not complete, so this will not work as-is
today. Sending it now to get early feedback on the approach.

Signed-off-by: Maxime Ripard <mripard@kernel.org>
---
Maxime Ripard (7):
      drm/atomic: colorop: Rename state to state_to_destroy
      drm/atomic: Create function to insert CRTC state into a commit
      drm/atomic: Create function to insert plane state into a commit
      drm/atomic: Create function to insert colorop state into a commit
      drm/atomic: Create function to insert private obj state into a commit
      drm/atomic: Create function to insert connector state into a commit
      drm/atomic: Allow filling a commit with pristine object states

Sebastian Wick (1):
      drm/atomic-uapi: Add DRM_MODE_ATOMIC_RESET flag

 drivers/gpu/drm/drm_atomic.c        | 327 +++++++++++++++++++++++++++++-------
 drivers/gpu/drm/drm_atomic_helper.c |   2 +-
 drivers/gpu/drm/drm_atomic_uapi.c   |  13 ++
 include/drm/drm_atomic.h            |  19 ++-
 include/uapi/drm/drm_mode.h         |  14 +-
 5 files changed, 307 insertions(+), 68 deletions(-)
---
base-commit: cff96362794a5c1f3adb013b4a46c7233149a629
change-id: 20260708-drm-reset-state-flag-2fb2b5711f97

Best regards,
-- 
Maxime Ripard <mripard@kernel.org>


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

* [PATCH RFC 1/8] drm/atomic: colorop: Rename state to state_to_destroy
  2026-07-08 16:08 [PATCH RFC 0/8] drm: Add DRM_MODE_ATOMIC_RESET flag Maxime Ripard
@ 2026-07-08 16:08 ` Maxime Ripard
  2026-07-08 16:16   ` sashiko-bot
  2026-07-08 16:08 ` [PATCH RFC 2/8] drm/atomic: Create function to insert CRTC state into a commit Maxime Ripard
                   ` (8 subsequent siblings)
  9 siblings, 1 reply; 15+ messages in thread
From: Maxime Ripard @ 2026-07-08 16:08 UTC (permalink / raw)
  To: Maarten Lankhorst, Thomas Zimmermann, David Airlie, Simona Vetter
  Cc: Daniel Stone, Harry Wentland, Jonas Ådahl,
	Michel Dänzer, Pekka Paalanen, Sebastian Wick, Simon Ser,
	Victoria Brekenfeld, Xaver Hugl, dri-devel, linux-kernel,
	Maxime Ripard

The atomic state tracking structures used to have a generic state
field to track the state to free when tearing down the
drm_atomic_commit. It has since been renamed to state_to_destroy in
__drm_planes_state, __drm_crtcs_state, __drm_connnectors_state, and
__drm_private_objs_state to better describe its purpose.

The colorop support has been added after that rename, but
__drm_colorops_state still uses the old state name. Rename it to
state_to_destroy for consistency, and add the matching kerneldoc.

Signed-off-by: Maxime Ripard <mripard@kernel.org>
---
 drivers/gpu/drm/drm_atomic.c        |  4 ++--
 drivers/gpu/drm/drm_atomic_helper.c |  2 +-
 include/drm/drm_atomic.h            | 18 +++++++++++++++++-
 3 files changed, 20 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index 735ab7badc2e..4bc6bdfb6f1f 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -341,13 +341,13 @@ void drm_atomic_commit_default_clear(struct drm_atomic_commit *state)
 
 		if (!colorop)
 			continue;
 
 		drm_colorop_atomic_destroy_state(colorop,
-						 state->colorops[i].state);
+						 state->colorops[i].state_to_destroy);
 		state->colorops[i].ptr = NULL;
-		state->colorops[i].state = NULL;
+		state->colorops[i].state_to_destroy = NULL;
 		state->colorops[i].old_state = NULL;
 		state->colorops[i].new_state = NULL;
 	}
 
 	for (i = 0; i < state->num_private_objs; i++) {
diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
index 285aac3554df..c4752bd7d999 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -3349,11 +3349,11 @@ int drm_atomic_helper_swap_state(struct drm_atomic_commit *state,
 		WARN_ON(colorop->state != old_colorop_state);
 
 		old_colorop_state->state = state;
 		new_colorop_state->state = NULL;
 
-		state->colorops[i].state = old_colorop_state;
+		state->colorops[i].state_to_destroy = old_colorop_state;
 		colorop->state = new_colorop_state;
 	}
 
 	drm_panic_lock(state->dev, flags);
 	for_each_oldnew_plane_in_state(state, plane, old_plane_state, new_plane_state, i) {
diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h
index 88087910ab1a..00b3e9fc429a 100644
--- a/include/drm/drm_atomic.h
+++ b/include/drm/drm_atomic.h
@@ -157,11 +157,27 @@ struct drm_crtc_commit {
 	bool abort_completion;
 };
 
 struct __drm_colorops_state {
 	struct drm_colorop *ptr;
-	struct drm_colorop_state *state, *old_state, *new_state;
+
+	/**
+	 * @state_to_destroy:
+	 *
+	 * Used to track the @drm_colorop_state we will need to free
+	 * when tearing down the associated &drm_atomic_commit in
+	 * $drm_mode_config_funcs.atomic_state_clear or
+	 * drm_atomic_commit_default_clear().
+	 *
+	 * Before a commit, and the call to
+	 * drm_atomic_helper_swap_state() in particular, it points to
+	 * the same state than @new_state. After a commit, it points to
+	 * the same state than @old_state.
+	 */
+	struct drm_colorop_state *state_to_destroy;
+
+	struct drm_colorop_state *old_state, *new_state;
 };
 
 struct __drm_planes_state {
 	struct drm_plane *ptr;
 

-- 
2.54.0


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

* [PATCH RFC 2/8] drm/atomic: Create function to insert CRTC state into a commit
  2026-07-08 16:08 [PATCH RFC 0/8] drm: Add DRM_MODE_ATOMIC_RESET flag Maxime Ripard
  2026-07-08 16:08 ` [PATCH RFC 1/8] drm/atomic: colorop: Rename state to state_to_destroy Maxime Ripard
@ 2026-07-08 16:08 ` Maxime Ripard
  2026-07-08 16:08 ` [PATCH RFC 3/8] drm/atomic: Create function to insert plane " Maxime Ripard
                   ` (7 subsequent siblings)
  9 siblings, 0 replies; 15+ messages in thread
From: Maxime Ripard @ 2026-07-08 16:08 UTC (permalink / raw)
  To: Maarten Lankhorst, Thomas Zimmermann, David Airlie, Simona Vetter
  Cc: Daniel Stone, Harry Wentland, Jonas Ådahl,
	Michel Dänzer, Pekka Paalanen, Sebastian Wick, Simon Ser,
	Victoria Brekenfeld, Xaver Hugl, dri-devel, linux-kernel,
	Maxime Ripard

drm_atomic_get_crtc_state() allocates a new CRTC state by duplicating
the current one and inserts it into the atomic commit as a single
operation.

However, a later change will need to insert a CRTC state into a
commit without going through the full allocation and duplication path
in drm_atomic_get_crtc_state().

Extract the state insertion logic into a new static
drm_atomic_commit_set_crtc_state() helper, and convert
drm_atomic_get_crtc_state() to use it.

Signed-off-by: Maxime Ripard <mripard@kernel.org>
---
 drivers/gpu/drm/drm_atomic.c | 29 +++++++++++++++++++++++------
 1 file changed, 23 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index 4bc6bdfb6f1f..4ffe5147ab16 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -421,10 +421,27 @@ void __drm_atomic_commit_free(struct kref *ref)
 
 	drm_dev_put(dev);
 }
 EXPORT_SYMBOL(__drm_atomic_commit_free);
 
+static int drm_atomic_commit_set_crtc_state(struct drm_atomic_commit *commit,
+					    struct drm_crtc *crtc,
+					    struct drm_crtc_state *crtc_state)
+{
+	int index = drm_crtc_index(crtc);
+
+	drm_modeset_lock_assert_held(&crtc->mutex);
+
+	commit->crtcs[index].state_to_destroy = crtc_state;
+	commit->crtcs[index].old_state = crtc->state;
+	commit->crtcs[index].new_state = crtc_state;
+	commit->crtcs[index].ptr = crtc;
+	crtc_state->state = commit;
+
+	return 0;
+}
+
 /**
  * drm_atomic_get_crtc_state - get CRTC state
  * @state: global atomic state object
  * @crtc: CRTC to get state object for
  *
@@ -443,11 +460,11 @@ EXPORT_SYMBOL(__drm_atomic_commit_free);
  */
 struct drm_crtc_state *
 drm_atomic_get_crtc_state(struct drm_atomic_commit *state,
 			  struct drm_crtc *crtc)
 {
-	int ret, index = drm_crtc_index(crtc);
+	int ret;
 	struct drm_crtc_state *crtc_state;
 
 	WARN_ON(!state->acquire_ctx);
 	drm_WARN_ON(state->dev, state->checked);
 
@@ -461,15 +478,15 @@ drm_atomic_get_crtc_state(struct drm_atomic_commit *state,
 
 	crtc_state = crtc->funcs->atomic_duplicate_state(crtc);
 	if (!crtc_state)
 		return ERR_PTR(-ENOMEM);
 
-	state->crtcs[index].state_to_destroy = crtc_state;
-	state->crtcs[index].old_state = crtc->state;
-	state->crtcs[index].new_state = crtc_state;
-	state->crtcs[index].ptr = crtc;
-	crtc_state->state = state;
+	ret = drm_atomic_commit_set_crtc_state(state, crtc, crtc_state);
+	if (ret) {
+		crtc->funcs->atomic_destroy_state(crtc, crtc_state);
+		return ERR_PTR(ret);
+	}
 
 	drm_dbg_atomic(state->dev, "Added [CRTC:%d:%s] %p state to %p\n",
 		       crtc->base.id, crtc->name, crtc_state, state);
 
 	return crtc_state;

-- 
2.54.0


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

* [PATCH RFC 3/8] drm/atomic: Create function to insert plane state into a commit
  2026-07-08 16:08 [PATCH RFC 0/8] drm: Add DRM_MODE_ATOMIC_RESET flag Maxime Ripard
  2026-07-08 16:08 ` [PATCH RFC 1/8] drm/atomic: colorop: Rename state to state_to_destroy Maxime Ripard
  2026-07-08 16:08 ` [PATCH RFC 2/8] drm/atomic: Create function to insert CRTC state into a commit Maxime Ripard
@ 2026-07-08 16:08 ` Maxime Ripard
  2026-07-08 16:08 ` [PATCH RFC 4/8] drm/atomic: Create function to insert colorop " Maxime Ripard
                   ` (6 subsequent siblings)
  9 siblings, 0 replies; 15+ messages in thread
From: Maxime Ripard @ 2026-07-08 16:08 UTC (permalink / raw)
  To: Maarten Lankhorst, Thomas Zimmermann, David Airlie, Simona Vetter
  Cc: Daniel Stone, Harry Wentland, Jonas Ådahl,
	Michel Dänzer, Pekka Paalanen, Sebastian Wick, Simon Ser,
	Victoria Brekenfeld, Xaver Hugl, dri-devel, linux-kernel,
	Maxime Ripard

drm_atomic_get_plane_state() allocates a new plane state by
duplicating the current one and inserts it into the atomic commit as
a single operation.

However, a later change will need to insert a plane state into a
commit without going through the full allocation and duplication path
in drm_atomic_get_plane_state().

Extract the state insertion logic into a new static
drm_atomic_commit_set_plane_state() helper, and convert
drm_atomic_get_plane_state() to use it.

Signed-off-by: Maxime Ripard <mripard@kernel.org>
---
 drivers/gpu/drm/drm_atomic.c | 29 +++++++++++++++++++++++------
 1 file changed, 23 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index 4ffe5147ab16..56542494ab56 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -624,10 +624,27 @@ static int drm_atomic_connector_check(struct drm_connector *connector,
 	}
 
 	return 0;
 }
 
+static int drm_atomic_commit_set_plane_state(struct drm_atomic_commit *commit,
+					     struct drm_plane *plane,
+					     struct drm_plane_state *plane_state)
+{
+	int index = drm_plane_index(plane);
+
+	drm_modeset_lock_assert_held(&plane->mutex);
+
+	commit->planes[index].state_to_destroy = plane_state;
+	commit->planes[index].old_state = plane->state;
+	commit->planes[index].new_state = plane_state;
+	commit->planes[index].ptr = plane;
+	plane_state->state = commit;
+
+	return 0;
+}
+
 /**
  * drm_atomic_get_plane_state - get plane state
  * @state: global atomic state object
  * @plane: plane to get state object for
  *
@@ -642,11 +659,11 @@ static int drm_atomic_connector_check(struct drm_connector *connector,
  */
 struct drm_plane_state *
 drm_atomic_get_plane_state(struct drm_atomic_commit *state,
 			  struct drm_plane *plane)
 {
-	int ret, index = drm_plane_index(plane);
+	int ret;
 	struct drm_plane_state *plane_state;
 
 	WARN_ON(!state->acquire_ctx);
 	drm_WARN_ON(state->dev, state->checked);
 
@@ -665,15 +682,15 @@ drm_atomic_get_plane_state(struct drm_atomic_commit *state,
 
 	plane_state = plane->funcs->atomic_duplicate_state(plane);
 	if (!plane_state)
 		return ERR_PTR(-ENOMEM);
 
-	state->planes[index].state_to_destroy = plane_state;
-	state->planes[index].ptr = plane;
-	state->planes[index].old_state = plane->state;
-	state->planes[index].new_state = plane_state;
-	plane_state->state = state;
+	ret = drm_atomic_commit_set_plane_state(state, plane, plane_state);
+	if (ret) {
+		plane->funcs->atomic_destroy_state(plane, plane_state);
+		return ERR_PTR(ret);
+	}
 
 	drm_dbg_atomic(plane->dev, "Added [PLANE:%d:%s] %p state to %p\n",
 		       plane->base.id, plane->name, plane_state, state);
 
 	if (plane_state->crtc) {

-- 
2.54.0


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

* [PATCH RFC 4/8] drm/atomic: Create function to insert colorop state into a commit
  2026-07-08 16:08 [PATCH RFC 0/8] drm: Add DRM_MODE_ATOMIC_RESET flag Maxime Ripard
                   ` (2 preceding siblings ...)
  2026-07-08 16:08 ` [PATCH RFC 3/8] drm/atomic: Create function to insert plane " Maxime Ripard
@ 2026-07-08 16:08 ` Maxime Ripard
  2026-07-08 16:08 ` [PATCH RFC 5/8] drm/atomic: Create function to insert private obj " Maxime Ripard
                   ` (5 subsequent siblings)
  9 siblings, 0 replies; 15+ messages in thread
From: Maxime Ripard @ 2026-07-08 16:08 UTC (permalink / raw)
  To: Maarten Lankhorst, Thomas Zimmermann, David Airlie, Simona Vetter
  Cc: Daniel Stone, Harry Wentland, Jonas Ådahl,
	Michel Dänzer, Pekka Paalanen, Sebastian Wick, Simon Ser,
	Victoria Brekenfeld, Xaver Hugl, dri-devel, linux-kernel,
	Maxime Ripard

drm_atomic_get_colorop_state() allocates a new colorop state by
duplicating the current one and inserts it into the atomic commit as
a single operation.

However, a later change will need to insert a colorop state into a
commit without going through the full allocation and duplication path
in drm_atomic_get_colorop_state().

Extract the state insertion logic into a new static
drm_atomic_commit_set_colorop_state() helper, and convert
drm_atomic_get_colorop_state() to use it.

Signed-off-by: Maxime Ripard <mripard@kernel.org>
---
 drivers/gpu/drm/drm_atomic.c | 29 +++++++++++++++++++++++------
 1 file changed, 23 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index 56542494ab56..f006de9b7263 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -704,10 +704,27 @@ drm_atomic_get_plane_state(struct drm_atomic_commit *state,
 
 	return plane_state;
 }
 EXPORT_SYMBOL(drm_atomic_get_plane_state);
 
+static int drm_atomic_commit_set_colorop_state(struct drm_atomic_commit *commit,
+					       struct drm_colorop *colorop,
+					       struct drm_colorop_state *colorop_state)
+{
+	int index = drm_colorop_index(colorop);
+
+	drm_modeset_lock_assert_held(&colorop->plane->mutex);
+
+	commit->colorops[index].state_to_destroy = colorop_state;
+	commit->colorops[index].old_state = colorop->state;
+	commit->colorops[index].new_state = colorop_state;
+	commit->colorops[index].ptr = colorop;
+	colorop_state->state = commit;
+
+	return 0;
+}
+
 /**
  * drm_atomic_get_colorop_state - get colorop state
  * @state: global atomic state object
  * @colorop: colorop to get state object for
  *
@@ -723,11 +740,11 @@ EXPORT_SYMBOL(drm_atomic_get_plane_state);
  */
 struct drm_colorop_state *
 drm_atomic_get_colorop_state(struct drm_atomic_commit *state,
 			     struct drm_colorop *colorop)
 {
-	int ret, index = drm_colorop_index(colorop);
+	int ret;
 	struct drm_colorop_state *colorop_state;
 
 	WARN_ON(!state->acquire_ctx);
 
 	colorop_state = drm_atomic_get_new_colorop_state(state, colorop);
@@ -740,15 +757,15 @@ drm_atomic_get_colorop_state(struct drm_atomic_commit *state,
 
 	colorop_state = drm_atomic_helper_colorop_duplicate_state(colorop);
 	if (!colorop_state)
 		return ERR_PTR(-ENOMEM);
 
-	state->colorops[index].state = colorop_state;
-	state->colorops[index].ptr = colorop;
-	state->colorops[index].old_state = colorop->state;
-	state->colorops[index].new_state = colorop_state;
-	colorop_state->state = state;
+	ret = drm_atomic_commit_set_colorop_state(state, colorop, colorop_state);
+	if (ret) {
+		drm_colorop_atomic_destroy_state(colorop, colorop_state);
+		return ERR_PTR(ret);
+	}
 
 	drm_dbg_atomic(colorop->dev, "Added [COLOROP:%d:%d] %p state to %p\n",
 		       colorop->base.id, colorop->type, colorop_state, state);
 
 	return colorop_state;

-- 
2.54.0


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

* [PATCH RFC 5/8] drm/atomic: Create function to insert private obj state into a commit
  2026-07-08 16:08 [PATCH RFC 0/8] drm: Add DRM_MODE_ATOMIC_RESET flag Maxime Ripard
                   ` (3 preceding siblings ...)
  2026-07-08 16:08 ` [PATCH RFC 4/8] drm/atomic: Create function to insert colorop " Maxime Ripard
@ 2026-07-08 16:08 ` Maxime Ripard
  2026-07-08 16:08 ` [PATCH RFC 6/8] drm/atomic: Create function to insert connector " Maxime Ripard
                   ` (4 subsequent siblings)
  9 siblings, 0 replies; 15+ messages in thread
From: Maxime Ripard @ 2026-07-08 16:08 UTC (permalink / raw)
  To: Maarten Lankhorst, Thomas Zimmermann, David Airlie, Simona Vetter
  Cc: Daniel Stone, Harry Wentland, Jonas Ådahl,
	Michel Dänzer, Pekka Paalanen, Sebastian Wick, Simon Ser,
	Victoria Brekenfeld, Xaver Hugl, dri-devel, linux-kernel,
	Maxime Ripard

drm_atomic_get_private_obj_state() allocates a new private object
state by duplicating the current one and inserts it into the atomic
commit as a single operation.

However, a later change will need to insert a private object state
into a commit without going through the full allocation and
duplication path in drm_atomic_get_private_obj_state().

Extract the state insertion logic, including the array reallocation,
into a new static drm_atomic_commit_set_private_obj_state() helper,
and convert drm_atomic_get_private_obj_state() to use it.

Signed-off-by: Maxime Ripard <mripard@kernel.org>
---
 drivers/gpu/drm/drm_atomic.c | 57 ++++++++++++++++++++++++++++----------------
 1 file changed, 37 insertions(+), 20 deletions(-)

diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index f006de9b7263..d4dcab2d851c 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -1097,10 +1097,41 @@ drm_atomic_private_obj_fini(struct drm_private_obj *obj)
 	obj->funcs->atomic_destroy_state(obj, obj->state);
 	drm_modeset_lock_fini(&obj->lock);
 }
 EXPORT_SYMBOL(drm_atomic_private_obj_fini);
 
+static int drm_atomic_commit_set_private_obj_state(struct drm_atomic_commit *commit,
+						   struct drm_private_obj *obj,
+						   struct drm_private_state *obj_state)
+{
+	struct __drm_private_objs_state *arr;
+	int index, num_objs;
+	size_t size;
+
+	drm_modeset_lock_assert_held(&obj->lock);
+
+	num_objs = commit->num_private_objs + 1;
+	size = sizeof(*commit->private_objs) * num_objs;
+	arr = krealloc(commit->private_objs, size, GFP_KERNEL);
+	if (!arr)
+		return -ENOMEM;
+
+	commit->private_objs = arr;
+	index = commit->num_private_objs;
+	memset(&commit->private_objs[index], 0, sizeof(*commit->private_objs));
+
+	commit->private_objs[index].state_to_destroy = obj_state;
+	commit->private_objs[index].old_state = obj->state;
+	commit->private_objs[index].new_state = obj_state;
+	commit->private_objs[index].ptr = obj;
+	obj_state->state = commit;
+
+	commit->num_private_objs = num_objs;
+
+	return 0;
+}
+
 /**
  * drm_atomic_get_private_obj_state - get private object state
  * @state: global atomic state
  * @obj: private object to get the state for
  *
@@ -1113,13 +1144,11 @@ EXPORT_SYMBOL(drm_atomic_private_obj_fini);
  */
 struct drm_private_state *
 drm_atomic_get_private_obj_state(struct drm_atomic_commit *state,
 				 struct drm_private_obj *obj)
 {
-	int index, num_objs, ret;
-	size_t size;
-	struct __drm_private_objs_state *arr;
+	int ret;
 	struct drm_private_state *obj_state;
 
 	WARN_ON(!state->acquire_ctx);
 	drm_WARN_ON(state->dev, state->checked);
 
@@ -1129,31 +1158,19 @@ drm_atomic_get_private_obj_state(struct drm_atomic_commit *state,
 
 	ret = drm_modeset_lock(&obj->lock, state->acquire_ctx);
 	if (ret)
 		return ERR_PTR(ret);
 
-	num_objs = state->num_private_objs + 1;
-	size = sizeof(*state->private_objs) * num_objs;
-	arr = krealloc(state->private_objs, size, GFP_KERNEL);
-	if (!arr)
-		return ERR_PTR(-ENOMEM);
-
-	state->private_objs = arr;
-	index = state->num_private_objs;
-	memset(&state->private_objs[index], 0, sizeof(*state->private_objs));
-
 	obj_state = obj->funcs->atomic_duplicate_state(obj);
 	if (!obj_state)
 		return ERR_PTR(-ENOMEM);
 
-	state->private_objs[index].state_to_destroy = obj_state;
-	state->private_objs[index].old_state = obj->state;
-	state->private_objs[index].new_state = obj_state;
-	state->private_objs[index].ptr = obj;
-	obj_state->state = state;
-
-	state->num_private_objs = num_objs;
+	ret = drm_atomic_commit_set_private_obj_state(state, obj, obj_state);
+	if (ret) {
+		obj->funcs->atomic_destroy_state(obj, obj_state);
+		return ERR_PTR(ret);
+	}
 
 	drm_dbg_atomic(state->dev,
 		       "Added new private object %p state %p to %p\n",
 		       obj, obj_state, state);
 

-- 
2.54.0


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

* [PATCH RFC 6/8] drm/atomic: Create function to insert connector state into a commit
  2026-07-08 16:08 [PATCH RFC 0/8] drm: Add DRM_MODE_ATOMIC_RESET flag Maxime Ripard
                   ` (4 preceding siblings ...)
  2026-07-08 16:08 ` [PATCH RFC 5/8] drm/atomic: Create function to insert private obj " Maxime Ripard
@ 2026-07-08 16:08 ` Maxime Ripard
  2026-07-08 16:08 ` [PATCH RFC 7/8] drm/atomic: Allow filling a commit with pristine object states Maxime Ripard
                   ` (3 subsequent siblings)
  9 siblings, 0 replies; 15+ messages in thread
From: Maxime Ripard @ 2026-07-08 16:08 UTC (permalink / raw)
  To: Maarten Lankhorst, Thomas Zimmermann, David Airlie, Simona Vetter
  Cc: Daniel Stone, Harry Wentland, Jonas Ådahl,
	Michel Dänzer, Pekka Paalanen, Sebastian Wick, Simon Ser,
	Victoria Brekenfeld, Xaver Hugl, dri-devel, linux-kernel,
	Maxime Ripard

drm_atomic_get_connector_state() allocates a new connector state by
duplicating the current one and inserts it into the atomic commit as
a single operation.

However, a later change will need to insert a connector state into a
commit without going through the full allocation and duplication path
in drm_atomic_get_connector_state().

Extract the state insertion logic, including the dynamic array
reallocation, into a new static
drm_atomic_commit_set_connector_state() helper, and convert
drm_atomic_get_connector_state() to use it.

Signed-off-by: Maxime Ripard <mripard@kernel.org>
---
 drivers/gpu/drm/drm_atomic.c | 67 +++++++++++++++++++++++++++-----------------
 1 file changed, 42 insertions(+), 25 deletions(-)

diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index d4dcab2d851c..79971d4b56a4 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -1408,10 +1408,46 @@ drm_atomic_get_new_crtc_for_encoder(struct drm_atomic_commit *state,
 
 	return conn_state->crtc;
 }
 EXPORT_SYMBOL(drm_atomic_get_new_crtc_for_encoder);
 
+static int drm_atomic_commit_set_connector_state(struct drm_atomic_commit *commit,
+						 struct drm_connector *connector,
+						 struct drm_connector_state *connector_state)
+{
+	struct drm_mode_config *config = &connector->dev->mode_config;
+	int index;
+
+	drm_modeset_lock_assert_held(&config->connection_mutex);
+
+	index = drm_connector_index(connector);
+	if (index >= commit->num_connector) {
+		struct __drm_connnectors_state *c;
+		int alloc = max(index + 1, config->num_connector);
+
+		c = krealloc_array(commit->connectors, alloc,
+				   sizeof(*commit->connectors), GFP_KERNEL);
+		if (!c)
+			return -ENOMEM;
+
+		commit->connectors = c;
+		memset(&commit->connectors[commit->num_connector], 0,
+		       sizeof(*commit->connectors) * (alloc - commit->num_connector));
+
+		commit->num_connector = alloc;
+	}
+
+	drm_connector_get(connector);
+	commit->connectors[index].state_to_destroy = connector_state;
+	commit->connectors[index].old_state = connector->state;
+	commit->connectors[index].new_state = connector_state;
+	commit->connectors[index].ptr = connector;
+	connector_state->state = commit;
+
+	return 0;
+}
+
 /**
  * drm_atomic_get_connector_state - get connector state
  * @state: global atomic state object
  * @connector: connector to get state object for
  *
@@ -1426,53 +1462,34 @@ EXPORT_SYMBOL(drm_atomic_get_new_crtc_for_encoder);
  */
 struct drm_connector_state *
 drm_atomic_get_connector_state(struct drm_atomic_commit *state,
 			  struct drm_connector *connector)
 {
-	int ret, index;
+	int ret;
 	struct drm_mode_config *config = &connector->dev->mode_config;
 	struct drm_connector_state *connector_state;
 
 	WARN_ON(!state->acquire_ctx);
 	drm_WARN_ON(state->dev, state->checked);
 
 	ret = drm_modeset_lock(&config->connection_mutex, state->acquire_ctx);
 	if (ret)
 		return ERR_PTR(ret);
 
-	index = drm_connector_index(connector);
-
-	if (index >= state->num_connector) {
-		struct __drm_connnectors_state *c;
-		int alloc = max(index + 1, config->num_connector);
-
-		c = krealloc_array(state->connectors, alloc,
-				   sizeof(*state->connectors), GFP_KERNEL);
-		if (!c)
-			return ERR_PTR(-ENOMEM);
-
-		state->connectors = c;
-		memset(&state->connectors[state->num_connector], 0,
-		       sizeof(*state->connectors) * (alloc - state->num_connector));
-
-		state->num_connector = alloc;
-	}
-
 	connector_state = drm_atomic_get_new_connector_state(state, connector);
 	if (connector_state)
 		return connector_state;
 
 	connector_state = connector->funcs->atomic_duplicate_state(connector);
 	if (!connector_state)
 		return ERR_PTR(-ENOMEM);
 
-	drm_connector_get(connector);
-	state->connectors[index].state_to_destroy = connector_state;
-	state->connectors[index].old_state = connector->state;
-	state->connectors[index].new_state = connector_state;
-	state->connectors[index].ptr = connector;
-	connector_state->state = state;
+	ret = drm_atomic_commit_set_connector_state(state, connector, connector_state);
+	if (ret) {
+		connector->funcs->atomic_destroy_state(connector, connector_state);
+		return ERR_PTR(ret);
+	}
 
 	drm_dbg_atomic(connector->dev, "Added [CONNECTOR:%d:%s] %p state to %p\n",
 			 connector->base.id, connector->name,
 			 connector_state, state);
 

-- 
2.54.0


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

* [PATCH RFC 7/8] drm/atomic: Allow filling a commit with pristine object states
  2026-07-08 16:08 [PATCH RFC 0/8] drm: Add DRM_MODE_ATOMIC_RESET flag Maxime Ripard
                   ` (5 preceding siblings ...)
  2026-07-08 16:08 ` [PATCH RFC 6/8] drm/atomic: Create function to insert connector " Maxime Ripard
@ 2026-07-08 16:08 ` Maxime Ripard
  2026-07-08 16:24   ` sashiko-bot
  2026-07-08 16:08 ` [PATCH RFC 8/8] drm/atomic-uapi: Add DRM_MODE_ATOMIC_RESET flag Maxime Ripard
                   ` (2 subsequent siblings)
  9 siblings, 1 reply; 15+ messages in thread
From: Maxime Ripard @ 2026-07-08 16:08 UTC (permalink / raw)
  To: Maarten Lankhorst, Thomas Zimmermann, David Airlie, Simona Vetter
  Cc: Daniel Stone, Harry Wentland, Jonas Ådahl,
	Michel Dänzer, Pekka Paalanen, Sebastian Wick, Simon Ser,
	Victoria Brekenfeld, Xaver Hugl, dri-devel, linux-kernel,
	Maxime Ripard

The upcoming DRM_MODE_ATOMIC_RESET flag will need to create an atomic
commit that brings the entire device back to a pristine state, as if
no configuration had ever been applied.

Create drm_atomic_commit_fill_with_defaults() which iterates over all
CRTCs, planes, connectors, and color operations in the device and
inserts a fresh default state for each one into the commit. This uses
the atomic_create_state() hooks rather than atomic_duplicate_state(),
since atomic_create_state() provides exactly this pristine state on a
per-object basis.

Signed-off-by: Maxime Ripard <mripard@kernel.org>
---
 drivers/gpu/drm/drm_atomic.c | 112 +++++++++++++++++++++++++++++++++++++++++++
 include/drm/drm_atomic.h     |   1 +
 2 files changed, 113 insertions(+)

diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index 79971d4b56a4..0c1a02d0e871 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -1608,10 +1608,122 @@ drm_atomic_get_new_bridge_state(const struct drm_atomic_commit *state,
 
 	return drm_priv_to_bridge_state(obj_state);
 }
 EXPORT_SYMBOL(drm_atomic_get_new_bridge_state);
 
+/**
+ * drm_atomic_commit_fill_with_defaults - populate a commit with pristine states
+ * @commit: atomic commit to fill
+ *
+ * Iterate over all CRTCs, planes, connectors, and color operations in
+ * the device and insert a freshly created default state for each one
+ * into @commit. The states are created through the atomic_create_state()
+ * hooks, producing the same initial state the driver starts with rather
+ * than a copy of the current hardware state.
+ *
+ * This is meant to be used with the %DRM_MODE_ATOMIC_RESET flag, which
+ * needs to bring the device back to a known baseline before applying
+ * userspace property changes on top.
+ *
+ * Returns:
+ * 0 on success, or a negative error code on failure.
+ */
+int drm_atomic_commit_fill_with_defaults(struct drm_atomic_commit *commit)
+{
+	struct drm_device *dev = commit->dev;
+	struct drm_mode_config *config = &dev->mode_config;
+	struct drm_crtc *crtc;
+	struct drm_plane *plane;
+	struct drm_connector *connector;
+	struct drm_connector_list_iter conn_iter;
+	struct drm_colorop *colorop;
+	int ret;
+
+	WARN_ON(!commit->acquire_ctx);
+
+	drm_for_each_crtc(crtc, dev) {
+		struct drm_crtc_state *crtc_state;
+
+		ret = drm_modeset_lock(&crtc->mutex, commit->acquire_ctx);
+		if (ret)
+			return ret;
+
+		crtc_state = crtc->funcs->atomic_create_state(crtc);
+		if (IS_ERR(crtc_state))
+			return PTR_ERR(crtc_state);
+
+		ret = drm_atomic_commit_set_crtc_state(commit, crtc, crtc_state);
+		if (ret) {
+			crtc->funcs->atomic_destroy_state(crtc, crtc_state);
+			return ret;
+		}
+	}
+
+	drm_for_each_plane(plane, dev) {
+		struct drm_plane_state *plane_state;
+
+		ret = drm_modeset_lock(&plane->mutex, commit->acquire_ctx);
+		if (ret)
+			return ret;
+
+		plane_state = plane->funcs->atomic_create_state(plane);
+		if (IS_ERR(plane_state))
+			return PTR_ERR(plane_state);
+
+		ret = drm_atomic_commit_set_plane_state(commit, plane, plane_state);
+		if (ret) {
+			plane->funcs->atomic_destroy_state(plane, plane_state);
+			return ret;
+		}
+	}
+
+	drm_connector_list_iter_begin(dev, &conn_iter);
+	drm_for_each_connector_iter(connector, &conn_iter) {
+		struct drm_connector_state *connector_state;
+
+		ret = drm_modeset_lock(&config->connection_mutex, commit->acquire_ctx);
+		if (ret) {
+			drm_connector_list_iter_end(&conn_iter);
+			return ret;
+		}
+
+		connector_state = connector->funcs->atomic_create_state(connector);
+		if (IS_ERR(connector_state)) {
+			drm_connector_list_iter_end(&conn_iter);
+			ret = PTR_ERR(connector_state);
+			return ret;
+		}
+
+		ret = drm_atomic_commit_set_connector_state(commit, connector, connector_state);
+		if (ret) {
+			connector->funcs->atomic_destroy_state(connector, connector_state);
+			drm_connector_list_iter_end(&conn_iter);
+			return ret;
+		}
+	}
+	drm_connector_list_iter_end(&conn_iter);
+
+	drm_for_each_colorop(colorop, dev) {
+		struct drm_colorop_state *colorop_state;
+
+		colorop_state = drm_atomic_helper_colorop_create_state(colorop);
+		if (IS_ERR(colorop_state))
+			return PTR_ERR(colorop_state);
+
+		drm_modeset_lock_assert_held(&colorop->plane->mutex);
+
+		ret = drm_atomic_commit_set_colorop_state(commit, colorop, colorop_state);
+		if (ret) {
+			drm_colorop_atomic_destroy_state(colorop, colorop_state);
+			return ret;
+		}
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(drm_atomic_commit_fill_with_defaults);
+
 /**
  * drm_atomic_add_encoder_bridges - add bridges attached to an encoder
  * @state: atomic state
  * @encoder: DRM encoder
  *
diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h
index 00b3e9fc429a..e61a1bcd278b 100644
--- a/include/drm/drm_atomic.h
+++ b/include/drm/drm_atomic.h
@@ -698,10 +698,11 @@ static inline void drm_crtc_commit_put(struct drm_crtc_commit *commit)
 
 int drm_crtc_commit_wait(struct drm_crtc_commit *commit);
 
 struct drm_atomic_commit * __must_check
 drm_atomic_commit_alloc(struct drm_device *dev);
+int drm_atomic_commit_fill_with_defaults(struct drm_atomic_commit *commit);
 void drm_atomic_commit_clear(struct drm_atomic_commit *state);
 
 /**
  * drm_atomic_commit_get - acquire a reference to the atomic state
  * @state: The atomic state

-- 
2.54.0


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

* [PATCH RFC 8/8] drm/atomic-uapi: Add DRM_MODE_ATOMIC_RESET flag
  2026-07-08 16:08 [PATCH RFC 0/8] drm: Add DRM_MODE_ATOMIC_RESET flag Maxime Ripard
                   ` (6 preceding siblings ...)
  2026-07-08 16:08 ` [PATCH RFC 7/8] drm/atomic: Allow filling a commit with pristine object states Maxime Ripard
@ 2026-07-08 16:08 ` Maxime Ripard
  2026-07-08 16:26   ` sashiko-bot
  2026-07-08 18:25 ` [PATCH RFC 0/8] drm: " Xaver Hugl
  2026-07-10 17:01 ` Michel Dänzer
  9 siblings, 1 reply; 15+ messages in thread
From: Maxime Ripard @ 2026-07-08 16:08 UTC (permalink / raw)
  To: Maarten Lankhorst, Thomas Zimmermann, David Airlie, Simona Vetter
  Cc: Daniel Stone, Harry Wentland, Jonas Ådahl,
	Michel Dänzer, Pekka Paalanen, Sebastian Wick, Simon Ser,
	Victoria Brekenfeld, Xaver Hugl, dri-devel, linux-kernel,
	Maxime Ripard

From: Sebastian Wick <sebastian.wick@redhat.com>

Userspace currently has no atomic way to reset all KMS object states
to their defaults. To bring a display pipeline to a known state, a
compositor must explicitly set every property on every object, which
requires tracking which properties exist and what their defaults are.

Introduce DRM_MODE_ATOMIC_RESET (0x0800) which, when passed to the
atomic ioctl, fills the commit with default states for all KMS
objects before applying the properties supplied in the request.
Properties not explicitly included in the commit remain at their
defaults (CRTCs inactive, planes disabled, connectors unbound, and
so on).

The flag cannot be combined with DRM_MODE_PAGE_FLIP_ASYNC, since a
full state reset is incompatible with an async flip.

Signed-off-by: Sebastian Wick <sebastian.wick@redhat.com>
Co-developed-by: Maxime Ripard <mripard@kernel.org>
Signed-off-by: Maxime Ripard <mripard@kernel.org>
---
 drivers/gpu/drm/drm_atomic_uapi.c | 13 +++++++++++++
 include/uapi/drm/drm_mode.h       | 14 +++++++++++++-
 2 files changed, 26 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c
index 1050dddadb17..cdcc6efb9a00 100644
--- a/drivers/gpu/drm/drm_atomic_uapi.c
+++ b/drivers/gpu/drm/drm_atomic_uapi.c
@@ -1658,10 +1658,17 @@ int drm_mode_atomic_ioctl(struct drm_device *dev,
 		drm_dbg_atomic(dev,
 			       "commit failed: page-flip event requested with test-only commit\n");
 		return -EINVAL;
 	}
 
+	if ((arg->flags & DRM_MODE_ATOMIC_RESET) &&
+			(arg->flags & DRM_MODE_PAGE_FLIP_ASYNC)) {
+		drm_dbg_atomic(dev,
+			       "commit failed: reset cannot be combined with async flip\n");
+		return -EINVAL;
+	}
+
 	state = drm_atomic_commit_alloc(dev);
 	if (!state)
 		return -ENOMEM;
 
 	drm_modeset_acquire_init(&ctx, DRM_MODESET_ACQUIRE_INTERRUPTIBLE);
@@ -1673,10 +1680,16 @@ int drm_mode_atomic_ioctl(struct drm_device *dev,
 	copied_objs = 0;
 	copied_props = 0;
 	fence_state = NULL;
 	num_fences = 0;
 
+	if (arg->flags & DRM_MODE_ATOMIC_RESET) {
+		ret = drm_atomic_commit_fill_with_defaults(state);
+		if (ret)
+			goto out;
+	}
+
 	for (i = 0; i < arg->count_objs; i++) {
 		uint32_t obj_id, count_props;
 		struct drm_mode_object *obj;
 
 		if (get_user(obj_id, objs_ptr + copied_objs)) {
diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h
index bd435effdcee..43024028f695 100644
--- a/include/uapi/drm/drm_mode.h
+++ b/include/uapi/drm/drm_mode.h
@@ -1314,10 +1314,21 @@ struct drm_mode_destroy_dumb {
  * To the best of the driver's knowledge, visual artifacts are guaranteed to
  * not appear when this flag is not set. Some sinks might display visual
  * artifacts outside of the driver's control.
  */
 #define DRM_MODE_ATOMIC_ALLOW_MODESET 0x0400
+/**
+ * DRM_MODE_ATOMIC_RESET
+ *
+ * Reset all KMS object states (CRTCs, planes, connectors, color operations)
+ * to their default values before applying the properties in this commit.
+ * Properties not explicitly included in the commit will remain at their
+ * defaults (CRTCs inactive, planes disabled, connectors unbound, etc.).
+ *
+ * This flag cannot be combined with &DRM_MODE_PAGE_FLIP_ASYNC.
+ */
+#define DRM_MODE_ATOMIC_RESET 0x0800
 
 /**
  * DRM_MODE_ATOMIC_FLAGS
  *
  * Bitfield of flags accepted by the &DRM_IOCTL_MODE_ATOMIC IOCTL in
@@ -1326,11 +1337,12 @@ struct drm_mode_destroy_dumb {
 #define DRM_MODE_ATOMIC_FLAGS (\
 		DRM_MODE_PAGE_FLIP_EVENT |\
 		DRM_MODE_PAGE_FLIP_ASYNC |\
 		DRM_MODE_ATOMIC_TEST_ONLY |\
 		DRM_MODE_ATOMIC_NONBLOCK |\
-		DRM_MODE_ATOMIC_ALLOW_MODESET)
+		DRM_MODE_ATOMIC_ALLOW_MODESET |\
+		DRM_MODE_ATOMIC_RESET)
 
 struct drm_mode_atomic {
 	__u32 flags;
 	__u32 count_objs;
 	__u64 objs_ptr;

-- 
2.54.0


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

* Re: [PATCH RFC 1/8] drm/atomic: colorop: Rename state to state_to_destroy
  2026-07-08 16:08 ` [PATCH RFC 1/8] drm/atomic: colorop: Rename state to state_to_destroy Maxime Ripard
@ 2026-07-08 16:16   ` sashiko-bot
  0 siblings, 0 replies; 15+ messages in thread
From: sashiko-bot @ 2026-07-08 16:16 UTC (permalink / raw)
  To: Maxime Ripard; +Cc: dri-devel

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Low] Incomplete rename of the `state` field to `state_to_destroy` in `struct __drm_colorops_state` causes a compilation failure.
--

--- Patch [1]: [PATCH RFC 1/8] drm/atomic: colorop: Rename state to state_to_destroy ---
commit d09bd0c6257ce0056d0f8ea064c0723f0d09039a
Author: Maxime Ripard <mripard@kernel.org>

drm/atomic: colorop: Rename state to state_to_destroy

This patch renames the state field to state_to_destroy in the
__drm_colorops_state structure to better describe its purpose and match
other atomic state tracking structures.

> diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h
> --- a/include/drm/drm_atomic.h
> +++ b/include/drm/drm_atomic.h
> @@ -159,7 +159,23 @@ struct drm_crtc_commit {
>  
>  struct __drm_colorops_state {
>  	struct drm_colorop *ptr;
> -	struct drm_colorop_state *state, *old_state, *new_state;
> +
> +	/**
> +	 * @state_to_destroy:

[ ... ]

> +	struct drm_colorop_state *state_to_destroy;
> +
> +	struct drm_colorop_state *old_state, *new_state;
>  };

[Severity: Low]
Does this incomplete rename cause a compilation failure?

In drivers/gpu/drm/drm_atomic.c:drm_atomic_get_colorop_state(), the code
still attempts to assign to the old field name:

	state->colorops[index].state = colorop_state;
	state->colorops[index].ptr = colorop;
	state->colorops[index].old_state = colorop->state;

Should this be updated to state_to_destroy as well?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260708-drm-reset-state-flag-v1-0-c37dc985485d@kernel.org?part=1

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

* Re: [PATCH RFC 7/8] drm/atomic: Allow filling a commit with pristine object states
  2026-07-08 16:08 ` [PATCH RFC 7/8] drm/atomic: Allow filling a commit with pristine object states Maxime Ripard
@ 2026-07-08 16:24   ` sashiko-bot
  0 siblings, 0 replies; 15+ messages in thread
From: sashiko-bot @ 2026-07-08 16:24 UTC (permalink / raw)
  To: Maxime Ripard; +Cc: dri-devel

Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
- [Critical] Unchecked calls to the `atomic_create_state` hook on CRTCs, planes, and connectors will cause a kernel panic on drivers that do not implement them.
- [High] The function fails to reset private objects (`drm_private_obj`), resulting in an incomplete and inconsistent baseline state.
- [Medium] The locking order for `connection_mutex` in `drm_atomic_commit_fill_with_defaults` is inverted relative to the established DRM locking order.
--

--- Patch [7]: [PATCH RFC 7/8] drm/atomic: Allow filling a commit with pristine object states ---
commit e9e433a7ce1a444bdbe24747a11cf419bea31b2b
Author: Maxime Ripard <mripard@kernel.org>

drm/atomic: Allow filling a commit with pristine object states

This patch creates drm_atomic_commit_fill_with_defaults() to iterate over
all CRTCs, planes, connectors, and color operations in the device and insert
a fresh default state for each one. This brings the device back to a known
baseline before applying userspace property changes.

> diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
> index 79971d4b56a49..0c1a02d0e871d 100644
> --- a/drivers/gpu/drm/drm_atomic.c
> +++ b/drivers/gpu/drm/drm_atomic.c

[ ... ]

> @@ -1610,6 +1610,118 @@ drm_atomic_get_new_bridge_state(const struct drm_atomic_commit *state,
>  }
>  EXPORT_SYMBOL(drm_atomic_get_new_bridge_state);
>  
> +/**
> + * drm_atomic_commit_fill_with_defaults - populate a commit with pristine states

[ ... ]

> +int drm_atomic_commit_fill_with_defaults(struct drm_atomic_commit *commit)
> +{
> +	struct drm_device *dev = commit->dev;
> +	struct drm_mode_config *config = &dev->mode_config;
> +	struct drm_crtc *crtc;
> +	struct drm_plane *plane;
> +	struct drm_connector *connector;
> +	struct drm_connector_list_iter conn_iter;
> +	struct drm_colorop *colorop;
> +	int ret;
> +
> +	WARN_ON(!commit->acquire_ctx);
> +
> +	drm_for_each_crtc(crtc, dev) {
> +		struct drm_crtc_state *crtc_state;
> +
> +		ret = drm_modeset_lock(&crtc->mutex, commit->acquire_ctx);
> +		if (ret)
> +			return ret;
> +
> +		crtc_state = crtc->funcs->atomic_create_state(crtc);

[Severity: Critical]
Is it safe to call atomic_create_state without checking if the function pointer
exists?

Some drivers (like i915) might rely on the reset callback instead and leave
atomic_create_state unimplemented. Could this unconditional call lead to a NULL
pointer dereference here, as well as in the plane and connector loops below?

> +		if (IS_ERR(crtc_state))
> +			return PTR_ERR(crtc_state);
> +
> +		ret = drm_atomic_commit_set_crtc_state(commit, crtc, crtc_state);
> +		if (ret) {
> +			crtc->funcs->atomic_destroy_state(crtc, crtc_state);
> +			return ret;
> +		}
> +	}

[ ... ]

> +	drm_connector_list_iter_begin(dev, &conn_iter);
> +	drm_for_each_connector_iter(connector, &conn_iter) {
> +		struct drm_connector_state *connector_state;
> +
> +		ret = drm_modeset_lock(&config->connection_mutex, commit->acquire_ctx);

[Severity: Medium]
Does acquiring connection_mutex here invert the standard DRM locking order?

The established canonical sequence (such as in drm_modeset_lock_all_ctx)
typically acquires connection_mutex before the CRTC and plane locks. Since the
CRTC and plane locks were already acquired in the loops above, could acquiring
connection_mutex now result in unnecessary transaction backoffs and retries?

> +		if (ret) {
> +			drm_connector_list_iter_end(&conn_iter);
> +			return ret;
> +		}
> +
> +		connector_state = connector->funcs->atomic_create_state(connector);
> +		if (IS_ERR(connector_state)) {

[ ... ]

> +	drm_for_each_colorop(colorop, dev) {
> +		struct drm_colorop_state *colorop_state;
> +
> +		colorop_state = drm_atomic_helper_colorop_create_state(colorop);
> +		if (IS_ERR(colorop_state))
> +			return PTR_ERR(colorop_state);
> +
> +		drm_modeset_lock_assert_held(&colorop->plane->mutex);
> +
> +		ret = drm_atomic_commit_set_colorop_state(commit, colorop, colorop_state);
> +		if (ret) {
> +			drm_colorop_atomic_destroy_state(colorop, colorop_state);
> +			return ret;
> +		}
> +	}
> +

[Severity: High]
Should this function also iterate over and reset private objects
(drm_private_obj) before returning?

Modern DRM features like DP MST topologies, DisplayPort tunnels, and global
bandwidth allocators maintain their state in private objects. If these are
omitted from the reset, could it leave the topology or bandwidth state
inconsistent with the newly reset hardware baseline?

> +	return 0;
> +}
> +EXPORT_SYMBOL(drm_atomic_commit_fill_with_defaults);

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260708-drm-reset-state-flag-v1-0-c37dc985485d@kernel.org?part=7

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

* Re: [PATCH RFC 8/8] drm/atomic-uapi: Add DRM_MODE_ATOMIC_RESET flag
  2026-07-08 16:08 ` [PATCH RFC 8/8] drm/atomic-uapi: Add DRM_MODE_ATOMIC_RESET flag Maxime Ripard
@ 2026-07-08 16:26   ` sashiko-bot
  0 siblings, 0 replies; 15+ messages in thread
From: sashiko-bot @ 2026-07-08 16:26 UTC (permalink / raw)
  To: Maxime Ripard; +Cc: dri-devel

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [Critical] The newly added DRM_MODE_ATOMIC_RESET flag allows userspace to crash the kernel by unconditionally dereferencing an unimplemented `atomic_create_state` hook on CRTCs, planes, and connectors.
- [High] The DRM_MODE_ATOMIC_RESET flag bypasses DRM lease boundaries, allowing a restricted client to reset all displays on the device.
--

--- Patch [8]: [PATCH RFC 8/8] drm/atomic-uapi: Add DRM_MODE_ATOMIC_RESET flag ---
commit f7802a930a44f2b2c525a72c03344afc1a5cba57
Author: Sebastian Wick <sebastian.wick@redhat.com>
Subject: drm/atomic-uapi: Add DRM_MODE_ATOMIC_RESET flag

Introduce DRM_MODE_ATOMIC_RESET (0x0800) which, when passed to the
atomic ioctl, fills the commit with default states for all KMS objects
before applying the properties supplied in the request. The flag cannot
be combined with DRM_MODE_PAGE_FLIP_ASYNC.

> diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c
> index 1050dddadb17e..cdcc6efb9a00f 100644
> --- a/drivers/gpu/drm/drm_atomic_uapi.c
> +++ b/drivers/gpu/drm/drm_atomic_uapi.c
[ ... ]
> @@ -1675,6 +1682,12 @@ int drm_mode_atomic_ioctl(struct drm_device *dev,
>  	fence_state = NULL;
>  	num_fences = 0;
>  
> +	if (arg->flags & DRM_MODE_ATOMIC_RESET) {
> +		ret = drm_atomic_commit_fill_with_defaults(state);

[Severity: Critical]
Can this cause a NULL pointer dereference for drivers that don't implement the
atomic_create_state hook?

When userspace passes DRM_MODE_ATOMIC_RESET, this calls
drm_atomic_commit_fill_with_defaults(), which unconditionally calls the
atomic_create_state hook for CRTCs, planes, and connectors:

drivers/gpu/drm/drm_atomic.c:drm_atomic_commit_fill_with_defaults() {
	...
	drm_for_each_crtc(crtc, dev) {
		...
		crtc_state = crtc->funcs->atomic_create_state(crtc);
		...
	}
	...
}

If a driver doesn't implement this optional hook, will this dereference a NULL
pointer?


[Severity: High]
Does this bypass DRM lease boundaries?

When called here, drm_atomic_commit_fill_with_defaults() iterates globally over
all CRTCs, planes, and connectors on the device without checking file_priv or
enforcing lease boundaries.

Could a restricted client use this flag to break lease isolation and forcibly
reset or turn off all displays on the system?

> +		if (ret)
> +			goto out;
> +	}
> +
>  	for (i = 0; i < arg->count_objs; i++) {
>  		uint32_t obj_id, count_props;
>  		struct drm_mode_object *obj;

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260708-drm-reset-state-flag-v1-0-c37dc985485d@kernel.org?part=8

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

* Re: [PATCH RFC 0/8] drm: Add DRM_MODE_ATOMIC_RESET flag
  2026-07-08 16:08 [PATCH RFC 0/8] drm: Add DRM_MODE_ATOMIC_RESET flag Maxime Ripard
                   ` (7 preceding siblings ...)
  2026-07-08 16:08 ` [PATCH RFC 8/8] drm/atomic-uapi: Add DRM_MODE_ATOMIC_RESET flag Maxime Ripard
@ 2026-07-08 18:25 ` Xaver Hugl
  2026-07-10 17:01 ` Michel Dänzer
  9 siblings, 0 replies; 15+ messages in thread
From: Xaver Hugl @ 2026-07-08 18:25 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Maarten Lankhorst, Thomas Zimmermann, David Airlie, Simona Vetter,
	Daniel Stone, Harry Wentland, Jonas Ådahl,
	Michel Dänzer, Pekka Paalanen, Sebastian Wick, Simon Ser,
	Victoria Brekenfeld, dri-devel, linux-kernel

Hi,

Thanks for working on this, it'll be great to finally have this solved properly.

> Open question: should DRM_MODE_ATOMIC_RESET require
> DRM_MODE_ATOMIC_ALLOW_MODESET? A full state reset will change CRTC
> active states, which is effectively a modeset. Without requiring it,
> a reset could pass flag validation but fail later at atomic_check in
> a confusing way.
The compositor may use the same CRTC states, modes etc; whether or not
the commit actually ends up requiring a modeset depends entirely on
the exact contents of the commit. So I definitely wouldn't require
ALLOW_MODESET.

- Xaver

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

* Re: [PATCH RFC 0/8] drm: Add DRM_MODE_ATOMIC_RESET flag
  2026-07-08 16:08 [PATCH RFC 0/8] drm: Add DRM_MODE_ATOMIC_RESET flag Maxime Ripard
                   ` (8 preceding siblings ...)
  2026-07-08 18:25 ` [PATCH RFC 0/8] drm: " Xaver Hugl
@ 2026-07-10 17:01 ` Michel Dänzer
  2026-07-13  7:11   ` Maxime Ripard
  9 siblings, 1 reply; 15+ messages in thread
From: Michel Dänzer @ 2026-07-10 17:01 UTC (permalink / raw)
  To: Maxime Ripard, Maarten Lankhorst, Thomas Zimmermann, David Airlie,
	Simona Vetter
  Cc: Daniel Stone, Harry Wentland, Jonas Ådahl, Pekka Paalanen,
	Sebastian Wick, Simon Ser, Victoria Brekenfeld, Xaver Hugl,
	dri-devel, linux-kernel

On 7/8/26 18:08, Maxime Ripard wrote:
> 
> Userspace currently has no atomic way to bring a display pipeline back
> to a pristine state. A compositor that wants to start from a known
> baseline must explicitly set every property on every KMS object to its
> default value, which requires tracking which properties exist and what
> their defaults are. This is fragile and must be updated every time a
> new property is added to the kernel.
> 
> This series introduces a new DRM_MODE_ATOMIC_RESET flag for the
> atomic ioctl. When set, the kernel fills the commit with default
> states for all KMS objects before applying the properties supplied in
> the request. Properties not explicitly included remain at their
> defaults (CRTCs inactive, planes disabled, connectors unbound, and so
> on). This allows userspace to describe the desired end state
> declaratively, without having to care about the current state or the
> full set of properties.

Nice!


> Patch 8 wires it all up by adding DRM_MODE_ATOMIC_RESET to the atomic
> ioctl.

The new flag should be accompanied by a new DRM_CAP_* cap, so user space knows when the new flag is valid.


> This series is untested and relies on all drivers implementing the
> atomic_create_state hook, which is not yet the case. The conversion
> is actively in progress but not complete, so this will not work as-is
> today.

As discussed on IRC, the new cap could be made conditional on the atomic_create_state hook being available. That would allow this series to land before all in-tree drivers are converted. (As a bonus, it would also avoid issues with out-of-tree drivers which might not support the atomic_create_state hook)


-- 
Earthling Michel Dänzer       \        GNOME / Xwayland / Mesa developer
https://redhat.com             \               Libre software enthusiast

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

* Re: [PATCH RFC 0/8] drm: Add DRM_MODE_ATOMIC_RESET flag
  2026-07-10 17:01 ` Michel Dänzer
@ 2026-07-13  7:11   ` Maxime Ripard
  0 siblings, 0 replies; 15+ messages in thread
From: Maxime Ripard @ 2026-07-13  7:11 UTC (permalink / raw)
  To: Michel Dänzer
  Cc: Maarten Lankhorst, Thomas Zimmermann, David Airlie, Simona Vetter,
	Daniel Stone, Harry Wentland, Jonas Ådahl, Pekka Paalanen,
	Sebastian Wick, Simon Ser, Victoria Brekenfeld, Xaver Hugl,
	dri-devel, linux-kernel

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

Hi Michel,

On Fri, Jul 10, 2026 at 07:01:29PM +0200, Michel Dänzer wrote:
> On 7/8/26 18:08, Maxime Ripard wrote:
> > 
> > Userspace currently has no atomic way to bring a display pipeline back
> > to a pristine state. A compositor that wants to start from a known
> > baseline must explicitly set every property on every KMS object to its
> > default value, which requires tracking which properties exist and what
> > their defaults are. This is fragile and must be updated every time a
> > new property is added to the kernel.
> > 
> > This series introduces a new DRM_MODE_ATOMIC_RESET flag for the
> > atomic ioctl. When set, the kernel fills the commit with default
> > states for all KMS objects before applying the properties supplied in
> > the request. Properties not explicitly included remain at their
> > defaults (CRTCs inactive, planes disabled, connectors unbound, and so
> > on). This allows userspace to describe the desired end state
> > declaratively, without having to care about the current state or the
> > full set of properties.
> 
> Nice!
> 
> 
> > Patch 8 wires it all up by adding DRM_MODE_ATOMIC_RESET to the atomic
> > ioctl.
> 
> The new flag should be accompanied by a new DRM_CAP_* cap, so user
> space knows when the new flag is valid.

Ack.

> > This series is untested and relies on all drivers implementing the
> > atomic_create_state hook, which is not yet the case. The conversion
> > is actively in progress but not complete, so this will not work as-is
> > today.
> 
> As discussed on IRC, the new cap could be made conditional on the
> atomic_create_state hook being available. That would allow this series
> to land before all in-tree drivers are converted. (As a bonus, it
> would also avoid issues with out-of-tree drivers which might not
> support the atomic_create_state hook)

My initial reaction when we discussed it on IRC was that the conversion
from reset to atomic_create_state is going to remove reset, so by the
time it's merged, an out-of-tree driver that wouldn't implement
atomic_create_state would not compile.

That being said, I just remembered that i915 implements neither, so it's
a good thing to have indeed.

Maxime

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 273 bytes --]

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

end of thread, other threads:[~2026-07-13  7:16 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-08 16:08 [PATCH RFC 0/8] drm: Add DRM_MODE_ATOMIC_RESET flag Maxime Ripard
2026-07-08 16:08 ` [PATCH RFC 1/8] drm/atomic: colorop: Rename state to state_to_destroy Maxime Ripard
2026-07-08 16:16   ` sashiko-bot
2026-07-08 16:08 ` [PATCH RFC 2/8] drm/atomic: Create function to insert CRTC state into a commit Maxime Ripard
2026-07-08 16:08 ` [PATCH RFC 3/8] drm/atomic: Create function to insert plane " Maxime Ripard
2026-07-08 16:08 ` [PATCH RFC 4/8] drm/atomic: Create function to insert colorop " Maxime Ripard
2026-07-08 16:08 ` [PATCH RFC 5/8] drm/atomic: Create function to insert private obj " Maxime Ripard
2026-07-08 16:08 ` [PATCH RFC 6/8] drm/atomic: Create function to insert connector " Maxime Ripard
2026-07-08 16:08 ` [PATCH RFC 7/8] drm/atomic: Allow filling a commit with pristine object states Maxime Ripard
2026-07-08 16:24   ` sashiko-bot
2026-07-08 16:08 ` [PATCH RFC 8/8] drm/atomic-uapi: Add DRM_MODE_ATOMIC_RESET flag Maxime Ripard
2026-07-08 16:26   ` sashiko-bot
2026-07-08 18:25 ` [PATCH RFC 0/8] drm: " Xaver Hugl
2026-07-10 17:01 ` Michel Dänzer
2026-07-13  7:11   ` Maxime Ripard

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.