Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/ttm: Add helpers for shrinking

Add a number of helpers for shrinking that access core TTM and
core MM functionality in a way that make them unsuitable for
driver open-coding.

v11:
- New patch (split off from previous) and additional helpers.
v13:
- Adapt to ttm_backup interface change.
- Take resource off LRU when backed up.

Signed-off-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
Reviewed-by: Matthew Brost <matthew.brost@intel.com>
Acked-by: Dave Airlie <airlied@redhat.com>
Acked-by: Christian König <christian.koenig@amd.com>
Link: https://lore.kernel.org/intel-xe/20250305092220.123405-6-thomas.hellstrom@linux.intel.com

+158 -1
+106 -1
drivers/gpu/drm/ttm/ttm_bo_util.c
··· 28 28 /* 29 29 * Authors: Thomas Hellstrom <thellstrom-at-vmware-dot-com> 30 30 */ 31 - 31 + #include <linux/swap.h> 32 32 #include <linux/vmalloc.h> 33 33 34 34 #include <drm/ttm/ttm_bo.h> ··· 1052 1052 return bo ? bo : ttm_bo_lru_cursor_next(curs); 1053 1053 } 1054 1054 EXPORT_SYMBOL(ttm_bo_lru_cursor_first); 1055 + 1056 + /** 1057 + * ttm_bo_shrink() - Helper to shrink a ttm buffer object. 1058 + * @ctx: The struct ttm_operation_ctx used for the shrinking operation. 1059 + * @bo: The buffer object. 1060 + * @flags: Flags governing the shrinking behaviour. 1061 + * 1062 + * The function uses the ttm_tt_back_up functionality to back up or 1063 + * purge a struct ttm_tt. If the bo is not in system, it's first 1064 + * moved there. 1065 + * 1066 + * Return: The number of pages shrunken or purged, or 1067 + * negative error code on failure. 1068 + */ 1069 + long ttm_bo_shrink(struct ttm_operation_ctx *ctx, struct ttm_buffer_object *bo, 1070 + const struct ttm_bo_shrink_flags flags) 1071 + { 1072 + static const struct ttm_place sys_placement_flags = { 1073 + .fpfn = 0, 1074 + .lpfn = 0, 1075 + .mem_type = TTM_PL_SYSTEM, 1076 + .flags = 0, 1077 + }; 1078 + static struct ttm_placement sys_placement = { 1079 + .num_placement = 1, 1080 + .placement = &sys_placement_flags, 1081 + }; 1082 + struct ttm_tt *tt = bo->ttm; 1083 + long lret; 1084 + 1085 + dma_resv_assert_held(bo->base.resv); 1086 + 1087 + if (flags.allow_move && bo->resource->mem_type != TTM_PL_SYSTEM) { 1088 + int ret = ttm_bo_validate(bo, &sys_placement, ctx); 1089 + 1090 + /* Consider -ENOMEM and -ENOSPC non-fatal. */ 1091 + if (ret) { 1092 + if (ret == -ENOMEM || ret == -ENOSPC) 1093 + ret = -EBUSY; 1094 + return ret; 1095 + } 1096 + } 1097 + 1098 + ttm_bo_unmap_virtual(bo); 1099 + lret = ttm_bo_wait_ctx(bo, ctx); 1100 + if (lret < 0) 1101 + return lret; 1102 + 1103 + if (bo->bulk_move) { 1104 + spin_lock(&bo->bdev->lru_lock); 1105 + ttm_resource_del_bulk_move(bo->resource, bo); 1106 + spin_unlock(&bo->bdev->lru_lock); 1107 + } 1108 + 1109 + lret = ttm_tt_backup(bo->bdev, tt, (struct ttm_backup_flags) 1110 + {.purge = flags.purge, 1111 + .writeback = flags.writeback}); 1112 + 1113 + if (lret <= 0 && bo->bulk_move) { 1114 + spin_lock(&bo->bdev->lru_lock); 1115 + ttm_resource_add_bulk_move(bo->resource, bo); 1116 + spin_unlock(&bo->bdev->lru_lock); 1117 + } 1118 + 1119 + if (lret < 0 && lret != -EINTR) 1120 + return -EBUSY; 1121 + 1122 + return lret; 1123 + } 1124 + EXPORT_SYMBOL(ttm_bo_shrink); 1125 + 1126 + /** 1127 + * ttm_bo_shrink_suitable() - Whether a bo is suitable for shinking 1128 + * @ctx: The struct ttm_operation_ctx governing the shrinking. 1129 + * @bo: The candidate for shrinking. 1130 + * 1131 + * Check whether the object, given the information available to TTM, 1132 + * is suitable for shinking, This function can and should be used 1133 + * before attempting to shrink an object. 1134 + * 1135 + * Return: true if suitable. false if not. 1136 + */ 1137 + bool ttm_bo_shrink_suitable(struct ttm_buffer_object *bo, struct ttm_operation_ctx *ctx) 1138 + { 1139 + return bo->ttm && ttm_tt_is_populated(bo->ttm) && !bo->pin_count && 1140 + (!ctx->no_wait_gpu || 1141 + dma_resv_test_signaled(bo->base.resv, DMA_RESV_USAGE_BOOKKEEP)); 1142 + } 1143 + EXPORT_SYMBOL(ttm_bo_shrink_suitable); 1144 + 1145 + /** 1146 + * ttm_bo_shrink_avoid_wait() - Whether to avoid waiting for GPU 1147 + * during shrinking 1148 + * 1149 + * In some situations, like direct reclaim, waiting (in particular gpu waiting) 1150 + * should be avoided since it may stall a system that could otherwise make progress 1151 + * shrinking something else less time consuming. 1152 + * 1153 + * Return: true if gpu waiting should be avoided, false if not. 1154 + */ 1155 + bool ttm_bo_shrink_avoid_wait(void) 1156 + { 1157 + return !current_is_kswapd(); 1158 + } 1159 + EXPORT_SYMBOL(ttm_bo_shrink_avoid_wait);
+29
drivers/gpu/drm/ttm/ttm_tt.c
··· 531 531 return ttm_pages_limit; 532 532 } 533 533 EXPORT_SYMBOL(ttm_tt_pages_limit); 534 + 535 + /** 536 + * ttm_tt_setup_backup() - Allocate and assign a backup structure for a ttm_tt 537 + * @tt: The ttm_tt for wich to allocate and assign a backup structure. 538 + * 539 + * Assign a backup structure to be used for tt backup. This should 540 + * typically be done at bo creation, to avoid allocations at shrinking 541 + * time. 542 + * 543 + * Return: 0 on success, negative error code on failure. 544 + */ 545 + int ttm_tt_setup_backup(struct ttm_tt *tt) 546 + { 547 + struct ttm_backup *backup = 548 + ttm_backup_shmem_create(((loff_t)tt->num_pages) << PAGE_SHIFT); 549 + 550 + if (WARN_ON_ONCE(!(tt->page_flags & TTM_TT_FLAG_EXTERNAL_MAPPABLE))) 551 + return -EINVAL; 552 + 553 + if (IS_ERR(backup)) 554 + return PTR_ERR(backup); 555 + 556 + if (tt->backup) 557 + ttm_backup_fini(tt->backup); 558 + 559 + tt->backup = backup; 560 + return 0; 561 + } 562 + EXPORT_SYMBOL(ttm_tt_setup_backup);
+21
include/drm/ttm/ttm_bo.h
··· 226 226 struct ttm_resource_manager *man, s64 target); 227 227 228 228 /** 229 + * struct ttm_bo_shrink_flags - flags to govern the bo shrinking behaviour 230 + * @purge: Purge the content rather than backing it up. 231 + * @writeback: Attempt to immediately write content to swap space. 232 + * @allow_move: Allow moving to system before shrinking. This is typically 233 + * not desired for zombie- or ghost objects (with zombie object meaning 234 + * objects with a zero gem object refcount) 235 + */ 236 + struct ttm_bo_shrink_flags { 237 + u32 purge : 1; 238 + u32 writeback : 1; 239 + u32 allow_move : 1; 240 + }; 241 + 242 + long ttm_bo_shrink(struct ttm_operation_ctx *ctx, struct ttm_buffer_object *bo, 243 + const struct ttm_bo_shrink_flags flags); 244 + 245 + bool ttm_bo_shrink_suitable(struct ttm_buffer_object *bo, struct ttm_operation_ctx *ctx); 246 + 247 + bool ttm_bo_shrink_avoid_wait(void); 248 + 249 + /** 229 250 * ttm_bo_get - reference a struct ttm_buffer_object 230 251 * 231 252 * @bo: The buffer object.
+2
include/drm/ttm/ttm_tt.h
··· 298 298 int ttm_tt_restore(struct ttm_device *bdev, struct ttm_tt *tt, 299 299 const struct ttm_operation_ctx *ctx); 300 300 301 + int ttm_tt_setup_backup(struct ttm_tt *tt); 302 + 301 303 #if IS_ENABLED(CONFIG_AGP) 302 304 #include <linux/agp_backend.h> 303 305