Following the design direction communicated here:

https://lore.kernel.org/linux-mm/b7491378-defd-4f1c-31e2-29e4c77e2...@amd.com/T/#ma918844aa8a6efe8768fdcda0c6590d5c93850c9

Export the LRU walker for driver shrinker use and add a bo
shrinker helper for initial use by the xe driver.

v8:
- Split out from another patch.
- Use a struct for bool arguments to increase readability (Matt Brost).
- Unmap user-space cpu-mappings before shrinking pages.
- Explain non-fatal error codes (Matt Brost)

Signed-off-by: Thomas Hellström <thomas.hellst...@linux.intel.com>
---
 drivers/gpu/drm/ttm/ttm_bo_util.c | 65 +++++++++++++++++++++++++++++++
 include/drm/ttm/ttm_bo.h          | 17 ++++++++
 2 files changed, 82 insertions(+)

diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c 
b/drivers/gpu/drm/ttm/ttm_bo_util.c
index 3c07f4712d5c..3490e3347de9 100644
--- a/drivers/gpu/drm/ttm/ttm_bo_util.c
+++ b/drivers/gpu/drm/ttm/ttm_bo_util.c
@@ -919,3 +919,68 @@ s64 ttm_lru_walk_for_evict(struct ttm_lru_walk *walk, 
struct ttm_device *bdev,
 
        return progress;
 }
+EXPORT_SYMBOL(ttm_lru_walk_for_evict);
+
+/**
+ * ttm_bo_try_shrink - LRU walk helper to shrink a ttm buffer object.
+ * @walk: The struct xe_ttm_lru_walk that describes the walk.
+ * @bo: The buffer object.
+ * @flags: Flags governing the shrinking behaviour.
+ *
+ * The function uses the ttm_tt_back_up functionality to back up or
+ * purge a struct ttm_tt. If the bo is not in system, it's first
+ * moved there, unless @flags.allow_move is false.
+ *
+ * Return: The number of pages shrunken or purged, or
+ * negative error code on failure.
+ */
+long ttm_bo_try_shrink(struct ttm_lru_walk *walk, struct ttm_buffer_object *bo,
+                      const struct ttm_bo_shrink_flags flags)
+{
+       static const struct ttm_place sys_placement_flags = {
+               .fpfn = 0,
+               .lpfn = 0,
+               .mem_type = TTM_PL_SYSTEM,
+               .flags = 0,
+       };
+       static struct ttm_placement sys_placement = {
+               .num_placement = 1,
+               .placement = &sys_placement_flags,
+       };
+       struct ttm_operation_ctx *ctx = walk->ctx;
+       struct ttm_tt *tt = bo->ttm;
+       long lret;
+
+       dma_resv_assert_held(bo->base.resv);
+
+       if (!tt || !ttm_tt_is_populated(tt))
+               return 0;
+
+       if (flags.allow_move && bo->resource->mem_type != TTM_PL_SYSTEM) {
+               int ret = ttm_bo_validate(bo, &sys_placement, ctx);
+
+               /* Consider -ENOMEM and -ENOSPC non-fatal. */
+               if (ret) {
+                       if (ret == -ENOMEM || ret == -ENOSPC)
+                               ret = -EBUSY;
+                       return ret;
+               }
+       }
+
+       ttm_bo_unmap_virtual(bo);
+       lret = ttm_bo_wait_ctx(bo, ctx);
+       if (lret < 0) {
+               if (lret == -ERESTARTSYS)
+                       return lret;
+               return 0;
+       }
+
+       lret = ttm_tt_backup(bo->bdev, tt, (struct ttm_backup_flags)
+                            {.purge = flags.purge,
+                             .writeback = flags.writeback});
+       if (lret < 0 && lret != -EINTR)
+               return 0;
+
+       return lret;
+}
+EXPORT_SYMBOL(ttm_bo_try_shrink);
diff --git a/include/drm/ttm/ttm_bo.h b/include/drm/ttm/ttm_bo.h
index d1a732d56259..479ada85cea1 100644
--- a/include/drm/ttm/ttm_bo.h
+++ b/include/drm/ttm/ttm_bo.h
@@ -229,6 +229,23 @@ struct ttm_lru_walk {
 s64 ttm_lru_walk_for_evict(struct ttm_lru_walk *walk, struct ttm_device *bdev,
                           struct ttm_resource_manager *man, s64 target);
 
+/**
+ * struct ttm_bo_shrink_flags - flags to govern the bo shrinking behaviour
+ * @purge: Purge the content rather than backing it up.
+ * @writeback: Attempt to immediately write content to swap space.
+ * @allow_move: Allow moving to system before shrinking. This is typically
+ * not desired for zombie- or ghost objects (with zombie object meaning
+ * objects with a zero gem object refcount)
+ */
+struct ttm_bo_shrink_flags {
+       u32 purge : 1;
+       u32 writeback : 1;
+       u32 allow_move : 1;
+};
+
+long ttm_bo_try_shrink(struct ttm_lru_walk *walk, struct ttm_buffer_object *bo,
+                      const struct ttm_bo_shrink_flags flags);
+
 /**
  * ttm_bo_get - reference a struct ttm_buffer_object
  *
-- 
2.44.0

Reply via email to