[RFC PATCH v4 06/14] drm/ttm: Add a shrinker and shrinker accounting
Thomas Hellström
thomas.hellstrom at linux.intel.com
Sat Feb 11 13:46:00 UTC 2023
Register a TTM shrinker.
Signed-off-by: Thomas Hellström <thomas.hellstrom at linux.intel.com>
---
drivers/gpu/drm/ttm/ttm_device.c | 1 +
drivers/gpu/drm/ttm/ttm_tt.c | 90 ++++++++++++++++++++++++++++++++
include/drm/ttm/ttm_tt.h | 2 +
3 files changed, 93 insertions(+)
diff --git a/drivers/gpu/drm/ttm/ttm_device.c b/drivers/gpu/drm/ttm/ttm_device.c
index a50e452e5245..f53994fa8fda 100644
--- a/drivers/gpu/drm/ttm/ttm_device.c
+++ b/drivers/gpu/drm/ttm/ttm_device.c
@@ -54,6 +54,7 @@ static void ttm_global_release(void)
if (--ttm_glob_use_count > 0)
goto out;
+ ttm_tt_mgr_fini();
ttm_pool_mgr_fini();
debugfs_remove(ttm_debugfs_root);
diff --git a/drivers/gpu/drm/ttm/ttm_tt.c b/drivers/gpu/drm/ttm/ttm_tt.c
index 771e5f3c2fee..fbf42db8a211 100644
--- a/drivers/gpu/drm/ttm/ttm_tt.c
+++ b/drivers/gpu/drm/ttm/ttm_tt.c
@@ -37,6 +37,7 @@
#include <linux/module.h>
#include <drm/drm_cache.h>
#include <drm/ttm/ttm_bo.h>
+#include <drm/ttm/ttm_pool.h>
#include <drm/ttm/ttm_tt.h>
#include "ttm_module.h"
@@ -54,6 +55,11 @@ module_param_named(dma32_pages_limit, ttm_dma32_pages_limit, ulong, 0644);
static atomic_long_t ttm_pages_allocated;
static atomic_long_t ttm_dma32_pages_allocated;
+static long shrinkable_pages;
+static long purgeable_pages;
+static DEFINE_RWLOCK(shrinkable_lock);
+static struct shrinker mm_shrinker;
+
static bool ttm_tt_shrinkable(const struct ttm_device *bdev,
const struct ttm_tt *tt)
{
@@ -69,6 +75,14 @@ static void ttm_tt_mod_allocated(bool dma32, long value)
atomic_long_add(value, &ttm_dma32_pages_allocated);
}
+static void ttm_tt_mod_shrinkable_pages(long shrinkable, long purgeable)
+{
+ write_lock(&shrinkable_lock);
+ shrinkable_pages += shrinkable;
+ purgeable_pages += purgeable;
+ write_unlock(&shrinkable_lock);
+}
+
/*
* Allocates a ttm structure for the given BO.
*/
@@ -352,6 +366,9 @@ int ttm_tt_populate(struct ttm_device *bdev,
}
}
+ if (ttm_tt_shrinkable(bdev, ttm))
+ ttm_tt_mod_shrinkable_pages(ttm->num_pages, 0);
+
return 0;
error:
@@ -368,6 +385,9 @@ void ttm_tt_unpopulate(struct ttm_device *bdev, struct ttm_tt *ttm)
if (!ttm_tt_is_populated(ttm))
return;
+ if (ttm_tt_shrinkable(bdev, ttm))
+ ttm_tt_mod_shrinkable_pages(-(long)ttm->num_pages, 0);
+
if (bdev->funcs->ttm_tt_unpopulate)
bdev->funcs->ttm_tt_unpopulate(bdev, ttm);
else
@@ -394,6 +414,71 @@ DEFINE_SHOW_ATTRIBUTE(ttm_tt_debugfs_shrink);
#endif
+static unsigned long ttm_tt_shrinker_count(struct shrinker *shrink,
+ struct shrink_control *sc)
+{
+ unsigned long num_pages;
+
+ num_pages = get_nr_swap_pages();
+ read_lock(&shrinkable_lock);
+ num_pages = min_t(unsigned long, num_pages, shrinkable_pages);
+ num_pages += purgeable_pages;
+ read_unlock(&shrinkable_lock);
+
+ return num_pages ? num_pages : SHRINK_EMPTY;
+}
+
+static unsigned long ttm_tt_shrinker_scan(struct shrinker *shrink,
+ struct shrink_control *sc)
+{
+ bool is_kswapd = current_is_kswapd();
+ struct ttm_operation_ctx ctx = {
+ .interruptible = false,
+ .no_wait_gpu = !is_kswapd,
+ };
+ unsigned long nr_to_scan, freed = 0;
+ long ret;
+
+ sc->nr_scanned = 0;
+ nr_to_scan = sc->nr_to_scan;
+
+ while (freed < nr_to_scan) {
+ ret = ttm_global_swapout(&ctx, TTM_SHRINK_PURGE);
+ if (ret <= 0)
+ break;
+
+ freed += ret;
+ }
+
+ sc->nr_scanned = freed;
+ if (freed < nr_to_scan)
+ nr_to_scan -= freed;
+ else
+ nr_to_scan = 0;
+ if (!nr_to_scan)
+ return freed ? freed : SHRINK_STOP;
+
+ while (freed < nr_to_scan) {
+ ret = ttm_global_swapout(&ctx, TTM_SHRINK_SWAP);
+ if (ret <= 0)
+ break;
+
+ freed += ret;
+ }
+
+ sc->nr_scanned = freed;
+
+ return freed ? freed : SHRINK_STOP;
+}
+
+void ttm_tt_mgr_fini(void)
+{
+ WARN_ON(atomic_long_read(&ttm_pages_allocated));
+ WARN_ON(atomic_long_read(&ttm_dma32_pages_allocated));
+ WARN_ON(shrinkable_pages);
+ WARN_ON(purgeable_pages);
+ unregister_shrinker(&mm_shrinker);
+}
/*
* ttm_tt_mgr_init - register with the MM shrinker
@@ -412,6 +497,11 @@ void ttm_tt_mgr_init(unsigned long num_pages, unsigned long num_dma32_pages)
if (!ttm_dma32_pages_limit)
ttm_dma32_pages_limit = num_dma32_pages;
+
+ mm_shrinker.count_objects = ttm_tt_shrinker_count;
+ mm_shrinker.scan_objects = ttm_tt_shrinker_scan;
+ mm_shrinker.seeks = DEFAULT_SEEKS;
+ (void)register_shrinker(&mm_shrinker, "ttm-objects");
}
static void ttm_kmap_iter_tt_map_local(struct ttm_kmap_iter *iter,
diff --git a/include/drm/ttm/ttm_tt.h b/include/drm/ttm/ttm_tt.h
index 627168eba8f6..3f99787e2b93 100644
--- a/include/drm/ttm/ttm_tt.h
+++ b/include/drm/ttm/ttm_tt.h
@@ -221,6 +221,8 @@ static inline void ttm_tt_mark_for_clear(struct ttm_tt *ttm)
void ttm_tt_mgr_init(unsigned long num_pages, unsigned long num_dma32_pages);
+void ttm_tt_mgr_fini(void);
+
struct ttm_kmap_iter *ttm_kmap_iter_tt_init(struct ttm_kmap_iter_tt *iter_tt,
struct ttm_tt *tt);
--
2.34.1
More information about the Intel-gfx-trybot
mailing list