Skip to content

Commit 8415a9c

Browse files
Thomas Hellströmgregkh
authored andcommitted
drm/xe: Defer buffer object shrinker write-backs and GPU waits
commit 2dd7a47 upstream. 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 (cherry picked from commit 80944d3) Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent b89714b commit 8415a9c

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
@@ -53,10 +53,10 @@ xe_shrinker_mod_pages(struct xe_shrinker *shrinker, long shrinkable, long purgea
5353
write_unlock(&shrinker->lock);
5454
}
5555

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

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

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

0 commit comments

Comments
 (0)