18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 OR MIT */ 28c2ecf20Sopenharmony_ci/************************************************************************** 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Copyright © 2018 VMware, Inc., Palo Alto, CA., USA 58c2ecf20Sopenharmony_ci * All Rights Reserved. 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 88c2ecf20Sopenharmony_ci * copy of this software and associated documentation files (the 98c2ecf20Sopenharmony_ci * "Software"), to deal in the Software without restriction, including 108c2ecf20Sopenharmony_ci * without limitation the rights to use, copy, modify, merge, publish, 118c2ecf20Sopenharmony_ci * distribute, sub license, and/or sell copies of the Software, and to 128c2ecf20Sopenharmony_ci * permit persons to whom the Software is furnished to do so, subject to 138c2ecf20Sopenharmony_ci * the following conditions: 148c2ecf20Sopenharmony_ci * 158c2ecf20Sopenharmony_ci * The above copyright notice and this permission notice (including the 168c2ecf20Sopenharmony_ci * next paragraph) shall be included in all copies or substantial portions 178c2ecf20Sopenharmony_ci * of the Software. 188c2ecf20Sopenharmony_ci * 198c2ecf20Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 208c2ecf20Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 218c2ecf20Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 228c2ecf20Sopenharmony_ci * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, 238c2ecf20Sopenharmony_ci * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 248c2ecf20Sopenharmony_ci * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 258c2ecf20Sopenharmony_ci * USE OR OTHER DEALINGS IN THE SOFTWARE. 268c2ecf20Sopenharmony_ci * 278c2ecf20Sopenharmony_ci **************************************************************************/ 288c2ecf20Sopenharmony_ci#ifndef _VMWGFX_VALIDATION_H_ 298c2ecf20Sopenharmony_ci#define _VMWGFX_VALIDATION_H_ 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ci#include <linux/list.h> 328c2ecf20Sopenharmony_ci#include <linux/ww_mutex.h> 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci#include <drm/drm_hashtab.h> 358c2ecf20Sopenharmony_ci#include <drm/ttm/ttm_execbuf_util.h> 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_ci#define VMW_RES_DIRTY_NONE 0 388c2ecf20Sopenharmony_ci#define VMW_RES_DIRTY_SET BIT(0) 398c2ecf20Sopenharmony_ci#define VMW_RES_DIRTY_CLEAR BIT(1) 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ci/** 428c2ecf20Sopenharmony_ci * struct vmw_validation_mem - Custom interface to provide memory reservations 438c2ecf20Sopenharmony_ci * for the validation code. 448c2ecf20Sopenharmony_ci * @reserve_mem: Callback to reserve memory 458c2ecf20Sopenharmony_ci * @unreserve_mem: Callback to unreserve memory 468c2ecf20Sopenharmony_ci * @gran: Reservation granularity. Contains a hint how much memory should 478c2ecf20Sopenharmony_ci * be reserved in each call to @reserve_mem(). A slow implementation may want 488c2ecf20Sopenharmony_ci * reservation to be done in large batches. 498c2ecf20Sopenharmony_ci */ 508c2ecf20Sopenharmony_cistruct vmw_validation_mem { 518c2ecf20Sopenharmony_ci int (*reserve_mem)(struct vmw_validation_mem *m, size_t size); 528c2ecf20Sopenharmony_ci void (*unreserve_mem)(struct vmw_validation_mem *m, size_t size); 538c2ecf20Sopenharmony_ci size_t gran; 548c2ecf20Sopenharmony_ci}; 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ci/** 578c2ecf20Sopenharmony_ci * struct vmw_validation_context - Per command submission validation context 588c2ecf20Sopenharmony_ci * @ht: Hash table used to find resource- or buffer object duplicates 598c2ecf20Sopenharmony_ci * @resource_list: List head for resource validation metadata 608c2ecf20Sopenharmony_ci * @resource_ctx_list: List head for resource validation metadata for 618c2ecf20Sopenharmony_ci * resources that need to be validated before those in @resource_list 628c2ecf20Sopenharmony_ci * @bo_list: List head for buffer objects 638c2ecf20Sopenharmony_ci * @page_list: List of pages used by the memory allocator 648c2ecf20Sopenharmony_ci * @ticket: Ticked used for ww mutex locking 658c2ecf20Sopenharmony_ci * @res_mutex: Pointer to mutex used for resource reserving 668c2ecf20Sopenharmony_ci * @merge_dups: Whether to merge metadata for duplicate resources or 678c2ecf20Sopenharmony_ci * buffer objects 688c2ecf20Sopenharmony_ci * @mem_size_left: Free memory left in the last page in @page_list 698c2ecf20Sopenharmony_ci * @page_address: Kernel virtual address of the last page in @page_list 708c2ecf20Sopenharmony_ci * @vm: A pointer to the memory reservation interface or NULL if no 718c2ecf20Sopenharmony_ci * memory reservation is needed. 728c2ecf20Sopenharmony_ci * @vm_size_left: Amount of reserved memory that so far has not been allocated. 738c2ecf20Sopenharmony_ci * @total_mem: Amount of reserved memory. 748c2ecf20Sopenharmony_ci */ 758c2ecf20Sopenharmony_cistruct vmw_validation_context { 768c2ecf20Sopenharmony_ci struct drm_open_hash *ht; 778c2ecf20Sopenharmony_ci struct list_head resource_list; 788c2ecf20Sopenharmony_ci struct list_head resource_ctx_list; 798c2ecf20Sopenharmony_ci struct list_head bo_list; 808c2ecf20Sopenharmony_ci struct list_head page_list; 818c2ecf20Sopenharmony_ci struct ww_acquire_ctx ticket; 828c2ecf20Sopenharmony_ci struct mutex *res_mutex; 838c2ecf20Sopenharmony_ci unsigned int merge_dups; 848c2ecf20Sopenharmony_ci unsigned int mem_size_left; 858c2ecf20Sopenharmony_ci u8 *page_address; 868c2ecf20Sopenharmony_ci struct vmw_validation_mem *vm; 878c2ecf20Sopenharmony_ci size_t vm_size_left; 888c2ecf20Sopenharmony_ci size_t total_mem; 898c2ecf20Sopenharmony_ci}; 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_cistruct vmw_buffer_object; 928c2ecf20Sopenharmony_cistruct vmw_resource; 938c2ecf20Sopenharmony_cistruct vmw_fence_obj; 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_ci#if 0 968c2ecf20Sopenharmony_ci/** 978c2ecf20Sopenharmony_ci * DECLARE_VAL_CONTEXT - Declare a validation context with initialization 988c2ecf20Sopenharmony_ci * @_name: The name of the variable 998c2ecf20Sopenharmony_ci * @_ht: The hash table used to find dups or NULL if none 1008c2ecf20Sopenharmony_ci * @_merge_dups: Whether to merge duplicate buffer object- or resource 1018c2ecf20Sopenharmony_ci * entries. If set to true, ideally a hash table pointer should be supplied 1028c2ecf20Sopenharmony_ci * as well unless the number of resources and buffer objects per validation 1038c2ecf20Sopenharmony_ci * is known to be very small 1048c2ecf20Sopenharmony_ci */ 1058c2ecf20Sopenharmony_ci#endif 1068c2ecf20Sopenharmony_ci#define DECLARE_VAL_CONTEXT(_name, _ht, _merge_dups) \ 1078c2ecf20Sopenharmony_ci struct vmw_validation_context _name = \ 1088c2ecf20Sopenharmony_ci { .ht = _ht, \ 1098c2ecf20Sopenharmony_ci .resource_list = LIST_HEAD_INIT((_name).resource_list), \ 1108c2ecf20Sopenharmony_ci .resource_ctx_list = LIST_HEAD_INIT((_name).resource_ctx_list), \ 1118c2ecf20Sopenharmony_ci .bo_list = LIST_HEAD_INIT((_name).bo_list), \ 1128c2ecf20Sopenharmony_ci .page_list = LIST_HEAD_INIT((_name).page_list), \ 1138c2ecf20Sopenharmony_ci .res_mutex = NULL, \ 1148c2ecf20Sopenharmony_ci .merge_dups = _merge_dups, \ 1158c2ecf20Sopenharmony_ci .mem_size_left = 0, \ 1168c2ecf20Sopenharmony_ci } 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_ci/** 1198c2ecf20Sopenharmony_ci * vmw_validation_has_bos - return whether the validation context has 1208c2ecf20Sopenharmony_ci * any buffer objects registered. 1218c2ecf20Sopenharmony_ci * 1228c2ecf20Sopenharmony_ci * @ctx: The validation context 1238c2ecf20Sopenharmony_ci * Returns: Whether any buffer objects are registered 1248c2ecf20Sopenharmony_ci */ 1258c2ecf20Sopenharmony_cistatic inline bool 1268c2ecf20Sopenharmony_civmw_validation_has_bos(struct vmw_validation_context *ctx) 1278c2ecf20Sopenharmony_ci{ 1288c2ecf20Sopenharmony_ci return !list_empty(&ctx->bo_list); 1298c2ecf20Sopenharmony_ci} 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_ci/** 1328c2ecf20Sopenharmony_ci * vmw_validation_set_val_mem - Register a validation mem object for 1338c2ecf20Sopenharmony_ci * validation memory reservation 1348c2ecf20Sopenharmony_ci * @ctx: The validation context 1358c2ecf20Sopenharmony_ci * @vm: Pointer to a struct vmw_validation_mem 1368c2ecf20Sopenharmony_ci * 1378c2ecf20Sopenharmony_ci * Must be set before the first attempt to allocate validation memory. 1388c2ecf20Sopenharmony_ci */ 1398c2ecf20Sopenharmony_cistatic inline void 1408c2ecf20Sopenharmony_civmw_validation_set_val_mem(struct vmw_validation_context *ctx, 1418c2ecf20Sopenharmony_ci struct vmw_validation_mem *vm) 1428c2ecf20Sopenharmony_ci{ 1438c2ecf20Sopenharmony_ci ctx->vm = vm; 1448c2ecf20Sopenharmony_ci} 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_ci/** 1478c2ecf20Sopenharmony_ci * vmw_validation_set_ht - Register a hash table for duplicate finding 1488c2ecf20Sopenharmony_ci * @ctx: The validation context 1498c2ecf20Sopenharmony_ci * @ht: Pointer to a hash table to use for duplicate finding 1508c2ecf20Sopenharmony_ci * This function is intended to be used if the hash table wasn't 1518c2ecf20Sopenharmony_ci * available at validation context declaration time 1528c2ecf20Sopenharmony_ci */ 1538c2ecf20Sopenharmony_cistatic inline void vmw_validation_set_ht(struct vmw_validation_context *ctx, 1548c2ecf20Sopenharmony_ci struct drm_open_hash *ht) 1558c2ecf20Sopenharmony_ci{ 1568c2ecf20Sopenharmony_ci ctx->ht = ht; 1578c2ecf20Sopenharmony_ci} 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_ci/** 1608c2ecf20Sopenharmony_ci * vmw_validation_bo_reserve - Reserve buffer objects registered with a 1618c2ecf20Sopenharmony_ci * validation context 1628c2ecf20Sopenharmony_ci * @ctx: The validation context 1638c2ecf20Sopenharmony_ci * @intr: Perform waits interruptible 1648c2ecf20Sopenharmony_ci * 1658c2ecf20Sopenharmony_ci * Return: Zero on success, -ERESTARTSYS when interrupted, negative error 1668c2ecf20Sopenharmony_ci * code on failure 1678c2ecf20Sopenharmony_ci */ 1688c2ecf20Sopenharmony_cistatic inline int 1698c2ecf20Sopenharmony_civmw_validation_bo_reserve(struct vmw_validation_context *ctx, 1708c2ecf20Sopenharmony_ci bool intr) 1718c2ecf20Sopenharmony_ci{ 1728c2ecf20Sopenharmony_ci return ttm_eu_reserve_buffers(&ctx->ticket, &ctx->bo_list, intr, 1738c2ecf20Sopenharmony_ci NULL); 1748c2ecf20Sopenharmony_ci} 1758c2ecf20Sopenharmony_ci 1768c2ecf20Sopenharmony_ci/** 1778c2ecf20Sopenharmony_ci * vmw_validation_bo_fence - Unreserve and fence buffer objects registered 1788c2ecf20Sopenharmony_ci * with a validation context 1798c2ecf20Sopenharmony_ci * @ctx: The validation context 1808c2ecf20Sopenharmony_ci * 1818c2ecf20Sopenharmony_ci * This function unreserves the buffer objects previously reserved using 1828c2ecf20Sopenharmony_ci * vmw_validation_bo_reserve, and fences them with a fence object. 1838c2ecf20Sopenharmony_ci */ 1848c2ecf20Sopenharmony_cistatic inline void 1858c2ecf20Sopenharmony_civmw_validation_bo_fence(struct vmw_validation_context *ctx, 1868c2ecf20Sopenharmony_ci struct vmw_fence_obj *fence) 1878c2ecf20Sopenharmony_ci{ 1888c2ecf20Sopenharmony_ci ttm_eu_fence_buffer_objects(&ctx->ticket, &ctx->bo_list, 1898c2ecf20Sopenharmony_ci (void *) fence); 1908c2ecf20Sopenharmony_ci} 1918c2ecf20Sopenharmony_ci 1928c2ecf20Sopenharmony_ci/** 1938c2ecf20Sopenharmony_ci * vmw_validation_context_init - Initialize a validation context 1948c2ecf20Sopenharmony_ci * @ctx: Pointer to the validation context to initialize 1958c2ecf20Sopenharmony_ci * 1968c2ecf20Sopenharmony_ci * This function initializes a validation context with @merge_dups set 1978c2ecf20Sopenharmony_ci * to false 1988c2ecf20Sopenharmony_ci */ 1998c2ecf20Sopenharmony_cistatic inline void 2008c2ecf20Sopenharmony_civmw_validation_context_init(struct vmw_validation_context *ctx) 2018c2ecf20Sopenharmony_ci{ 2028c2ecf20Sopenharmony_ci memset(ctx, 0, sizeof(*ctx)); 2038c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&ctx->resource_list); 2048c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&ctx->resource_ctx_list); 2058c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&ctx->bo_list); 2068c2ecf20Sopenharmony_ci} 2078c2ecf20Sopenharmony_ci 2088c2ecf20Sopenharmony_ci/** 2098c2ecf20Sopenharmony_ci * vmw_validation_align - Align a validation memory allocation 2108c2ecf20Sopenharmony_ci * @val: The size to be aligned 2118c2ecf20Sopenharmony_ci * 2128c2ecf20Sopenharmony_ci * Returns: @val aligned to the granularity used by the validation memory 2138c2ecf20Sopenharmony_ci * allocator. 2148c2ecf20Sopenharmony_ci */ 2158c2ecf20Sopenharmony_cistatic inline unsigned int vmw_validation_align(unsigned int val) 2168c2ecf20Sopenharmony_ci{ 2178c2ecf20Sopenharmony_ci return ALIGN(val, sizeof(long)); 2188c2ecf20Sopenharmony_ci} 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_ciint vmw_validation_add_bo(struct vmw_validation_context *ctx, 2218c2ecf20Sopenharmony_ci struct vmw_buffer_object *vbo, 2228c2ecf20Sopenharmony_ci bool as_mob, bool cpu_blit); 2238c2ecf20Sopenharmony_ciint vmw_validation_bo_validate_single(struct ttm_buffer_object *bo, 2248c2ecf20Sopenharmony_ci bool interruptible, 2258c2ecf20Sopenharmony_ci bool validate_as_mob); 2268c2ecf20Sopenharmony_ciint vmw_validation_bo_validate(struct vmw_validation_context *ctx, bool intr); 2278c2ecf20Sopenharmony_civoid vmw_validation_unref_lists(struct vmw_validation_context *ctx); 2288c2ecf20Sopenharmony_ciint vmw_validation_add_resource(struct vmw_validation_context *ctx, 2298c2ecf20Sopenharmony_ci struct vmw_resource *res, 2308c2ecf20Sopenharmony_ci size_t priv_size, 2318c2ecf20Sopenharmony_ci u32 dirty, 2328c2ecf20Sopenharmony_ci void **p_node, 2338c2ecf20Sopenharmony_ci bool *first_usage); 2348c2ecf20Sopenharmony_civoid vmw_validation_drop_ht(struct vmw_validation_context *ctx); 2358c2ecf20Sopenharmony_ciint vmw_validation_res_reserve(struct vmw_validation_context *ctx, 2368c2ecf20Sopenharmony_ci bool intr); 2378c2ecf20Sopenharmony_civoid vmw_validation_res_unreserve(struct vmw_validation_context *ctx, 2388c2ecf20Sopenharmony_ci bool backoff); 2398c2ecf20Sopenharmony_civoid vmw_validation_res_switch_backup(struct vmw_validation_context *ctx, 2408c2ecf20Sopenharmony_ci void *val_private, 2418c2ecf20Sopenharmony_ci struct vmw_buffer_object *vbo, 2428c2ecf20Sopenharmony_ci unsigned long backup_offset); 2438c2ecf20Sopenharmony_ciint vmw_validation_res_validate(struct vmw_validation_context *ctx, bool intr); 2448c2ecf20Sopenharmony_ci 2458c2ecf20Sopenharmony_ciint vmw_validation_prepare(struct vmw_validation_context *ctx, 2468c2ecf20Sopenharmony_ci struct mutex *mutex, bool intr); 2478c2ecf20Sopenharmony_civoid vmw_validation_revert(struct vmw_validation_context *ctx); 2488c2ecf20Sopenharmony_civoid vmw_validation_done(struct vmw_validation_context *ctx, 2498c2ecf20Sopenharmony_ci struct vmw_fence_obj *fence); 2508c2ecf20Sopenharmony_ci 2518c2ecf20Sopenharmony_civoid *vmw_validation_mem_alloc(struct vmw_validation_context *ctx, 2528c2ecf20Sopenharmony_ci unsigned int size); 2538c2ecf20Sopenharmony_ciint vmw_validation_preload_bo(struct vmw_validation_context *ctx); 2548c2ecf20Sopenharmony_ciint vmw_validation_preload_res(struct vmw_validation_context *ctx, 2558c2ecf20Sopenharmony_ci unsigned int size); 2568c2ecf20Sopenharmony_civoid vmw_validation_res_set_dirty(struct vmw_validation_context *ctx, 2578c2ecf20Sopenharmony_ci void *val_private, u32 dirty); 2588c2ecf20Sopenharmony_civoid vmw_validation_bo_backoff(struct vmw_validation_context *ctx); 2598c2ecf20Sopenharmony_ci 2608c2ecf20Sopenharmony_ci#endif 261