Merge branch 'main' into 'main'

Draft: Error reporting on atomic_ioctl failure

See merge request mesa/libdrm!450
This commit is contained in:
Arun Raghavendra Murthy 2026-04-30 03:06:10 +00:00
commit 7555ab23c5
4 changed files with 88 additions and 1 deletions

View file

@ -806,6 +806,13 @@ struct drm_gem_change_handle {
* commits.
*/
#define DRM_CAP_ATOMIC_ASYNC_PAGE_FLIP 0x15
/**
* DRM_CAP_ATOMIC_ERROR_REPORTING
*
* If set to 1, the driver supports reporting of failure codes on error in
* atomic ioctl().
*/
#define DRM_CAP_ATOMIC_ERROR_REPORTING 0x16
/* DRM_IOCTL_GET_CAP ioctl argument type */
struct drm_get_cap {

View file

@ -45,6 +45,7 @@ extern "C" {
#define DRM_CONNECTOR_NAME_LEN 32
#define DRM_DISPLAY_MODE_LEN 32
#define DRM_PROP_NAME_LEN 32
#define DRM_MODE_ATOMIC_FAILURE_STRING_LEN 128
#define DRM_MODE_TYPE_BUILTIN (1<<0) /* deprecated */
#define DRM_MODE_TYPE_CLOCK_C ((1<<1) | DRM_MODE_TYPE_BUILTIN) /* deprecated */
@ -166,6 +167,10 @@ extern "C" {
#define DRM_MODE_LINK_STATUS_GOOD 0
#define DRM_MODE_LINK_STATUS_BAD 1
/* Panel type property */
#define DRM_MODE_PANEL_TYPE_UNKNOWN 0
#define DRM_MODE_PANEL_TYPE_OLED 1
/*
* DRM_MODE_ROTATE_<degrees>
*
@ -1339,6 +1344,42 @@ struct drm_mode_destroy_dumb {
DRM_MODE_ATOMIC_NONBLOCK |\
DRM_MODE_ATOMIC_ALLOW_MODESET)
/**
* enum drm_mode_atomic_failure_codes - error codes for failures in atomic_ioctl
* @DRM_MODE_ATOMIC_INVALID_API_USAGE: invallid API usage(DRM_ATOMIC not
* enabled, invalid falg, page_flip event
* with test-only, etc)
* @DRM_MODE_ATOMIC_CRTC_NEED_FULL_MODESET: Need full modeset on this crtc
* @DRM_MODE_ATOMIC_NEED_FULL_MODESET: Need full modeset on all connected crtc's
* @DRM_MODE_ATOMIC_ASYNC_PROP_CHANGED: Property changed in async flip
*/
enum drm_mode_atomic_failure_codes {
DRM_MODE_ATOMIC_INVALID_API_USAGE,
DRM_MODE_ATOMIC_CRTC_NEED_FULL_MODESET,
DRM_MODE_ATOMIC_NEED_FULL_MODESET,
DRM_MODE_ATOMIC_ASYNC_PROP_CHANGED,
};
/**
* struct drm_mode_atomic_err_code - struct to store the error code
*
* pointer to this struct will be stored in reserved variable of
* struct drm_mode_atomic to report the failure cause to the user.
*
* @failure_code: error codes defined in enum drm_moide_atomic_failure_code
* @failure_objs_ptr: pointer to the drm_object that caused error
* @reserved: reserved for future use
* @count_objs: count of drm_objects if multiple drm_objects caused error
* @failure_string: user readable error message string
*/
struct drm_mode_atomic_err_code {
__u64 failure_code;
__u64 failure_objs_ptr;
__u64 reserved;
__u32 count_objs;
char failure_string[DRM_MODE_ATOMIC_FAILURE_STRING_LEN];
};
struct drm_mode_atomic {
__u32 flags;
__u32 count_objs;

View file

@ -1363,9 +1363,15 @@ struct _drmModeAtomicReqItem {
struct _drmModeAtomicReq {
uint32_t cursor;
uint32_t size_items;
struct drm_mode_atomic_err_code *err_code_ptr;
drmModeAtomicReqItemPtr items;
};
drm_public const struct drm_mode_atomic_err_code * drmModeAtomicGetErrorCode(drmModeAtomicReqPtr req)
{
return req->err_code_ptr;
}
drm_public drmModeAtomicReqPtr drmModeAtomicAlloc(void)
{
drmModeAtomicReqPtr req;
@ -1377,6 +1383,9 @@ drm_public drmModeAtomicReqPtr drmModeAtomicAlloc(void)
req->items = NULL;
req->cursor = 0;
req->size_items = 0;
req->err_code_ptr = drmMalloc(sizeof(struct drm_mode_atomic_err_code));
if (!req->err_code_ptr)
return NULL;
return req;
}
@ -1395,9 +1404,21 @@ drm_public drmModeAtomicReqPtr drmModeAtomicDuplicate(const drmModeAtomicReqPtr
new->cursor = old->cursor;
new->size_items = old->size_items;
if (old->err_code_ptr) {
new->err_code_ptr = drmMalloc(sizeof(struct drm_mode_atomic_err_code));
if (!new->err_code_ptr) {
free(new);
return NULL;
}
memcpy(new->err_code_ptr, old->err_code_ptr, sizeof(struct drm_mode_atomic_err_code));
} else
new->err_code_ptr = NULL;
if (old->size_items) {
new->items = drmMalloc(old->size_items * sizeof(*new->items));
if (!new->items) {
if (new->err_code_ptr)
free(new->err_code_ptr);
free(new);
return NULL;
}
@ -1441,6 +1462,10 @@ drm_public int drmModeAtomicMerge(drmModeAtomicReqPtr base,
base->items[i].cursor = i;
base->cursor += augment->cursor;
if (base->err_code_ptr)
memcpy(base->err_code_ptr, augment->err_code_ptr,
sizeof(struct drm_mode_atomic_err_code));
return 0;
}
@ -1497,6 +1522,10 @@ drm_public void drmModeAtomicFree(drmModeAtomicReqPtr req)
if (req->items)
drmFree(req->items);
if (req->err_code_ptr) {
drmFree(req->err_code_ptr);
}
drmFree(req);
}
@ -1518,6 +1547,7 @@ drm_public int drmModeAtomicCommit(int fd, const drmModeAtomicReqPtr req,
{
drmModeAtomicReqPtr sorted;
struct drm_mode_atomic atomic;
uint64_t err_reporting = 0;
uint32_t *objs_ptr = NULL;
uint32_t *count_props_ptr = NULL;
uint32_t *props_ptr = NULL;
@ -1609,8 +1639,15 @@ drm_public int drmModeAtomicCommit(int fd, const drmModeAtomicReqPtr req,
atomic.prop_values_ptr = VOID2U64(prop_values_ptr);
atomic.user_data = VOID2U64(user_data);
ret = DRM_IOCTL(fd, DRM_IOCTL_MODE_ATOMIC, &atomic);
/* TODO: This capability has to read on init once and retrived on each commit */
/* Check if atomic error reporting is available */
drmGetCap(fd, DRM_CAP_ATOMIC_ERROR_REPORTING, &err_reporting);
if (err_reporting)
atomic.reserved = (uintptr_t)req->err_code_ptr;
else
atomic.reserved = 0;
ret = DRM_IOCTL(fd, DRM_IOCTL_MODE_ATOMIC, &atomic);
out:
drmFree(objs_ptr);
drmFree(count_props_ptr);

View file

@ -536,6 +536,8 @@ drmModeDestroyDumbBuffer(int fd, uint32_t handle);
extern int
drmModeMapDumbBuffer(int fd, uint32_t handle, uint64_t *offset);
extern const struct drm_mode_atomic_err_code * drmModeAtomicGetErrorCode(drmModeAtomicReqPtr req);
#if defined(__cplusplus)
}
#endif