Skip to content

Commit 80944d3

Browse files
author
Thomas Hellström
committed
drm/xe: Defer buffer object shrinker write-backs and GPU waits
When the xe buffer-object shrinker allows GPU waits and write-back, (typically from kswapd), perform multiple passes, skipping subsequent passes if the shrinker number of scanned objects target is reached. 1) Without GPU waits and write-back 2) Without write-back 3) With both GPU-waits and write-back This is to avoid stalls and costly write- and readbacks unless they are really necessary. v2: - Don't test for scan completion twice. (Stuart Summers) - Update tags. Reported-by: melvyn <melvyn2@dnsense.pub> Closes: https://gitlab.freedesktop.org/drm/xe/kernel/-/issues/5557 Cc: Summers Stuart <stuart.summers@intel.com> Fixes: 00c8efc ("drm/xe: Add a shrinker for xe bos") Cc: <stable@vger.kernel.org> # v6.15+ Signed-off-by: Thomas Hellström <thomas.hellstrom@linux.intel.com> Reviewed-by: Stuart Summers <stuart.summers@intel.com> Link: https://lore.kernel.org/r/20250805074842.11359-1-thomas.hellstrom@linux.intel.com
1 parent 9b7ca35 commit 80944d3

File tree

1 file changed

+47
-4
lines changed

1 file changed

+47
-4
lines changed

drivers/gpu/drm/xe/xe_shrinker.c

Lines changed: 47 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,10 +54,10 @@ xe_shrinker_mod_pages(struct xe_shrinker *shrinker, long shrinkable, long purgea
5454
write_unlock(&shrinker->lock);
5555
}
5656

57-
static s64 xe_shrinker_walk(struct xe_device *xe,
58-
struct ttm_operation_ctx *ctx,
59-
const struct xe_bo_shrink_flags flags,
60-
unsigned long to_scan, unsigned long *scanned)
57+
static s64 __xe_shrinker_walk(struct xe_device *xe,
58+
struct ttm_operation_ctx *ctx,
59+
const struct xe_bo_shrink_flags flags,
60+
unsigned long to_scan, unsigned long *scanned)
6161
{
6262
unsigned int mem_type;
6363
s64 freed = 0, lret;
@@ -87,6 +87,48 @@ static s64 xe_shrinker_walk(struct xe_device *xe,
8787
return freed;
8888
}
8989

90+
/*
91+
* Try shrinking idle objects without writeback first, then if not sufficient,
92+
* try also non-idle objects and finally if that's not sufficient either,
93+
* add writeback. This avoids stalls and explicit writebacks with light or
94+
* moderate memory pressure.
95+
*/
96+
static s64 xe_shrinker_walk(struct xe_device *xe,
97+
struct ttm_operation_ctx *ctx,
98+
const struct xe_bo_shrink_flags flags,
99+
unsigned long to_scan, unsigned long *scanned)
100+
{
101+
bool no_wait_gpu = true;
102+
struct xe_bo_shrink_flags save_flags = flags;
103+
s64 lret, freed;
104+
105+
swap(no_wait_gpu, ctx->no_wait_gpu);
106+
save_flags.writeback = false;
107+
lret = __xe_shrinker_walk(xe, ctx, save_flags, to_scan, scanned);
108+
swap(no_wait_gpu, ctx->no_wait_gpu);
109+
if (lret < 0 || *scanned >= to_scan)
110+
return lret;
111+
112+
freed = lret;
113+
if (!ctx->no_wait_gpu) {
114+
lret = __xe_shrinker_walk(xe, ctx, save_flags, to_scan, scanned);
115+
if (lret < 0)
116+
return lret;
117+
freed += lret;
118+
if (*scanned >= to_scan)
119+
return freed;
120+
}
121+
122+
if (flags.writeback) {
123+
lret = __xe_shrinker_walk(xe, ctx, flags, to_scan, scanned);
124+
if (lret < 0)
125+
return lret;
126+
freed += lret;
127+
}
128+
129+
return freed;
130+
}
131+
90132
static unsigned long
91133
xe_shrinker_count(struct shrinker *shrink, struct shrink_control *sc)
92134
{
@@ -193,6 +235,7 @@ static unsigned long xe_shrinker_scan(struct shrinker *shrink, struct shrink_con
193235
runtime_pm = xe_shrinker_runtime_pm_get(shrinker, true, 0, can_backup);
194236

195237
shrink_flags.purge = false;
238+
196239
lret = xe_shrinker_walk(shrinker->xe, &ctx, shrink_flags,
197240
nr_to_scan, &nr_scanned);
198241
if (lret >= 0)

0 commit comments

Comments
 (0)