Skip to content

Commit 2dd7a47

Browse files
Thomas Hellströmrodrigovivi
authored andcommitted
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 <[email protected]> Closes: https://gitlab.freedesktop.org/drm/xe/kernel/-/issues/5557 Cc: Summers Stuart <[email protected]> Fixes: 00c8efc ("drm/xe: Add a shrinker for xe bos") Cc: <[email protected]> # v6.15+ Signed-off-by: Thomas Hellström <[email protected]> Reviewed-by: Stuart Summers <[email protected]> Link: https://lore.kernel.org/r/[email protected] (cherry picked from commit 80944d3) Signed-off-by: Rodrigo Vivi <[email protected]>
1 parent 145832f commit 2dd7a47

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;
@@ -93,6 +93,48 @@ static s64 xe_shrinker_walk(struct xe_device *xe,
9393
return freed;
9494
}
9595

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

201243
shrink_flags.purge = false;
244+
202245
lret = xe_shrinker_walk(shrinker->xe, &ctx, shrink_flags,
203246
nr_to_scan, &nr_scanned);
204247
if (lret >= 0)

0 commit comments

Comments
 (0)