|
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,3 +1052,108 @@ struct ttm_buffer_object *ttm_bo_lru_cursor_first(struct ttm_bo_lru_cursor *curs
|
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); |
0 commit comments