1 /* 2 * Copyright 2020 Advanced Micro Devices, Inc. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 * OTHER DEALINGS IN THE SOFTWARE. 21 * 22 * Authors: Christian König 23 */ 24 25 #ifndef _TTM_RESOURCE_H_ 26 #define _TTM_RESOURCE_H_ 27 28 #include <linux/types.h> 29 #include <linux/list.h> 30 #include <linux/mutex.h> 31 #include <linux/iosys-map.h> 32 #include <linux/dma-fence.h> 33 34 #include <drm/drm_print.h> 35 #include <drm/ttm/ttm_caching.h> 36 #include <drm/ttm/ttm_kmap_iter.h> 37 38 #define TTM_MAX_BO_PRIORITY 4U 39 #define TTM_NUM_MEM_TYPES 8 40 41 struct ttm_device; 42 struct ttm_resource_manager; 43 struct ttm_resource; 44 struct ttm_place; 45 struct ttm_buffer_object; 46 struct ttm_placement; 47 struct iosys_map; 48 struct io_mapping; 49 struct sg_table; 50 struct scatterlist; 51 52 /** 53 * enum ttm_lru_item_type - enumerate ttm_lru_item subclasses 54 */ 55 enum ttm_lru_item_type { 56 /** @TTM_LRU_RESOURCE: The resource subclass */ 57 TTM_LRU_RESOURCE, 58 /** @TTM_LRU_HITCH: The iterator hitch subclass */ 59 TTM_LRU_HITCH 60 }; 61 62 /** 63 * struct ttm_lru_item - The TTM lru list node base class 64 * @link: The list link 65 * @type: The subclass type 66 */ 67 struct ttm_lru_item { 68 struct list_head link; 69 enum ttm_lru_item_type type; 70 }; 71 72 /** 73 * ttm_lru_item_init() - initialize a struct ttm_lru_item 74 * @item: The item to initialize 75 * @type: The subclass type 76 */ 77 static inline void ttm_lru_item_init(struct ttm_lru_item *item, 78 enum ttm_lru_item_type type) 79 { 80 item->type = type; 81 INIT_LIST_HEAD(&item->link); 82 } 83 84 static inline bool ttm_lru_item_is_res(const struct ttm_lru_item *item) 85 { 86 return item->type == TTM_LRU_RESOURCE; 87 } 88 89 struct ttm_resource_manager_func { 90 /** 91 * struct ttm_resource_manager_func member alloc 92 * 93 * @man: Pointer to a memory type manager. 94 * @bo: Pointer to the buffer object we're allocating space for. 95 * @place: Placement details. 96 * @res: Resulting pointer to the ttm_resource. 97 * 98 * This function should allocate space in the memory type managed 99 * by @man. Placement details if applicable are given by @place. If 100 * successful, a filled in ttm_resource object should be returned in 101 * @res. @res::start should be set to a value identifying the beginning 102 * of the range allocated, and the function should return zero. 103 * If the manager can't fulfill the request -ENOSPC should be returned. 104 * If a system error occurred, preventing the request to be fulfilled, 105 * the function should return a negative error code. 106 * 107 * This function may not be called from within atomic context and needs 108 * to take care of its own locking to protect any data structures 109 * managing the space. 110 */ 111 int (*alloc)(struct ttm_resource_manager *man, 112 struct ttm_buffer_object *bo, 113 const struct ttm_place *place, 114 struct ttm_resource **res); 115 116 /** 117 * struct ttm_resource_manager_func member free 118 * 119 * @man: Pointer to a memory type manager. 120 * @res: Pointer to a struct ttm_resource to be freed. 121 * 122 * This function frees memory type resources previously allocated. 123 * May not be called from within atomic context. 124 */ 125 void (*free)(struct ttm_resource_manager *man, 126 struct ttm_resource *res); 127 128 /** 129 * struct ttm_resource_manager_func member intersects 130 * 131 * @man: Pointer to a memory type manager. 132 * @res: Pointer to a struct ttm_resource to be checked. 133 * @place: Placement to check against. 134 * @size: Size of the check. 135 * 136 * Test if @res intersects with @place + @size. Used to judge if 137 * evictions are valueable or not. 138 */ 139 bool (*intersects)(struct ttm_resource_manager *man, 140 struct ttm_resource *res, 141 const struct ttm_place *place, 142 size_t size); 143 144 /** 145 * struct ttm_resource_manager_func member compatible 146 * 147 * @man: Pointer to a memory type manager. 148 * @res: Pointer to a struct ttm_resource to be checked. 149 * @place: Placement to check against. 150 * @size: Size of the check. 151 * 152 * Test if @res compatible with @place + @size. Used to check of 153 * the need to move the backing store or not. 154 */ 155 bool (*compatible)(struct ttm_resource_manager *man, 156 struct ttm_resource *res, 157 const struct ttm_place *place, 158 size_t size); 159 160 /** 161 * struct ttm_resource_manager_func member debug 162 * 163 * @man: Pointer to a memory type manager. 164 * @printer: Prefix to be used in printout to identify the caller. 165 * 166 * This function is called to print out the state of the memory 167 * type manager to aid debugging of out-of-memory conditions. 168 * It may not be called from within atomic context. 169 */ 170 void (*debug)(struct ttm_resource_manager *man, 171 struct drm_printer *printer); 172 }; 173 174 /** 175 * struct ttm_resource_manager 176 * 177 * @use_type: The memory type is enabled. 178 * @use_tt: If a TT object should be used for the backing store. 179 * @size: Size of the managed region. 180 * @bdev: ttm device this manager belongs to 181 * @func: structure pointer implementing the range manager. See above 182 * @move_lock: lock for move fence 183 * @move: The fence of the last pipelined move operation. 184 * @lru: The lru list for this memory type. 185 * 186 * This structure is used to identify and manage memory types for a device. 187 */ 188 struct ttm_resource_manager { 189 /* 190 * No protection. Constant from start. 191 */ 192 bool use_type; 193 bool use_tt; 194 struct ttm_device *bdev; 195 uint64_t size; 196 const struct ttm_resource_manager_func *func; 197 spinlock_t move_lock; 198 199 /* 200 * Protected by @move_lock. 201 */ 202 struct dma_fence *move; 203 204 /* 205 * Protected by the bdev->lru_lock. 206 */ 207 struct list_head lru[TTM_MAX_BO_PRIORITY]; 208 209 /** 210 * @usage: How much of the resources are used, protected by the 211 * bdev->lru_lock. 212 */ 213 uint64_t usage; 214 }; 215 216 /** 217 * struct ttm_bus_placement 218 * 219 * @addr: mapped virtual address 220 * @offset: physical addr 221 * @is_iomem: is this io memory ? 222 * @caching: See enum ttm_caching 223 * 224 * Structure indicating the bus placement of an object. 225 */ 226 struct ttm_bus_placement { 227 void *addr; 228 phys_addr_t offset; 229 bool is_iomem; 230 enum ttm_caching caching; 231 }; 232 233 /** 234 * struct ttm_resource 235 * 236 * @start: Start of the allocation. 237 * @size: Actual size of resource in bytes. 238 * @mem_type: Resource type of the allocation. 239 * @placement: Placement flags. 240 * @bus: Placement on io bus accessible to the CPU 241 * @bo: weak reference to the BO, protected by ttm_device::lru_lock 242 * 243 * Structure indicating the placement and space resources used by a 244 * buffer object. 245 */ 246 struct ttm_resource { 247 unsigned long start; 248 size_t size; 249 uint32_t mem_type; 250 uint32_t placement; 251 struct ttm_bus_placement bus; 252 struct ttm_buffer_object *bo; 253 254 /** 255 * @lru: Least recently used list, see &ttm_resource_manager.lru 256 */ 257 struct ttm_lru_item lru; 258 }; 259 260 /** 261 * ttm_lru_item_to_res() - Downcast a struct ttm_lru_item to a struct ttm_resource 262 * @item: The struct ttm_lru_item to downcast 263 * 264 * Return: Pointer to the embedding struct ttm_resource 265 */ 266 static inline struct ttm_resource * 267 ttm_lru_item_to_res(struct ttm_lru_item *item) 268 { 269 return container_of(item, struct ttm_resource, lru); 270 } 271 272 /** 273 * struct ttm_lru_bulk_move_pos 274 * 275 * @first: first res in the bulk move range 276 * @last: last res in the bulk move range 277 * 278 * Range of resources for a lru bulk move. 279 */ 280 struct ttm_lru_bulk_move_pos { 281 struct ttm_resource *first; 282 struct ttm_resource *last; 283 }; 284 285 /** 286 * struct ttm_lru_bulk_move 287 * @pos: first/last lru entry for resources in the each domain/priority 288 * @cursor_list: The list of cursors currently traversing any of 289 * the sublists of @pos. Protected by the ttm device's lru_lock. 290 * 291 * Container for the current bulk move state. Should be used with 292 * ttm_lru_bulk_move_init() and ttm_bo_set_bulk_move(). 293 * All BOs in a bulk_move structure need to share the same reservation object to 294 * ensure that the bulk as a whole is locked for eviction even if only one BO of 295 * the bulk is evicted. 296 */ 297 struct ttm_lru_bulk_move { 298 struct ttm_lru_bulk_move_pos pos[TTM_NUM_MEM_TYPES][TTM_MAX_BO_PRIORITY]; 299 struct list_head cursor_list; 300 }; 301 302 /** 303 * struct ttm_resource_cursor 304 * @man: The resource manager currently being iterated over 305 * @hitch: A hitch list node inserted before the next resource 306 * to iterate over. 307 * @bulk_link: A list link for the list of cursors traversing the 308 * bulk sublist of @bulk. Protected by the ttm device's lru_lock. 309 * @bulk: Pointer to struct ttm_lru_bulk_move whose subrange @hitch is 310 * inserted to. NULL if none. Never dereference this pointer since 311 * the struct ttm_lru_bulk_move object pointed to might have been 312 * freed. The pointer is only for comparison. 313 * @mem_type: The memory type of the LRU list being traversed. 314 * This field is valid iff @bulk != NULL. 315 * @priority: the current priority 316 * 317 * Cursor to iterate over the resources in a manager. 318 */ 319 struct ttm_resource_cursor { 320 struct ttm_resource_manager *man; 321 struct ttm_lru_item hitch; 322 struct list_head bulk_link; 323 struct ttm_lru_bulk_move *bulk; 324 unsigned int mem_type; 325 unsigned int priority; 326 }; 327 328 void ttm_resource_cursor_fini(struct ttm_resource_cursor *cursor); 329 330 /** 331 * struct ttm_kmap_iter_iomap - Specialization for a struct io_mapping + 332 * struct sg_table backed struct ttm_resource. 333 * @base: Embedded struct ttm_kmap_iter providing the usage interface. 334 * @iomap: struct io_mapping representing the underlying linear io_memory. 335 * @st: sg_table into @iomap, representing the memory of the struct ttm_resource. 336 * @start: Offset that needs to be subtracted from @st to make 337 * sg_dma_address(st->sgl) - @start == 0 for @iomap start. 338 * @cache: Scatterlist traversal cache for fast lookups. 339 * @cache.sg: Pointer to the currently cached scatterlist segment. 340 * @cache.i: First index of @sg. PAGE_SIZE granularity. 341 * @cache.end: Last index + 1 of @sg. PAGE_SIZE granularity. 342 * @cache.offs: First offset into @iomap of @sg. PAGE_SIZE granularity. 343 */ 344 struct ttm_kmap_iter_iomap { 345 struct ttm_kmap_iter base; 346 struct io_mapping *iomap; 347 struct sg_table *st; 348 resource_size_t start; 349 struct { 350 struct scatterlist *sg; 351 pgoff_t i; 352 pgoff_t end; 353 pgoff_t offs; 354 } cache; 355 }; 356 357 /** 358 * struct ttm_kmap_iter_linear_io - Iterator specialization for linear io 359 * @base: The base iterator 360 * @dmap: Points to the starting address of the region 361 * @needs_unmap: Whether we need to unmap on fini 362 */ 363 struct ttm_kmap_iter_linear_io { 364 struct ttm_kmap_iter base; 365 struct iosys_map dmap; 366 bool needs_unmap; 367 }; 368 369 /** 370 * ttm_resource_manager_set_used 371 * 372 * @man: A memory manager object. 373 * @used: usage state to set. 374 * 375 * Set the manager in use flag. If disabled the manager is no longer 376 * used for object placement. 377 */ 378 static inline void 379 ttm_resource_manager_set_used(struct ttm_resource_manager *man, bool used) 380 { 381 int i; 382 383 for (i = 0; i < TTM_MAX_BO_PRIORITY; i++) 384 WARN_ON(!list_empty(&man->lru[i])); 385 man->use_type = used; 386 } 387 388 /** 389 * ttm_resource_manager_used 390 * 391 * @man: Manager to get used state for 392 * 393 * Get the in use flag for a manager. 394 * Returns: 395 * true is used, false if not. 396 */ 397 static inline bool ttm_resource_manager_used(struct ttm_resource_manager *man) 398 { 399 return man->use_type; 400 } 401 402 /** 403 * ttm_resource_manager_cleanup 404 * 405 * @man: A memory manager object. 406 * 407 * Cleanup the move fences from the memory manager object. 408 */ 409 static inline void 410 ttm_resource_manager_cleanup(struct ttm_resource_manager *man) 411 { 412 dma_fence_put(man->move); 413 man->move = NULL; 414 } 415 416 void ttm_lru_bulk_move_init(struct ttm_lru_bulk_move *bulk); 417 void ttm_lru_bulk_move_tail(struct ttm_lru_bulk_move *bulk); 418 void ttm_lru_bulk_move_fini(struct ttm_device *bdev, 419 struct ttm_lru_bulk_move *bulk); 420 421 void ttm_resource_add_bulk_move(struct ttm_resource *res, 422 struct ttm_buffer_object *bo); 423 void ttm_resource_del_bulk_move(struct ttm_resource *res, 424 struct ttm_buffer_object *bo); 425 void ttm_resource_move_to_lru_tail(struct ttm_resource *res); 426 427 void ttm_resource_init(struct ttm_buffer_object *bo, 428 const struct ttm_place *place, 429 struct ttm_resource *res); 430 void ttm_resource_fini(struct ttm_resource_manager *man, 431 struct ttm_resource *res); 432 433 int ttm_resource_alloc(struct ttm_buffer_object *bo, 434 const struct ttm_place *place, 435 struct ttm_resource **res); 436 void ttm_resource_free(struct ttm_buffer_object *bo, struct ttm_resource **res); 437 bool ttm_resource_intersects(struct ttm_device *bdev, 438 struct ttm_resource *res, 439 const struct ttm_place *place, 440 size_t size); 441 bool ttm_resource_compatible(struct ttm_resource *res, 442 struct ttm_placement *placement, 443 bool evicting); 444 void ttm_resource_set_bo(struct ttm_resource *res, 445 struct ttm_buffer_object *bo); 446 447 void ttm_resource_manager_init(struct ttm_resource_manager *man, 448 struct ttm_device *bdev, 449 uint64_t size); 450 451 int ttm_resource_manager_evict_all(struct ttm_device *bdev, 452 struct ttm_resource_manager *man); 453 454 uint64_t ttm_resource_manager_usage(struct ttm_resource_manager *man); 455 void ttm_resource_manager_debug(struct ttm_resource_manager *man, 456 struct drm_printer *p); 457 458 struct ttm_resource * 459 ttm_resource_manager_first(struct ttm_resource_manager *man, 460 struct ttm_resource_cursor *cursor); 461 struct ttm_resource * 462 ttm_resource_manager_next(struct ttm_resource_cursor *cursor); 463 464 struct ttm_resource * 465 ttm_lru_first_res_or_null(struct list_head *head); 466 467 /** 468 * ttm_resource_manager_for_each_res - iterate over all resources 469 * @man: the resource manager 470 * @cursor: struct ttm_resource_cursor for the current position 471 * @res: the current resource 472 * 473 * Iterate over all the evictable resources in a resource manager. 474 */ 475 #define ttm_resource_manager_for_each_res(man, cursor, res) \ 476 for (res = ttm_resource_manager_first(man, cursor); res; \ 477 res = ttm_resource_manager_next(cursor)) 478 479 struct ttm_kmap_iter * 480 ttm_kmap_iter_iomap_init(struct ttm_kmap_iter_iomap *iter_io, 481 struct io_mapping *iomap, 482 struct sg_table *st, 483 resource_size_t start); 484 485 struct ttm_kmap_iter_linear_io; 486 487 struct ttm_kmap_iter * 488 ttm_kmap_iter_linear_io_init(struct ttm_kmap_iter_linear_io *iter_io, 489 struct ttm_device *bdev, 490 struct ttm_resource *mem); 491 492 void ttm_kmap_iter_linear_io_fini(struct ttm_kmap_iter_linear_io *iter_io, 493 struct ttm_device *bdev, 494 struct ttm_resource *mem); 495 496 void ttm_resource_manager_create_debugfs(struct ttm_resource_manager *man, 497 struct dentry * parent, 498 const char *name); 499 #endif 500