[PATCH RFC] drm/atomic: Return readable error value on error for atomic_ioctl

Arun R Murthy arun.r.murthy at intel.com
Fri Jun 27 07:04:48 UTC 2025


There can be multiple reasons for a failure in atomic_ioctl. Most often
in these error conditions -EINVAL is returned. User/Compositor would
have to blindly take a call on failure of this ioctl so as to use
ALLOW_MODESET or any. It would be good if user/compositor gets a
readable error code on failure so they can take proper corrections in
the next commit.
The struct drm_mode_atomic is being passed by the user/compositor which
holds the properties for modeset/flip. Reusing the same struct for
returning the error code in case of failure can save by creating a new
uapi/interface for returning the error code.
There is an element reserved in the struct drm_mode_atomic which can be
used to return the user readable error code.
Here an effort is made using this reserved variable to return the error
code.

This is incomplete, just a start with returning few error codes have
been made. New flags can be added accordingly. Its a 64bit variable and
should suffice 64 error codes and should be sufficient.

Signed-off-by: Arun R Murthy <arun.r.murthy at intel.com>
---
 drivers/gpu/drm/drm_atomic.c      |  5 +++++
 drivers/gpu/drm/drm_atomic_uapi.c | 17 ++++++++++++-----
 include/drm/drm_atomic.h          |  7 +++++++
 include/uapi/drm/drm_mode.h       | 28 ++++++++++++++++++++++++++++
 4 files changed, 52 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index cd15cf52f0c9144711da5879da57884674aea9e4..0cf73022955437260d138c6a1e2bb9a8a4eca2f0 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -1513,6 +1513,8 @@ int drm_atomic_check_only(struct drm_atomic_state *state)
 			if (drm_atomic_crtc_needs_modeset(new_crtc_state)) {
 				drm_dbg_atomic(dev, "[CRTC:%d:%s] requires full modeset\n",
 					       crtc->base.id, crtc->name);
+				state->error_code = DRM_MODE_ATOMIC_CRTC_NEED_FULL_MODESET;
+
 				return -EINVAL;
 			}
 		}
@@ -1537,8 +1539,11 @@ int drm_atomic_check_only(struct drm_atomic_state *state)
 		drm_dbg_atomic(dev,
 			       "driver added CRTC to commit: requested 0x%x, affected 0x%0x\n",
 			       requested_crtc, affected_crtc);
+		state->error_code = DRM_MODE_ATOMIC_NEED_FULL_MODESET;
 		WARN(!state->allow_modeset, "adding CRTC not allowed without modesets: requested 0x%x, affected 0x%0x\n",
 		     requested_crtc, affected_crtc);
+
+		return -EINVAL;
 	}
 
 	return 0;
diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c
index ecc73d52bfae41a7ef455a7e13649ec56c690b90..ff711c8d6ef204c1e50c6bb506af6f5adb4d9b4e 100644
--- a/drivers/gpu/drm/drm_atomic_uapi.c
+++ b/drivers/gpu/drm/drm_atomic_uapi.c
@@ -1400,6 +1400,11 @@ int drm_mode_atomic_ioctl(struct drm_device *dev,
 	if (!drm_core_check_feature(dev, DRIVER_ATOMIC))
 		return -EOPNOTSUPP;
 
+	if (arg->reserved) {
+		drm_dbg_atomic(dev, "commit failed: reserved field set\n");
+		return -EINVAL;
+	}
+
 	/* disallow for userspace that has not enabled atomic cap (even
 	 * though this may be a bit overkill, since legacy userspace
 	 * wouldn't know how to call this ioctl)
@@ -1407,16 +1412,13 @@ int drm_mode_atomic_ioctl(struct drm_device *dev,
 	if (!file_priv->atomic) {
 		drm_dbg_atomic(dev,
 			       "commit failed: atomic cap not enabled\n");
+		arg->reserved = DRM_MODE_ATOMIC_CAP_NOT_ENABLED;
 		return -EINVAL;
 	}
 
 	if (arg->flags & ~DRM_MODE_ATOMIC_FLAGS) {
 		drm_dbg_atomic(dev, "commit failed: invalid flag\n");
-		return -EINVAL;
-	}
-
-	if (arg->reserved) {
-		drm_dbg_atomic(dev, "commit failed: reserved field set\n");
+		arg->reserved = DRM_MODE_ATOMIC_INVALID_FLAG;
 		return -EINVAL;
 	}
 
@@ -1424,6 +1426,7 @@ int drm_mode_atomic_ioctl(struct drm_device *dev,
 		if (!dev->mode_config.async_page_flip) {
 			drm_dbg_atomic(dev,
 				       "commit failed: DRM_MODE_PAGE_FLIP_ASYNC not supported\n");
+			arg->reserved = DRM_MODE_ATOMIC_PAGE_FLIP_ASYNC;
 			return -EINVAL;
 		}
 
@@ -1435,6 +1438,7 @@ int drm_mode_atomic_ioctl(struct drm_device *dev,
 			(arg->flags & DRM_MODE_PAGE_FLIP_EVENT)) {
 		drm_dbg_atomic(dev,
 			       "commit failed: page-flip event requested with test-only commit\n");
+		arg->reserved = DRM_MODE_ATOMIC_FLIP_EVENT_WITH_CHECKONLY;
 		return -EINVAL;
 	}
 
@@ -1541,6 +1545,9 @@ int drm_mode_atomic_ioctl(struct drm_device *dev,
 		ret = drm_atomic_commit(state);
 	}
 
+	/* update the error code if any error to allow user handling it */
+	arg->reserved = state->error_code;
+
 out:
 	complete_signaling(dev, state, fence_state, num_fences, !ret);
 
diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h
index 38636a593c9d98cadda85ccd67326cb152f0dd27..55799d848408e23ae5ece2dd694d119489a87ede 100644
--- a/include/drm/drm_atomic.h
+++ b/include/drm/drm_atomic.h
@@ -524,6 +524,13 @@ struct drm_atomic_state {
 	 * commit without blocking.
 	 */
 	struct work_struct commit_work;
+
+	/* @error_code
+	 *
+	 * flag to convey user readable error to the user.
+	 * Error codes defined in DRM_MODE_ATOMIC_ERR_FLAGS
+	 */
+	u64 error_code;
 };
 
 void __drm_crtc_commit_free(struct kref *kref);
diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h
index c082810c08a8b234ef2672ecf54fc8c05ddc2bd3..dccf0e8a40cd06e89b0e016356d4fef89cd93a29 100644
--- a/include/uapi/drm/drm_mode.h
+++ b/include/uapi/drm/drm_mode.h
@@ -1149,6 +1149,34 @@ struct drm_mode_destroy_dumb {
 		DRM_MODE_ATOMIC_NONBLOCK |\
 		DRM_MODE_ATOMIC_ALLOW_MODESET)
 
+/* atomic not set in the drm_file */
+#define DRM_MODE_ATOMIC_CAP_NOT_ENABLED			BIT(0)
+/* atomic flag passed not in DRM_MODE_ATOMIC_FLAGS list */
+#define DRM_MODE_ATOMIC_INVALID_FLAG			BIT(1)
+/* DRM_MODE_PAGE_FLIP_LEGACY not supported with atomic ioctl  */
+#define DRM_MODE_ATOMIC_PAGE_FLIP_ASYNC			BIT(2)
+/* flip event with atomic check only not supported */
+#define DRM_MODE_ATOMIC_FLIP_EVENT_WITH_CHECKONLY	BIT(3)
+/* atomic property change requested need full crtc modeset */
+#define DRM_MODE_ATOMIC_CRTC_NEED_FULL_MODESET		BIT(4)
+/* atomic property change requested has impact on all connected crtc */
+#define DRM_MODE_ATOMIC_NEED_FULL_MODESET		BIT(5)
+
+/**
+ * DRM_MODE_ATOMIC_ERR_FLAGS
+ *
+ * Bit field of the reserved element in drm_mode_atomic will be
+ * used for returning meaningful error message to the compositor
+ * so that compositor can take necessary correction going ahead.
+ */
+#define DRM_MODE_ATOMIC_ERR_FLAGS (\
+		DRM_MODE_ATOMIC_CAP_NOT_ENABLED |\
+		DRM_MODE_ATOMIC_INVALID_FLAG |\
+		DRM_MODE_ATOMIC_PAGE_FLIP_ASYNC |\
+		DRM_MODE_ATOMIC_FLIP_EVENT_WITH_CHECKONLY |\
+		DRM_MODE_ATOMIC_CRTC_NEED_FULL_MODESET |\
+		DRM_MODE_ATOMIC_NEED_FULL_MODESET)
+
 struct drm_mode_atomic {
 	__u32 flags;
 	__u32 count_objs;

---
base-commit: bd57aee20daefb7b0dfe9017663668c92115ff19
change-id: 20250625-atomic-ed735b97002f

Best regards,
-- 
Arun R Murthy <arun.r.murthy at intel.com>



More information about the dri-devel mailing list