1 /* SPDX-License-Identifier: GPL-2.0 OR MIT */ 2 /************************************************************************** 3 * 4 * Copyright © 2018 VMware, Inc., Palo Alto, CA., USA 5 * All Rights Reserved. 6 * 7 * Permission is hereby granted, free of charge, to any person obtaining a 8 * copy of this software and associated documentation files (the 9 * "Software"), to deal in the Software without restriction, including 10 * without limitation the rights to use, copy, modify, merge, publish, 11 * distribute, sub license, and/or sell copies of the Software, and to 12 * permit persons to whom the Software is furnished to do so, subject to 13 * the following conditions: 14 * 15 * The above copyright notice and this permission notice (including the 16 * next paragraph) shall be included in all copies or substantial portions 17 * of the Software. 18 * 19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 22 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, 23 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 24 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 25 * USE OR OTHER DEALINGS IN THE SOFTWARE. 26 * 27 **************************************************************************/ 28 #ifndef _VMWGFX_VALIDATION_H_ 29 #define _VMWGFX_VALIDATION_H_ 30 31 #include <drm/drm_hashtab.h> 32 #include <linux/list.h> 33 #include <linux/ww_mutex.h> 34 #include <drm/ttm/ttm_execbuf_util.h> 35 36 /** 37 * struct vmw_validation_mem - Custom interface to provide memory reservations 38 * for the validation code. 39 * @reserve_mem: Callback to reserve memory 40 * @unreserve_mem: Callback to unreserve memory 41 * @gran: Reservation granularity. Contains a hint how much memory should 42 * be reserved in each call to @reserve_mem(). A slow implementation may want 43 * reservation to be done in large batches. 44 */ 45 struct vmw_validation_mem { 46 int (*reserve_mem)(struct vmw_validation_mem *m, size_t size); 47 void (*unreserve_mem)(struct vmw_validation_mem *m, size_t size); 48 size_t gran; 49 }; 50 51 /** 52 * struct vmw_validation_context - Per command submission validation context 53 * @ht: Hash table used to find resource- or buffer object duplicates 54 * @resource_list: List head for resource validation metadata 55 * @resource_ctx_list: List head for resource validation metadata for 56 * resources that need to be validated before those in @resource_list 57 * @bo_list: List head for buffer objects 58 * @page_list: List of pages used by the memory allocator 59 * @ticket: Ticked used for ww mutex locking 60 * @res_mutex: Pointer to mutex used for resource reserving 61 * @merge_dups: Whether to merge metadata for duplicate resources or 62 * buffer objects 63 * @mem_size_left: Free memory left in the last page in @page_list 64 * @page_address: Kernel virtual address of the last page in @page_list 65 * @vm: A pointer to the memory reservation interface or NULL if no 66 * memory reservation is needed. 67 * @vm_size_left: Amount of reserved memory that so far has not been allocated. 68 * @total_mem: Amount of reserved memory. 69 */ 70 struct vmw_validation_context { 71 struct drm_open_hash *ht; 72 struct list_head resource_list; 73 struct list_head resource_ctx_list; 74 struct list_head bo_list; 75 struct list_head page_list; 76 struct ww_acquire_ctx ticket; 77 struct mutex *res_mutex; 78 unsigned int merge_dups; 79 unsigned int mem_size_left; 80 u8 *page_address; 81 struct vmw_validation_mem *vm; 82 size_t vm_size_left; 83 size_t total_mem; 84 }; 85 86 struct vmw_buffer_object; 87 struct vmw_resource; 88 struct vmw_fence_obj; 89 90 #if 0 91 /** 92 * DECLARE_VAL_CONTEXT - Declare a validation context with initialization 93 * @_name: The name of the variable 94 * @_ht: The hash table used to find dups or NULL if none 95 * @_merge_dups: Whether to merge duplicate buffer object- or resource 96 * entries. If set to true, ideally a hash table pointer should be supplied 97 * as well unless the number of resources and buffer objects per validation 98 * is known to be very small 99 */ 100 #endif 101 #define DECLARE_VAL_CONTEXT(_name, _ht, _merge_dups) \ 102 struct vmw_validation_context _name = \ 103 { .ht = _ht, \ 104 .resource_list = LIST_HEAD_INIT((_name).resource_list), \ 105 .resource_ctx_list = LIST_HEAD_INIT((_name).resource_ctx_list), \ 106 .bo_list = LIST_HEAD_INIT((_name).bo_list), \ 107 .page_list = LIST_HEAD_INIT((_name).page_list), \ 108 .res_mutex = NULL, \ 109 .merge_dups = _merge_dups, \ 110 .mem_size_left = 0, \ 111 } 112 113 /** 114 * vmw_validation_has_bos - return whether the validation context has 115 * any buffer objects registered. 116 * 117 * @ctx: The validation context 118 * Returns: Whether any buffer objects are registered 119 */ 120 static inline bool 121 vmw_validation_has_bos(struct vmw_validation_context *ctx) 122 { 123 return !list_empty(&ctx->bo_list); 124 } 125 126 /** 127 * vmw_validation_set_val_mem - Register a validation mem object for 128 * validation memory reservation 129 * @ctx: The validation context 130 * @vm: Pointer to a struct vmw_validation_mem 131 * 132 * Must be set before the first attempt to allocate validation memory. 133 */ 134 static inline void 135 vmw_validation_set_val_mem(struct vmw_validation_context *ctx, 136 struct vmw_validation_mem *vm) 137 { 138 ctx->vm = vm; 139 } 140 141 /** 142 * vmw_validation_set_ht - Register a hash table for duplicate finding 143 * @ctx: The validation context 144 * @ht: Pointer to a hash table to use for duplicate finding 145 * This function is intended to be used if the hash table wasn't 146 * available at validation context declaration time 147 */ 148 static inline void vmw_validation_set_ht(struct vmw_validation_context *ctx, 149 struct drm_open_hash *ht) 150 { 151 ctx->ht = ht; 152 } 153 154 /** 155 * vmw_validation_bo_reserve - Reserve buffer objects registered with a 156 * validation context 157 * @ctx: The validation context 158 * @intr: Perform waits interruptible 159 * 160 * Return: Zero on success, -ERESTARTSYS when interrupted, negative error 161 * code on failure 162 */ 163 static inline int 164 vmw_validation_bo_reserve(struct vmw_validation_context *ctx, 165 bool intr) 166 { 167 return ttm_eu_reserve_buffers(&ctx->ticket, &ctx->bo_list, intr, 168 NULL); 169 } 170 171 /** 172 * vmw_validation_bo_backoff - Unreserve buffer objects registered with a 173 * validation context 174 * @ctx: The validation context 175 * 176 * This function unreserves the buffer objects previously reserved using 177 * vmw_validation_bo_reserve. It's typically used as part of an error path 178 */ 179 static inline void 180 vmw_validation_bo_backoff(struct vmw_validation_context *ctx) 181 { 182 ttm_eu_backoff_reservation(&ctx->ticket, &ctx->bo_list); 183 } 184 185 /** 186 * vmw_validation_bo_fence - Unreserve and fence buffer objects registered 187 * with a validation context 188 * @ctx: The validation context 189 * 190 * This function unreserves the buffer objects previously reserved using 191 * vmw_validation_bo_reserve, and fences them with a fence object. 192 */ 193 static inline void 194 vmw_validation_bo_fence(struct vmw_validation_context *ctx, 195 struct vmw_fence_obj *fence) 196 { 197 ttm_eu_fence_buffer_objects(&ctx->ticket, &ctx->bo_list, 198 (void *) fence); 199 } 200 201 /** 202 * vmw_validation_context_init - Initialize a validation context 203 * @ctx: Pointer to the validation context to initialize 204 * 205 * This function initializes a validation context with @merge_dups set 206 * to false 207 */ 208 static inline void 209 vmw_validation_context_init(struct vmw_validation_context *ctx) 210 { 211 memset(ctx, 0, sizeof(*ctx)); 212 INIT_LIST_HEAD(&ctx->resource_list); 213 INIT_LIST_HEAD(&ctx->resource_ctx_list); 214 INIT_LIST_HEAD(&ctx->bo_list); 215 } 216 217 /** 218 * vmw_validation_align - Align a validation memory allocation 219 * @val: The size to be aligned 220 * 221 * Returns: @val aligned to the granularity used by the validation memory 222 * allocator. 223 */ 224 static inline unsigned int vmw_validation_align(unsigned int val) 225 { 226 return ALIGN(val, sizeof(long)); 227 } 228 229 int vmw_validation_add_bo(struct vmw_validation_context *ctx, 230 struct vmw_buffer_object *vbo, 231 bool as_mob, bool cpu_blit); 232 int vmw_validation_bo_validate_single(struct ttm_buffer_object *bo, 233 bool interruptible, 234 bool validate_as_mob); 235 int vmw_validation_bo_validate(struct vmw_validation_context *ctx, bool intr); 236 void vmw_validation_unref_lists(struct vmw_validation_context *ctx); 237 int vmw_validation_add_resource(struct vmw_validation_context *ctx, 238 struct vmw_resource *res, 239 size_t priv_size, 240 void **p_node, 241 bool *first_usage); 242 void vmw_validation_drop_ht(struct vmw_validation_context *ctx); 243 int vmw_validation_res_reserve(struct vmw_validation_context *ctx, 244 bool intr); 245 void vmw_validation_res_unreserve(struct vmw_validation_context *ctx, 246 bool backoff); 247 void vmw_validation_res_switch_backup(struct vmw_validation_context *ctx, 248 void *val_private, 249 struct vmw_buffer_object *vbo, 250 unsigned long backup_offset); 251 int vmw_validation_res_validate(struct vmw_validation_context *ctx, bool intr); 252 253 int vmw_validation_prepare(struct vmw_validation_context *ctx, 254 struct mutex *mutex, bool intr); 255 void vmw_validation_revert(struct vmw_validation_context *ctx); 256 void vmw_validation_done(struct vmw_validation_context *ctx, 257 struct vmw_fence_obj *fence); 258 259 void *vmw_validation_mem_alloc(struct vmw_validation_context *ctx, 260 unsigned int size); 261 int vmw_validation_preload_bo(struct vmw_validation_context *ctx); 262 int vmw_validation_preload_res(struct vmw_validation_context *ctx, 263 unsigned int size); 264 #endif 265