Add reclaim to the dmem cgroup controller
Subsystems (7)
Thomas Hellström
maintainercover Add reclaim to the dmem cgroup controller
When writing a "max" limit lower than the current usage, the existing code silently failed. This series aims to improve on that by returning -EBUSY on failure and also attempt to synchronously reclaim device memory to push the usage under the new max limit to avoid the error.
Patch 1 implements error propagation.
Patch 2 implements and documents a reclaim callback interface
for the dmem controller.
Patch 3 implements a TTM reclaim callback.
Patch 4-5 hooks up the reclaim callback to the dmem cgroups-
aware drivers xe and amdgpu.
Thomas Hellström (5):
cgroup/dmem: Return error when setting max below current usage cgroup/dmem: Add reclaim callback for lowering max below current usage drm/ttm: Hook up a cgroup-aware reclaim callback for the dmem
controller
drm/xe: Wire up dmem cgroup reclaim for VRAM manager drm/amdgpu: Wire up dmem cgroup reclaim for VRAM manager
drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c | 10 +- drivers/gpu/drm/ttm/ttm_bo.c | 95 ++++++++++++++++- drivers/gpu/drm/ttm/ttm_bo_util.c | 3 +- drivers/gpu/drm/ttm/ttm_resource.c | 36 +++++++ drivers/gpu/drm/xe/xe_ttm_vram_mgr.c | 19 ++-- include/drm/ttm/ttm_bo.h | 10 ++ include/drm/ttm/ttm_resource.h | 4 + include/linux/cgroup_dmem.h | 11 ++ kernel/cgroup/dmem.c | 102 ++++++++++++++++--- 10 files changed, 265 insertions(+), 27 deletions(-)
Signature · 1 line
2.53.0
Thomas Hellström
maintainerPATCH 1/5 cgroup/dmem: Return error when setting max below current usage
Return -EBUSY to userspace when writing dmem.max below the cgroup's current device memory usage, rather than silently leaving the limit unchanged.
--- kernel/cgroup/dmem.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-)
kernel/cgroup/dmem.c +8 -6
@@ -144,22 +144,24 @@ static void free_cg_pool(struct dmem_cgroup_pool_state *pool)dmemcg_pool_put (pool); } -static void +static int set_resource_min (struct dmem_cgroup_pool_state *pool,u64 val) {page_counter_set_min (&pool->cnt, val); +return 0 ; } -static void +static int set_resource_low (struct dmem_cgroup_pool_state *pool,u64 val) {page_counter_set_low (&pool->cnt, val); +return 0 ; } -static void +static int set_resource_max (struct dmem_cgroup_pool_state *pool,u64 val) { -page_counter_set_max (&pool->cnt, val); +return page_counter_set_max (&pool->cnt, val); }static u64 get_resource_low (struct dmem_cgroup_pool_state *pool)
@@ -726,7 +728,7 @@ static int dmemcg_parse_limit(char *options, struct dmem_cgroup_region *region,static ssize_t dmemcg_limit_write (struct kernfs_open_file *of,char *buf,size_t nbytes,loff_t off, -void (*apply)(struct dmem_cgroup_pool_state *,u64 )) +int (*apply)(struct dmem_cgroup_pool_state *,u64 )) {struct dmemcg_state *dmemcs =css_to_dmemcs (of_css (of));int err =0 ;
@@ -773,7 +775,7 @@ static ssize_t dmemcg_limit_write(struct kernfs_open_file *of, }/* And commit */ -apply (pool, new_limit); + err =apply (pool, new_limit);dmemcg_pool_put (pool); out_put:
Signature · 1 line
2.53.0
Thomas Hellström
maintainerPATCH 2/5 cgroup/dmem: Add reclaim callback for lowering max below current usage
In reply to Thomas HellströmAdd an optional reclaim callback to struct dmem_cgroup_region. When dmem.max is set below current usage, invoke the callback to evict memory and retry setting the limit rather than failing immediately. Signal interruptions propagate back to the write() caller.
RFC:
Due to us updating the max limit _after_ the usage has been sufficiently lowered, this should be prone to failures if there are aggressive allocators running in parallel to the reclaim. So can we somehow enforce the new limit while the eviction is happening?
--- include/linux/cgroup_dmem.h | 11 +++++ kernel/cgroup/dmem.c | 94 +++++++++++++++++++++++++++++++++---- 2 files changed, 96 insertions(+), 9 deletions(-)
include/linux/cgroup_dmem.h +11 -0
@@ -26,6 +26,10 @@ bool dmem_cgroup_state_evict_valuable(struct dmem_cgroup_pool_state *limit_pool, bool ignore_low, bool *ret_hit_low);void dmem_cgroup_pool_state_put (struct dmem_cgroup_pool_state *pool); +void dmem_cgroup_region_set_reclaim (struct dmem_cgroup_region *region, +int (*reclaim)(struct dmem_cgroup_pool_state *pool, +u64 target_bytes,void *priv), +void *priv);#else static inline __printf(2,3) struct dmem_cgroup_region * dmem_cgroup_register_region(u64 size, const char *name_fmt, ...)
@@ -62,5 +66,12 @@ bool dmem_cgroup_state_evict_valuable(struct dmem_cgroup_pool_state *limit_pool,static inline void dmem_cgroup_pool_state_put (struct dmem_cgroup_pool_state *pool) { } +static inline void +dmem_cgroup_region_set_reclaim (struct dmem_cgroup_region *region, +int (*reclaim)(struct dmem_cgroup_pool_state *pool, +u64 target_bytes,void *priv), +void *priv) +{ } +#endif #endif /* _CGROUP_DMEM_H */
kernel/cgroup/dmem.c +85 -9
143 lines not on this page · raw message
Signature · 1 line
2.53.0
Maarten Lankhorst
maintainerRe: [PATCH 2/5] cgroup/dmem: Add reclaim callback for lowering max below current usage
Hey,
(Adding Thadeu to cc since they've been working on the same issue)
Den 2026-03-27 kl. 09:15, skrev Thomas Hellström:
Quoted 122 lines
Add an optional reclaim callback to struct
dmem_cgroup_region. When dmem.max is set below current usage, invoke the callback to evict memory and retry setting the limit rather than failing immediately. Signal interruptions propagate back to thewrite()caller.RFC:
Due to us updating the max limit _after_ the usage has been sufficiently lowered, this should be prone to failures if there are aggressive allocators running in parallel to the reclaim. So can we somehow enforce the new limit while the eviction is happening?Assisted-by GitHub Copilot:claude-sonnet-4.6Signed-off-by Thomas Hellström <[email protected]>--- include/linux/cgroup_dmem.h | 11 +++++ kernel/cgroup/dmem.c | 94 +++++++++++++++++++++++++++++++++---- 2 files changed, 96 insertions(+), 9 deletions(-)include/linux/cgroup_dmem.h +11
-0@@ -26,6 +26,10 @@ bool dmem_cgroup_state_evict_valuable(struct dmem_cgroup_pool_state *limit_pool, bool ignore_low, bool *ret_hit_low);void dmem_cgroup_pool_state_put (struct dmem_cgroup_pool_state *pool); +void dmem_cgroup_region_set_reclaim (struct dmem_cgroup_region *region, +int (*reclaim)(struct dmem_cgroup_pool_state *pool, +u64 target_bytes,void *priv), +void *priv);#else static inline __printf(2,3) struct dmem_cgroup_region * dmem_cgroup_register_region(u64 size, const char *name_fmt, ...)@@ -62,5 +66,12 @@ bool dmem_cgroup_state_evict_valuable(struct dmem_cgroup_pool_state *limit_pool,static inline void dmem_cgroup_pool_state_put (struct dmem_cgroup_pool_state *pool) { } +static inline void +dmem_cgroup_region_set_reclaim (struct dmem_cgroup_region *region, +int (*reclaim)(struct dmem_cgroup_pool_state *pool, +u64 target_bytes,void *priv), +void *priv) +{ } +#endif #endif /* _CGROUP_DMEM_H */ kernel/cgroup/dmem.c +43
-4@@ -51,6 +51,18 @@ struct dmem_cgroup_region {* No new pools should be added to the region afterwards. */ bool unregistered; + +/** +* @reclaim: Optional callback invoked when dmem.max is set below the +* current usage of a pool. The driver should attempt to free at least +* @target_bytes from @pool. May be called multiple times if usage +* remains above the limit after returning. +*/ +int (*reclaim)(struct dmem_cgroup_pool_state *pool,u64 target_bytes, +void *priv); + +/** @reclaim_priv: Private data passed to @reclaim. */ +void *reclaim_priv; };struct dmemcg_state {@@ -145,23 +157,59 @@ static void free_cg_pool(struct dmem_cgroup_pool_state *pool) }static int -set_resource_min (struct dmem_cgroup_pool_state *pool,u64 val) +set_resource_min (struct dmem_cgroup_pool_state *pool,u64 val, +struct dmem_cgroup_region *region) {page_counter_set_min (&pool->cnt, val);return 0 ; }static int -set_resource_low (struct dmem_cgroup_pool_state *pool,u64 val) +set_resource_low (struct dmem_cgroup_pool_state *pool,u64 val, +struct dmem_cgroup_region *region) {page_counter_set_low (&pool->cnt, val);return 0 ; }static int -set_resource_max (struct dmem_cgroup_pool_state *pool,u64 val) +set_resource_max (struct dmem_cgroup_pool_state *pool,u64 val, +struct dmem_cgroup_region *region) { -return page_counter_set_max (&pool->cnt, val); +int err =page_counter_set_max (&pool->cnt, val); + +if (err != -EBUSY || !region || !region->reclaim) +return err; + +/* +* The new max is below current usage. Ask the driver to evict memory +* and retry, up to a bounded number of times. Signal interruptions are +* propagated back to the write() caller; other reclaim failures leave +* -EBUSY as the result. +*/ +for (int retries =5 ; retries >0 ; retries--) { +u64 usage =page_counter_read (&pool->cnt); +u64 target = usage > val ? usage - val :0 ; +int reclaim_err; + +if (!target) { + err =page_counter_set_max (&pool->cnt, val); +break ; + } + + reclaim_err = region->reclaim (pool, target, region->reclaim_priv); +if (reclaim_err) { +if (reclaim_err == -EINTR || reclaim_err == -ERESTARTSYS ) + err = reclaim_err;
kernel/cgroup/dmem.c static void free_cg_pool(struct dmem_cgroup_pool_state *pool) · line 213
Quoted 10 lines
kernel/cgroup/dmem.c +9
-0+break ; + } + + err =page_counter_set_max (&pool->cnt, val); +if (err != -EBUSY ) +break ; + } + +return err; }
I mentioned this in chat but I wanted to mention it on the mailing list for others as well, can we reproduce the behavior from memory_max_write() in mm/memcontrol.c?
1. First set new limit through xchg.
2. If O_NONBLOCK is set -> do nothing, next allocation in target region will fail and cause reclaim.
3. If not set -> reclaim until below new limit or interrupted by a signal, return success in all cases here since we set new limit.
Quoted 59 lines
kernel/cgroup/dmem.c +31
-4static u64 get_resource_low (struct dmem_cgroup_pool_state *pool)@@ -186,9 +234,9 @@ static u64 get_resource_current(struct dmem_cgroup_pool_state *pool)static void reset_all_resource_limits (struct dmem_cgroup_pool_state *rpool) { -set_resource_min (rpool,0 ); -set_resource_low (rpool,0 ); -set_resource_max (rpool,PAGE_COUNTER_MAX ); +set_resource_min (rpool,0 ,NULL ); +set_resource_low (rpool,0 ,NULL ); +set_resource_max (rpool,PAGE_COUNTER_MAX ,NULL ); }static void dmemcs_offline (struct cgroup_subsys_state *css)@@ -570,6 +618,32 @@ void dmem_cgroup_pool_state_put(struct dmem_cgroup_pool_state *pool) }EXPORT_SYMBOL_GPL (dmem_cgroup_pool_state_put); +/** +* dmem_cgroup_region_set_reclaim - Register a reclaim callback on a region. +* @region: The region to register the callback for. +* @reclaim: Callback to invoke when dmem.max is set below current usage. +* Called with the pool that needs reclaiming and the number of +* bytes to free. Returns 0 on progress, negative on failure. +* @priv: Opaque pointer passed back to @reclaim. +* +* When dmem.max is lowered below the current usage of a cgroup pool, the +* dmem controller will call @reclaim with a target number of bytes to free. +* After @reclaim returns the controller retries setting the limit; if usage +* is still too high it calls @reclaim again, up to a bounded retry count. +*/ +void dmem_cgroup_region_set_reclaim (struct dmem_cgroup_region *region, +int (*reclaim)(struct dmem_cgroup_pool_state *pool, +u64 target_bytes,void *priv), +void *priv) +{ +if (!region) +return ; + + region->reclaim = reclaim; + region->reclaim_priv = priv; +} +EXPORT_SYMBOL_GPL (dmem_cgroup_region_set_reclaim); +static struct dmem_cgroup_pool_state *get_cg_pool_unlocked (struct dmemcg_state *cg,struct dmem_cgroup_region *region) {@@ -728,7 +802,8 @@ static int dmemcg_parse_limit(char *options, struct dmem_cgroup_region *region,static ssize_t dmemcg_limit_write (struct kernfs_open_file *of,char *buf,size_t nbytes,loff_t off, -int (*apply)(struct dmem_cgroup_pool_state *,u64 )) +int (*apply)(struct dmem_cgroup_pool_state *,u64 , +struct dmem_cgroup_region *)) {struct dmemcg_state *dmemcs =css_to_dmemcs (of_css (of));int err =0 ;
kernel/cgroup/dmem.c static ssize_t dmemcg_limit_write(struct kernfs_open_file *of, · line 857
Quoted 9 lines
kernel/cgroup/dmem.c +2
-1@@ -775,7 +850,8 @@ static ssize_t dmemcg_limit_write(struct kernfs_open_file *of, }/* And commit */ - err =apply (pool, new_limit); + err =apply (pool, new_limit, region); +dmemcg_pool_put (pool); out_put:
Kind regards,
~Maarten Lankhorst
Thomas Hellström
maintainerRe: [PATCH 2/5] cgroup/dmem: Add reclaim callback for lowering max below current usage
Quoted 169 lines · Maarten Lankhorst
Hey,
(Adding Thadeu to cc since they've been working on the same issue)
Den 2026-03-27 kl. 09:15, skrev Thomas Hellström:
Quoted 157 lines
Add an optional reclaim callback to struct
dmem_cgroup_region. When
dmem.max is set below current usage, invoke the callback to evict memory
and retry setting the limit rather than failing immediately. Signal
interruptions propagate back to thewrite()caller.RFC:
Due to us updating the max limit _after_ the usage has been sufficiently lowered, this should be prone to failures if there are aggressive allocators running in parallel to the reclaim. So can we somehow enforce the new limit while the eviction is happening?Assisted-by GitHub Copilot:claude-sonnet-4.6Signed-off-by Thomas Hellström <[email protected]>---
include/linux/cgroup_dmem.h | 11 +++++
kernel/cgroup/dmem.c | 94
+++++++++++++++++++++++++++++++++----2 files changed, 96 insertions(+), 9 deletions(-)include/linux/cgroup_dmem.h +0
-0@@ -26,6 +26,10 @@ bool dmem_cgroup_state_evict_valuable(struct dmem_cgroup_pool_state *limit_pool,bool
ignore_low, bool*ret_hit_low);
voiddmem_cgroup_pool_state_put(struct dmem_cgroup_pool_state *pool);
+void dmem_cgroup_region_set_reclaim(structdmem_cgroup_region*region,include/linux/cgroup_dmem.h +1
-0+ int (*reclaim)(struct
dmem_cgroup_pool_state*pool,include/linux/cgroup_dmem.h +1
-0+ u64
target_bytes, void *priv),include/linux/cgroup_dmem.h +1
-0+ void *priv);#else
static inline__printf(2,3)structdmem_cgroup_region*dmem_cgroup_register_region(u64 size, const char *name_fmt, ...)include/linux/cgroup_dmem.h +0
-0@@ -62,5 +66,12 @@ bool dmem_cgroup_state_evict_valuable(struct dmem_cgroup_pool_state *limit_pool,static inline void
dmem_cgroup_pool_state_put(struct dmem_cgroup_pool_state *pool)
{ }include/linux/cgroup_dmem.h +3
-0+static inline void +dmem_cgroup_region_set_reclaim(struct dmem_cgroup_region *region, + int (*reclaim)(struct
dmem_cgroup_pool_state*pool,include/linux/cgroup_dmem.h +1
-0+ u64 target_bytes,void *priv),
include/linux/cgroup_dmem.h +3
-0+ void *priv) +{ } +#endif
#endif /*_CGROUP_DMEM_H*/kernel/cgroup/dmem.c +3
-0@@ -51,6 +51,18 @@ struct dmem_cgroup_region {* No new pools should be added to the region afterwards. */ bool unregistered; + +/** +* @reclaim: Optional callback invoked when dmem.max is set below the
kernel/cgroup/dmem.c +1
-0+* current usage of a pool. The driver should attempt to free at least
kernel/cgroup/dmem.c +1
-0+* @target_bytes from @pool. May be called multiple times if usage
kernel/cgroup/dmem.c +3
-0+* remains above the limit after returning. +*/ + int (*reclaim)(struct dmem_cgroup_pool_state *pool, u64
target_bytes,kernel/cgroup/dmem.c +4
-0+ void *priv); + +/** @reclaim_priv: Private data passed to @reclaim. */ +void *reclaim_priv;};
structdmemcg_state{kernel/cgroup/dmem.c +0
-0@@ -145,23 +157,59 @@ static void free_cg_pool(struct dmem_cgroup_pool_state *pool) }
static intkernel/cgroup/dmem.c +2
-1-set_resource_min(struct dmem_cgroup_pool_state *pool, u64 val) +set_resource_min(struct dmem_cgroup_pool_state *pool, u64 val, + struct dmem_cgroup_region *region){
page_counter_set_min(&pool->cnt, val);
return 0;
}
static intkernel/cgroup/dmem.c +2
-1-set_resource_low(struct dmem_cgroup_pool_state *pool, u64 val) +set_resource_low(struct dmem_cgroup_pool_state *pool, u64 val, + struct dmem_cgroup_region *region){
page_counter_set_low(&pool->cnt, val);
return 0;
}
static intkernel/cgroup/dmem.c +2
-1-set_resource_max(struct dmem_cgroup_pool_state *pool, u64 val) +set_resource_max(struct dmem_cgroup_pool_state *pool, u64 val, + struct dmem_cgroup_region *region){
kernel/cgroup/dmem.c +7
-1-return page_counter_set_max (&pool->cnt, val); +int err =page_counter_set_max (&pool->cnt, val); + +if (err != -EBUSY || !region || !region->reclaim) +return err; + +/* +* The new max is below current usage. Ask the driver to evict memory
kernel/cgroup/dmem.c +1
-0+* and retry, up to a bounded number of times. Signal interruptions are
kernel/cgroup/dmem.c +1
-0+* propagated back to the write() caller; other reclaim failures leave
kernel/cgroup/dmem.c +9
-0+* -EBUSY as the result. +*/ +for (int retries =5 ; retries >0 ; retries--) { +u64 usage =page_counter_read (&pool->cnt); +u64 target = usage > val ? usage - val :0 ; +int reclaim_err; + +if (!target) { + err = page_counter_set_max(&pool->cnt,val);
kernel/cgroup/dmem.c +4
-0+break ; + } + + reclaim_err = region->reclaim(pool, target,
region->reclaim_priv);kernel/cgroup/dmem.c +2
-0+if (reclaim_err) { + if (reclaim_err == -EINTR || reclaim_err==
-ERESTARTSYS)kernel/cgroup/dmem.c +10
-0+ err = reclaim_err; +break ; + } + + err =page_counter_set_max (&pool->cnt, val); +if (err != -EBUSY ) +break ; + } + +return err;Quoted 1 line
}
I mentioned this in chat but I wanted to mention it on the mailing list for others as well,
can we reproduce the behavior frommemory_max_write()inmm/memcontrol.c?
Quoted 7 lines
1. First set new limit through xchg.
2. IfO_NONBLOCKis set -> do nothing, next allocation in target region will fail and cause reclaim.
3. If not set -> reclaim until below new limit or interrupted by a signal, return success in all cases here since we set new limit.
Yup.
For 3, we also need to consider the case where we fail to reclaim due to memory being pinned. If it's OK to (usually temporary) have current usage above max, that would work.
I have that coded up and also add a patch on top to defer reclaim to a thread if we bail due to signal or O_NONBLOCK. Perhaps we could discuss whether that's a good or bad idea in that patch.
Will send out when I've updated the IGT tests accordingly.
Thanks,
Thomas
Maarten Lankhorst
maintainerRe: [PATCH 2/5] cgroup/dmem: Add reclaim callback for lowering max below current usage
Hey,
Den 2026-04-22 kl. 10:42, skrev Thomas Hellström:
Quoted 180 lines · Maarten Lankhorst
Quoted 169 lines
Hey,
(Adding Thadeu to cc since they've been working on the same issue)
Den 2026-03-27 kl. 09:15, skrev Thomas Hellström:
Quoted 157 lines
Add an optional reclaim callback to struct
dmem_cgroup_region. When
dmem.max is set below current usage, invoke the callback to evict memory
and retry setting the limit rather than failing immediately. Signal
interruptions propagate back to thewrite()caller.RFC:
Due to us updating the max limit _after_ the usage has been sufficiently lowered, this should be prone to failures if there are aggressive allocators running in parallel to the reclaim. So can we somehow enforce the new limit while the eviction is happening?Assisted-by GitHub Copilot:claude-sonnet-4.6Signed-off-by Thomas Hellström <[email protected]>---
include/linux/cgroup_dmem.h | 11 +++++
kernel/cgroup/dmem.c | 94
+++++++++++++++++++++++++++++++++----2 files changed, 96 insertions(+), 9 deletions(-)include/linux/cgroup_dmem.h +0
-0@@ -26,6 +26,10 @@ bool dmem_cgroup_state_evict_valuable(struct dmem_cgroup_pool_state *limit_pool,bool
ignore_low, bool*ret_hit_low);
voiddmem_cgroup_pool_state_put(struct dmem_cgroup_pool_state *pool);
+void dmem_cgroup_region_set_reclaim(structdmem_cgroup_region*region,include/linux/cgroup_dmem.h +1
-0+ int (*reclaim)(struct
dmem_cgroup_pool_state*pool,include/linux/cgroup_dmem.h +1
-0+ u64
target_bytes, void *priv),include/linux/cgroup_dmem.h +1
-0+ void *priv);#else
static inline__printf(2,3)structdmem_cgroup_region*dmem_cgroup_register_region(u64 size, const char *name_fmt, ...)include/linux/cgroup_dmem.h +0
-0@@ -62,5 +66,12 @@ bool dmem_cgroup_state_evict_valuable(struct dmem_cgroup_pool_state *limit_pool,static inline void
dmem_cgroup_pool_state_put(struct dmem_cgroup_pool_state *pool)
{ }include/linux/cgroup_dmem.h +3
-0+static inline void +dmem_cgroup_region_set_reclaim(struct dmem_cgroup_region *region, + int (*reclaim)(struct
dmem_cgroup_pool_state*pool,include/linux/cgroup_dmem.h +1
-0+ u64 target_bytes,void *priv),
include/linux/cgroup_dmem.h +3
-0+ void *priv) +{ } +#endif
#endif /*_CGROUP_DMEM_H*/kernel/cgroup/dmem.c +3
-0@@ -51,6 +51,18 @@ struct dmem_cgroup_region {* No new pools should be added to the region afterwards. */ bool unregistered; + +/** +* @reclaim: Optional callback invoked when dmem.max is set below the
kernel/cgroup/dmem.c +1
-0+* current usage of a pool. The driver should attempt to free at least
kernel/cgroup/dmem.c +1
-0+* @target_bytes from @pool. May be called multiple times if usage
kernel/cgroup/dmem.c +3
-0+* remains above the limit after returning. +*/ + int (*reclaim)(struct dmem_cgroup_pool_state *pool, u64
target_bytes,kernel/cgroup/dmem.c +4
-0+ void *priv); + +/** @reclaim_priv: Private data passed to @reclaim. */ +void *reclaim_priv;};
structdmemcg_state{kernel/cgroup/dmem.c +0
-0@@ -145,23 +157,59 @@ static void free_cg_pool(struct dmem_cgroup_pool_state *pool) }
static intkernel/cgroup/dmem.c +2
-1-set_resource_min(struct dmem_cgroup_pool_state *pool, u64 val) +set_resource_min(struct dmem_cgroup_pool_state *pool, u64 val, + struct dmem_cgroup_region *region){
page_counter_set_min(&pool->cnt, val);
return 0;
}
static intkernel/cgroup/dmem.c +2
-1-set_resource_low(struct dmem_cgroup_pool_state *pool, u64 val) +set_resource_low(struct dmem_cgroup_pool_state *pool, u64 val, + struct dmem_cgroup_region *region){
page_counter_set_low(&pool->cnt, val);
return 0;
}
static intkernel/cgroup/dmem.c +2
-1-set_resource_max(struct dmem_cgroup_pool_state *pool, u64 val) +set_resource_max(struct dmem_cgroup_pool_state *pool, u64 val, + struct dmem_cgroup_region *region){
kernel/cgroup/dmem.c +7
-1-return page_counter_set_max (&pool->cnt, val); +int err =page_counter_set_max (&pool->cnt, val); + +if (err != -EBUSY || !region || !region->reclaim) +return err; + +/* +* The new max is below current usage. Ask the driver to evict memory
kernel/cgroup/dmem.c +1
-0+* and retry, up to a bounded number of times. Signal interruptions are
kernel/cgroup/dmem.c +1
-0+* propagated back to the write() caller; other reclaim failures leave
kernel/cgroup/dmem.c +9
-0+* -EBUSY as the result. +*/ +for (int retries =5 ; retries >0 ; retries--) { +u64 usage =page_counter_read (&pool->cnt); +u64 target = usage > val ? usage - val :0 ; +int reclaim_err; + +if (!target) { + err = page_counter_set_max(&pool->cnt,val);
kernel/cgroup/dmem.c +4
-0+break ; + } + + reclaim_err = region->reclaim(pool, target,
region->reclaim_priv);kernel/cgroup/dmem.c +2
-0+if (reclaim_err) { + if (reclaim_err == -EINTR || reclaim_err==
-ERESTARTSYS)kernel/cgroup/dmem.c +10
-0+ err = reclaim_err; +break ; + } + + err =page_counter_set_max (&pool->cnt, val); +if (err != -EBUSY ) +break ; + } + +return err;Quoted 1 line
}
I mentioned this in chat but I wanted to mention it on the mailing list for others as well,
can we reproduce the behavior frommemory_max_write()inmm/memcontrol.c?Quoted 7 lines
1. First set new limit through xchg.
2. IfO_NONBLOCKis set -> do nothing, next allocation in target region will fail and cause reclaim.
3. If not set -> reclaim until below new limit or interrupted by a signal, return success in all cases here since we set new limit.Yup.
Quoted 7 lines
For 3, we also need to consider the case where we fail to reclaim due to memory being pinned. If it's OK to (usually temporary) have current usage above max, that would work.
I have that coded up and also add a patch on top to defer reclaim to a thread if we bail due to signal or
O_NONBLOCK. Perhaps we could discuss whether that's a good or bad idea in that patch.
That doesn't sound like a good idea. The semantics of O_NONBLOCK are deliberately intended to be able to change the max without causing reclaim.
See the details in commit ("memcg: introduce non-blocking limit setting option")
I also believe it's ok not to continue reclaiming if aborted, the caller can always try again if necessary.
If we want to deviate from the memcg controller, we need a very good reason to do so. I'd like to keep the semantics the same if possible.
Quoted 4 lines
Will send out when I've updated the IGT tests accordingly.
Thanks,
Thomas
Kind regards,
~Maarten Lankhorst
Thomas Hellström
maintainerRe: [PATCH 2/5] cgroup/dmem: Add reclaim callback for lowering max below current usage
Quoted 212 lines · Maarten Lankhorst
Hey,
Den 2026-04-22 kl. 10:42, skrev Thomas Hellström:
Quoted 203 lines · Maarten Lankhorst
Quoted 185 lines
Hey,
(Adding Thadeu to cc since they've been working on the same issue)
Den 2026-03-27 kl. 09:15, skrev Thomas Hellström:
Quoted 171 lines
Add an optional reclaim callback to struct
dmem_cgroup_region. When
dmem.max is set below current usage, invoke the callback to evict
memory
and retry setting the limit rather than failing immediately. Signal
interruptions propagate back to thewrite()caller.RFC:
Due to us updating the max limit _after_ the usage has been sufficiently lowered, this should be prone to failures if there are
aggressive allocators running in parallel to the reclaim. So can we somehow enforce the new limit while the eviction is happening?Assisted-by GitHub Copilot:claude-sonnet-4.6Signed-off-by Thomas Hellström<[email protected]>
---
include/linux/cgroup_dmem.h | 11 +++++
kernel/cgroup/dmem.c | 94
+++++++++++++++++++++++++++++++++----2 files changed, 96 insertions(+), 9 deletions(-)include/linux/cgroup_dmem.h +0
-0@@ -26,6 +26,10 @@ bool dmem_cgroup_state_evict_valuable(struct dmem_cgroup_pool_state *limit_pool,bool
ignore_low, bool*ret_hit_low);
voiddmem_cgroup_pool_state_put(struct dmem_cgroup_pool_state *pool);
+void dmem_cgroup_region_set_reclaim(structdmem_cgroup_region*region,include/linux/cgroup_dmem.h +1
-0+ int (*reclaim)(struct
dmem_cgroup_pool_state*pool,include/linux/cgroup_dmem.h +1
-0+ u64
target_bytes, void *priv),include/linux/cgroup_dmem.h +1
-0+ void *priv);#else
static inline__printf(2,3)structdmem_cgroup_region*dmem_cgroup_register_region(u64 size, const char *name_fmt, ...)include/linux/cgroup_dmem.h +0
-0@@ -62,5 +66,12 @@ bool dmem_cgroup_state_evict_valuable(struct dmem_cgroup_pool_state *limit_pool,static inline void
dmem_cgroup_pool_state_put(struct dmem_cgroup_pool_state *pool)
{ }include/linux/cgroup_dmem.h +2
-0+static inline void +dmem_cgroup_region_set_reclaim(struct dmem_cgroup_region*region,
include/linux/cgroup_dmem.h +1
-0+ int (*reclaim)(struct
dmem_cgroup_pool_state*pool,include/linux/cgroup_dmem.h +1
-0+ u64
target_bytes,
void *priv),include/linux/cgroup_dmem.h +3
-0+ void *priv) +{ } +#endif
#endif /*_CGROUP_DMEM_H*/kernel/cgroup/dmem.c +0
-0@@ -51,6 +51,18 @@ struct dmem_cgroup_region { * No new pools should be added to the regionafterwards.
*/
bool unregistered;kernel/cgroup/dmem.c +3
-0+ +/** +* @reclaim: Optional callback invoked when dmem.max is
set below thekernel/cgroup/dmem.c +1
-0+* current usage of a pool. The driver should attempt to
free at leastkernel/cgroup/dmem.c +1
-0+* @target_bytes from @pool. May be called multiple times
if usagekernel/cgroup/dmem.c +3
-0+* remains above the limit after returning. +*/ + int (*reclaim)(struct dmem_cgroup_pool_state *pool,u64
target_bytes,kernel/cgroup/dmem.c +4
-0+ void *priv); + +/** @reclaim_priv: Private data passed to @reclaim. */ +void *reclaim_priv;};
structdmemcg_state{kernel/cgroup/dmem.c +0
-0@@ -145,23 +157,59 @@ static void free_cg_pool(struct dmem_cgroup_pool_state *pool) }
static intkernel/cgroup/dmem.c +2
-1-set_resource_min(struct dmem_cgroup_pool_state *pool, u64 val) +set_resource_min(struct dmem_cgroup_pool_state *pool, u64 val, + struct dmem_cgroup_region *region){
page_counter_set_min(&pool->cnt, val);
return 0;
}
static intkernel/cgroup/dmem.c +2
-1-set_resource_low(struct dmem_cgroup_pool_state *pool, u64 val) +set_resource_low(struct dmem_cgroup_pool_state *pool, u64 val, + struct dmem_cgroup_region *region){
page_counter_set_low(&pool->cnt, val);
return 0;
}
static intkernel/cgroup/dmem.c +2
-1-set_resource_max(struct dmem_cgroup_pool_state *pool, u64 val) +set_resource_max(struct dmem_cgroup_pool_state *pool, u64 val, + struct dmem_cgroup_region *region){
kernel/cgroup/dmem.c +7
-1-return page_counter_set_max (&pool->cnt, val); +int err =page_counter_set_max (&pool->cnt, val); + +if (err != -EBUSY || !region || !region->reclaim) +return err; + +/* +* The new max is below current usage. Ask the driver to
evict memorykernel/cgroup/dmem.c +1
-0+* and retry, up to a bounded number of times. Signal interruptions are
kernel/cgroup/dmem.c +1
-0+* propagated back to the write() caller; other reclaim
failures leavekernel/cgroup/dmem.c +9
-0+* -EBUSY as the result. +*/ +for (int retries =5 ; retries >0 ; retries--) { +u64 usage =page_counter_read (&pool->cnt); +u64 target = usage > val ? usage - val :0 ; +int reclaim_err; + +if (!target) { + err = page_counter_set_max(&pool->cnt,val);
kernel/cgroup/dmem.c +4
-0+break ; + } + + reclaim_err = region->reclaim(pool, target,
region->reclaim_priv);kernel/cgroup/dmem.c +2
-0+if (reclaim_err) { + if (reclaim_err == -EINTR ||
reclaim_err
==-ERESTARTSYS)kernel/cgroup/dmem.c +10
-0+ err = reclaim_err; +break ; + } + + err =page_counter_set_max (&pool->cnt, val); +if (err != -EBUSY ) +break ; + } + +return err;Quoted 1 line
}
I mentioned this in chat but I wanted to mention it on the mailing
list for others as well,
can we reproduce the behavior frommemory_max_write()inmm/memcontrol.c?Quoted 8 lines
1. First set new limit through xchg.
2. IfO_NONBLOCKis set -> do nothing, next allocation in target region will fail and cause reclaim.
3. If not set -> reclaim until below new limit or interrupted by a
signal, return success in all cases here since we set new limit.Yup.
For 3, we also need to consider the case where we fail to reclaim due
to memory being pinned. If it's OK to (usually temporary) have current
usage above max, that would work.Quoted 5 lines
I have that coded up and also add a patch on top to defer reclaim to a
thread if we bail due to signal orO_NONBLOCK. Perhaps we could discuss
whether that's a good or bad idea in that patch.
Quoted 7 lines
That doesn't sound like a good idea. The semantics of
O_NONBLOCKare deliberately intended to be able to change the max without causing
reclaim.See the details in commit ("memcg: introduce non-blocking limit setting option")
From reading the docs that introduces, it sounds more like that avoids *synchronous* reclaim, which is also in line with O_NONBLOCK semantics.
The analogy with launching a thread would be more that of kswapd doing the reclaim in the memcg case?
But OTOH, if we were to introduce a thread-driven dmem reclaim that would perhaps be something that wasn't directly tied to the dmem controller but rather to the dmem provider itself. (TTM in this case).
Thanks,
/Thomas
Quoted 16 lines
I also believe it's ok not to continue reclaiming if aborted, the caller can
always try again if necessary.If we want to deviate from the memcg controller, we need a very good reason
to do so. I'd like to keep the semantics the same if possible.Quoted 4 lines
Will send out when I've updated the IGT tests accordingly.
Thanks,
ThomasKind regards,
~Maarten Lankhorst
Maarten Lankhorst
maintainerRe: [PATCH 2/5] cgroup/dmem: Add reclaim callback for lowering max below current usage
Hey,
Den 2026-04-22 kl. 12:20, skrev Thomas Hellström:
Quoted 224 lines · Maarten Lankhorst
Quoted 212 lines
Hey,
Den 2026-04-22 kl. 10:42, skrev Thomas Hellström:
Quoted 203 lines · Maarten Lankhorst
Quoted 185 lines
Hey,
(Adding Thadeu to cc since they've been working on the same issue)
Den 2026-03-27 kl. 09:15, skrev Thomas Hellström:
Quoted 171 lines
Add an optional reclaim callback to struct
dmem_cgroup_region. When
dmem.max is set below current usage, invoke the callback to evict
memory
and retry setting the limit rather than failing immediately. Signal
interruptions propagate back to thewrite()caller.RFC:
Due to us updating the max limit _after_ the usage has been sufficiently lowered, this should be prone to failures if there are
aggressive allocators running in parallel to the reclaim. So can we somehow enforce the new limit while the eviction is happening?Assisted-by GitHub Copilot:claude-sonnet-4.6Signed-off-by Thomas Hellström<[email protected]>
---
include/linux/cgroup_dmem.h | 11 +++++
kernel/cgroup/dmem.c | 94
+++++++++++++++++++++++++++++++++----2 files changed, 96 insertions(+), 9 deletions(-)include/linux/cgroup_dmem.h +0
-0@@ -26,6 +26,10 @@ bool dmem_cgroup_state_evict_valuable(struct dmem_cgroup_pool_state *limit_pool,bool
ignore_low, bool*ret_hit_low);
voiddmem_cgroup_pool_state_put(struct dmem_cgroup_pool_state *pool);
+void dmem_cgroup_region_set_reclaim(structdmem_cgroup_region*region,include/linux/cgroup_dmem.h +1
-0+ int (*reclaim)(struct
dmem_cgroup_pool_state*pool,include/linux/cgroup_dmem.h +1
-0+ u64
target_bytes, void *priv),include/linux/cgroup_dmem.h +1
-0+ void *priv);#else
static inline__printf(2,3)structdmem_cgroup_region*dmem_cgroup_register_region(u64 size, const char *name_fmt, ...)include/linux/cgroup_dmem.h +0
-0@@ -62,5 +66,12 @@ bool dmem_cgroup_state_evict_valuable(struct dmem_cgroup_pool_state *limit_pool,static inline void
dmem_cgroup_pool_state_put(struct dmem_cgroup_pool_state *pool)
{ }include/linux/cgroup_dmem.h +2
-0+static inline void +dmem_cgroup_region_set_reclaim(struct dmem_cgroup_region*region,
include/linux/cgroup_dmem.h +1
-0+ int (*reclaim)(struct
dmem_cgroup_pool_state*pool,include/linux/cgroup_dmem.h +1
-0+ u64
target_bytes,
void *priv),include/linux/cgroup_dmem.h +3
-0+ void *priv) +{ } +#endif
#endif /*_CGROUP_DMEM_H*/kernel/cgroup/dmem.c +0
-0@@ -51,6 +51,18 @@ struct dmem_cgroup_region { * No new pools should be added to the regionafterwards.
*/
bool unregistered;kernel/cgroup/dmem.c +3
-0+ +/** +* @reclaim: Optional callback invoked when dmem.max is
set below thekernel/cgroup/dmem.c +1
-0+* current usage of a pool. The driver should attempt to
free at leastkernel/cgroup/dmem.c +1
-0+* @target_bytes from @pool. May be called multiple times
if usagekernel/cgroup/dmem.c +3
-0+* remains above the limit after returning. +*/ + int (*reclaim)(struct dmem_cgroup_pool_state *pool,u64
target_bytes,kernel/cgroup/dmem.c +4
-0+ void *priv); + +/** @reclaim_priv: Private data passed to @reclaim. */ +void *reclaim_priv;};
structdmemcg_state{kernel/cgroup/dmem.c +0
-0@@ -145,23 +157,59 @@ static void free_cg_pool(struct dmem_cgroup_pool_state *pool) }
static intkernel/cgroup/dmem.c +2
-1-set_resource_min(struct dmem_cgroup_pool_state *pool, u64 val) +set_resource_min(struct dmem_cgroup_pool_state *pool, u64 val, + struct dmem_cgroup_region *region){
page_counter_set_min(&pool->cnt, val);
return 0;
}
static intkernel/cgroup/dmem.c +2
-1-set_resource_low(struct dmem_cgroup_pool_state *pool, u64 val) +set_resource_low(struct dmem_cgroup_pool_state *pool, u64 val, + struct dmem_cgroup_region *region){
page_counter_set_low(&pool->cnt, val);
return 0;
}
static intkernel/cgroup/dmem.c +2
-1-set_resource_max(struct dmem_cgroup_pool_state *pool, u64 val) +set_resource_max(struct dmem_cgroup_pool_state *pool, u64 val, + struct dmem_cgroup_region *region){
kernel/cgroup/dmem.c +7
-1-return page_counter_set_max (&pool->cnt, val); +int err =page_counter_set_max (&pool->cnt, val); + +if (err != -EBUSY || !region || !region->reclaim) +return err; + +/* +* The new max is below current usage. Ask the driver to
evict memorykernel/cgroup/dmem.c +1
-0+* and retry, up to a bounded number of times. Signal interruptions are
kernel/cgroup/dmem.c +1
-0+* propagated back to the write() caller; other reclaim
failures leavekernel/cgroup/dmem.c +9
-0+* -EBUSY as the result. +*/ +for (int retries =5 ; retries >0 ; retries--) { +u64 usage =page_counter_read (&pool->cnt); +u64 target = usage > val ? usage - val :0 ; +int reclaim_err; + +if (!target) { + err = page_counter_set_max(&pool->cnt,val);
kernel/cgroup/dmem.c +4
-0+break ; + } + + reclaim_err = region->reclaim(pool, target,
region->reclaim_priv);kernel/cgroup/dmem.c +2
-0+if (reclaim_err) { + if (reclaim_err == -EINTR ||
reclaim_err
==-ERESTARTSYS)kernel/cgroup/dmem.c +10
-0+ err = reclaim_err; +break ; + } + + err =page_counter_set_max (&pool->cnt, val); +if (err != -EBUSY ) +break ; + } + +return err;Quoted 1 line
}
I mentioned this in chat but I wanted to mention it on the mailing
list for others as well,
can we reproduce the behavior frommemory_max_write()inmm/memcontrol.c?Quoted 8 lines
1. First set new limit through xchg.
2. IfO_NONBLOCKis set -> do nothing, next allocation in target region will fail and cause reclaim.
3. If not set -> reclaim until below new limit or interrupted by a
signal, return success in all cases here since we set new limit.Yup.
For 3, we also need to consider the case where we fail to reclaim due
to memory being pinned. If it's OK to (usually temporary) have current
usage above max, that would work.Quoted 5 lines
I have that coded up and also add a patch on top to defer reclaim to a
thread if we bail due to signal orO_NONBLOCK. Perhaps we could discuss
whether that's a good or bad idea in that patch.Quoted 7 lines
That doesn't sound like a good idea. The semantics of
O_NONBLOCKare deliberately intended to be able to change the max without causing
reclaim.See the details in commit ("memcg: introduce non-blocking limit setting option")
From reading the docs that introduces, it sounds more like that avoids *synchronous* reclaim, which is also in line with
O_NONBLOCKsemantics.
Quoted 6 lines
The analogy with launching a thread would be more that of kswapd doing the reclaim in the memcg case?
But OTOH, if we were to introduce a thread-driven dmem reclaim that would perhaps be something that wasn't directly tied to the dmem controller but rather to the dmem provider itself. (TTM in this case).
From the docs:
+ If memory.max is opened with O_NONBLOCK, then the synchronous + reclaim and oom-kill are bypassed. This is useful for admin + processes that need to dynamically adjust the job's memory limits + without expending their own CPU resources on memory reclamation. + The job will trigger the reclaim and/or oom-kill on its next + charge request.
The task writing to max will not trigger a reclaim, only set the new max value.
But when a process, part of the affected cgroup, tries to allocate memory, it will be forced to reclaim memory until below max again.
This is a workflow where instead of the updater doing all the evictions, the evictions handled by a process in the cgroup itself.
Quoted 16 lines
Quoted 16 lines
I also believe it's ok not to continue reclaiming if aborted, the caller can
always try again if necessary.If we want to deviate from the memcg controller, we need a very good reason
to do so. I'd like to keep the semantics the same if possible.Quoted 4 lines
Will send out when I've updated the IGT tests accordingly.
Thanks,
ThomasKind regards,
~Maarten Lankhorst
Thomas Hellström
maintainerRe: [PATCH 2/5] cgroup/dmem: Add reclaim callback for lowering max below current usage
Quoted 281 lines · Maarten Lankhorst
Hey,
Den 2026-04-22 kl. 12:20, skrev Thomas Hellström:
Quoted 258 lines · Maarten Lankhorst
Quoted 244 lines
Hey,
Den 2026-04-22 kl. 10:42, skrev Thomas Hellström:
Quoted 234 lines · Maarten Lankhorst
Quoted 212 lines
Hey,
(Adding Thadeu to cc since they've been working on the same issue)
Den 2026-03-27 kl. 09:15, skrev Thomas Hellström:
Quoted 198 lines
Add an optional reclaim callback to struct
dmem_cgroup_region.
When
dmem.max is set below current usage, invoke the callback to evict
memory
and retry setting the limit rather than failing immediately.
Signal
interruptions propagate back to thewrite()caller.RFC:
Due to us updating the max limit _after_ the usage has been sufficiently lowered, this should be prone to failures if there
are
aggressive allocators running in parallel to the reclaim. So can we somehow enforce the new limit while the eviction is
happening?Assisted-by GitHub Copilot:claude-sonnet-4.6Signed-off-by Thomas Hellström<[email protected]>
---
include/linux/cgroup_dmem.h | 11 +++++
kernel/cgroup/dmem.c | 94
+++++++++++++++++++++++++++++++++----2 files changed, 96 insertions(+), 9 deletions(-)include/linux/cgroup_dmem.h +0
-0@@ -26,6 +26,10 @@ booldmem_cgroup_state_evict_valuable(struct
dmem_cgroup_pool_state*limit_pool,
boolignore_low, bool*ret_hit_low);
void dmem_cgroup_pool_state_put(structdmem_cgroup_pool_state
*pool);
+void dmem_cgroup_region_set_reclaim(structdmem_cgroup_region
*region,include/linux/cgroup_dmem.h +1
-0+ int (*reclaim)(struct
dmem_cgroup_pool_state*pool,include/linux/cgroup_dmem.h +1
-0+ u64
target_bytes, void *priv),include/linux/cgroup_dmem.h +1
-0+ void *priv);#else
static inline__printf(2,3)structdmem_cgroup_region* dmem_cgroup_register_region(u64 size, const char*name_fmt,
...)include/linux/cgroup_dmem.h +0
-0@@ -62,5 +66,12 @@ booldmem_cgroup_state_evict_valuable(struct
dmem_cgroup_pool_state*limit_pool,
static inline voiddmem_cgroup_pool_state_put(struct dmem_cgroup_pool_state *pool)
{ }include/linux/cgroup_dmem.h +2
-0+static inline void +dmem_cgroup_region_set_reclaim(struct dmem_cgroup_region*region,
include/linux/cgroup_dmem.h +1
-0+ int (*reclaim)(struct
dmem_cgroup_pool_state*pool,include/linux/cgroup_dmem.h +1
-0+ u64
target_bytes,
void *priv),include/linux/cgroup_dmem.h +3
-0+ void *priv) +{ } +#endif
#endif /*_CGROUP_DMEM_H*/kernel/cgroup/dmem.c +0
-0@@ -51,6 +51,18 @@ struct dmem_cgroup_region { * No new pools should be added to the regionafterwards.
*/
bool unregistered;kernel/cgroup/dmem.c +3
-0+ +/** +* @reclaim: Optional callback invoked when dmem.max
is
set below thekernel/cgroup/dmem.c +1
-0+* current usage of a pool. The driver should attempt
to
free at leastkernel/cgroup/dmem.c +1
-0+* @target_bytes from @pool. May be called multiple
times
if usagekernel/cgroup/dmem.c +3
-0+* remains above the limit after returning. +*/ + int (*reclaim)(struct dmem_cgroup_pool_state*pool,
u64target_bytes,kernel/cgroup/dmem.c +3
-0+ void *priv); + +/** @reclaim_priv: Private data passed to @reclaim. */
kernel/cgroup/dmem.c +1
-0+void *reclaim_priv;};
structdmemcg_state{kernel/cgroup/dmem.c +0
-0@@ -145,23 +157,59 @@ static void free_cg_pool(struct dmem_cgroup_pool_state *pool) }
static int
-set_resource_min(structdmem_cgroup_pool_state*pool, u64 val)
+set_resource_min(structdmem_cgroup_pool_state*pool, u64 val,kernel/cgroup/dmem.c +1
-0+ struct dmem_cgroup_region *region){
page_counter_set_min(&pool->cnt, val); return 0;
}
static int
-set_resource_low(structdmem_cgroup_pool_state*pool, u64 val)
+set_resource_low(structdmem_cgroup_pool_state*pool, u64 val,kernel/cgroup/dmem.c +1
-0+ struct dmem_cgroup_region *region){
page_counter_set_low(&pool->cnt, val); return 0;
}
static int
-set_resource_max(structdmem_cgroup_pool_state*pool, u64 val)
+set_resource_max(structdmem_cgroup_pool_state*pool, u64 val,kernel/cgroup/dmem.c +1
-0+ struct dmem_cgroup_region *region){
kernel/cgroup/dmem.c +7
-1-return page_counter_set_max (&pool->cnt, val); +int err =page_counter_set_max (&pool->cnt, val); + +if (err != -EBUSY || !region || !region->reclaim) +return err; + +/* +* The new max is below current usage. Ask the driver
to
evict memorykernel/cgroup/dmem.c +1
-0+* and retry, up to a bounded number of times. Signal
interruptions arekernel/cgroup/dmem.c +1
-0+* propagated back to the write() caller; other reclaim
failures leavekernel/cgroup/dmem.c +5
-0+* -EBUSY as the result. +*/ +for (int retries =5 ; retries >0 ; retries--) { +u64 usage =page_counter_read (&pool->cnt); + u64 target = usage > val ? usage - val :0;
kernel/cgroup/dmem.c +4
-0+int reclaim_err; + +if (!target) { + err = page_counter_set_max(&pool-Quoted 1 line
cnt,
val);
kernel/cgroup/dmem.c +4
-0+break ; + } + + reclaim_err = region->reclaim(pool,target,
region->reclaim_priv);kernel/cgroup/dmem.c +2
-0+if (reclaim_err) { + if (reclaim_err == -EINTR ||
reclaim_err
==-ERESTARTSYS)kernel/cgroup/dmem.c +5
-0+ err = reclaim_err; +break ; + } + + err = page_counter_set_max(&pool->cnt,val);
kernel/cgroup/dmem.c +5
-0+if (err != -EBUSY ) +break ; + } + +return err;Quoted 1 line
}
I mentioned this in chat but I wanted to mention it on the mailing
list for others as well,
can we reproduce the behavior frommemory_max_write()inmm/memcontrol.c?Quoted 11 lines
1. First set new limit through xchg.
2. IfO_NONBLOCKis set -> do nothing, next allocation in target
region will fail and cause reclaim.
3. If not set -> reclaim until below new limit or interrupted by
a
signal, return success in all cases here since we set new limit.Yup.
For 3, we also need to consider the case where we fail to reclaim
due
to memory being pinned. If it's OK to (usually temporary) have current
usage above max, that would work.Quoted 6 lines
I have that coded up and also add a patch on top to defer reclaim
to a
thread if we bail due to signal orO_NONBLOCK. Perhaps we could discuss
whether that's a good or bad idea in that patch.Quoted 7 lines
That doesn't sound like a good idea. The semantics of
O_NONBLOCKare deliberately intended to be able to change the max without causing
reclaim.See the details in commit ("memcg: introduce non-blocking limit setting option")
From reading the docs that introduces, it sounds more like that avoids
*synchronous* reclaim, which is also in line withO_NONBLOCKsemantics.Quoted 8 lines
The analogy with launching a thread would be more that of kswapd doing
the reclaim in the memcg case?But OTOH, if we were to introduce a thread-driven dmem reclaim that would perhaps be something that wasn't directly tied to the dmem controller but rather to the dmem provider itself. (TTM in this case).
From the docs:
+ If memory.max is opened withO_NONBLOCK, then the synchronous
+ reclaim and oom-kill are bypassed. This is useful for admin + processes that need to dynamically adjust the job's memory limits
+ without expending their own CPU resources on memory reclamation.
+ The job will trigger the reclaim and/or oom-kill on its next + charge request.
Quoted 2 lines
The task writing to max will not trigger a reclaim, only set the new max value.
I still read *synchronous* reclaim.
Quoted 8 lines
But when a process, part of the affected cgroup, tries to allocate memory,
it will be forced to reclaim memory until below max again.This is a workflow where instead of the updater doing all the evictions, the evictions handled by a process in the cgroup itself.
But kswapd is still used to do background per-cgroup reclaim in this case, right?
Thanks,
Thomas
Quoted 18 lines
Quoted 18 lines
Quoted 18 lines
I also believe it's ok not to continue reclaiming if aborted, the caller can
always try again if necessary.If we want to deviate from the memcg controller, we need a very good
reason
to do so. I'd like to keep the semantics the same if possible.Quoted 4 lines
Will send out when I've updated the IGT tests accordingly.
Thanks,
ThomasKind regards,
~Maarten Lankhorst
Michal Koutný
maintainerRe: [PATCH 2/5] cgroup/dmem: Add reclaim callback for lowering max below current usage
Quoted 10 lines · Thomas Hellström
Quoted 2 lines
The task writing to max will not trigger a reclaim, only set the new max value.
I still read *synchronous* reclaim.
Quoted 5 lines
But when a process, part of the affected cgroup, tries to allocate memory,
it will be forced to reclaim memory until below max again.
Quoted 6 lines
Quoted 3 lines
This is a workflow where instead of the updater doing all the evictions, the evictions handled by a process in the cgroup itself.
But kswapd is still used to do background per-cgroup reclaim in this case, right?
kswapd is driven by the global zone watermarks, it would only reclaim in the cgroup proportionally to its usage to fulfill that global "limit". The actual memcg's memory.max doesn't affect kswapd, it's really when reclaim is triggered upon hitting the limit from within the memcg.
(The background per-cgroup analogy of kswapd for memcgs is proactive memory.reclaim but there's no dedicated kthread, it's up to the user to decide when and what to write into memory.reclaim.)
HTH,
Michal
Re: [PATCH 2/5] cgroup/dmem: Add reclaim callback for lowering max below current usage
In reply to Thomas HellströmQuoted 84 lines · Thomas Hellström
Add an optional reclaim callback to struct
dmem_cgroup_region. When dmem.max is set below current usage, invoke the callback to evict memory and retry setting the limit rather than failing immediately. Signal interruptions propagate back to thewrite()caller.RFC:
Due to us updating the max limit _after_ the usage has been sufficiently lowered, this should be prone to failures if there are aggressive allocators running in parallel to the reclaim. So can we somehow enforce the new limit while the eviction is happening?Assisted-by GitHub Copilot:claude-sonnet-4.6Signed-off-by Thomas Hellström <[email protected]>--- include/linux/cgroup_dmem.h | 11 +++++ kernel/cgroup/dmem.c | 94 +++++++++++++++++++++++++++++++++---- 2 files changed, 96 insertions(+), 9 deletions(-)include/linux/cgroup_dmem.h +11
-0@@ -26,6 +26,10 @@ bool dmem_cgroup_state_evict_valuable(struct dmem_cgroup_pool_state *limit_pool, bool ignore_low, bool *ret_hit_low);void dmem_cgroup_pool_state_put (struct dmem_cgroup_pool_state *pool); +void dmem_cgroup_region_set_reclaim (struct dmem_cgroup_region *region, +int (*reclaim)(struct dmem_cgroup_pool_state *pool, +u64 target_bytes,void *priv), +void *priv);#else static inline __printf(2,3) struct dmem_cgroup_region * dmem_cgroup_register_region(u64 size, const char *name_fmt, ...)@@ -62,5 +66,12 @@ bool dmem_cgroup_state_evict_valuable(struct dmem_cgroup_pool_state *limit_pool,static inline void dmem_cgroup_pool_state_put (struct dmem_cgroup_pool_state *pool) { } +static inline void +dmem_cgroup_region_set_reclaim (struct dmem_cgroup_region *region, +int (*reclaim)(struct dmem_cgroup_pool_state *pool, +u64 target_bytes,void *priv), +void *priv) +{ } +#endif #endif /* _CGROUP_DMEM_H */ kernel/cgroup/dmem.c +14
-2@@ -51,6 +51,18 @@ struct dmem_cgroup_region {* No new pools should be added to the region afterwards. */ bool unregistered; + +/** +* @reclaim: Optional callback invoked when dmem.max is set below the +* current usage of a pool. The driver should attempt to free at least +* @target_bytes from @pool. May be called multiple times if usage +* remains above the limit after returning. +*/ +int (*reclaim)(struct dmem_cgroup_pool_state *pool,u64 target_bytes, +void *priv); + +/** @reclaim_priv: Private data passed to @reclaim. */ +void *reclaim_priv; };struct dmemcg_state {@@ -145,23 +157,59 @@ static void free_cg_pool(struct dmem_cgroup_pool_state *pool) }static int -set_resource_min (struct dmem_cgroup_pool_state *pool,u64 val) +set_resource_min (struct dmem_cgroup_pool_state *pool,u64 val, +struct dmem_cgroup_region *region) {page_counter_set_min (&pool->cnt, val);return 0 ; } static int -set_resource_low (struct dmem_cgroup_pool_state *pool,u64 val)
kernel/cgroup/dmem.c static void free_cg_pool(struct dmem_cgroup_pool_state *pool) · line 176
Quoted 10 lines
kernel/cgroup/dmem.c +3
-1+set_resource_low(struct dmem_cgroup_pool_state *pool, u64 val, + struct dmem_cgroup_region *region) { page_counter_set_low(&pool->cnt, val);return 0 ; } static int -set_resource_max (struct dmem_cgroup_pool_state *pool,u64 val) +set_resource_max(struct dmem_cgroup_pool_state *pool, u64 val,
Though we are discussing how to set the maximum, renaming 'val' to 'max' would improve readability in the next version.
Quoted 106 lines
kernel/cgroup/dmem.c +68
-6+ struct dmem_cgroup_region *region) { -return page_counter_set_max (&pool->cnt, val); +int err =page_counter_set_max (&pool->cnt, val); + +if (err != -EBUSY || !region || !region->reclaim) +return err; + +/* +* The new max is below current usage. Ask the driver to evict memory +* and retry, up to a bounded number of times. Signal interruptions are +* propagated back to the write() caller; other reclaim failures leave +* -EBUSY as the result. +*/ +for (int retries =5 ; retries >0 ; retries--) { +u64 usage =page_counter_read (&pool->cnt); +u64 target = usage > val ? usage - val :0 ; +int reclaim_err; + +if (!target) { + err =page_counter_set_max (&pool->cnt, val); +break ; + } + + reclaim_err = region->reclaim (pool, target, region->reclaim_priv); +if (reclaim_err) { +if (reclaim_err == -EINTR || reclaim_err == -ERESTARTSYS ) + err = reclaim_err; +break ; + } + + err =page_counter_set_max (&pool->cnt, val); +if (err != -EBUSY ) +break ; + } + +return err; }static u64 get_resource_low (struct dmem_cgroup_pool_state *pool)@@ -186,9 +234,9 @@ static u64 get_resource_current(struct dmem_cgroup_pool_state *pool)static void reset_all_resource_limits (struct dmem_cgroup_pool_state *rpool) { -set_resource_min (rpool,0 ); -set_resource_low (rpool,0 ); -set_resource_max (rpool,PAGE_COUNTER_MAX ); +set_resource_min (rpool,0 ,NULL ); +set_resource_low (rpool,0 ,NULL ); +set_resource_max (rpool,PAGE_COUNTER_MAX ,NULL ); }static void dmemcs_offline (struct cgroup_subsys_state *css)@@ -570,6 +618,32 @@ void dmem_cgroup_pool_state_put(struct dmem_cgroup_pool_state *pool) }EXPORT_SYMBOL_GPL (dmem_cgroup_pool_state_put); +/** +* dmem_cgroup_region_set_reclaim - Register a reclaim callback on a region. +* @region: The region to register the callback for. +* @reclaim: Callback to invoke when dmem.max is set below current usage. +* Called with the pool that needs reclaiming and the number of +* bytes to free. Returns 0 on progress, negative on failure. +* @priv: Opaque pointer passed back to @reclaim. +* +* When dmem.max is lowered below the current usage of a cgroup pool, the +* dmem controller will call @reclaim with a target number of bytes to free. +* After @reclaim returns the controller retries setting the limit; if usage +* is still too high it calls @reclaim again, up to a bounded retry count. +*/ +void dmem_cgroup_region_set_reclaim (struct dmem_cgroup_region *region, +int (*reclaim)(struct dmem_cgroup_pool_state *pool, +u64 target_bytes,void *priv), +void *priv) +{ +if (!region) +return ; + + region->reclaim = reclaim; + region->reclaim_priv = priv; +} +EXPORT_SYMBOL_GPL (dmem_cgroup_region_set_reclaim); +static struct dmem_cgroup_pool_state *get_cg_pool_unlocked (struct dmemcg_state *cg,struct dmem_cgroup_region *region) {@@ -728,7 +802,8 @@ static int dmemcg_parse_limit(char *options, struct dmem_cgroup_region *region,static ssize_t dmemcg_limit_write (struct kernfs_open_file *of,char *buf,size_t nbytes,loff_t off, -int (*apply)(struct dmem_cgroup_pool_state *,u64 )) +int (*apply)(struct dmem_cgroup_pool_state *,u64 , +struct dmem_cgroup_region *)) {struct dmemcg_state *dmemcs =css_to_dmemcs (of_css (of));int err =0 ;@@ -775,7 +850,8 @@ static ssize_t dmemcg_limit_write(struct kernfs_open_file *of, }/* And commit */ - err =apply (pool, new_limit); + err =apply (pool, new_limit, region); +dmemcg_pool_put (pool); out_put:
Signature · 2 lines
Best regards, Ridong
Thomas Hellström
maintainerRe: [PATCH 2/5] cgroup/dmem: Add reclaim callback for lowering max below current usage
Quoted 113 lines · Chen Ridong
Quoted 110 lines · Thomas Hellström
Add an optional reclaim callback to struct
dmem_cgroup_region. When
dmem.max is set below current usage, invoke the callback to evict memory
and retry setting the limit rather than failing immediately. Signal
interruptions propagate back to thewrite()caller.RFC:
Due to us updating the max limit _after_ the usage has been sufficiently lowered, this should be prone to failures if there are aggressive allocators running in parallel to the reclaim. So can we somehow enforce the new limit while the eviction is happening?Assisted-by GitHub Copilot:claude-sonnet-4.6Signed-off-by Thomas Hellström <[email protected]>---
include/linux/cgroup_dmem.h| 11 +++++
kernel/cgroup/dmem.c | 94
+++++++++++++++++++++++++++++++++----2 files changed, 96 insertions(+), 9 deletions(-)include/linux/cgroup_dmem.h +0
-0@@ -26,6 +26,10 @@ bool dmem_cgroup_state_evict_valuable(struct dmem_cgroup_pool_state *limit_pool,bool
ignore_low, bool*ret_hit_low);
voiddmem_cgroup_pool_state_put(struct dmem_cgroup_pool_state *pool);
+void dmem_cgroup_region_set_reclaim(structdmem_cgroup_region*region,include/linux/cgroup_dmem.h +1
-0+ int (*reclaim)(struct
dmem_cgroup_pool_state*pool,include/linux/cgroup_dmem.h +1
-0+ u64
target_bytes, void *priv),include/linux/cgroup_dmem.h +1
-0+ void *priv);#else
static inline__printf(2,3)structdmem_cgroup_region*dmem_cgroup_register_region(u64 size, const char *name_fmt, ...)include/linux/cgroup_dmem.h +0
-0@@ -62,5 +66,12 @@ bool dmem_cgroup_state_evict_valuable(struct dmem_cgroup_pool_state *limit_pool,static inline void
dmem_cgroup_pool_state_put(struct dmem_cgroup_pool_state *pool)
{ }include/linux/cgroup_dmem.h +3
-0+static inline void +dmem_cgroup_region_set_reclaim(struct dmem_cgroup_region *region, + int (*reclaim)(struct
dmem_cgroup_pool_state*pool,include/linux/cgroup_dmem.h +1
-0+ u64 target_bytes,void *priv),
include/linux/cgroup_dmem.h +3
-0+ void *priv) +{ } +#endif
#endif /*_CGROUP_DMEM_H*/kernel/cgroup/dmem.c +3
-0@@ -51,6 +51,18 @@ struct dmem_cgroup_region {* No new pools should be added to the region afterwards. */ bool unregistered; + +/** +* @reclaim: Optional callback invoked when dmem.max is set below the
kernel/cgroup/dmem.c +1
-0+* current usage of a pool. The driver should attempt to free at least
kernel/cgroup/dmem.c +1
-0+* @target_bytes from @pool. May be called multiple times if usage
kernel/cgroup/dmem.c +3
-0+* remains above the limit after returning. +*/ + int (*reclaim)(struct dmem_cgroup_pool_state *pool, u64
target_bytes,kernel/cgroup/dmem.c +4
-0+ void *priv); + +/** @reclaim_priv: Private data passed to @reclaim. */ +void *reclaim_priv;};
structdmemcg_state{kernel/cgroup/dmem.c +0
-0@@ -145,23 +157,59 @@ static void free_cg_pool(struct dmem_cgroup_pool_state *pool) }
static intkernel/cgroup/dmem.c +2
-1-set_resource_min(struct dmem_cgroup_pool_state *pool, u64 val) +set_resource_min(struct dmem_cgroup_pool_state *pool, u64 val, + struct dmem_cgroup_region *region){
page_counter_set_min(&pool->cnt, val);
return 0;
}
static intkernel/cgroup/dmem.c +2
-1-set_resource_low(struct dmem_cgroup_pool_state *pool, u64 val) +set_resource_low(struct dmem_cgroup_pool_state *pool, u64 val, + struct dmem_cgroup_region *region){
page_counter_set_low(&pool->cnt, val);
return 0;
}
Quoted 8 lines
kernel/cgroup/dmem.c static void free_cg_pool(struct dmem_cgroup_pool_state *pool) · line 176
Quoted 4 lines
static intkernel/cgroup/dmem.c +1
-1-set_resource_max(struct dmem_cgroup_pool_state *pool, u64 val) +set_resource_max(struct dmem_cgroup_pool_state *pool, u64 val,Though we are discussing how to set the maximum, renaming 'val' to 'max' would
improve readability in the next version.
Since all the set_resource_xxx() functions are using @val, that'd be an unrelated change. Possibly in a follow-up patch?
Thanks,
Thomas
Thomas Hellström
maintainerPATCH 3/5 drm/ttm: Hook up a cgroup-aware reclaim callback for the dmem controller
In reply to Thomas HellströmAdd ttm_bo_evict_cgroup() to evict buffer objects charged to a specific dmem cgroup pool from a resource manager's LRU until a byte target is met. Add ttm_resource_manager_set_dmem_region() to register the TTM eviction path as the reclaim callback for a dmem cgroup region.
The eviction context is interruptible; signals abort the operation and propagate back through the write() syscall.
Introduce a new mode for the bo LRU walker so that sleeping locks can be taken. This can be used when the caller doesn't hold any previous dma_resv locks, and where it intends to hold at most one lock at a time.
Like the rest of the TTM eviction this should sooner than later be converted to full WW transactions.
--- drivers/gpu/drm/ttm/ttm_bo.c | 95 +++++++++++++++++++++++++++++- drivers/gpu/drm/ttm/ttm_bo_util.c | 3 +- drivers/gpu/drm/ttm/ttm_resource.c | 36 +++++++++++ include/drm/ttm/ttm_bo.h | 10 ++++ include/drm/ttm/ttm_resource.h | 4 ++ 5 files changed, 144 insertions(+), 4 deletions(-)
drivers/gpu/drm/ttm/ttm_bo.c +92 -3
@@ -515,12 +515,20 @@ static s64 ttm_bo_evict_cb(struct ttm_lru_walk *walk, struct ttm_buffer_object * {struct ttm_bo_evict_walk *evict_walk =container_of (walk,typeof (*evict_walk), walk); +/* Capture size before eviction in case res is cleared. */ +s64 bo_size = bo->base.size;s64 lret;if (!dmem_cgroup_state_evict_valuable (evict_walk->limit_pool, bo->resource->css, evict_walk->try_low, &evict_walk->hit_low))return 0 ; +/* +* evict_walk->place is NULL in cgroup drain mode. Drivers' +* eviction_valuable() callbacks must handle a NULL place, treating it +* as "any placement": the TTM base implementation already does so via +* ttm_resource_intersects(). +*/ if (bo->pin_count || !bo->bdev->funcs->eviction_valuable (bo, evict_walk->place))return 0 ;
@@ -536,11 +544,15 @@ static s64 ttm_bo_evict_cb(struct ttm_lru_walk *walk, struct ttm_buffer_object * goto out; evict_walk->evicted++; -if (evict_walk->res) +if (evict_walk->res) { lret =ttm_resource_alloc (evict_walk->evictor, evict_walk->place, evict_walk->res,NULL ); -if (lret ==0 ) -return 1 ; +if (lret ==0 ) +return 1 ; + }else { +/* Cgroup drain: return bytes freed for byte-denominated progress. */ +return bo_size; + } out:/* Errors that should terminate the walk. */ if (lret == -ENOSPC )
@@ -614,6 +626,83 @@ static int ttm_bo_evict_alloc(struct ttm_device *bdev,return 0 ; } +/** +* ttm_bo_evict_cgroup - Evict buffer objects charged to a specific cgroup. +* @bdev: The TTM device. +* @man: The resource manager whose LRU to walk. +* @limit_pool: The cgroup pool state whose members should be evicted. +* @target_bytes: Number of bytes to free. +* @ctx: The TTM operation context. +* +* Walk the LRU of @man and evict buffer objects that are charged to the +* cgroup identified by @limit_pool, until at least @target_bytes have been +* freed. Mirrors the two-pass (trylock -> sleeping-lock, low-watermark) +* strategy used by ttm_bo_evict_alloc(). +* +* Return: >= @target_bytes on full success, 0..target_bytes-1 if partial, +* negative error code on fatal error. +*/ +s64 ttm_bo_evict_cgroup (struct ttm_device *bdev, +struct ttm_resource_manager *man, +struct dmem_cgroup_pool_state *limit_pool, +s64 target_bytes, +struct ttm_operation_ctx *ctx) +{ +struct ttm_bo_evict_walk evict_walk = { + .walk = { + .ops = &ttm_evict_walk_ops, + .arg = { .ctx = ctx }, + }, + .limit_pool = limit_pool, +/* place, evictor, res left NULL: selects cgroup drain mode */ + }; +s64 lret, pass; + + evict_walk.walk.arg.trylock_only = true; + lret =ttm_lru_walk_for_evict (&evict_walk.walk, bdev, man, target_bytes); +if (lret <0 || lret >= target_bytes) +return lret; + +/* Second pass: also evict BOs at the low watermark. */ +if (evict_walk.hit_low) { + evict_walk.try_low = true; + pass =ttm_lru_walk_for_evict (&evict_walk.walk, bdev, man, + target_bytes - lret); +if (pass <0 ) +return pass; + lret += pass; +if (lret >= target_bytes) +return lret; + } + +/* Full sleeping-lock pass for remaining target. */ + evict_walk.try_low = evict_walk.hit_low = false; + evict_walk.walk.arg.trylock_only = false; + +retry: + evict_walk.walk.arg.sleeping_lock = true; +do { + evict_walk.evicted =0 ; + pass =ttm_lru_walk_for_evict (&evict_walk.walk, bdev, man, + target_bytes - lret); +if (pass <0 ) { + lret = pass; + goto out; + } + lret += pass; + }while (lret < target_bytes && evict_walk.evicted); + +/* One more attempt if we hit the low limit during sleeping-lock pass. */ +if (lret < target_bytes && evict_walk.hit_low && !evict_walk.try_low) { + evict_walk.try_low = true; + goto retry; + } + +out: +return lret; +} +EXPORT_SYMBOL (ttm_bo_evict_cgroup); +/** * ttm_bo_pin - Pin the buffer object. * @bo: The buffer object to pin
drivers/gpu/drm/ttm/ttm_bo_util.c +2 -1
@@ -999,7 +999,8 @@ __ttm_bo_lru_cursor_next(struct ttm_bo_lru_cursor *curs) bo = res->bo;if (ttm_lru_walk_trylock (curs, bo)) bo_locked = true; -else if (!arg->ticket || arg->ctx->no_wait_gpu || arg->trylock_only) +else if ((!arg->ticket && !arg->sleeping_lock) || arg->ctx->no_wait_gpu || + arg->trylock_only)continue ;if (!ttm_bo_get_unless_zero (bo)) {
drivers/gpu/drm/ttm/ttm_resource.c +36 -0
@@ -937,3 +937,39 @@ void ttm_resource_manager_create_debugfs(struct ttm_resource_manager *man,#endif }EXPORT_SYMBOL (ttm_resource_manager_create_debugfs); + +static int ttm_resource_manager_dmem_reclaim (struct dmem_cgroup_pool_state *pool, +u64 target_bytes,void *priv) +{ +struct ttm_resource_manager *man = priv; +struct ttm_operation_ctx ctx = { .interruptible = true }; +s64 freed; + + freed =ttm_bo_evict_cgroup (man->bdev, man, pool, target_bytes, &ctx); +if (freed <0 ) +return freed; + +return freed >= (s64 )target_bytes ?0 : -ENOSPC ; +} + +/** +* ttm_resource_manager_set_dmem_region - Associate a dmem cgroup region with a +* resource manager and register a reclaim +* callback. +* @man: The resource manager. +* @region: The dmem cgroup region to associate, may be NULL or IS_ERR(). +* +* Sets @man->cg and registers ttm_resource_manager_dmem_reclaim() so that +* writing to dmem.max below current usage triggers TTM eviction rather than +* returning -EBUSY to userspace. +*/ +void ttm_resource_manager_set_dmem_region (struct ttm_resource_manager *man, +struct dmem_cgroup_region *region) +{ + man->cg = region; +if (!IS_ERR_OR_NULL (region)) +dmem_cgroup_region_set_reclaim (region, + ttm_resource_manager_dmem_reclaim, + man); +} +EXPORT_SYMBOL (ttm_resource_manager_set_dmem_region);
include/drm/ttm/ttm_bo.h +10 -0
@@ -226,6 +226,11 @@ struct ttm_lru_walk_arg {struct ww_acquire_ctx *ticket;/** @trylock_only: Only use trylock for locking. */ bool trylock_only; +/** +* @sleeping_lock: Use sleeping locks even with %NULL @ticket. +* @trylock_only has precedence over this field. +*/ +bool sleeping_lock; };/**
@@ -431,6 +436,11 @@ void ttm_bo_unpin(struct ttm_buffer_object *bo);int ttm_bo_evict_first (struct ttm_device *bdev,struct ttm_resource_manager *man,struct ttm_operation_ctx *ctx); +s64 ttm_bo_evict_cgroup (struct ttm_device *bdev, +struct ttm_resource_manager *man, +struct dmem_cgroup_pool_state *limit_pool, +s64 target_bytes, +struct ttm_operation_ctx *ctx);int ttm_bo_access (struct ttm_buffer_object *bo,unsigned long offset,void *buf,int len,int write); vm_fault_t ttm_bo_vm_reserve(struct ttm_buffer_object *bo,
include/drm/ttm/ttm_resource.h +4 -0
@@ -39,6 +39,7 @@struct dentry ;struct dmem_cgroup_device ; +struct dmem_cgroup_region ;struct drm_printer ;struct ttm_device ;struct ttm_resource_manager ;
@@ -475,6 +476,9 @@ void ttm_resource_manager_init(struct ttm_resource_manager *man,struct ttm_device *bdev, uint64_t size); +void ttm_resource_manager_set_dmem_region (struct ttm_resource_manager *man, +struct dmem_cgroup_region *region); +int ttm_resource_manager_evict_all (struct ttm_device *bdev,struct ttm_resource_manager *man);
Signature · 1 line
2.53.0
Thomas Hellström
maintainerPATCH 4/5 drm/xe: Wire up dmem cgroup reclaim for VRAM manager
In reply to Thomas HellströmRegister the VRAM manager with the dmem cgroup reclaim infrastructure so that lowering dmem.max below current VRAM usage triggers TTM eviction rather than failing with -EBUSY.
--- drivers/gpu/drm/xe/xe_ttm_vram_mgr.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-)
drivers/gpu/drm/xe/xe_ttm_vram_mgr.c +12 -7
@@ -303,13 +303,6 @@ int __xe_ttm_vram_mgr_init(struct xe_device *xe, struct xe_ttm_vram_mgr *mgr,struct ttm_resource_manager *man = &mgr->manager;int err; -if (mem_type !=XE_PL_STOLEN ) { -const char *name = mem_type ==XE_PL_VRAM0 ?"vram0" :"vram1" ; - man->cg =drmm_cgroup_register_region (&xe->drm, name, size); -if (IS_ERR (man->cg)) -return PTR_ERR (man->cg); - } - man->func = &xe_ttm_vram_mgr_func; mgr->mem_type = mem_type;mutex_init (&mgr->lock);
@@ -318,6 +311,18 @@ int __xe_ttm_vram_mgr_init(struct xe_device *xe, struct xe_ttm_vram_mgr *mgr, mgr->visible_avail = io_size;ttm_resource_manager_init (man, &xe->ttm, size); + +if (mem_type !=XE_PL_STOLEN ) { +const char *name = mem_type ==XE_PL_VRAM0 ?"vram0" :"vram1" ; +struct dmem_cgroup_region *cg = +drmm_cgroup_register_region (&xe->drm, name, size); + +if (IS_ERR (cg)) +return PTR_ERR (cg); + +ttm_resource_manager_set_dmem_region (man, cg); + } + err =gpu_buddy_init (&mgr->mm, man->size, default_page_size);if (err)return err;
Signature · 1 line
2.53.0
Thomas Hellström
maintainerPATCH 5/5 drm/amdgpu: Wire up dmem cgroup reclaim for VRAM manager
In reply to Thomas HellströmRegister the VRAM manager with the dmem cgroup reclaim infrastructure so that lowering dmem.max below current VRAM usage triggers TTM eviction rather than failing with -EBUSY.
Guard place->flags in amdgpu_ttm_bo_eviction_valuable() against NULL, as the TTM reclaim path passes a NULL place in cgroup drain mode.
--- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c | 10 +++++++--- 2 files changed, 8 insertions(+), 4 deletions(-)
drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +1 -1
@@ -1491,7 +1491,7 @@ static bool amdgpu_ttm_bo_eviction_valuable(struct ttm_buffer_object *bo,dma_resv_for_each_fence (&resv_cursor, bo->base.resv,DMA_RESV_USAGE_BOOKKEEP , f) {if (amdkfd_fence_check_mm (f, current->mm) && - !(place->flags &TTM_PL_FLAG_CONTIGUOUS )) + !(place && (place->flags &TTM_PL_FLAG_CONTIGUOUS )))return false; }
drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c +7 -3
@@ -916,14 +916,18 @@ int amdgpu_vram_mgr_init(struct amdgpu_device *adev) {struct amdgpu_vram_mgr *mgr = &adev->mman.vram_mgr;struct ttm_resource_manager *man = &mgr->manager; +struct dmem_cgroup_region *cg;int err; - man->cg =drmm_cgroup_register_region (adev_to_drm (adev),"vram" , adev->gmc.real_vram_size); -if (IS_ERR (man->cg)) -return PTR_ERR (man->cg);ttm_resource_manager_init (man, &adev->mman.bdev, adev->gmc.real_vram_size); + cg =drmm_cgroup_register_region (adev_to_drm (adev),"vram" , + adev->gmc.real_vram_size); +if (IS_ERR (cg)) +return PTR_ERR (cg); +ttm_resource_manager_set_dmem_region (man, cg); +mutex_init (&mgr->lock);INIT_LIST_HEAD (&mgr->reservations_pending);INIT_LIST_HEAD (&mgr->reserved_pages);
Signature · 1 line
2.53.0
Patchwork
CI✗ CI.checkpatch: warning for Add reclaim to the dmem cgroup controller
In reply to Thomas Hellström== Series Details ==
== Series Details ==
Series: Add reclaim to the dmem cgroup controller
URL : https://patchwork.freedesktop.org/series/163970/
State : warning
== Summary ==
+ KERNEL=/kernel
+ git clone https://gitlab.freedesktop.org/drm/maintainer-tools mt Cloning into 'mt'...
warning: redirecting to https://gitlab.freedesktop.org/drm/maintainer-tools.git/
+ git -C mt rev-list -n1 origin/master 1f57ba1afceae32108bd24770069f764d940a0e4
+ cd /kernel
+ git config --global --add safe.directory /kernel
+ git log -n1
commit 15b809cf5f895b449941f471fd9df6958021d555
Author: Thomas Hellström <[email protected]> Date: Fri Mar 27 09:16:00 2026 +0100
drm/amdgpu: Wire up dmem cgroup reclaim for VRAM manager
Register the VRAM manager with the dmem cgroup reclaim infrastructure so that lowering dmem.max below current VRAM usage triggers TTM eviction rather than failing with -EBUSY.
Guard place->flags in amdgpu_ttm_bo_eviction_valuable() against NULL, as the TTM reclaim path passes a NULL place in cgroup drain mode.
+ /mt/dim checkpatch a748e8ef327c92c865410957509417b30f026304 drm-intel 5396b03267e5 cgroup/dmem: Return error when setting max below current usage -:14: WARNING:BAD_SIGN_OFF: Non-standard signature: Assisted-by:
#14:
-:14: ERROR:BAD_SIGN_OFF: Unrecognized email address: 'GitHub Copilot:claude-sonnet-4.6' #14:
total: 1 errors, 1 warnings, 0 checks, 44 lines checked4906968a231c cgroup/dmem: Add reclaim callback for lowering max below current usage -:22: WARNING:BAD_SIGN_OFF: Non-standard signature: Assisted-by:
#22:
-:22: ERROR:BAD_SIGN_OFF: Unrecognized email address: 'GitHub Copilot:claude-sonnet-4.6' #22:
total: 1 errors, 1 warnings, 0 checks, 165 lines checked34a61b9a5a27 drm/ttm: Hook up a cgroup-aware reclaim callback for the dmem controller -:26: WARNING:BAD_SIGN_OFF: Non-standard signature: Assisted-by:
#26:
-:26: ERROR:BAD_SIGN_OFF: Unrecognized email address: 'GitHub Copilot:claude-sonnet-4.6' #26:
-:127: CHECK:MULTIPLE_ASSIGNMENTS: multiple assignments should be avoided #127: FILE: drivers/gpu/drm/ttm/ttm_bo.c:679:
+ evict_walk.try_low = evict_walk.hit_low = false;
total: 1 errors, 1 warnings, 1 checks, 207 lines checked 0571172946e7 drm/xe: Wire up dmem cgroup reclaim for VRAM manager -:13: WARNING:BAD_SIGN_OFF: Non-standard signature: Assisted-by:
#13:
-:13: ERROR:BAD_SIGN_OFF: Unrecognized email address: 'GitHub Copilot:claude-sonnet-4.6' #13:
total: 1 errors, 1 warnings, 0 checks, 31 lines checked 15b809cf5f89 drm/amdgpu: Wire up dmem cgroup reclaim for VRAM manager -:16: WARNING:BAD_SIGN_OFF: Non-standard signature: Assisted-by:
#16:
-:16: ERROR:BAD_SIGN_OFF: Unrecognized email address: 'GitHub Copilot:claude-sonnet-4.6' #16:
total: 1 errors, 1 warnings, 0 checks, 29 lines checked
Patchwork
CI✓ CI.KUnit: success for Add reclaim to the dmem cgroup controller
In reply to Thomas Hellström== Series Details ==
== Series Details ==
Series: Add reclaim to the dmem cgroup controller
URL : https://patchwork.freedesktop.org/series/163970/
State : success
== Summary ==
+ trap cleanup EXIT
+ /kernel/tools/testing/kunit/kunit.py run --kunitconfig /kernel/drivers/gpu/drm/xe/.kunitconfig [08:26:00] Configuring KUnit Kernel ...
Generating .config ...
Populating config with:
$ make ARCH=um O=.kunit olddefconfig [08:26:04] Building KUnit Kernel ... Populating config with: $ make ARCH=um O=.kunit olddefconfig Building with: $ make all compile_commands.json scripts_gdb ARCH=um O=.kunit --jobs=48 [08:26:35] Starting KUnit Kernel (1/1)... [08:26:35] ============================================================ Running tests with: $ .kunit/linux kunit.enable=1 mem=1G console=tty kunit_shutdown=halt [08:26:35] ================== guc_buf (11 subtests) =================== [08:26:35] [PASSED] test_smallest [08:26:35] [PASSED] test_largest [08:26:35] [PASSED] test_granular [08:26:35] [PASSED] test_unique [08:26:35] [PASSED] test_overlap [08:26:35] [PASSED] test_reusable [08:26:35] [PASSED] test_too_big [08:26:35] [PASSED] test_flush [08:26:35] [PASSED] test_lookup [08:26:35] [PASSED] test_data [08:26:35] [PASSED] test_class [08:26:35] ===================== [PASSED] guc_buf ===================== [08:26:35] =================== guc_dbm (7 subtests) =================== [08:26:35] [PASSED] test_empty [08:26:35] [PASSED] test_default [08:26:35] ======================== test_size ======================== [08:26:35] [PASSED] 4 [08:26:35] [PASSED] 8 [08:26:35] [PASSED] 32 [08:26:35] [PASSED] 256 [08:26:35] ==================== [PASSED] test_size ==================== [08:26:35] ======================= test_reuse ======================== [08:26:35] [PASSED] 4 [08:26:35] [PASSED] 8 [08:26:35] [PASSED] 32 [08:26:35] [PASSED] 256 [08:26:35] =================== [PASSED] test_reuse ==================== [08:26:35] =================== test_range_overlap ==================== [08:26:35] [PASSED] 4 [08:26:35] [PASSED] 8 [08:26:35] [PASSED] 32 [08:26:35] [PASSED] 256 [08:26:35] =============== [PASSED] test_range_overlap ================ [08:26:35] =================== test_range_compact ==================== [08:26:35] [PASSED] 4 [08:26:35] [PASSED] 8 [08:26:35] [PASSED] 32 [08:26:35] [PASSED] 256 [08:26:35] =============== [PASSED] test_range_compact ================ [08:26:35] ==================== test_range_spare ===================== [08:26:35] [PASSED] 4 [08:26:35] [PASSED] 8 [08:26:35] [PASSED] 32 [08:26:35] [PASSED] 256 [08:26:35] ================ [PASSED] test_range_spare ================= [08:26:35] ===================== [PASSED] guc_dbm ===================== [08:26:35] =================== guc_idm (6 subtests) =================== [08:26:35] [PASSED] bad_init [08:26:35] [PASSED] no_init [08:26:35] [PASSED] init_fini [08:26:35] [PASSED] check_used [08:26:35] [PASSED] check_quota [08:26:35] [PASSED] check_all [08:26:35] ===================== [PASSED] guc_idm ===================== [08:26:35] ================== no_relay (3 subtests) =================== [08:26:35] [PASSED] xe_drops_guc2pf_if_not_ready [08:26:35] [PASSED] xe_drops_guc2vf_if_not_ready [08:26:35] [PASSED] xe_rejects_send_if_not_ready [08:26:35] ==================== [PASSED] no_relay ===================== [08:26:35] ================== pf_relay (14 subtests) ================== [08:26:35] [PASSED] pf_rejects_guc2pf_too_short [08:26:35] [PASSED] pf_rejects_guc2pf_too_long [08:26:35] [PASSED] pf_rejects_guc2pf_no_payload [08:26:35] [PASSED] pf_fails_no_payload [08:26:35] [PASSED] pf_fails_bad_origin [08:26:35] [PASSED] pf_fails_bad_type [08:26:35] [PASSED] pf_txn_reports_error [08:26:35] [PASSED] pf_txn_sends_pf2guc [08:26:35] [PASSED] pf_sends_pf2guc [08:26:35] [SKIPPED] pf_loopback_nop [08:26:35] [SKIPPED] pf_loopback_echo [08:26:35] [SKIPPED] pf_loopback_fail [08:26:35] [SKIPPED] pf_loopback_busy [08:26:35] [SKIPPED] pf_loopback_retry [08:26:35] ==================== [PASSED] pf_relay ===================== [08:26:35] ================== vf_relay (3 subtests) =================== [08:26:35] [PASSED] vf_rejects_guc2vf_too_short [08:26:35] [PASSED] vf_rejects_guc2vf_too_long [08:26:35] [PASSED] vf_rejects_guc2vf_no_payload [08:26:35] ==================== [PASSED] vf_relay ===================== [08:26:35] ================ pf_gt_config (9 subtests) ================= [08:26:35] [PASSED] fair_contexts_1vf [08:26:35] [PASSED] fair_doorbells_1vf [08:26:35] [PASSED] fair_ggtt_1vf [08:26:35] ====================== fair_vram_1vf ====================== [08:26:35] [PASSED] 3.50 GiB [08:26:35] [PASSED] 11.5 GiB [08:26:35] [PASSED] 15.5 GiB [08:26:35] [PASSED] 31.5 GiB [08:26:35] [PASSED] 63.5 GiB [08:26:35] [PASSED] 1.91 GiB [08:26:35] ================== [PASSED] fair_vram_1vf ================== [08:26:35] ================ fair_vram_1vf_admin_only ================= [08:26:35] [PASSED] 3.50 GiB [08:26:35] [PASSED] 11.5 GiB [08:26:35] [PASSED] 15.5 GiB [08:26:35] [PASSED] 31.5 GiB [08:26:35] [PASSED] 63.5 GiB [08:26:35] [PASSED] 1.91 GiB [08:26:35] ============ [PASSED] fair_vram_1vf_admin_only ============= [08:26:35] ====================== fair_contexts ====================== [08:26:35] [PASSED] 1 VF [08:26:35] [PASSED] 2 VFs [08:26:35] [PASSED] 3 VFs [08:26:35] [PASSED] 4 VFs [08:26:35] [PASSED] 5 VFs [08:26:35] [PASSED] 6 VFs [08:26:35] [PASSED] 7 VFs [08:26:35] [PASSED] 8 VFs [08:26:35] [PASSED] 9 VFs [08:26:35] [PASSED] 10 VFs [08:26:35] [PASSED] 11 VFs [08:26:35] [PASSED] 12 VFs [08:26:35] [PASSED] 13 VFs [08:26:35] [PASSED] 14 VFs [08:26:35] [PASSED] 15 VFs [08:26:35] [PASSED] 16 VFs [08:26:35] [PASSED] 17 VFs [08:26:35] [PASSED] 18 VFs [08:26:35] [PASSED] 19 VFs [08:26:35] [PASSED] 20 VFs [08:26:35] [PASSED] 21 VFs [08:26:35] [PASSED] 22 VFs [08:26:35] [PASSED] 23 VFs [08:26:35] [PASSED] 24 VFs [08:26:35] [PASSED] 25 VFs [08:26:35] [PASSED] 26 VFs [08:26:35] [PASSED] 27 VFs [08:26:35] [PASSED] 28 VFs [08:26:35] [PASSED] 29 VFs [08:26:35] [PASSED] 30 VFs [08:26:35] [PASSED] 31 VFs [08:26:35] [PASSED] 32 VFs [08:26:35] [PASSED] 33 VFs [08:26:35] [PASSED] 34 VFs [08:26:35] [PASSED] 35 VFs [08:26:35] [PASSED] 36 VFs [08:26:35] [PASSED] 37 VFs [08:26:35] [PASSED] 38 VFs [08:26:35] [PASSED] 39 VFs [08:26:35] [PASSED] 40 VFs [08:26:35] [PASSED] 41 VFs [08:26:35] [PASSED] 42 VFs [08:26:35] [PASSED] 43 VFs [08:26:35] [PASSED] 44 VFs [08:26:35] [PASSED] 45 VFs [08:26:35] [PASSED] 46 VFs [08:26:35] [PASSED] 47 VFs [08:26:35] [PASSED] 48 VFs [08:26:35] [PASSED] 49 VFs [08:26:35] [PASSED] 50 VFs [08:26:35] [PASSED] 51 VFs [08:26:35] [PASSED] 52 VFs [08:26:35] [PASSED] 53 VFs [08:26:35] [PASSED] 54 VFs [08:26:35] [PASSED] 55 VFs [08:26:35] [PASSED] 56 VFs [08:26:35] [PASSED] 57 VFs [08:26:35] [PASSED] 58 VFs [08:26:35] [PASSED] 59 VFs [08:26:35] [PASSED] 60 VFs [08:26:35] [PASSED] 61 VFs [08:26:35] [PASSED] 62 VFs [08:26:35] [PASSED] 63 VFs [08:26:35] ================== [PASSED] fair_contexts ================== [08:26:35] ===================== fair_doorbells ====================== [08:26:35] [PASSED] 1 VF [08:26:35] [PASSED] 2 VFs [08:26:35] [PASSED] 3 VFs [08:26:35] [PASSED] 4 VFs [08:26:35] [PASSED] 5 VFs [08:26:35] [PASSED] 6 VFs [08:26:35] [PASSED] 7 VFs [08:26:35] [PASSED] 8 VFs [08:26:35] [PASSED] 9 VFs [08:26:35] [PASSED] 10 VFs [08:26:35] [PASSED] 11 VFs [08:26:35] [PASSED] 12 VFs [08:26:35] [PASSED] 13 VFs [08:26:35] [PASSED] 14 VFs [08:26:35] [PASSED] 15 VFs [08:26:35] [PASSED] 16 VFs [08:26:35] [PASSED] 17 VFs [08:26:35] [PASSED] 18 VFs [08:26:35] [PASSED] 19 VFs [08:26:35] [PASSED] 20 VFs [08:26:35] [PASSED] 21 VFs [08:26:35] [PASSED] 22 VFs [08:26:35] [PASSED] 23 VFs [08:26:35] [PASSED] 24 VFs [08:26:35] [PASSED] 25 VFs [08:26:35] [PASSED] 26 VFs [08:26:35] [PASSED] 27 VFs [08:26:35] [PASSED] 28 VFs [08:26:35] [PASSED] 29 VFs [08:26:35] [PASSED] 30 VFs [08:26:35] [PASSED] 31 VFs [08:26:35] [PASSED] 32 VFs [08:26:35] [PASSED] 33 VFs [08:26:35] [PASSED] 34 VFs [08:26:35] [PASSED] 35 VFs [08:26:35] [PASSED] 36 VFs [08:26:35] [PASSED] 37 VFs [08:26:35] [PASSED] 38 VFs [08:26:35] [PASSED] 39 VFs [08:26:35] [PASSED] 40 VFs [08:26:35] [PASSED] 41 VFs [08:26:35] [PASSED] 42 VFs [08:26:35] [PASSED] 43 VFs [08:26:35] [PASSED] 44 VFs [08:26:35] [PASSED] 45 VFs [08:26:35] [PASSED] 46 VFs [08:26:35] [PASSED] 47 VFs [08:26:35] [PASSED] 48 VFs [08:26:35] [PASSED] 49 VFs [08:26:35] [PASSED] 50 VFs [08:26:35] [PASSED] 51 VFs [08:26:35] [PASSED] 52 VFs [08:26:35] [PASSED] 53 VFs [08:26:35] [PASSED] 54 VFs [08:26:35] [PASSED] 55 VFs [08:26:35] [PASSED] 56 VFs [08:26:35] [PASSED] 57 VFs [08:26:35] [PASSED] 58 VFs [08:26:35] [PASSED] 59 VFs [08:26:35] [PASSED] 60 VFs [08:26:35] [PASSED] 61 VFs [08:26:35] [PASSED] 62 VFs [08:26:35] [PASSED] 63 VFs [08:26:35] ================= [PASSED] fair_doorbells ================== [08:26:35] ======================== fair_ggtt ======================== [08:26:35] [PASSED] 1 VF [08:26:35] [PASSED] 2 VFs [08:26:35] [PASSED] 3 VFs [08:26:35] [PASSED] 4 VFs [08:26:35] [PASSED] 5 VFs [08:26:35] [PASSED] 6 VFs [08:26:35] [PASSED] 7 VFs [08:26:35] [PASSED] 8 VFs [08:26:35] [PASSED] 9 VFs [08:26:35] [PASSED] 10 VFs [08:26:35] [PASSED] 11 VFs [08:26:35] [PASSED] 12 VFs [08:26:35] [PASSED] 13 VFs [08:26:35] [PASSED] 14 VFs [08:26:35] [PASSED] 15 VFs [08:26:35] [PASSED] 16 VFs [08:26:35] [PASSED] 17 VFs [08:26:35] [PASSED] 18 VFs [08:26:35] [PASSED] 19 VFs [08:26:35] [PASSED] 20 VFs [08:26:35] [PASSED] 21 VFs [08:26:35] [PASSED] 22 VFs [08:26:35] [PASSED] 23 VFs [08:26:35] [PASSED] 24 VFs [08:26:35] [PASSED] 25 VFs [08:26:35] [PASSED] 26 VFs [08:26:35] [PASSED] 27 VFs [08:26:35] [PASSED] 28 VFs [08:26:35] [PASSED] 29 VFs [08:26:35] [PASSED] 30 VFs [08:26:35] [PASSED] 31 VFs [08:26:35] [PASSED] 32 VFs [08:26:35] [PASSED] 33 VFs [08:26:35] [PASSED] 34 VFs [08:26:35] [PASSED] 35 VFs [08:26:35] [PASSED] 36 VFs [08:26:35] [PASSED] 37 VFs [08:26:35] [PASSED] 38 VFs [08:26:35] [PASSED] 39 VFs [08:26:35] [PASSED] 40 VFs [08:26:35] [PASSED] 41 VFs [08:26:35] [PASSED] 42 VFs [08:26:35] [PASSED] 43 VFs [08:26:35] [PASSED] 44 VFs [08:26:35] [PASSED] 45 VFs [08:26:35] [PASSED] 46 VFs [08:26:35] [PASSED] 47 VFs [08:26:35] [PASSED] 48 VFs [08:26:35] [PASSED] 49 VFs [08:26:35] [PASSED] 50 VFs [08:26:35] [PASSED] 51 VFs [08:26:35] [PASSED] 52 VFs [08:26:35] [PASSED] 53 VFs [08:26:35] [PASSED] 54 VFs [08:26:35] [PASSED] 55 VFs [08:26:35] [PASSED] 56 VFs [08:26:35] [PASSED] 57 VFs [08:26:35] [PASSED] 58 VFs [08:26:35] [PASSED] 59 VFs [08:26:35] [PASSED] 60 VFs [08:26:35] [PASSED] 61 VFs [08:26:35] [PASSED] 62 VFs [08:26:35] [PASSED] 63 VFs [08:26:35] ==================== [PASSED] fair_ggtt ==================== [08:26:35] ======================== fair_vram ======================== [08:26:35] [PASSED] 1 VF [08:26:35] [PASSED] 2 VFs [08:26:35] [PASSED] 3 VFs [08:26:35] [PASSED] 4 VFs [08:26:35] [PASSED] 5 VFs [08:26:35] [PASSED] 6 VFs [08:26:35] [PASSED] 7 VFs [08:26:35] [PASSED] 8 VFs [08:26:35] [PASSED] 9 VFs [08:26:35] [PASSED] 10 VFs [08:26:35] [PASSED] 11 VFs [08:26:35] [PASSED] 12 VFs [08:26:35] [PASSED] 13 VFs [08:26:35] [PASSED] 14 VFs [08:26:35] [PASSED] 15 VFs [08:26:35] [PASSED] 16 VFs [08:26:35] [PASSED] 17 VFs [08:26:35] [PASSED] 18 VFs [08:26:35] [PASSED] 19 VFs [08:26:35] [PASSED] 20 VFs [08:26:35] [PASSED] 21 VFs [08:26:35] [PASSED] 22 VFs [08:26:35] [PASSED] 23 VFs [08:26:35] [PASSED] 24 VFs [08:26:35] [PASSED] 25 VFs [08:26:35] [PASSED] 26 VFs [08:26:35] [PASSED] 27 VFs [08:26:35] [PASSED] 28 VFs [08:26:35] [PASSED] 29 VFs [08:26:35] [PASSED] 30 VFs [08:26:35] [PASSED] 31 VFs [08:26:35] [PASSED] 32 VFs [08:26:35] [PASSED] 33 VFs [08:26:35] [PASSED] 34 VFs [08:26:35] [PASSED] 35 VFs [08:26:35] [PASSED] 36 VFs [08:26:35] [PASSED] 37 VFs [08:26:35] [PASSED] 38 VFs [08:26:35] [PASSED] 39 VFs [08:26:35] [PASSED] 40 VFs [08:26:35] [PASSED] 41 VFs [08:26:35] [PASSED] 42 VFs [08:26:35] [PASSED] 43 VFs [08:26:35] [PASSED] 44 VFs [08:26:35] [PASSED] 45 VFs [08:26:35] [PASSED] 46 VFs [08:26:35] [PASSED] 47 VFs [08:26:35] [PASSED] 48 VFs [08:26:35] [PASSED] 49 VFs [08:26:35] [PASSED] 50 VFs [08:26:35] [PASSED] 51 VFs [08:26:35] [PASSED] 52 VFs [08:26:35] [PASSED] 53 VFs [08:26:35] [PASSED] 54 VFs [08:26:35] [PASSED] 55 VFs [08:26:35] [PASSED] 56 VFs [08:26:35] [PASSED] 57 VFs [08:26:35] [PASSED] 58 VFs [08:26:35] [PASSED] 59 VFs [08:26:35] [PASSED] 60 VFs [08:26:35] [PASSED] 61 VFs [08:26:35] [PASSED] 62 VFs [08:26:35] [PASSED] 63 VFs [08:26:35] ==================== [PASSED] fair_vram ==================== [08:26:35] ================== [PASSED] pf_gt_config =================== [08:26:35] ===================== lmtt (1 subtest) ===================== [08:26:35] ======================== test_ops ========================= [08:26:35] [PASSED] 2-level [08:26:35] [PASSED] multi-level [08:26:35] ==================== [PASSED] test_ops ===================== [08:26:35] ====================== [PASSED] lmtt ======================= [08:26:35] ================= pf_service (11 subtests) ================= [08:26:35] [PASSED] pf_negotiate_any [08:26:35] [PASSED] pf_negotiate_base_match [08:26:35] [PASSED] pf_negotiate_base_newer [08:26:35] [PASSED] pf_negotiate_base_next [08:26:35] [SKIPPED] pf_negotiate_base_older [08:26:35] [PASSED] pf_negotiate_base_prev [08:26:35] [PASSED] pf_negotiate_latest_match [08:26:35] [PASSED] pf_negotiate_latest_newer [08:26:35] [PASSED] pf_negotiate_latest_next [08:26:35] [SKIPPED] pf_negotiate_latest_older [08:26:35] [SKIPPED] pf_negotiate_latest_prev [08:26:35] =================== [PASSED] pf_service ==================== [08:26:35] ================= xe_guc_g2g (2 subtests) ================== [08:26:35] ============== xe_live_guc_g2g_kunit_default ============== [08:26:35] ========= [SKIPPED] xe_live_guc_g2g_kunit_default ========== [08:26:35] ============== xe_live_guc_g2g_kunit_allmem =============== [08:26:35] ========== [SKIPPED] xe_live_guc_g2g_kunit_allmem ========== [08:26:35] =================== [SKIPPED] xe_guc_g2g =================== [08:26:35] =================== xe_mocs (2 subtests) =================== [08:26:35] ================ xe_live_mocs_kernel_kunit ================ [08:26:35] =========== [SKIPPED] xe_live_mocs_kernel_kunit ============ [08:26:35] ================ xe_live_mocs_reset_kunit ================= [08:26:35] ============ [SKIPPED] xe_live_mocs_reset_kunit ============ [08:26:35] ==================== [SKIPPED] xe_mocs ===================== [08:26:35] ================= xe_migrate (2 subtests) ================== [08:26:35] ================= xe_migrate_sanity_kunit ================= [08:26:35] ============ [SKIPPED] xe_migrate_sanity_kunit ============= [08:26:35] ================== xe_validate_ccs_kunit ================== [08:26:35] ============= [SKIPPED] xe_validate_ccs_kunit ============== [08:26:35] =================== [SKIPPED] xe_migrate =================== [08:26:35] ================== xe_dma_buf (1 subtest) ================== [08:26:35] ==================== xe_dma_buf_kunit ===================== [08:26:35] ================ [SKIPPED] xe_dma_buf_kunit ================ [08:26:35] =================== [SKIPPED] xe_dma_buf =================== [08:26:35] ================= xe_bo_shrink (1 subtest) ================= [08:26:35] =================== xe_bo_shrink_kunit ==================== [08:26:35] =============== [SKIPPED] xe_bo_shrink_kunit =============== [08:26:35] ================== [SKIPPED] xe_bo_shrink ================== [08:26:35] ==================== xe_bo (2 subtests) ==================== [08:26:35] ================== xe_ccs_migrate_kunit =================== [08:26:35] ============== [SKIPPED] xe_ccs_migrate_kunit ============== [08:26:35] ==================== xe_bo_evict_kunit ==================== [08:26:35] =============== [SKIPPED] xe_bo_evict_kunit ================ [08:26:35] ===================== [SKIPPED] xe_bo ====================== [08:26:35] ==================== args (13 subtests) ==================== [08:26:35] [PASSED] count_args_test [08:26:35] [PASSED] call_args_example [08:26:35] [PASSED] call_args_test [08:26:35] [PASSED] drop_first_arg_example [08:26:35] [PASSED] drop_first_arg_test [08:26:35] [PASSED] first_arg_example [08:26:35] [PASSED] first_arg_test [08:26:35] [PASSED] last_arg_example [08:26:35] [PASSED] last_arg_test [08:26:35] [PASSED] pick_arg_example [08:26:35] [PASSED] if_args_example [08:26:35] [PASSED] if_args_test [08:26:35] [PASSED] sep_comma_example [08:26:35] ====================== [PASSED] args ======================= [08:26:35] =================== xe_pci (3 subtests) ==================== [08:26:35] ==================== check_graphics_ip ==================== [08:26:35] [PASSED] 12.00 Xe_LP [08:26:35] [PASSED] 12.10 Xe_LP+ [08:26:35] [PASSED] 12.55 Xe_HPG [08:26:35] [PASSED] 12.60 Xe_HPC [08:26:35] [PASSED] 12.70 Xe_LPG [08:26:35] [PASSED] 12.71 Xe_LPG [08:26:35] [PASSED] 12.74 Xe_LPG+ [08:26:35] [PASSED] 20.01 Xe2_HPG [08:26:35] [PASSED] 20.02 Xe2_HPG [08:26:35] [PASSED] 20.04 Xe2_LPG [08:26:35] [PASSED] 30.00 Xe3_LPG [08:26:35] [PASSED] 30.01 Xe3_LPG [08:26:35] [PASSED] 30.03 Xe3_LPG [08:26:35] [PASSED] 30.04 Xe3_LPG [08:26:35] [PASSED] 30.05 Xe3_LPG [08:26:35] [PASSED] 35.10 Xe3p_LPG [08:26:35] [PASSED] 35.11 Xe3p_XPC [08:26:35] ================ [PASSED] check_graphics_ip ================ [08:26:35] ===================== check_media_ip ====================== [08:26:35] [PASSED] 12.00 Xe_M [08:26:35] [PASSED] 12.55 Xe_HPM [08:26:35] [PASSED] 13.00 Xe_LPM+ [08:26:35] [PASSED] 13.01 Xe2_HPM [08:26:35] [PASSED] 20.00 Xe2_LPM [08:26:35] [PASSED] 30.00 Xe3_LPM [08:26:35] [PASSED] 30.02 Xe3_LPM [08:26:35] [PASSED] 35.00 Xe3p_LPM [08:26:35] [PASSED] 35.03 Xe3p_HPM [08:26:35] ================= [PASSED] check_media_ip ================== [08:26:35] =================== check_platform_desc =================== [08:26:35] [PASSED] 0x9A60 (TIGERLAKE) [08:26:35] [PASSED] 0x9A68 (TIGERLAKE) [08:26:35] [PASSED] 0x9A70 (TIGERLAKE) [08:26:35] [PASSED] 0x9A40 (TIGERLAKE) [08:26:35] [PASSED] 0x9A49 (TIGERLAKE) [08:26:35] [PASSED] 0x9A59 (TIGERLAKE) [08:26:35] [PASSED] 0x9A78 (TIGERLAKE) [08:26:35] [PASSED] 0x9AC0 (TIGERLAKE) [08:26:35] [PASSED] 0x9AC9 (TIGERLAKE) [08:26:35] [PASSED] 0x9AD9 (TIGERLAKE) [08:26:35] [PASSED] 0x9AF8 (TIGERLAKE) [08:26:35] [PASSED] 0x4C80 (ROCKETLAKE) [08:26:35] [PASSED] 0x4C8A (ROCKETLAKE) [08:26:35] [PASSED] 0x4C8B (ROCKETLAKE) [08:26:35] [PASSED] 0x4C8C (ROCKETLAKE) [08:26:35] [PASSED] 0x4C90 (ROCKETLAKE) [08:26:35] [PASSED] 0x4C9A (ROCKETLAKE) [08:26:35] [PASSED] 0x4680 (ALDERLAKE_S) [08:26:35] [PASSED] 0x4682 (ALDERLAKE_S) [08:26:35] [PASSED] 0x4688 (ALDERLAKE_S) [08:26:35] [PASSED] 0x468A (ALDERLAKE_S) [08:26:35] [PASSED] 0x468B (ALDERLAKE_S) [08:26:35] [PASSED] 0x4690 (ALDERLAKE_S) [08:26:35] [PASSED] 0x4692 (ALDERLAKE_S) [08:26:35] [PASSED] 0x4693 (ALDERLAKE_S) [08:26:35] [PASSED] 0x46A0 (ALDERLAKE_P) [08:26:35] [PASSED] 0x46A1 (ALDERLAKE_P) [08:26:35] [PASSED] 0x46A2 (ALDERLAKE_P) [08:26:35] [PASSED] 0x46A3 (ALDERLAKE_P) [08:26:35] [PASSED] 0x46A6 (ALDERLAKE_P) [08:26:35] [PASSED] 0x46A8 (ALDERLAKE_P) [08:26:35] [PASSED] 0x46AA (ALDERLAKE_P) [08:26:35] [PASSED] 0x462A (ALDERLAKE_P) [08:26:35] [PASSED] 0x4626 (ALDERLAKE_P) [08:26:35] [PASSED] 0x4628 (ALDERLAKE_P) [08:26:35] [PASSED] 0x46B0 (ALDERLAKE_P) [08:26:35] [PASSED] 0x46B1 (ALDERLAKE_P) [08:26:35] [PASSED] 0x46B2 (ALDERLAKE_P) [08:26:35] [PASSED] 0x46B3 (ALDERLAKE_P) [08:26:35] [PASSED] 0x46C0 (ALDERLAKE_P) [08:26:35] [PASSED] 0x46C1 (ALDERLAKE_P) [08:26:35] [PASSED] 0x46C2 (ALDERLAKE_P) [08:26:35] [PASSED] 0x46C3 (ALDERLAKE_P) [08:26:35] [PASSED] 0x46D0 (ALDERLAKE_N) [08:26:35] [PASSED] 0x46D1 (ALDERLAKE_N) [08:26:35] [PASSED] 0x46D2 (ALDERLAKE_N) [08:26:35] [PASSED] 0x46D3 (ALDERLAKE_N) [08:26:35] [PASSED] 0x46D4 (ALDERLAKE_N) [08:26:35] [PASSED] 0xA721 (ALDERLAKE_P) [08:26:35] [PASSED] 0xA7A1 (ALDERLAKE_P) [08:26:35] [PASSED] 0xA7A9 (ALDERLAKE_P) [08:26:35] [PASSED] 0xA7AC (ALDERLAKE_P) [08:26:35] [PASSED] 0xA7AD (ALDERLAKE_P) [08:26:35] [PASSED] 0xA720 (ALDERLAKE_P) [08:26:35] [PASSED] 0xA7A0 (ALDERLAKE_P) [08:26:35] [PASSED] 0xA7A8 (ALDERLAKE_P) [08:26:35] [PASSED] 0xA7AA (ALDERLAKE_P) [08:26:35] [PASSED] 0xA7AB (ALDERLAKE_P) [08:26:35] [PASSED] 0xA780 (ALDERLAKE_S) [08:26:35] [PASSED] 0xA781 (ALDERLAKE_S) [08:26:35] [PASSED] 0xA782 (ALDERLAKE_S) [08:26:35] [PASSED] 0xA783 (ALDERLAKE_S) [08:26:35] [PASSED] 0xA788 (ALDERLAKE_S) [08:26:35] [PASSED] 0xA789 (ALDERLAKE_S) [08:26:35] [PASSED] 0xA78A (ALDERLAKE_S) [08:26:35] [PASSED] 0xA78B (ALDERLAKE_S) [08:26:35] [PASSED] 0x4905 (DG1) [08:26:35] [PASSED] 0x4906 (DG1) [08:26:35] [PASSED] 0x4907 (DG1) [08:26:35] [PASSED] 0x4908 (DG1) [08:26:35] [PASSED] 0x4909 (DG1) [08:26:35] [PASSED] 0x56C0 (DG2) [08:26:35] [PASSED] 0x56C2 (DG2) [08:26:35] [PASSED] 0x56C1 (DG2) [08:26:35] [PASSED] 0x7D51 (METEORLAKE) [08:26:35] [PASSED] 0x7DD1 (METEORLAKE) [08:26:35] [PASSED] 0x7D41 (METEORLAKE) [08:26:35] [PASSED] 0x7D67 (METEORLAKE) [08:26:35] [PASSED] 0xB640 (METEORLAKE) [08:26:35] [PASSED] 0x56A0 (DG2) [08:26:35] [PASSED] 0x56A1 (DG2) [08:26:35] [PASSED] 0x56A2 (DG2) [08:26:35] [PASSED] 0x56BE (DG2) [08:26:35] [PASSED] 0x56BF (DG2) [08:26:35] [PASSED] 0x5690 (DG2) [08:26:35] [PASSED] 0x5691 (DG2) [08:26:35] [PASSED] 0x5692 (DG2) [08:26:35] [PASSED] 0x56A5 (DG2) [08:26:35] [PASSED] 0x56A6 (DG2) [08:26:35] [PASSED] 0x56B0 (DG2) [08:26:35] [PASSED] 0x56B1 (DG2) [08:26:35] [PASSED] 0x56BA (DG2) [08:26:35] [PASSED] 0x56BB (DG2) [08:26:35] [PASSED] 0x56BC (DG2) [08:26:35] [PASSED] 0x56BD (DG2) [08:26:35] [PASSED] 0x5693 (DG2) [08:26:35] [PASSED] 0x5694 (DG2) [08:26:35] [PASSED] 0x5695 (DG2) [08:26:35] [PASSED] 0x56A3 (DG2) [08:26:35] [PASSED] 0x56A4 (DG2) [08:26:35] [PASSED] 0x56B2 (DG2) [08:26:35] [PASSED] 0x56B3 (DG2) [08:26:35] [PASSED] 0x5696 (DG2) [08:26:35] [PASSED] 0x5697 (DG2) [08:26:35] [PASSED] 0xB69 (PVC) [08:26:35] [PASSED] 0xB6E (PVC) [08:26:35] [PASSED] 0xBD4 (PVC) [08:26:35] [PASSED] 0xBD5 (PVC) [08:26:35] [PASSED] 0xBD6 (PVC) [08:26:35] [PASSED] 0xBD7 (PVC) [08:26:35] [PASSED] 0xBD8 (PVC) [08:26:35] [PASSED] 0xBD9 (PVC) [08:26:35] [PASSED] 0xBDA (PVC) [08:26:35] [PASSED] 0xBDB (PVC) [08:26:35] [PASSED] 0xBE0 (PVC) [08:26:35] [PASSED] 0xBE1 (PVC) [08:26:35] [PASSED] 0xBE5 (PVC) [08:26:35] [PASSED] 0x7D40 (METEORLAKE) [08:26:35] [PASSED] 0x7D45 (METEORLAKE) [08:26:35] [PASSED] 0x7D55 (METEORLAKE) [08:26:35] [PASSED] 0x7D60 (METEORLAKE) [08:26:35] [PASSED] 0x7DD5 (METEORLAKE) [08:26:35] [PASSED] 0x6420 (LUNARLAKE) [08:26:35] [PASSED] 0x64A0 (LUNARLAKE) [08:26:35] [PASSED] 0x64B0 (LUNARLAKE) [08:26:35] [PASSED] 0xE202 (BATTLEMAGE) [08:26:35] [PASSED] 0xE209 (BATTLEMAGE) [08:26:35] [PASSED] 0xE20B (BATTLEMAGE) [08:26:35] [PASSED] 0xE20C (BATTLEMAGE) [08:26:35] [PASSED] 0xE20D (BATTLEMAGE) [08:26:35] [PASSED] 0xE210 (BATTLEMAGE) [08:26:35] [PASSED] 0xE211 (BATTLEMAGE) [08:26:35] [PASSED] 0xE212 (BATTLEMAGE) [08:26:35] [PASSED] 0xE216 (BATTLEMAGE) [08:26:35] [PASSED] 0xE220 (BATTLEMAGE) [08:26:35] [PASSED] 0xE221 (BATTLEMAGE) [08:26:35] [PASSED] 0xE222 (BATTLEMAGE) [08:26:35] [PASSED] 0xE223 (BATTLEMAGE) [08:26:35] [PASSED] 0xB080 (PANTHERLAKE) [08:26:35] [PASSED] 0xB081 (PANTHERLAKE) [08:26:35] [PASSED] 0xB082 (PANTHERLAKE) [08:26:35] [PASSED] 0xB083 (PANTHERLAKE) [08:26:35] [PASSED] 0xB084 (PANTHERLAKE) [08:26:35] [PASSED] 0xB085 (PANTHERLAKE) [08:26:35] [PASSED] 0xB086 (PANTHERLAKE) [08:26:35] [PASSED] 0xB087 (PANTHERLAKE) [08:26:35] [PASSED] 0xB08F (PANTHERLAKE) [08:26:35] [PASSED] 0xB090 (PANTHERLAKE) [08:26:35] [PASSED] 0xB0A0 (PANTHERLAKE) [08:26:35] [PASSED] 0xB0B0 (PANTHERLAKE) [08:26:35] [PASSED] 0xFD80 (PANTHERLAKE) [08:26:35] [PASSED] 0xFD81 (PANTHERLAKE) [08:26:35] [PASSED] 0xD740 (NOVALAKE_S) [08:26:35] [PASSED] 0xD741 (NOVALAKE_S) [08:26:35] [PASSED] 0xD742 (NOVALAKE_S) [08:26:35] [PASSED] 0xD743 (NOVALAKE_S) [08:26:35] [PASSED] 0xD744 (NOVALAKE_S) [08:26:35] [PASSED] 0xD745 (NOVALAKE_S) [08:26:35] [PASSED] 0x674C (CRESCENTISLAND) [08:26:35] [PASSED] 0xD750 (NOVALAKE_P) [08:26:35] [PASSED] 0xD751 (NOVALAKE_P) [08:26:35] [PASSED] 0xD752 (NOVALAKE_P) [08:26:35] [PASSED] 0xD753 (NOVALAKE_P) [08:26:35] [PASSED] 0xD754 (NOVALAKE_P) [08:26:35] [PASSED] 0xD755 (NOVALAKE_P) [08:26:35] [PASSED] 0xD756 (NOVALAKE_P) [08:26:35] [PASSED] 0xD757 (NOVALAKE_P) [08:26:35] [PASSED] 0xD75F (NOVALAKE_P) [08:26:35] =============== [PASSED] check_platform_desc =============== [08:26:35] ===================== [PASSED] xe_pci ====================== [08:26:35] =================== xe_rtp (2 subtests) ==================== [08:26:35] =============== xe_rtp_process_to_sr_tests ================ [08:26:35] [PASSED] coalesce-same-reg [08:26:35] [PASSED] no-match-no-add [08:26:35] [PASSED] match-or [08:26:35] [PASSED] match-or-xfail [08:26:35] [PASSED] no-match-no-add-multiple-rules [08:26:35] [PASSED] two-regs-two-entries [08:26:35] [PASSED] clr-one-set-other [08:26:35] [PASSED] set-field [08:26:35] [PASSED] conflict-duplicate stty: 'standard input': Inappropriate ioctl for device [08:26:35] [PASSED] conflict-not-disjoint [08:26:35] [PASSED] conflict-reg-type [08:26:35] =========== [PASSED] xe_rtp_process_to_sr_tests ============ [08:26:35] ================== xe_rtp_process_tests =================== [08:26:35] [PASSED] active1 [08:26:35] [PASSED] active2 [08:26:35] [PASSED] active-inactive [08:26:35] [PASSED] inactive-active [08:26:35] [PASSED] inactive-1st_or_active-inactive [08:26:35] [PASSED] inactive-2nd_or_active-inactive [08:26:35] [PASSED] inactive-last_or_active-inactive [08:26:35] [PASSED] inactive-no_or_active-inactive [08:26:35] ============== [PASSED] xe_rtp_process_tests =============== [08:26:35] ===================== [PASSED] xe_rtp ====================== [08:26:35] ==================== xe_wa (1 subtest) ===================== [08:26:35] ======================== xe_wa_gt ========================= [08:26:35] [PASSED] TIGERLAKE B0 [08:26:35] [PASSED] DG1 A0 [08:26:35] [PASSED] DG1 B0 [08:26:35] [PASSED] ALDERLAKE_S A0 [08:26:35] [PASSED] ALDERLAKE_S B0 [08:26:35] [PASSED] ALDERLAKE_S C0 [08:26:35] [PASSED] ALDERLAKE_S D0 [08:26:35] [PASSED] ALDERLAKE_P A0 [08:26:35] [PASSED] ALDERLAKE_P B0 [08:26:35] [PASSED] ALDERLAKE_P C0 [08:26:35] [PASSED] ALDERLAKE_S RPLS D0 [08:26:35] [PASSED] ALDERLAKE_P RPLU E0 [08:26:35] [PASSED] DG2 G10 C0 [08:26:35] [PASSED] DG2 G11 B1 [08:26:35] [PASSED] DG2 G12 A1 [08:26:35] [PASSED] METEORLAKE 12.70(Xe_LPG) A0 13.00(Xe_LPM+) A0 [08:26:35] [PASSED] METEORLAKE 12.71(Xe_LPG) A0 13.00(Xe_LPM+) A0 [08:26:35] [PASSED] METEORLAKE 12.74(Xe_LPG+) A0 13.00(Xe_LPM+) A0 [08:26:35] [PASSED] LUNARLAKE 20.04(Xe2_LPG) A0 20.00(Xe2_LPM) A0 [08:26:35] [PASSED] LUNARLAKE 20.04(Xe2_LPG) B0 20.00(Xe2_LPM) A0 [08:26:35] [PASSED] BATTLEMAGE 20.01(Xe2_HPG) A0 13.01(Xe2_HPM) A1 [08:26:35] [PASSED] PANTHERLAKE 30.00(Xe3_LPG) A0 30.00(Xe3_LPM) A0 [08:26:35] ==================== [PASSED] xe_wa_gt ===================== [08:26:35] ====================== [PASSED] xe_wa ====================== [08:26:35] ============================================================ [08:26:35] Testing complete. Ran 597 tests: passed: 579, skipped: 18 [08:26:36] Elapsed time: 35.316s total, 4.237s configuring, 30.462s building, 0.595s running
+ /kernel/tools/testing/kunit/kunit.py run --kunitconfig /kernel/drivers/gpu/drm/tests/.kunitconfig [08:26:36] Configuring KUnit Kernel ...
Regenerating .config ...
Populating config with:
$ make ARCH=um O=.kunit olddefconfig [08:26:37] Building KUnit Kernel ... Populating config with: $ make ARCH=um O=.kunit olddefconfig Building with: $ make all compile_commands.json scripts_gdb ARCH=um O=.kunit --jobs=48 [08:27:02] Starting KUnit Kernel (1/1)... [08:27:02] ============================================================ Running tests with: $ .kunit/linux kunit.enable=1 mem=1G console=tty kunit_shutdown=halt [08:27:02] ============ drm_test_pick_cmdline (2 subtests) ============ [08:27:02] [PASSED] drm_test_pick_cmdline_res_1920_1080_60 [08:27:02] =============== drm_test_pick_cmdline_named =============== [08:27:02] [PASSED] NTSC [08:27:02] [PASSED] NTSC-J [08:27:02] [PASSED] PAL [08:27:02] [PASSED] PAL-M [08:27:02] =========== [PASSED] drm_test_pick_cmdline_named =========== [08:27:02] ============== [PASSED] drm_test_pick_cmdline ============== [08:27:02] == drm_test_atomic_get_connector_for_encoder (1 subtest) === [08:27:02] [PASSED] drm_test_drm_atomic_get_connector_for_encoder [08:27:02] ==== [PASSED] drm_test_atomic_get_connector_for_encoder ==== [08:27:02] =========== drm_validate_clone_mode (2 subtests) =========== [08:27:02] ============== drm_test_check_in_clone_mode =============== [08:27:02] [PASSED] in_clone_mode [08:27:02] [PASSED] not_in_clone_mode [08:27:02] ========== [PASSED] drm_test_check_in_clone_mode =========== [08:27:02] =============== drm_test_check_valid_clones =============== [08:27:02] [PASSED] not_in_clone_mode [08:27:02] [PASSED] valid_clone [08:27:02] [PASSED] invalid_clone [08:27:02] =========== [PASSED] drm_test_check_valid_clones =========== [08:27:02] ============= [PASSED] drm_validate_clone_mode ============= [08:27:02] ============= drm_validate_modeset (1 subtest) ============= [08:27:02] [PASSED] drm_test_check_connector_changed_modeset [08:27:02] ============== [PASSED] drm_validate_modeset =============== [08:27:02] ====== drm_test_bridge_get_current_state (2 subtests) ====== [08:27:02] [PASSED] drm_test_drm_bridge_get_current_state_atomic [08:27:02] [PASSED] drm_test_drm_bridge_get_current_state_legacy [08:27:02] ======== [PASSED] drm_test_bridge_get_current_state ======== [08:27:02] ====== drm_test_bridge_helper_reset_crtc (3 subtests) ====== [08:27:02] [PASSED] drm_test_drm_bridge_helper_reset_crtc_atomic [08:27:02] [PASSED] drm_test_drm_bridge_helper_reset_crtc_atomic_disabled [08:27:02] [PASSED] drm_test_drm_bridge_helper_reset_crtc_legacy [08:27:02] ======== [PASSED] drm_test_bridge_helper_reset_crtc ======== [08:27:02] ============== drm_bridge_alloc (2 subtests) =============== [08:27:02] [PASSED] drm_test_drm_bridge_alloc_basic [08:27:02] [PASSED] drm_test_drm_bridge_alloc_get_put [08:27:02] ================ [PASSED] drm_bridge_alloc ================= [08:27:02] ============= drm_cmdline_parser (40 subtests) ============= [08:27:02] [PASSED] drm_test_cmdline_force_d_only [08:27:02] [PASSED] drm_test_cmdline_force_D_only_dvi [08:27:02] [PASSED] drm_test_cmdline_force_D_only_hdmi [08:27:02] [PASSED] drm_test_cmdline_force_D_only_not_digital [08:27:02] [PASSED] drm_test_cmdline_force_e_only [08:27:02] [PASSED] drm_test_cmdline_res [08:27:02] [PASSED] drm_test_cmdline_res_vesa [08:27:02] [PASSED] drm_test_cmdline_res_vesa_rblank [08:27:02] [PASSED] drm_test_cmdline_res_rblank [08:27:02] [PASSED] drm_test_cmdline_res_bpp [08:27:02] [PASSED] drm_test_cmdline_res_refresh [08:27:02] [PASSED] drm_test_cmdline_res_bpp_refresh [08:27:02] [PASSED] drm_test_cmdline_res_bpp_refresh_interlaced [08:27:02] [PASSED] drm_test_cmdline_res_bpp_refresh_margins [08:27:02] [PASSED] drm_test_cmdline_res_bpp_refresh_force_off [08:27:02] [PASSED] drm_test_cmdline_res_bpp_refresh_force_on [08:27:02] [PASSED] drm_test_cmdline_res_bpp_refresh_force_on_analog [08:27:02] [PASSED] drm_test_cmdline_res_bpp_refresh_force_on_digital [08:27:02] [PASSED] drm_test_cmdline_res_bpp_refresh_interlaced_margins_force_on [08:27:02] [PASSED] drm_test_cmdline_res_margins_force_on [08:27:02] [PASSED] drm_test_cmdline_res_vesa_margins [08:27:02] [PASSED] drm_test_cmdline_name [08:27:02] [PASSED] drm_test_cmdline_name_bpp [08:27:02] [PASSED] drm_test_cmdline_name_option [08:27:02] [PASSED] drm_test_cmdline_name_bpp_option [08:27:02] [PASSED] drm_test_cmdline_rotate_0 [08:27:02] [PASSED] drm_test_cmdline_rotate_90 [08:27:02] [PASSED] drm_test_cmdline_rotate_180 [08:27:02] [PASSED] drm_test_cmdline_rotate_270 [08:27:02] [PASSED] drm_test_cmdline_hmirror [08:27:02] [PASSED] drm_test_cmdline_vmirror [08:27:02] [PASSED] drm_test_cmdline_margin_options [08:27:02] [PASSED] drm_test_cmdline_multiple_options [08:27:02] [PASSED] drm_test_cmdline_bpp_extra_and_option [08:27:02] [PASSED] drm_test_cmdline_extra_and_option [08:27:02] [PASSED] drm_test_cmdline_freestanding_options [08:27:02] [PASSED] drm_test_cmdline_freestanding_force_e_and_options [08:27:02] [PASSED] drm_test_cmdline_panel_orientation [08:27:02] ================ drm_test_cmdline_invalid ================= [08:27:02] [PASSED] margin_only [08:27:02] [PASSED] interlace_only [08:27:02] [PASSED] res_missing_x [08:27:02] [PASSED] res_missing_y [08:27:02] [PASSED] res_bad_y [08:27:02] [PASSED] res_missing_y_bpp [08:27:02] [PASSED] res_bad_bpp [08:27:02] [PASSED] res_bad_refresh [08:27:02] [PASSED] res_bpp_refresh_force_on_off [08:27:02] [PASSED] res_invalid_mode [08:27:02] [PASSED] res_bpp_wrong_place_mode [08:27:02] [PASSED] name_bpp_refresh [08:27:02] [PASSED] name_refresh [08:27:02] [PASSED] name_refresh_wrong_mode [08:27:02] [PASSED] name_refresh_invalid_mode [08:27:02] [PASSED] rotate_multiple [08:27:02] [PASSED] rotate_invalid_val [08:27:02] [PASSED] rotate_truncated [08:27:02] [PASSED] invalid_option [08:27:02] [PASSED] invalid_tv_option [08:27:02] [PASSED] truncated_tv_option [08:27:02] ============ [PASSED] drm_test_cmdline_invalid ============= [08:27:02] =============== drm_test_cmdline_tv_options =============== [08:27:02] [PASSED] NTSC [08:27:02] [PASSED] NTSC_443 [08:27:02] [PASSED] NTSC_J [08:27:02] [PASSED] PAL [08:27:02] [PASSED] PAL_M [08:27:02] [PASSED] PAL_N [08:27:02] [PASSED] SECAM [08:27:02] [PASSED] MONO_525 [08:27:02] [PASSED] MONO_625 [08:27:02] =========== [PASSED] drm_test_cmdline_tv_options =========== [08:27:02] =============== [PASSED] drm_cmdline_parser ================ [08:27:02] ========== drmm_connector_hdmi_init (20 subtests) ========== [08:27:02] [PASSED] drm_test_connector_hdmi_init_valid [08:27:02] [PASSED] drm_test_connector_hdmi_init_bpc_8 [08:27:02] [PASSED] drm_test_connector_hdmi_init_bpc_10 [08:27:02] [PASSED] drm_test_connector_hdmi_init_bpc_12 [08:27:02] [PASSED] drm_test_connector_hdmi_init_bpc_invalid [08:27:02] [PASSED] drm_test_connector_hdmi_init_bpc_null [08:27:02] [PASSED] drm_test_connector_hdmi_init_formats_empty [08:27:02] [PASSED] drm_test_connector_hdmi_init_formats_no_rgb [08:27:02] === drm_test_connector_hdmi_init_formats_yuv420_allowed === [08:27:02] [PASSED] supported_formats=0x9 yuv420_allowed=1 [08:27:02] [PASSED] supported_formats=0x9 yuv420_allowed=0 [08:27:02] [PASSED] supported_formats=0x5 yuv420_allowed=1 [08:27:02] [PASSED] supported_formats=0x5 yuv420_allowed=0 [08:27:02] === [PASSED] drm_test_connector_hdmi_init_formats_yuv420_allowed === [08:27:02] [PASSED] drm_test_connector_hdmi_init_null_ddc [08:27:02] [PASSED] drm_test_connector_hdmi_init_null_product [08:27:02] [PASSED] drm_test_connector_hdmi_init_null_vendor [08:27:02] [PASSED] drm_test_connector_hdmi_init_product_length_exact [08:27:02] [PASSED] drm_test_connector_hdmi_init_product_length_too_long [08:27:02] [PASSED] drm_test_connector_hdmi_init_product_valid [08:27:02] [PASSED] drm_test_connector_hdmi_init_vendor_length_exact [08:27:02] [PASSED] drm_test_connector_hdmi_init_vendor_length_too_long [08:27:02] [PASSED] drm_test_connector_hdmi_init_vendor_valid [08:27:02] ========= drm_test_connector_hdmi_init_type_valid ========= [08:27:02] [PASSED] HDMI-A [08:27:02] [PASSED] HDMI-B [08:27:02] ===== [PASSED] drm_test_connector_hdmi_init_type_valid ===== [08:27:02] ======== drm_test_connector_hdmi_init_type_invalid ======== [08:27:02] [PASSED] Unknown [08:27:02] [PASSED] VGA [08:27:02] [PASSED] DVI-I [08:27:02] [PASSED] DVI-D [08:27:02] [PASSED] DVI-A [08:27:02] [PASSED] Composite [08:27:02] [PASSED] SVIDEO [08:27:02] [PASSED] LVDS [08:27:02] [PASSED] Component [08:27:02] [PASSED] DIN [08:27:02] [PASSED] DP [08:27:02] [PASSED] TV [08:27:02] [PASSED] eDP [08:27:02] [PASSED] Virtual [08:27:02] [PASSED] DSI [08:27:02] [PASSED] DPI [08:27:02] [PASSED] Writeback [08:27:02] [PASSED] SPI [08:27:02] [PASSED] USB [08:27:02] ==== [PASSED] drm_test_connector_hdmi_init_type_invalid ==== [08:27:02] ============ [PASSED] drmm_connector_hdmi_init ============= [08:27:02] ============= drmm_connector_init (3 subtests) ============= [08:27:02] [PASSED] drm_test_drmm_connector_init [08:27:02] [PASSED] drm_test_drmm_connector_init_null_ddc [08:27:02] ========= drm_test_drmm_connector_init_type_valid ========= [08:27:02] [PASSED] Unknown [08:27:02] [PASSED] VGA [08:27:02] [PASSED] DVI-I [08:27:02] [PASSED] DVI-D [08:27:02] [PASSED] DVI-A [08:27:02] [PASSED] Composite [08:27:02] [PASSED] SVIDEO [08:27:02] [PASSED] LVDS [08:27:02] [PASSED] Component [08:27:02] [PASSED] DIN [08:27:02] [PASSED] DP [08:27:02] [PASSED] HDMI-A [08:27:02] [PASSED] HDMI-B [08:27:02] [PASSED] TV [08:27:02] [PASSED] eDP [08:27:02] [PASSED] Virtual [08:27:02] [PASSED] DSI [08:27:02] [PASSED] DPI [08:27:02] [PASSED] Writeback [08:27:02] [PASSED] SPI [08:27:02] [PASSED] USB [08:27:02] ===== [PASSED] drm_test_drmm_connector_init_type_valid ===== [08:27:02] =============== [PASSED] drmm_connector_init =============== [08:27:02] ========= drm_connector_dynamic_init (6 subtests) ========== [08:27:02] [PASSED] drm_test_drm_connector_dynamic_init [08:27:02] [PASSED] drm_test_drm_connector_dynamic_init_null_ddc [08:27:02] [PASSED] drm_test_drm_connector_dynamic_init_not_added [08:27:02] [PASSED] drm_test_drm_connector_dynamic_init_properties [08:27:02] ===== drm_test_drm_connector_dynamic_init_type_valid ====== [08:27:02] [PASSED] Unknown [08:27:02] [PASSED] VGA [08:27:02] [PASSED] DVI-I [08:27:02] [PASSED] DVI-D [08:27:02] [PASSED] DVI-A [08:27:02] [PASSED] Composite [08:27:02] [PASSED] SVIDEO [08:27:02] [PASSED] LVDS [08:27:02] [PASSED] Component [08:27:02] [PASSED] DIN [08:27:02] [PASSED] DP [08:27:02] [PASSED] HDMI-A [08:27:02] [PASSED] HDMI-B [08:27:02] [PASSED] TV [08:27:02] [PASSED] eDP [08:27:02] [PASSED] Virtual [08:27:02] [PASSED] DSI [08:27:02] [PASSED] DPI [08:27:02] [PASSED] Writeback [08:27:02] [PASSED] SPI [08:27:02] [PASSED] USB [08:27:02] = [PASSED] drm_test_drm_connector_dynamic_init_type_valid == [08:27:02] ======== drm_test_drm_connector_dynamic_init_name ========= [08:27:02] [PASSED] Unknown [08:27:02] [PASSED] VGA [08:27:02] [PASSED] DVI-I [08:27:02] [PASSED] DVI-D [08:27:02] [PASSED] DVI-A [08:27:02] [PASSED] Composite [08:27:02] [PASSED] SVIDEO [08:27:02] [PASSED] LVDS [08:27:02] [PASSED] Component [08:27:02] [PASSED] DIN [08:27:02] [PASSED] DP [08:27:02] [PASSED] HDMI-A [08:27:02] [PASSED] HDMI-B [08:27:02] [PASSED] TV [08:27:02] [PASSED] eDP [08:27:02] [PASSED] Virtual [08:27:02] [PASSED] DSI [08:27:02] [PASSED] DPI [08:27:02] [PASSED] Writeback [08:27:02] [PASSED] SPI [08:27:02] [PASSED] USB [08:27:02] ==== [PASSED] drm_test_drm_connector_dynamic_init_name ===== [08:27:02] =========== [PASSED] drm_connector_dynamic_init ============ [08:27:02] ==== drm_connector_dynamic_register_early (4 subtests) ===== [08:27:02] [PASSED] drm_test_drm_connector_dynamic_register_early_on_list [08:27:02] [PASSED] drm_test_drm_connector_dynamic_register_early_defer [08:27:02] [PASSED] drm_test_drm_connector_dynamic_register_early_no_init [08:27:02] [PASSED] drm_test_drm_connector_dynamic_register_early_no_mode_object [08:27:02] ====== [PASSED] drm_connector_dynamic_register_early ======= [08:27:02] ======= drm_connector_dynamic_register (7 subtests) ======== [08:27:02] [PASSED] drm_test_drm_connector_dynamic_register_on_list [08:27:02] [PASSED] drm_test_drm_connector_dynamic_register_no_defer [08:27:02] [PASSED] drm_test_drm_connector_dynamic_register_no_init [08:27:02] [PASSED] drm_test_drm_connector_dynamic_register_mode_object [08:27:02] [PASSED] drm_test_drm_connector_dynamic_register_sysfs [08:27:02] [PASSED] drm_test_drm_connector_dynamic_register_sysfs_name [08:27:02] [PASSED] drm_test_drm_connector_dynamic_register_debugfs [08:27:02] ========= [PASSED] drm_connector_dynamic_register ========== [08:27:02] = drm_connector_attach_broadcast_rgb_property (2 subtests) = [08:27:02] [PASSED] drm_test_drm_connector_attach_broadcast_rgb_property [08:27:02] [PASSED] drm_test_drm_connector_attach_broadcast_rgb_property_hdmi_connector [08:27:02] === [PASSED] drm_connector_attach_broadcast_rgb_property === [08:27:02] ========== drm_get_tv_mode_from_name (2 subtests) ========== [08:27:02] ========== drm_test_get_tv_mode_from_name_valid =========== [08:27:02] [PASSED] NTSC [08:27:02] [PASSED] NTSC-443 [08:27:02] [PASSED] NTSC-J [08:27:02] [PASSED] PAL [08:27:02] [PASSED] PAL-M [08:27:02] [PASSED] PAL-N [08:27:02] [PASSED] SECAM [08:27:02] [PASSED] Mono [08:27:02] ====== [PASSED] drm_test_get_tv_mode_from_name_valid ======= [08:27:02] [PASSED] drm_test_get_tv_mode_from_name_truncated [08:27:02] ============ [PASSED] drm_get_tv_mode_from_name ============ [08:27:02] = drm_test_connector_hdmi_compute_mode_clock (12 subtests) = [08:27:02] [PASSED] drm_test_drm_hdmi_compute_mode_clock_rgb [08:27:02] [PASSED] drm_test_drm_hdmi_compute_mode_clock_rgb_10bpc [08:27:02] [PASSED] drm_test_drm_hdmi_compute_mode_clock_rgb_10bpc_vic_1 [08:27:02] [PASSED] drm_test_drm_hdmi_compute_mode_clock_rgb_12bpc [08:27:02] [PASSED] drm_test_drm_hdmi_compute_mode_clock_rgb_12bpc_vic_1 [08:27:02] [PASSED] drm_test_drm_hdmi_compute_mode_clock_rgb_double [08:27:02] = drm_test_connector_hdmi_compute_mode_clock_yuv420_valid = [08:27:02] [PASSED] VIC 96 [08:27:02] [PASSED] VIC 97 [08:27:02] [PASSED] VIC 101 [08:27:02] [PASSED] VIC 102 [08:27:02] [PASSED] VIC 106 [08:27:02] [PASSED] VIC 107 [08:27:02] === [PASSED] drm_test_connector_hdmi_compute_mode_clock_yuv420_valid === [08:27:02] [PASSED] drm_test_connector_hdmi_compute_mode_clock_yuv420_10_bpc [08:27:02] [PASSED] drm_test_connector_hdmi_compute_mode_clock_yuv420_12_bpc [08:27:02] [PASSED] drm_test_connector_hdmi_compute_mode_clock_yuv422_8_bpc [08:27:02] [PASSED] drm_test_connector_hdmi_compute_mode_clock_yuv422_10_bpc [08:27:02] [PASSED] drm_test_connector_hdmi_compute_mode_clock_yuv422_12_bpc [08:27:02] === [PASSED] drm_test_connector_hdmi_compute_mode_clock ==== [08:27:02] == drm_hdmi_connector_get_broadcast_rgb_name (2 subtests) == [08:27:02] === drm_test_drm_hdmi_connector_get_broadcast_rgb_name ==== [08:27:02] [PASSED] Automatic [08:27:02] [PASSED] Full [08:27:02] [PASSED] Limited 16:235 [08:27:02] === [PASSED] drm_test_drm_hdmi_connector_get_broadcast_rgb_name === [08:27:02] [PASSED] drm_test_drm_hdmi_connector_get_broadcast_rgb_name_invalid [08:27:02] ==== [PASSED] drm_hdmi_connector_get_broadcast_rgb_name ==== [08:27:02] == drm_hdmi_connector_get_output_format_name (2 subtests) == [08:27:02] === drm_test_drm_hdmi_connector_get_output_format_name ==== [08:27:02] [PASSED] RGB [08:27:02] [PASSED] YUV 4:2:0 [08:27:02] [PASSED] YUV 4:2:2 [08:27:02] [PASSED] YUV 4:4:4 [08:27:02] === [PASSED] drm_test_drm_hdmi_connector_get_output_format_name === [08:27:02] [PASSED] drm_test_drm_hdmi_connector_get_output_format_name_invalid [08:27:02] ==== [PASSED] drm_hdmi_connector_get_output_format_name ==== [08:27:02] ============= drm_damage_helper (21 subtests) ============== [08:27:02] [PASSED] drm_test_damage_iter_no_damage [08:27:02] [PASSED] drm_test_damage_iter_no_damage_fractional_src [08:27:02] [PASSED] drm_test_damage_iter_no_damage_src_moved [08:27:02] [PASSED] drm_test_damage_iter_no_damage_fractional_src_moved [08:27:02] [PASSED] drm_test_damage_iter_no_damage_not_visible [08:27:02] [PASSED] drm_test_damage_iter_no_damage_no_crtc [08:27:02] [PASSED] drm_test_damage_iter_no_damage_no_fb [08:27:02] [PASSED] drm_test_damage_iter_simple_damage [08:27:02] [PASSED] drm_test_damage_iter_single_damage [08:27:02] [PASSED] drm_test_damage_iter_single_damage_intersect_src [08:27:02] [PASSED] drm_test_damage_iter_single_damage_outside_src [08:27:02] [PASSED] drm_test_damage_iter_single_damage_fractional_src [08:27:02] [PASSED] drm_test_damage_iter_single_damage_intersect_fractional_src [08:27:02] [PASSED] drm_test_damage_iter_single_damage_outside_fractional_src [08:27:02] [PASSED] drm_test_damage_iter_single_damage_src_moved [08:27:02] [PASSED] drm_test_damage_iter_single_damage_fractional_src_moved [08:27:02] [PASSED] drm_test_damage_iter_damage [08:27:02] [PASSED] drm_test_damage_iter_damage_one_intersect [08:27:02] [PASSED] drm_test_damage_iter_damage_one_outside [08:27:02] [PASSED] drm_test_damage_iter_damage_src_moved [08:27:02] [PASSED] drm_test_damage_iter_damage_not_visible [08:27:02] ================ [PASSED] drm_damage_helper ================ [08:27:02] ============== drm_dp_mst_helper (3 subtests) ============== [08:27:02] ============== drm_test_dp_mst_calc_pbn_mode ============== [08:27:02] [PASSED] Clock 154000 BPP 30 DSC disabled [08:27:02] [PASSED] Clock 234000 BPP 30 DSC disabled [08:27:02] [PASSED] Clock 297000 BPP 24 DSC disabled [08:27:02] [PASSED] Clock 332880 BPP 24 DSC enabled [08:27:02] [PASSED] Clock 324540 BPP 24 DSC enabled [08:27:02] ========== [PASSED] drm_test_dp_mst_calc_pbn_mode ========== [08:27:02] ============== drm_test_dp_mst_calc_pbn_div =============== [08:27:02] [PASSED] Link rate 2000000 lane count 4 [08:27:02] [PASSED] Link rate 2000000 lane count 2 [08:27:02] [PASSED] Link rate 2000000 lane count 1 [08:27:02] [PASSED] Link rate 1350000 lane count 4 [08:27:02] [PASSED] Link rate 1350000 lane count 2 [08:27:02] [PASSED] Link rate 1350000 lane count 1 [08:27:02] [PASSED] Link rate 1000000 lane count 4 [08:27:02] [PASSED] Link rate 1000000 lane count 2 [08:27:02] [PASSED] Link rate 1000000 lane count 1 [08:27:02] [PASSED] Link rate 810000 lane count 4 [08:27:02] [PASSED] Link rate 810000 lane count 2 [08:27:02] [PASSED] Link rate 810000 lane count 1 [08:27:02] [PASSED] Link rate 540000 lane count 4 [08:27:02] [PASSED] Link rate 540000 lane count 2 [08:27:02] [PASSED] Link rate 540000 lane count 1 [08:27:02] [PASSED] Link rate 270000 lane count 4 [08:27:02] [PASSED] Link rate 270000 lane count 2 [08:27:02] [PASSED] Link rate 270000 lane count 1 [08:27:02] [PASSED] Link rate 162000 lane count 4 [08:27:02] [PASSED] Link rate 162000 lane count 2 [08:27:02] [PASSED] Link rate 162000 lane count 1 [08:27:02] ========== [PASSED] drm_test_dp_mst_calc_pbn_div =========== [08:27:02] ========= drm_test_dp_mst_sideband_msg_req_decode ========= [08:27:02] [PASSED] DP_ENUM_PATH_RESOURCES with port number [08:27:02] [PASSED] DP_POWER_UP_PHY with port number [08:27:02] [PASSED] DP_POWER_DOWN_PHY with port number [08:27:02] [PASSED] DP_ALLOCATE_PAYLOAD with SDP stream sinks [08:27:02] [PASSED] DP_ALLOCATE_PAYLOAD with port number [08:27:02] [PASSED] DP_ALLOCATE_PAYLOAD with VCPI [08:27:02] [PASSED] DP_ALLOCATE_PAYLOAD with PBN [08:27:02] [PASSED] DP_QUERY_PAYLOAD with port number [08:27:02] [PASSED] DP_QUERY_PAYLOAD with VCPI [08:27:02] [PASSED] DP_REMOTE_DPCD_READ with port number [08:27:02] [PASSED] DP_REMOTE_DPCD_READ with DPCD address [08:27:02] [PASSED] DP_REMOTE_DPCD_READ with max number of bytes [08:27:02] [PASSED] DP_REMOTE_DPCD_WRITE with port number [08:27:02] [PASSED] DP_REMOTE_DPCD_WRITE with DPCD address [08:27:02] [PASSED] DP_REMOTE_DPCD_WRITE with data array [08:27:02] [PASSED] DP_REMOTE_I2C_READ with port number [08:27:02] [PASSED] DP_REMOTE_I2C_READ with I2C device ID [08:27:02] [PASSED] DP_REMOTE_I2C_READ with transactions array [08:27:02] [PASSED] DP_REMOTE_I2C_WRITE with port number [08:27:02] [PASSED] DP_REMOTE_I2C_WRITE with I2C device ID [08:27:02] [PASSED] DP_REMOTE_I2C_WRITE with data array [08:27:02] [PASSED] DP_QUERY_STREAM_ENC_STATUS with stream ID [08:27:02] [PASSED] DP_QUERY_STREAM_ENC_STATUS with client ID [08:27:02] [PASSED] DP_QUERY_STREAM_ENC_STATUS with stream event [08:27:02] [PASSED] DP_QUERY_STREAM_ENC_STATUS with valid stream event [08:27:02] [PASSED] DP_QUERY_STREAM_ENC_STATUS with stream behavior [08:27:02] [PASSED] DP_QUERY_STREAM_ENC_STATUS with a valid stream behavior [08:27:02] ===== [PASSED] drm_test_dp_mst_sideband_msg_req_decode ===== [08:27:02] ================ [PASSED] drm_dp_mst_helper ================ [08:27:02] ================== drm_exec (7 subtests) =================== [08:27:02] [PASSED] sanitycheck [08:27:02] [PASSED] test_lock [08:27:02] [PASSED] test_lock_unlock [08:27:02] [PASSED] test_duplicates [08:27:02] [PASSED] test_prepare [08:27:02] [PASSED] test_prepare_array [08:27:02] [PASSED] test_multiple_loops [08:27:02] ==================== [PASSED] drm_exec ===================== [08:27:02] =========== drm_format_helper_test (17 subtests) =========== [08:27:02] ============== drm_test_fb_xrgb8888_to_gray8 ============== [08:27:02] [PASSED] single_pixel_source_buffer [08:27:02] [PASSED] single_pixel_clip_rectangle [08:27:02] [PASSED] well_known_colors [08:27:02] [PASSED] destination_pitch [08:27:02] ========== [PASSED] drm_test_fb_xrgb8888_to_gray8 ========== [08:27:02] ============= drm_test_fb_xrgb8888_to_rgb332 ============== [08:27:02] [PASSED] single_pixel_source_buffer [08:27:02] [PASSED] single_pixel_clip_rectangle [08:27:02] [PASSED] well_known_colors [08:27:02] [PASSED] destination_pitch [08:27:02] ========= [PASSED] drm_test_fb_xrgb8888_to_rgb332 ========== [08:27:02] ============= drm_test_fb_xrgb8888_to_rgb565 ============== [08:27:02] [PASSED] single_pixel_source_buffer [08:27:02] [PASSED] single_pixel_clip_rectangle [08:27:02] [PASSED] well_known_colors [08:27:02] [PASSED] destination_pitch [08:27:02] ========= [PASSED] drm_test_fb_xrgb8888_to_rgb565 ========== [08:27:02] ============ drm_test_fb_xrgb8888_to_xrgb1555 ============= [08:27:02] [PASSED] single_pixel_source_buffer [08:27:02] [PASSED] single_pixel_clip_rectangle [08:27:02] [PASSED] well_known_colors [08:27:02] [PASSED] destination_pitch [08:27:02] ======== [PASSED] drm_test_fb_xrgb8888_to_xrgb1555 ========= [08:27:02] ============ drm_test_fb_xrgb8888_to_argb1555 ============= [08:27:02] [PASSED] single_pixel_source_buffer [08:27:02] [PASSED] single_pixel_clip_rectangle [08:27:02] [PASSED] well_known_colors [08:27:02] [PASSED] destination_pitch [08:27:02] ======== [PASSED] drm_test_fb_xrgb8888_to_argb1555 ========= [08:27:02] ============ drm_test_fb_xrgb8888_to_rgba5551 ============= [08:27:02] [PASSED] single_pixel_source_buffer [08:27:02] [PASSED] single_pixel_clip_rectangle [08:27:02] [PASSED] well_known_colors [08:27:02] [PASSED] destination_pitch [08:27:02] ======== [PASSED] drm_test_fb_xrgb8888_to_rgba5551 ========= [08:27:02] ============= drm_test_fb_xrgb8888_to_rgb888 ============== [08:27:02] [PASSED] single_pixel_source_buffer [08:27:02] [PASSED] single_pixel_clip_rectangle [08:27:02] [PASSED] well_known_colors [08:27:02] [PASSED] destination_pitch [08:27:02] ========= [PASSED] drm_test_fb_xrgb8888_to_rgb888 ========== [08:27:02] ============= drm_test_fb_xrgb8888_to_bgr888 ============== [08:27:02] [PASSED] single_pixel_source_buffer [08:27:02] [PASSED] single_pixel_clip_rectangle [08:27:02] [PASSED] well_known_colors [08:27:02] [PASSED] destination_pitch [08:27:02] ========= [PASSED] drm_test_fb_xrgb8888_to_bgr888 ========== [08:27:02] ============ drm_test_fb_xrgb8888_to_argb8888 ============= [08:27:02] [PASSED] single_pixel_source_buffer [08:27:02] [PASSED] single_pixel_clip_rectangle [08:27:02] [PASSED] well_known_colors [08:27:02] [PASSED] destination_pitch [08:27:02] ======== [PASSED] drm_test_fb_xrgb8888_to_argb8888 ========= [08:27:02] =========== drm_test_fb_xrgb8888_to_xrgb2101010 =========== [08:27:02] [PASSED] single_pixel_source_buffer [08:27:02] [PASSED] single_pixel_clip_rectangle [08:27:02] [PASSED] well_known_colors [08:27:02] [PASSED] destination_pitch [08:27:02] ======= [PASSED] drm_test_fb_xrgb8888_to_xrgb2101010 ======= [08:27:02] =========== drm_test_fb_xrgb8888_to_argb2101010 =========== [08:27:02] [PASSED] single_pixel_source_buffer [08:27:02] [PASSED] single_pixel_clip_rectangle [08:27:02] [PASSED] well_known_colors [08:27:02] [PASSED] destination_pitch [08:27:02] ======= [PASSED] drm_test_fb_xrgb8888_to_argb2101010 ======= [08:27:02] ============== drm_test_fb_xrgb8888_to_mono =============== [08:27:02] [PASSED] single_pixel_source_buffer [08:27:02] [PASSED] single_pixel_clip_rectangle [08:27:02] [PASSED] well_known_colors [08:27:02] [PASSED] destination_pitch [08:27:02] ========== [PASSED] drm_test_fb_xrgb8888_to_mono =========== [08:27:02] ==================== drm_test_fb_swab ===================== [08:27:02] [PASSED] single_pixel_source_buffer [08:27:02] [PASSED] single_pixel_clip_rectangle [08:27:02] [PASSED] well_known_colors [08:27:02] [PASSED] destination_pitch [08:27:02] ================ [PASSED] drm_test_fb_swab ================= [08:27:02] ============ drm_test_fb_xrgb8888_to_xbgr8888 ============= [08:27:02] [PASSED] single_pixel_source_buffer [08:27:02] [PASSED] single_pixel_clip_rectangle [08:27:02] [PASSED] well_known_colors [08:27:02] [PASSED] destination_pitch [08:27:02] ======== [PASSED] drm_test_fb_xrgb8888_to_xbgr8888 ========= [08:27:02] ============ drm_test_fb_xrgb8888_to_abgr8888 ============= [08:27:02] [PASSED] single_pixel_source_buffer [08:27:02] [PASSED] single_pixel_clip_rectangle [08:27:02] [PASSED] well_known_colors [08:27:02] [PASSED] destination_pitch [08:27:02] ======== [PASSED] drm_test_fb_xrgb8888_to_abgr8888 ========= [08:27:02] ================= drm_test_fb_clip_offset ================= [08:27:02] [PASSED] pass through [08:27:02] [PASSED] horizontal offset [08:27:02] [PASSED] vertical offset [08:27:02] [PASSED] horizontal and vertical offset [08:27:02] [PASSED] horizontal offset (custom pitch) [08:27:02] [PASSED] vertical offset (custom pitch) [08:27:02] [PASSED] horizontal and vertical offset (custom pitch) [08:27:02] ============= [PASSED] drm_test_fb_clip_offset ============= [08:27:02] =================== drm_test_fb_memcpy ==================== [08:27:02] [PASSED] single_pixel_source_buffer: XR24 little-endian (0x34325258) [08:27:02] [PASSED] single_pixel_source_buffer: XRA8 little-endian (0x38415258) [08:27:02] [PASSED] single_pixel_source_buffer: YU24 little-endian (0x34325559) [08:27:02] [PASSED] single_pixel_clip_rectangle: XB24 little-endian (0x34324258) [08:27:02] [PASSED] single_pixel_clip_rectangle: XRA8 little-endian (0x38415258) [08:27:02] [PASSED] single_pixel_clip_rectangle: YU24 little-endian (0x34325559) [08:27:02] [PASSED] well_known_colors: XB24 little-endian (0x34324258) [08:27:02] [PASSED] well_known_colors: XRA8 little-endian (0x38415258) [08:27:02] [PASSED] well_known_colors: YU24 little-endian (0x34325559) [08:27:02] [PASSED] destination_pitch: XB24 little-endian (0x34324258) [08:27:02] [PASSED] destination_pitch: XRA8 little-endian (0x38415258) [08:27:02] [PASSED] destination_pitch: YU24 little-endian (0x34325559) [08:27:02] =============== [PASSED] drm_test_fb_memcpy ================ [08:27:02] ============= [PASSED] drm_format_helper_test ============== [08:27:02] ================= drm_format (18 subtests) ================= [08:27:02] [PASSED] drm_test_format_block_width_invalid [08:27:02] [PASSED] drm_test_format_block_width_one_plane [08:27:02] [PASSED] drm_test_format_block_width_two_plane [08:27:02] [PASSED] drm_test_format_block_width_three_plane [08:27:02] [PASSED] drm_test_format_block_width_tiled [08:27:02] [PASSED] drm_test_format_block_height_invalid [08:27:02] [PASSED] drm_test_format_block_height_one_plane [08:27:02] [PASSED] drm_test_format_block_height_two_plane [08:27:02] [PASSED] drm_test_format_block_height_three_plane [08:27:02] [PASSED] drm_test_format_block_height_tiled [08:27:02] [PASSED] drm_test_format_min_pitch_invalid [08:27:02] [PASSED] drm_test_format_min_pitch_one_plane_8bpp [08:27:02] [PASSED] drm_test_format_min_pitch_one_plane_16bpp [08:27:02] [PASSED] drm_test_format_min_pitch_one_plane_24bpp [08:27:02] [PASSED] drm_test_format_min_pitch_one_plane_32bpp [08:27:02] [PASSED] drm_test_format_min_pitch_two_plane [08:27:02] [PASSED] drm_test_format_min_pitch_three_plane_8bpp [08:27:02] [PASSED] drm_test_format_min_pitch_tiled [08:27:02] =================== [PASSED] drm_format ==================== [08:27:02] ============== drm_framebuffer (10 subtests) =============== [08:27:02] ========== drm_test_framebuffer_check_src_coords ========== [08:27:02] [PASSED] Success: source fits into fb [08:27:02] [PASSED] Fail: overflowing fb with x-axis coordinate [08:27:02] [PASSED] Fail: overflowing fb with y-axis coordinate [08:27:02] [PASSED] Fail: overflowing fb with source width [08:27:02] [PASSED] Fail: overflowing fb with source height [08:27:02] ====== [PASSED] drm_test_framebuffer_check_src_coords ====== [08:27:02] [PASSED] drm_test_framebuffer_cleanup [08:27:02] =============== drm_test_framebuffer_create =============== [08:27:02] [PASSED] ABGR8888 normal sizes [08:27:02] [PASSED] ABGR8888 max sizes [08:27:02] [PASSED] ABGR8888 pitch greater than min required [08:27:02] [PASSED] ABGR8888 pitch less than min required [08:27:02] [PASSED] ABGR8888 Invalid width [08:27:02] [PASSED] ABGR8888 Invalid buffer handle [08:27:02] [PASSED] No pixel format [08:27:02] [PASSED] ABGR8888 Width 0 [08:27:02] [PASSED] ABGR8888 Height 0 [08:27:02] [PASSED] ABGR8888 Out of bound height * pitch combination [08:27:02] [PASSED] ABGR8888 Large buffer offset [08:27:02] [PASSED] ABGR8888 Buffer offset for inexistent plane [08:27:02] [PASSED] ABGR8888 Invalid flag [08:27:02] [PASSED] ABGR8888 Set DRM_MODE_FB_MODIFIERS without modifiers [08:27:02] [PASSED] ABGR8888 Valid buffer modifier [08:27:02] [PASSED] ABGR8888 Invalid buffer modifier(DRM_FORMAT_MOD_SAMSUNG_64_32_TILE) [08:27:02] [PASSED] ABGR8888 Extra pitches without DRM_MODE_FB_MODIFIERS [08:27:02] [PASSED] ABGR8888 Extra pitches with DRM_MODE_FB_MODIFIERS [08:27:02] [PASSED] NV12 Normal sizes [08:27:02] [PASSED] NV12 Max sizes [08:27:02] [PASSED] NV12 Invalid pitch [08:27:02] [PASSED] NV12 Invalid modifier/missing DRM_MODE_FB_MODIFIERS flag [08:27:02] [PASSED] NV12 different modifier per-plane [08:27:02] [PASSED] NV12 with DRM_FORMAT_MOD_SAMSUNG_64_32_TILE [08:27:02] [PASSED] NV12 Valid modifiers without DRM_MODE_FB_MODIFIERS [08:27:02] [PASSED] NV12 Modifier for inexistent plane [08:27:02] [PASSED] NV12 Handle for inexistent plane [08:27:02] [PASSED] NV12 Handle for inexistent plane without DRM_MODE_FB_MODIFIERS [08:27:02] [PASSED] YVU420 DRM_MODE_FB_MODIFIERS set without modifier [08:27:02] [PASSED] YVU420 Normal sizes [08:27:02] [PASSED] YVU420 Max sizes [08:27:02] [PASSED] YVU420 Invalid pitch [08:27:02] [PASSED] YVU420 Different pitches [08:27:02] [PASSED] YVU420 Different buffer offsets/pitches [08:27:02] [PASSED] YVU420 Modifier set just for plane 0, without DRM_MODE_FB_MODIFIERS [08:27:02] [PASSED] YVU420 Modifier set just for planes 0, 1, without DRM_MODE_FB_MODIFIERS [08:27:02] [PASSED] YVU420 Modifier set just for plane 0, 1, with DRM_MODE_FB_MODIFIERS [08:27:02] [PASSED] YVU420 Valid modifier [08:27:02] [PASSED] YVU420 Different modifiers per plane [08:27:02] [PASSED] YVU420 Modifier for inexistent plane [08:27:02] [PASSED] YUV420_10BIT Invalid modifier(DRM_FORMAT_MOD_LINEAR) [08:27:02] [PASSED] X0L2 Normal sizes [08:27:02] [PASSED] X0L2 Max sizes [08:27:02] [PASSED] X0L2 Invalid pitch [08:27:02] [PASSED] X0L2 Pitch greater than minimum required [08:27:02] [PASSED] X0L2 Handle for inexistent plane [08:27:02] [PASSED] X0L2 Offset for inexistent plane, without DRM_MODE_FB_MODIFIERS set [08:27:02] [PASSED] X0L2 Modifier without DRM_MODE_FB_MODIFIERS set [08:27:02] [PASSED] X0L2 Valid modifier [08:27:02] [PASSED] X0L2 Modifier for inexistent plane [08:27:02] =========== [PASSED] drm_test_framebuffer_create =========== [08:27:02] [PASSED] drm_test_framebuffer_free [08:27:02] [PASSED] drm_test_framebuffer_init [08:27:02] [PASSED] drm_test_framebuffer_init_bad_format [08:27:02] [PASSED] drm_test_framebuffer_init_dev_mismatch [08:27:02] [PASSED] drm_test_framebuffer_lookup [08:27:02] [PASSED] drm_test_framebuffer_lookup_inexistent [08:27:02] [PASSED] drm_test_framebuffer_modifiers_not_supported [08:27:02] ================= [PASSED] drm_framebuffer ================= [08:27:02] ================ drm_gem_shmem (8 subtests) ================ [08:27:02] [PASSED] drm_gem_shmem_test_obj_create [08:27:02] [PASSED] drm_gem_shmem_test_obj_create_private [08:27:02] [PASSED] drm_gem_shmem_test_pin_pages [08:27:02] [PASSED] drm_gem_shmem_test_vmap [08:27:02] [PASSED] drm_gem_shmem_test_get_sg_table [08:27:02] [PASSED] drm_gem_shmem_test_get_pages_sgt [08:27:02] [PASSED] drm_gem_shmem_test_madvise [08:27:02] [PASSED] drm_gem_shmem_test_purge [08:27:02] ================== [PASSED] drm_gem_shmem ================== [08:27:02] === drm_atomic_helper_connector_hdmi_check (27 subtests) === [08:27:02] [PASSED] drm_test_check_broadcast_rgb_auto_cea_mode [08:27:02] [PASSED] drm_test_check_broadcast_rgb_auto_cea_mode_vic_1 [08:27:02] [PASSED] drm_test_check_broadcast_rgb_full_cea_mode [08:27:02] [PASSED] drm_test_check_broadcast_rgb_full_cea_mode_vic_1 [08:27:02] [PASSED] drm_test_check_broadcast_rgb_limited_cea_mode [08:27:02] [PASSED] drm_test_check_broadcast_rgb_limited_cea_mode_vic_1 [08:27:02] ====== drm_test_check_broadcast_rgb_cea_mode_yuv420 ======= [08:27:02] [PASSED] Automatic [08:27:02] [PASSED] Full [08:27:02] [PASSED] Limited 16:235 [08:27:02] == [PASSED] drm_test_check_broadcast_rgb_cea_mode_yuv420 === [08:27:02] [PASSED] drm_test_check_broadcast_rgb_crtc_mode_changed [08:27:02] [PASSED] drm_test_check_broadcast_rgb_crtc_mode_not_changed [08:27:02] [PASSED] drm_test_check_disable_connector [08:27:02] [PASSED] drm_test_check_hdmi_funcs_reject_rate [08:27:02] [PASSED] drm_test_check_max_tmds_rate_bpc_fallback_rgb [08:27:02] [PASSED] drm_test_check_max_tmds_rate_bpc_fallback_yuv420 [08:27:02] [PASSED] drm_test_check_max_tmds_rate_bpc_fallback_ignore_yuv422 [08:27:02] [PASSED] drm_test_check_max_tmds_rate_bpc_fallback_ignore_yuv420 [08:27:02] [PASSED] drm_test_check_driver_unsupported_fallback_yuv420 [08:27:02] [PASSED] drm_test_check_output_bpc_crtc_mode_changed [08:27:02] [PASSED] drm_test_check_output_bpc_crtc_mode_not_changed [08:27:02] [PASSED] drm_test_check_output_bpc_dvi [08:27:02] [PASSED] drm_test_check_output_bpc_format_vic_1 [08:27:02] [PASSED] drm_test_check_output_bpc_format_display_8bpc_only [08:27:02] [PASSED] drm_test_check_output_bpc_format_display_rgb_only [08:27:02] [PASSED] drm_test_check_output_bpc_format_driver_8bpc_only [08:27:02] [PASSED] drm_test_check_output_bpc_format_driver_rgb_only [08:27:02] [PASSED] drm_test_check_tmds_char_rate_rgb_8bpc [08:27:02] [PASSED] drm_test_check_tmds_char_rate_rgb_10bpc [08:27:02] [PASSED] drm_test_check_tmds_char_rate_rgb_12bpc [08:27:02] ===== [PASSED] drm_atomic_helper_connector_hdmi_check ====== [08:27:02] === drm_atomic_helper_connector_hdmi_reset (6 subtests) ==== [08:27:02] [PASSED] drm_test_check_broadcast_rgb_value [08:27:02] [PASSED] drm_test_check_bpc_8_value [08:27:02] [PASSED] drm_test_check_bpc_10_value [08:27:02] [PASSED] drm_test_check_bpc_12_value [08:27:02] [PASSED] drm_test_check_format_value [08:27:02] [PASSED] drm_test_check_tmds_char_value [08:27:02] ===== [PASSED] drm_atomic_helper_connector_hdmi_reset ====== [08:27:02] = drm_atomic_helper_connector_hdmi_mode_valid (4 subtests) = [08:27:02] [PASSED] drm_test_check_mode_valid [08:27:02] [PASSED] drm_test_check_mode_valid_reject [08:27:02] [PASSED] drm_test_check_mode_valid_reject_rate [08:27:02] [PASSED] drm_test_check_mode_valid_reject_max_clock [08:27:02] === [PASSED] drm_atomic_helper_connector_hdmi_mode_valid === [08:27:02] = drm_atomic_helper_connector_hdmi_infoframes (5 subtests) = [08:27:02] [PASSED] drm_test_check_infoframes [08:27:02] [PASSED] drm_test_check_reject_avi_infoframe [08:27:02] [PASSED] drm_test_check_reject_hdr_infoframe_bpc_8 [08:27:02] [PASSED] drm_test_check_reject_hdr_infoframe_bpc_10 [08:27:02] [PASSED] drm_test_check_reject_audio_infoframe [08:27:02] === [PASSED] drm_atomic_helper_connector_hdmi_infoframes === [08:27:02] ================= drm_managed (2 subtests) ================= [08:27:02] [PASSED] drm_test_managed_release_action [08:27:02] [PASSED] drm_test_managed_run_action [08:27:02] =================== [PASSED] drm_managed =================== [08:27:02] =================== drm_mm (6 subtests) ==================== [08:27:02] [PASSED] drm_test_mm_init [08:27:02] [PASSED] drm_test_mm_debug [08:27:02] [PASSED] drm_test_mm_align32 [08:27:02] [PASSED] drm_test_mm_align64 [08:27:02] [PASSED] drm_test_mm_lowest [08:27:02] [PASSED] drm_test_mm_highest [08:27:02] ===================== [PASSED] drm_mm ====================== [08:27:02] ============= drm_modes_analog_tv (5 subtests) ============= [08:27:02] [PASSED] drm_test_modes_analog_tv_mono_576i [08:27:02] [PASSED] drm_test_modes_analog_tv_ntsc_480i [08:27:02] [PASSED] drm_test_modes_analog_tv_ntsc_480i_inlined [08:27:02] [PASSED] drm_test_modes_analog_tv_pal_576i [08:27:02] [PASSED] drm_test_modes_analog_tv_pal_576i_inlined [08:27:02] =============== [PASSED] drm_modes_analog_tv =============== [08:27:02] ============== drm_plane_helper (2 subtests) =============== [08:27:02] =============== drm_test_check_plane_state ================ [08:27:02] [PASSED] clipping_simple [08:27:02] [PASSED] clipping_rotate_reflect [08:27:02] [PASSED] positioning_simple [08:27:02] [PASSED] upscaling [08:27:02] [PASSED] downscaling [08:27:02] [PASSED] rounding1 [08:27:02] [PASSED] rounding2 [08:27:02] [PASSED] rounding3 [08:27:02] [PASSED] rounding4 [08:27:02] =========== [PASSED] drm_test_check_plane_state ============ [08:27:02] =========== drm_test_check_invalid_plane_state ============ [08:27:02] [PASSED] positioning_invalid [08:27:02] [PASSED] upscaling_invalid [08:27:02] [PASSED] downscaling_invalid [08:27:02] ======= [PASSED] drm_test_check_invalid_plane_state ======== [08:27:02] ================ [PASSED] drm_plane_helper ================= [08:27:02] ====== drm_connector_helper_tv_get_modes (1 subtest) ======= [08:27:02] ====== drm_test_connector_helper_tv_get_modes_check ======= [08:27:02] [PASSED] None [08:27:02] [PASSED] PAL [08:27:02] [PASSED] NTSC [08:27:02] [PASSED] Both, NTSC Default [08:27:02] [PASSED] Both, PAL Default [08:27:02] [PASSED] Both, NTSC Default, with PAL on command-line [08:27:02] [PASSED] Both, PAL Default, with NTSC on command-line [08:27:02] == [PASSED] drm_test_connector_helper_tv_get_modes_check === [08:27:02] ======== [PASSED] drm_connector_helper_tv_get_modes ======== [08:27:02] ================== drm_rect (9 subtests) =================== [08:27:02] [PASSED] drm_test_rect_clip_scaled_div_by_zero [08:27:02] [PASSED] drm_test_rect_clip_scaled_not_clipped [08:27:02] [PASSED] drm_test_rect_clip_scaled_clipped [08:27:02] [PASSED] drm_test_rect_clip_scaled_signed_vs_unsigned [08:27:02] ================= drm_test_rect_intersect ================= [08:27:02] [PASSED] top-left x bottom-right: 2x2+1+1 x 2x2+0+0 [08:27:02] [PASSED] top-right x bottom-left: 2x2+0+0 x 2x2+1-1 [08:27:02] [PASSED] bottom-left x top-right: 2x2+1-1 x 2x2+0+0 [08:27:02] [PASSED] bottom-right x top-left: 2x2+0+0 x 2x2+1+1 [08:27:02] [PASSED] right x left: 2x1+0+0 x 3x1+1+0 [08:27:02] [PASSED] left x right: 3x1+1+0 x 2x1+0+0 [08:27:02] [PASSED] up x bottom: 1x2+0+0 x 1x3+0-1 [08:27:02] [PASSED] bottom x up: 1x3+0-1 x 1x2+0+0 [08:27:02] [PASSED] touching corner: 1x1+0+0 x 2x2+1+1 [08:27:02] [PASSED] touching side: 1x1+0+0 x 1x1+1+0 [08:27:02] [PASSED] equal rects: 2x2+0+0 x 2x2+0+0 [08:27:02] [PASSED] inside another: 2x2+0+0 x 1x1+1+1 [08:27:02] [PASSED] far away: 1x1+0+0 x 1x1+3+6 [08:27:02] [PASSED] points intersecting: 0x0+5+10 x 0x0+5+10 [08:27:02] [PASSED] points not intersecting: 0x0+0+0 x 0x0+5+10 [08:27:02] ============= [PASSED] drm_test_rect_intersect ============= [08:27:02] ================ drm_test_rect_calc_hscale ================ [08:27:02] [PASSED] normal use [08:27:02] [PASSED] out of max range [08:27:02] [PASSED] out of min range [08:27:02] [PASSED] zero dst [08:27:02] [PASSED] negative src [08:27:02] [PASSED] negative dst [08:27:02] ============ [PASSED] drm_test_rect_calc_hscale ============ [08:27:02] ================ drm_test_rect_calc_vscale ================ [08:27:02] [PASSED] normal use [08:27:02] [PASSED] out of max range [08:27:02] [PASSED] out of min range [08:27:02] [PASSED] zero dst [08:27:02] [PASSED] negative src [08:27:02] [PASSED] negative dst stty: 'standard input': Inappropriate ioctl for device [08:27:02] ============ [PASSED] drm_test_rect_calc_vscale ============ [08:27:02] ================== drm_test_rect_rotate =================== [08:27:02] [PASSED] reflect-x [08:27:02] [PASSED] reflect-y [08:27:02] [PASSED] rotate-0 [08:27:02] [PASSED] rotate-90 [08:27:02] [PASSED] rotate-180 [08:27:02] [PASSED] rotate-270 [08:27:02] ============== [PASSED] drm_test_rect_rotate =============== [08:27:02] ================ drm_test_rect_rotate_inv ================= [08:27:02] [PASSED] reflect-x [08:27:02] [PASSED] reflect-y [08:27:02] [PASSED] rotate-0 [08:27:02] [PASSED] rotate-90 [08:27:02] [PASSED] rotate-180 [08:27:02] [PASSED] rotate-270 [08:27:02] ============ [PASSED] drm_test_rect_rotate_inv ============= [08:27:02] ==================== [PASSED] drm_rect ===================== [08:27:02] ============ drm_sysfb_modeset_test (1 subtest) ============ [08:27:02] ============ drm_test_sysfb_build_fourcc_list ============= [08:27:02] [PASSED] no native formats [08:27:02] [PASSED] XRGB8888 as native format [08:27:02] [PASSED] remove duplicates [08:27:02] [PASSED] convert alpha formats [08:27:02] [PASSED] random formats [08:27:02] ======== [PASSED] drm_test_sysfb_build_fourcc_list ========= [08:27:02] ============= [PASSED] drm_sysfb_modeset_test ============== [08:27:02] ================== drm_fixp (2 subtests) =================== [08:27:02] [PASSED] drm_test_int2fixp [08:27:02] [PASSED] drm_test_sm2fixp [08:27:02] ==================== [PASSED] drm_fixp ===================== [08:27:02] ============================================================ [08:27:02] Testing complete. Ran 621 tests: passed: 621 [08:27:02] Elapsed time: 26.140s total, 1.716s configuring, 24.257s building, 0.115s running
+ /kernel/tools/testing/kunit/kunit.py run --kunitconfig /kernel/drivers/gpu/drm/ttm/tests/.kunitconfig [08:27:02] Configuring KUnit Kernel ...
Regenerating .config ...
Populating config with:
$ make ARCH=um O=.kunit olddefconfig [08:27:03] Building KUnit Kernel ... Populating config with: $ make ARCH=um O=.kunit olddefconfig Building with: $ make all compile_commands.json scripts_gdb ARCH=um O=.kunit --jobs=48 [08:27:13] Starting KUnit Kernel (1/1)... [08:27:13] ============================================================ Running tests with: $ .kunit/linux kunit.enable=1 mem=1G console=tty kunit_shutdown=halt [08:27:13] ================= ttm_device (5 subtests) ================== [08:27:13] [PASSED] ttm_device_init_basic [08:27:13] [PASSED] ttm_device_init_multiple [08:27:13] [PASSED] ttm_device_fini_basic [08:27:13] [PASSED] ttm_device_init_no_vma_man [08:27:13] ================== ttm_device_init_pools ================== [08:27:13] [PASSED] No DMA allocations, no DMA32 required [08:27:13] [PASSED] DMA allocations, DMA32 required [08:27:13] [PASSED] No DMA allocations, DMA32 required [08:27:13] [PASSED] DMA allocations, no DMA32 required [08:27:13] ============== [PASSED] ttm_device_init_pools ============== [08:27:13] =================== [PASSED] ttm_device ==================== [08:27:13] ================== ttm_pool (8 subtests) =================== [08:27:13] ================== ttm_pool_alloc_basic =================== [08:27:13] [PASSED] One page [08:27:13] [PASSED] More than one page [08:27:13] [PASSED] Above the allocation limit [08:27:13] [PASSED] One page, with coherent DMA mappings enabled [08:27:13] [PASSED] Above the allocation limit, with coherent DMA mappings enabled [08:27:13] ============== [PASSED] ttm_pool_alloc_basic =============== [08:27:13] ============== ttm_pool_alloc_basic_dma_addr ============== [08:27:13] [PASSED] One page [08:27:13] [PASSED] More than one page [08:27:13] [PASSED] Above the allocation limit [08:27:13] [PASSED] One page, with coherent DMA mappings enabled [08:27:13] [PASSED] Above the allocation limit, with coherent DMA mappings enabled [08:27:13] ========== [PASSED] ttm_pool_alloc_basic_dma_addr ========== [08:27:13] [PASSED] ttm_pool_alloc_order_caching_match [08:27:13] [PASSED] ttm_pool_alloc_caching_mismatch [08:27:13] [PASSED] ttm_pool_alloc_order_mismatch [08:27:13] [PASSED] ttm_pool_free_dma_alloc [08:27:13] [PASSED] ttm_pool_free_no_dma_alloc [08:27:13] [PASSED] ttm_pool_fini_basic [08:27:13] ==================== [PASSED] ttm_pool ===================== [08:27:13] ================ ttm_resource (8 subtests) ================= [08:27:13] ================= ttm_resource_init_basic ================= [08:27:13] [PASSED] Init resource in TTM_PL_SYSTEM [08:27:13] [PASSED] Init resource in TTM_PL_VRAM [08:27:13] [PASSED] Init resource in a private placement [08:27:13] [PASSED] Init resource in TTM_PL_SYSTEM, set placement flags [08:27:13] ============= [PASSED] ttm_resource_init_basic ============= [08:27:13] [PASSED] ttm_resource_init_pinned [08:27:13] [PASSED] ttm_resource_fini_basic [08:27:13] [PASSED] ttm_resource_manager_init_basic [08:27:13] [PASSED] ttm_resource_manager_usage_basic [08:27:13] [PASSED] ttm_resource_manager_set_used_basic [08:27:13] [PASSED] ttm_sys_man_alloc_basic [08:27:13] [PASSED] ttm_sys_man_free_basic [08:27:13] ================== [PASSED] ttm_resource =================== [08:27:13] =================== ttm_tt (15 subtests) =================== [08:27:13] ==================== ttm_tt_init_basic ==================== [08:27:13] [PASSED] Page-aligned size [08:27:13] [PASSED] Extra pages requested [08:27:13] ================ [PASSED] ttm_tt_init_basic ================ [08:27:13] [PASSED] ttm_tt_init_misaligned [08:27:13] [PASSED] ttm_tt_fini_basic [08:27:13] [PASSED] ttm_tt_fini_sg [08:27:13] [PASSED] ttm_tt_fini_shmem [08:27:13] [PASSED] ttm_tt_create_basic [08:27:13] [PASSED] ttm_tt_create_invalid_bo_type [08:27:13] [PASSED] ttm_tt_create_ttm_exists [08:27:13] [PASSED] ttm_tt_create_failed [08:27:13] [PASSED] ttm_tt_destroy_basic [08:27:13] [PASSED] ttm_tt_populate_null_ttm [08:27:13] [PASSED] ttm_tt_populate_populated_ttm [08:27:13] [PASSED] ttm_tt_unpopulate_basic [08:27:13] [PASSED] ttm_tt_unpopulate_empty_ttm [08:27:13] [PASSED] ttm_tt_swapin_basic [08:27:13] ===================== [PASSED] ttm_tt ====================== [08:27:13] =================== ttm_bo (14 subtests) =================== [08:27:13] =========== ttm_bo_reserve_optimistic_no_ticket =========== [08:27:13] [PASSED] Cannot be interrupted and sleeps [08:27:13] [PASSED] Cannot be interrupted, locks straight away [08:27:13] [PASSED] Can be interrupted, sleeps [08:27:13] ======= [PASSED] ttm_bo_reserve_optimistic_no_ticket ======= [08:27:13] [PASSED] ttm_bo_reserve_locked_no_sleep [08:27:13] [PASSED] ttm_bo_reserve_no_wait_ticket [08:27:13] [PASSED] ttm_bo_reserve_double_resv [08:27:13] [PASSED] ttm_bo_reserve_interrupted [08:27:13] [PASSED] ttm_bo_reserve_deadlock [08:27:13] [PASSED] ttm_bo_unreserve_basic [08:27:13] [PASSED] ttm_bo_unreserve_pinned [08:27:13] [PASSED] ttm_bo_unreserve_bulk [08:27:13] [PASSED] ttm_bo_fini_basic [08:27:13] [PASSED] ttm_bo_fini_shared_resv [08:27:13] [PASSED] ttm_bo_pin_basic [08:27:13] [PASSED] ttm_bo_pin_unpin_resource [08:27:13] [PASSED] ttm_bo_multiple_pin_one_unpin [08:27:13] ===================== [PASSED] ttm_bo ====================== [08:27:13] ============== ttm_bo_validate (22 subtests) =============== [08:27:13] ============== ttm_bo_init_reserved_sys_man =============== [08:27:13] [PASSED] Buffer object for userspace [08:27:13] [PASSED] Kernel buffer object [08:27:13] [PASSED] Shared buffer object [08:27:13] ========== [PASSED] ttm_bo_init_reserved_sys_man =========== [08:27:13] ============== ttm_bo_init_reserved_mock_man ============== [08:27:13] [PASSED] Buffer object for userspace [08:27:13] [PASSED] Kernel buffer object [08:27:13] [PASSED] Shared buffer object [08:27:13] ========== [PASSED] ttm_bo_init_reserved_mock_man ========== [08:27:13] [PASSED] ttm_bo_init_reserved_resv [08:27:13] ================== ttm_bo_validate_basic ================== [08:27:13] [PASSED] Buffer object for userspace [08:27:13] [PASSED] Kernel buffer object [08:27:13] [PASSED] Shared buffer object [08:27:13] ============== [PASSED] ttm_bo_validate_basic ============== [08:27:13] [PASSED] ttm_bo_validate_invalid_placement [08:27:13] ============= ttm_bo_validate_same_placement ============== [08:27:13] [PASSED] System manager [08:27:13] [PASSED] VRAM manager [08:27:13] ========= [PASSED] ttm_bo_validate_same_placement ========== [08:27:13] [PASSED] ttm_bo_validate_failed_alloc [08:27:13] [PASSED] ttm_bo_validate_pinned [08:27:13] [PASSED] ttm_bo_validate_busy_placement [08:27:13] ================ ttm_bo_validate_multihop ================= [08:27:13] [PASSED] Buffer object for userspace [08:27:13] [PASSED] Kernel buffer object [08:27:13] [PASSED] Shared buffer object [08:27:13] ============ [PASSED] ttm_bo_validate_multihop ============= [08:27:13] ========== ttm_bo_validate_no_placement_signaled ========== [08:27:13] [PASSED] Buffer object in system domain, no page vector [08:27:13] [PASSED] Buffer object in system domain with an existing page vector [08:27:13] ====== [PASSED] ttm_bo_validate_no_placement_signaled ====== [08:27:13] ======== ttm_bo_validate_no_placement_not_signaled ======== [08:27:13] [PASSED] Buffer object for userspace [08:27:13] [PASSED] Kernel buffer object [08:27:13] [PASSED] Shared buffer object [08:27:13] ==== [PASSED] ttm_bo_validate_no_placement_not_signaled ==== [08:27:13] [PASSED] ttm_bo_validate_move_fence_signaled [08:27:13] ========= ttm_bo_validate_move_fence_not_signaled ========= [08:27:13] [PASSED] Waits for GPU [08:27:13] [PASSED] Tries to lock straight away [08:27:13] ===== [PASSED] ttm_bo_validate_move_fence_not_signaled ===== [08:27:13] [PASSED] ttm_bo_validate_swapout [08:27:13] [PASSED] ttm_bo_validate_happy_evict [08:27:13] [PASSED] ttm_bo_validate_all_pinned_evict [08:27:13] [PASSED] ttm_bo_validate_allowed_only_evict [08:27:13] [PASSED] ttm_bo_validate_deleted_evict [08:27:13] [PASSED] ttm_bo_validate_busy_domain_evict [08:27:13] [PASSED] ttm_bo_validate_evict_gutting [08:27:13] [PASSED] ttm_bo_validate_recrusive_evict stty: 'standard input': Inappropriate ioctl for device [08:27:13] ================= [PASSED] ttm_bo_validate ================= [08:27:13] ============================================================ [08:27:13] Testing complete. Ran 102 tests: passed: 102 [08:27:13] Elapsed time: 11.437s total, 1.650s configuring, 9.570s building, 0.182s running
+ cleanup
++ stat -c %u:%g /kernel
+ chown -R 1003:1003 /kernel
Thomas Hellström
maintainerQuoted 33 lines · Thomas Hellström
When writing a "max" limit lower than the current usage, the existing code silently failed. This series aims to improve on that by returning
-EBUSYon failure and also attempt to synchronously reclaim device memory to push the usage under the new max limit to avoid the error.Patch 1 implements error propagation.
Patch 2 implements and documents a reclaim callback interface for the dmem controller.
Patch 3 implements a TTM reclaim callback.
Patch 4-5 hooks up the reclaim callback to the dmem cgroups- aware drivers xe and amdgpu.Thomas Hellström (5):
cgroup/dmem: Return error when setting max below current usage cgroup/dmem: Add reclaim callback for lowering max below current usage
drm/ttm: Hook up a cgroup-aware reclaim callback for the dmem controller
drm/xe: Wire up dmem cgroup reclaim for VRAM manager drm/amdgpu: Wire up dmem cgroup reclaim for VRAM managerdrivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 2 +-
drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c| 10 +- drivers/gpu/drm/ttm/ttm_bo.c | 95 ++++++++++++++++- drivers/gpu/drm/ttm/ttm_bo_util.c | 3 +- drivers/gpu/drm/ttm/ttm_resource.c | 36 +++++++ drivers/gpu/drm/xe/xe_ttm_vram_mgr.c | 19 ++-- include/drm/ttm/ttm_bo.h | 10 ++ include/drm/ttm/ttm_resource.h | 4 + include/linux/cgroup_dmem.h | 11 ++ kernel/cgroup/dmem.c | 102 ++++++++++++++++- --
Quoted 1 line
10 files changed, 265 insertions(+), 27 deletions(-)
For reference, Series introducing igt test is here:
https://patchwork.freedesktop.org/series/163935/
/Thomas
Patchwork
CI✓ Xe.CI.BAT: success for Add reclaim to the dmem cgroup controller
In reply to Thomas Hellström== Series Details ==
== Series Details ==
Series: Add reclaim to the dmem cgroup controller
URL : https://patchwork.freedesktop.org/series/163970/
State : success
== Summary ==
CI Bug Log - changes from xe-4803-0a7844908d3616b88a7887704eb6dfa0d315be1b_BAT -> xe-pw-163970v1_BAT
====================================================
Summary
-------
**SUCCESS**
No regressions found.
Participating hosts (14 -> 14)
------------------------------
No changes in participating hosts
Known issues
------------
Here are the changes found in xe-pw-163970v1_BAT that come from known issues:
### IGT changes ###
#### Issues hit ####
* igt@kms_flip@basic-flip-vs-wf_vblank@d-edp1:
- bat-adlp-7: [PASS][1] -> [DMESG-WARN][2] ([Intel XE#7483])
[1]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4803-0a7844908d3616b88a7887704eb6dfa0d315be1b/bat-adlp-7/igt@kms_flip@[email protected]
[2]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-163970v1/bat-adlp-7/igt@kms_flip@[email protected]
* igt@xe_waitfence@reltime:
- bat-ptl-2: [PASS][3] -> [FAIL][4] ([Intel XE#6520])
[3]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4803-0a7844908d3616b88a7887704eb6dfa0d315be1b/bat-ptl-2/igt@[email protected]
[4]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-163970v1/bat-ptl-2/igt@[email protected]
#### Possible fixes ####
* igt@kms_flip@basic-flip-vs-wf_vblank@c-edp1:
- bat-adlp-7: [DMESG-WARN][5] ([Intel XE#7483]) -> [PASS][6]
[5]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4803-0a7844908d3616b88a7887704eb6dfa0d315be1b/bat-adlp-7/igt@kms_flip@[email protected]
[6]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-163970v1/bat-adlp-7/igt@kms_flip@[email protected]
* igt@xe_waitfence@engine:
- bat-dg2-oem2: [FAIL][7] ([Intel XE#6519]) -> [PASS][8]
[7]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4803-0a7844908d3616b88a7887704eb6dfa0d315be1b/bat-dg2-oem2/igt@[email protected]
[8]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-163970v1/bat-dg2-oem2/igt@[email protected]
[Intel XE#6519]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/6519
[Intel XE#6520]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/6520
[Intel XE#7483]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/7483
Build changes
-------------
* Linux: xe-4803-0a7844908d3616b88a7887704eb6dfa0d315be1b -> xe-pw-163970v1
IGT_8834: 8834
xe-4803-0a7844908d3616b88a7887704eb6dfa0d315be1b: 0a7844908d3616b88a7887704eb6dfa0d315be1b
xe-pw-163970v1: 163970v1
== Logs ==
For more details see: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-163970v1/index.html
Patchwork
CI✓ Xe.CI.FULL: success for Add reclaim to the dmem cgroup controller
In reply to Thomas Hellström== Series Details ==
== Series Details ==
Series: Add reclaim to the dmem cgroup controller
URL : https://patchwork.freedesktop.org/series/163970/
State : success
== Summary ==
CI Bug Log - changes from xe-4803-0a7844908d3616b88a7887704eb6dfa0d315be1b_FULL -> xe-pw-163970v1_FULL
====================================================
Summary
-------
**SUCCESS**
No regressions found.
Participating hosts (2 -> 2)
------------------------------
No changes in participating hosts
Known issues
------------
Here are the changes found in xe-pw-163970v1_FULL that come from known issues:
### IGT changes ###
#### Possible fixes ####
* igt@kms_flip@flip-vs-expired-vblank@b-edp1:
- shard-lnl: [FAIL][1] ([Intel XE#301]) -> [PASS][2] +1 other test pass
[1]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4803-0a7844908d3616b88a7887704eb6dfa0d315be1b/shard-lnl-8/igt@kms_flip@[email protected]
[2]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-163970v1/shard-lnl-1/igt@kms_flip@[email protected]
* igt@kms_pm_dc@dc5-psr:
- shard-lnl: [FAIL][3] ([Intel XE#7340]) -> [PASS][4]
[3]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4803-0a7844908d3616b88a7887704eb6dfa0d315be1b/shard-lnl-8/igt@[email protected]
[4]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-163970v1/shard-lnl-1/igt@[email protected]
* igt@kms_pm_dc@deep-pkgc:
- shard-lnl: [FAIL][5] ([Intel XE#2029] / [Intel XE#7395]) -> [PASS][6]
[5]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4803-0a7844908d3616b88a7887704eb6dfa0d315be1b/shard-lnl-1/igt@[email protected]
[6]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-163970v1/shard-lnl-3/igt@[email protected]
[Intel XE#2029]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2029
[Intel XE#301]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/301
[Intel XE#7340]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/7340
[Intel XE#7395]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/7395
Build changes
-------------
* Linux: xe-4803-0a7844908d3616b88a7887704eb6dfa0d315be1b -> xe-pw-163970v1
IGT_8834: 8834
xe-4803-0a7844908d3616b88a7887704eb6dfa0d315be1b: 0a7844908d3616b88a7887704eb6dfa0d315be1b
xe-pw-163970v1: 163970v1
== Logs ==
For more details see: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-163970v1/index.html