150 lines
4.3 KiB
Diff
150 lines
4.3 KiB
Diff
diff --git c/drivers/gpu/drm/xe/xe_shrinker.c i/drivers/gpu/drm/xe/xe_shrinker.c
|
|
--- c/drivers/gpu/drm/xe/xe_shrinker.c
|
|
+++ i/drivers/gpu/drm/xe/xe_shrinker.c
|
|
@@ -54,13 +54,33 @@ xe_shrinker_mod_pages(struct xe_shrinker *shrinker, long shrinkable, long purgea
|
|
write_unlock(&shrinker->lock);
|
|
}
|
|
|
|
-static int __xe_shrinker_walk(struct xe_device *xe,
|
|
+static bool __xe_shrinker_runtime_pm_get(struct xe_shrinker *shrinker)
|
|
+{
|
|
+ struct xe_device *xe = shrinker->xe;
|
|
+
|
|
+ if (xe_pm_runtime_get_if_active(xe))
|
|
+ return true;
|
|
+
|
|
+ if (xe_rpm_reclaim_safe(xe) && !ttm_bo_shrink_avoid_wait()) {
|
|
+ xe_pm_runtime_get(xe);
|
|
+ return true;
|
|
+ }
|
|
+
|
|
+ queue_work(xe->unordered_wq, &shrinker->pm_worker);
|
|
+
|
|
+ return false;
|
|
+}
|
|
+
|
|
+static int __xe_shrinker_walk(struct xe_shrinker *shrinker,
|
|
struct ttm_operation_ctx *ctx,
|
|
const struct xe_bo_shrink_flags flags,
|
|
unsigned long to_scan, unsigned long *scanned,
|
|
unsigned long *freed)
|
|
{
|
|
+ struct xe_device *xe = shrinker->xe;
|
|
unsigned int mem_type;
|
|
+ bool rpm = false;
|
|
+ int ret = 0;
|
|
s64 lret;
|
|
|
|
for (mem_type = XE_PL_SYSTEM; mem_type <= XE_PL_TT; ++mem_type) {
|
|
@@ -75,23 +95,36 @@ static int __xe_shrinker_walk(struct xe_device *xe,
|
|
if (!man || !man->use_tt)
|
|
continue;
|
|
|
|
+ if (mem_type != XE_PL_SYSTEM && !rpm &&
|
|
+ xe_device_is_l2_flush_optimized(xe)) {
|
|
+ if (!__xe_shrinker_runtime_pm_get(shrinker))
|
|
+ break;
|
|
+ rpm = true;
|
|
+ }
|
|
+
|
|
ttm_bo_lru_for_each_reserved_guarded(&curs, man, &arg, ttm_bo) {
|
|
if (!ttm_bo_shrink_suitable(ttm_bo, ctx))
|
|
continue;
|
|
|
|
lret = xe_bo_shrink(ctx, ttm_bo, flags, scanned);
|
|
- if (lret < 0)
|
|
- return lret;
|
|
+ if (lret < 0) {
|
|
+ ret = lret;
|
|
+ goto out;
|
|
+ }
|
|
|
|
*freed += lret;
|
|
if (*scanned >= to_scan)
|
|
- break;
|
|
+ goto out;
|
|
}
|
|
/* Trylocks should never error, just fail. */
|
|
xe_assert(xe, !IS_ERR(ttm_bo));
|
|
}
|
|
|
|
- return 0;
|
|
+out:
|
|
+ if (rpm)
|
|
+ xe_pm_runtime_put(xe);
|
|
+
|
|
+ return ret;
|
|
}
|
|
|
|
/*
|
|
@@ -100,7 +133,7 @@ static int __xe_shrinker_walk(struct xe_device *xe,
|
|
* add writeback. This avoids stalls and explicit writebacks with light or
|
|
* moderate memory pressure.
|
|
*/
|
|
-static int xe_shrinker_walk(struct xe_device *xe,
|
|
+static int xe_shrinker_walk(struct xe_shrinker *shrinker,
|
|
struct ttm_operation_ctx *ctx,
|
|
const struct xe_bo_shrink_flags flags,
|
|
unsigned long to_scan, unsigned long *scanned,
|
|
@@ -112,20 +145,21 @@ static int xe_shrinker_walk(struct xe_device *xe,
|
|
|
|
swap(no_wait_gpu, ctx->no_wait_gpu);
|
|
save_flags.writeback = false;
|
|
- ret = __xe_shrinker_walk(xe, ctx, save_flags, to_scan, scanned, freed);
|
|
+ ret = __xe_shrinker_walk(shrinker, ctx, save_flags, to_scan, scanned,
|
|
+ freed);
|
|
swap(no_wait_gpu, ctx->no_wait_gpu);
|
|
if (ret || *scanned >= to_scan)
|
|
return ret;
|
|
|
|
if (!ctx->no_wait_gpu) {
|
|
- ret = __xe_shrinker_walk(xe, ctx, save_flags, to_scan, scanned,
|
|
+ ret = __xe_shrinker_walk(shrinker, ctx, save_flags, to_scan, scanned,
|
|
freed);
|
|
if (ret || *scanned >= to_scan)
|
|
return ret;
|
|
}
|
|
|
|
if (flags.writeback)
|
|
- ret = __xe_shrinker_walk(xe, ctx, flags, to_scan, scanned,
|
|
+ ret = __xe_shrinker_walk(shrinker, ctx, flags, to_scan, scanned,
|
|
freed);
|
|
|
|
return ret;
|
|
@@ -176,16 +210,7 @@ static bool xe_shrinker_runtime_pm_get(struct xe_shrinker *shrinker, bool force,
|
|
return false;
|
|
}
|
|
|
|
- if (!xe_pm_runtime_get_if_active(xe)) {
|
|
- if (xe_rpm_reclaim_safe(xe) && !ttm_bo_shrink_avoid_wait()) {
|
|
- xe_pm_runtime_get(xe);
|
|
- return true;
|
|
- }
|
|
- queue_work(xe->unordered_wq, &shrinker->pm_worker);
|
|
- return false;
|
|
- }
|
|
-
|
|
- return true;
|
|
+ return __xe_shrinker_runtime_pm_get(shrinker);
|
|
}
|
|
|
|
static void xe_shrinker_runtime_pm_put(struct xe_shrinker *shrinker, bool runtime_pm)
|
|
@@ -221,7 +246,7 @@ static unsigned long xe_shrinker_scan(struct shrinker *shrink, struct shrink_con
|
|
runtime_pm = xe_shrinker_runtime_pm_get(shrinker, false, nr_to_scan, can_backup);
|
|
|
|
if (purgeable && nr_scanned < nr_to_scan)
|
|
- xe_shrinker_walk(shrinker->xe, &ctx, shrink_flags,
|
|
+ xe_shrinker_walk(shrinker, &ctx, shrink_flags,
|
|
nr_to_scan, &nr_scanned, &freed);
|
|
|
|
sc->nr_scanned = nr_scanned;
|
|
@@ -234,7 +259,7 @@ static unsigned long xe_shrinker_scan(struct shrinker *shrink, struct shrink_con
|
|
|
|
shrink_flags.purge = false;
|
|
|
|
- xe_shrinker_walk(shrinker->xe, &ctx, shrink_flags,
|
|
+ xe_shrinker_walk(shrinker, &ctx, shrink_flags,
|
|
nr_to_scan, &nr_scanned, &freed);
|
|
|
|
sc->nr_scanned = nr_scanned;
|