18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 OR MIT 28c2ecf20Sopenharmony_ci/************************************************************************** 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Copyright 2009 - 2015 VMware, Inc., Palo Alto, CA., USA 58c2ecf20Sopenharmony_ci * 68c2ecf20Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 78c2ecf20Sopenharmony_ci * copy of this software and associated documentation files (the 88c2ecf20Sopenharmony_ci * "Software"), to deal in the Software without restriction, including 98c2ecf20Sopenharmony_ci * without limitation the rights to use, copy, modify, merge, publish, 108c2ecf20Sopenharmony_ci * distribute, sub license, and/or sell copies of the Software, and to 118c2ecf20Sopenharmony_ci * permit persons to whom the Software is furnished to do so, subject to 128c2ecf20Sopenharmony_ci * the following conditions: 138c2ecf20Sopenharmony_ci * 148c2ecf20Sopenharmony_ci * The above copyright notice and this permission notice (including the 158c2ecf20Sopenharmony_ci * next paragraph) shall be included in all copies or substantial portions 168c2ecf20Sopenharmony_ci * of the Software. 178c2ecf20Sopenharmony_ci * 188c2ecf20Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 198c2ecf20Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 208c2ecf20Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 218c2ecf20Sopenharmony_ci * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, 228c2ecf20Sopenharmony_ci * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 238c2ecf20Sopenharmony_ci * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 248c2ecf20Sopenharmony_ci * USE OR OTHER DEALINGS IN THE SOFTWARE. 258c2ecf20Sopenharmony_ci * 268c2ecf20Sopenharmony_ci **************************************************************************/ 278c2ecf20Sopenharmony_ci#include <linux/sync_file.h> 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci#include "vmwgfx_drv.h" 308c2ecf20Sopenharmony_ci#include "vmwgfx_reg.h" 318c2ecf20Sopenharmony_ci#include <drm/ttm/ttm_bo_api.h> 328c2ecf20Sopenharmony_ci#include <drm/ttm/ttm_placement.h> 338c2ecf20Sopenharmony_ci#include "vmwgfx_so.h" 348c2ecf20Sopenharmony_ci#include "vmwgfx_binding.h" 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_ci#define VMW_RES_HT_ORDER 12 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci/* 398c2ecf20Sopenharmony_ci * Helper macro to get dx_ctx_node if available otherwise print an error 408c2ecf20Sopenharmony_ci * message. This is for use in command verifier function where if dx_ctx_node 418c2ecf20Sopenharmony_ci * is not set then command is invalid. 428c2ecf20Sopenharmony_ci */ 438c2ecf20Sopenharmony_ci#define VMW_GET_CTX_NODE(__sw_context) \ 448c2ecf20Sopenharmony_ci({ \ 458c2ecf20Sopenharmony_ci __sw_context->dx_ctx_node ? __sw_context->dx_ctx_node : ({ \ 468c2ecf20Sopenharmony_ci VMW_DEBUG_USER("SM context is not set at %s\n", __func__); \ 478c2ecf20Sopenharmony_ci __sw_context->dx_ctx_node; \ 488c2ecf20Sopenharmony_ci }); \ 498c2ecf20Sopenharmony_ci}) 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_ci#define VMW_DECLARE_CMD_VAR(__var, __type) \ 528c2ecf20Sopenharmony_ci struct { \ 538c2ecf20Sopenharmony_ci SVGA3dCmdHeader header; \ 548c2ecf20Sopenharmony_ci __type body; \ 558c2ecf20Sopenharmony_ci } __var 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_ci/** 588c2ecf20Sopenharmony_ci * struct vmw_relocation - Buffer object relocation 598c2ecf20Sopenharmony_ci * 608c2ecf20Sopenharmony_ci * @head: List head for the command submission context's relocation list 618c2ecf20Sopenharmony_ci * @vbo: Non ref-counted pointer to buffer object 628c2ecf20Sopenharmony_ci * @mob_loc: Pointer to location for mob id to be modified 638c2ecf20Sopenharmony_ci * @location: Pointer to location for guest pointer to be modified 648c2ecf20Sopenharmony_ci */ 658c2ecf20Sopenharmony_cistruct vmw_relocation { 668c2ecf20Sopenharmony_ci struct list_head head; 678c2ecf20Sopenharmony_ci struct vmw_buffer_object *vbo; 688c2ecf20Sopenharmony_ci union { 698c2ecf20Sopenharmony_ci SVGAMobId *mob_loc; 708c2ecf20Sopenharmony_ci SVGAGuestPtr *location; 718c2ecf20Sopenharmony_ci }; 728c2ecf20Sopenharmony_ci}; 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_ci/** 758c2ecf20Sopenharmony_ci * enum vmw_resource_relocation_type - Relocation type for resources 768c2ecf20Sopenharmony_ci * 778c2ecf20Sopenharmony_ci * @vmw_res_rel_normal: Traditional relocation. The resource id in the 788c2ecf20Sopenharmony_ci * command stream is replaced with the actual id after validation. 798c2ecf20Sopenharmony_ci * @vmw_res_rel_nop: NOP relocation. The command is unconditionally replaced 808c2ecf20Sopenharmony_ci * with a NOP. 818c2ecf20Sopenharmony_ci * @vmw_res_rel_cond_nop: Conditional NOP relocation. If the resource id after 828c2ecf20Sopenharmony_ci * validation is -1, the command is replaced with a NOP. Otherwise no action. 838c2ecf20Sopenharmony_ci */ 848c2ecf20Sopenharmony_cienum vmw_resource_relocation_type { 858c2ecf20Sopenharmony_ci vmw_res_rel_normal, 868c2ecf20Sopenharmony_ci vmw_res_rel_nop, 878c2ecf20Sopenharmony_ci vmw_res_rel_cond_nop, 888c2ecf20Sopenharmony_ci vmw_res_rel_max 898c2ecf20Sopenharmony_ci}; 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_ci/** 928c2ecf20Sopenharmony_ci * struct vmw_resource_relocation - Relocation info for resources 938c2ecf20Sopenharmony_ci * 948c2ecf20Sopenharmony_ci * @head: List head for the software context's relocation list. 958c2ecf20Sopenharmony_ci * @res: Non-ref-counted pointer to the resource. 968c2ecf20Sopenharmony_ci * @offset: Offset of single byte entries into the command buffer where the id 978c2ecf20Sopenharmony_ci * that needs fixup is located. 988c2ecf20Sopenharmony_ci * @rel_type: Type of relocation. 998c2ecf20Sopenharmony_ci */ 1008c2ecf20Sopenharmony_cistruct vmw_resource_relocation { 1018c2ecf20Sopenharmony_ci struct list_head head; 1028c2ecf20Sopenharmony_ci const struct vmw_resource *res; 1038c2ecf20Sopenharmony_ci u32 offset:29; 1048c2ecf20Sopenharmony_ci enum vmw_resource_relocation_type rel_type:3; 1058c2ecf20Sopenharmony_ci}; 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_ci/** 1088c2ecf20Sopenharmony_ci * struct vmw_ctx_validation_info - Extra validation metadata for contexts 1098c2ecf20Sopenharmony_ci * 1108c2ecf20Sopenharmony_ci * @head: List head of context list 1118c2ecf20Sopenharmony_ci * @ctx: The context resource 1128c2ecf20Sopenharmony_ci * @cur: The context's persistent binding state 1138c2ecf20Sopenharmony_ci * @staged: The binding state changes of this command buffer 1148c2ecf20Sopenharmony_ci */ 1158c2ecf20Sopenharmony_cistruct vmw_ctx_validation_info { 1168c2ecf20Sopenharmony_ci struct list_head head; 1178c2ecf20Sopenharmony_ci struct vmw_resource *ctx; 1188c2ecf20Sopenharmony_ci struct vmw_ctx_binding_state *cur; 1198c2ecf20Sopenharmony_ci struct vmw_ctx_binding_state *staged; 1208c2ecf20Sopenharmony_ci}; 1218c2ecf20Sopenharmony_ci 1228c2ecf20Sopenharmony_ci/** 1238c2ecf20Sopenharmony_ci * struct vmw_cmd_entry - Describe a command for the verifier 1248c2ecf20Sopenharmony_ci * 1258c2ecf20Sopenharmony_ci * @user_allow: Whether allowed from the execbuf ioctl. 1268c2ecf20Sopenharmony_ci * @gb_disable: Whether disabled if guest-backed objects are available. 1278c2ecf20Sopenharmony_ci * @gb_enable: Whether enabled iff guest-backed objects are available. 1288c2ecf20Sopenharmony_ci */ 1298c2ecf20Sopenharmony_cistruct vmw_cmd_entry { 1308c2ecf20Sopenharmony_ci int (*func) (struct vmw_private *, struct vmw_sw_context *, 1318c2ecf20Sopenharmony_ci SVGA3dCmdHeader *); 1328c2ecf20Sopenharmony_ci bool user_allow; 1338c2ecf20Sopenharmony_ci bool gb_disable; 1348c2ecf20Sopenharmony_ci bool gb_enable; 1358c2ecf20Sopenharmony_ci const char *cmd_name; 1368c2ecf20Sopenharmony_ci}; 1378c2ecf20Sopenharmony_ci 1388c2ecf20Sopenharmony_ci#define VMW_CMD_DEF(_cmd, _func, _user_allow, _gb_disable, _gb_enable) \ 1398c2ecf20Sopenharmony_ci [(_cmd) - SVGA_3D_CMD_BASE] = {(_func), (_user_allow),\ 1408c2ecf20Sopenharmony_ci (_gb_disable), (_gb_enable), #_cmd} 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_cistatic int vmw_resource_context_res_add(struct vmw_private *dev_priv, 1438c2ecf20Sopenharmony_ci struct vmw_sw_context *sw_context, 1448c2ecf20Sopenharmony_ci struct vmw_resource *ctx); 1458c2ecf20Sopenharmony_cistatic int vmw_translate_mob_ptr(struct vmw_private *dev_priv, 1468c2ecf20Sopenharmony_ci struct vmw_sw_context *sw_context, 1478c2ecf20Sopenharmony_ci SVGAMobId *id, 1488c2ecf20Sopenharmony_ci struct vmw_buffer_object **vmw_bo_p); 1498c2ecf20Sopenharmony_ci/** 1508c2ecf20Sopenharmony_ci * vmw_ptr_diff - Compute the offset from a to b in bytes 1518c2ecf20Sopenharmony_ci * 1528c2ecf20Sopenharmony_ci * @a: A starting pointer. 1538c2ecf20Sopenharmony_ci * @b: A pointer offset in the same address space. 1548c2ecf20Sopenharmony_ci * 1558c2ecf20Sopenharmony_ci * Returns: The offset in bytes between the two pointers. 1568c2ecf20Sopenharmony_ci */ 1578c2ecf20Sopenharmony_cistatic size_t vmw_ptr_diff(void *a, void *b) 1588c2ecf20Sopenharmony_ci{ 1598c2ecf20Sopenharmony_ci return (unsigned long) b - (unsigned long) a; 1608c2ecf20Sopenharmony_ci} 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_ci/** 1638c2ecf20Sopenharmony_ci * vmw_execbuf_bindings_commit - Commit modified binding state 1648c2ecf20Sopenharmony_ci * 1658c2ecf20Sopenharmony_ci * @sw_context: The command submission context 1668c2ecf20Sopenharmony_ci * @backoff: Whether this is part of the error path and binding state changes 1678c2ecf20Sopenharmony_ci * should be ignored 1688c2ecf20Sopenharmony_ci */ 1698c2ecf20Sopenharmony_cistatic void vmw_execbuf_bindings_commit(struct vmw_sw_context *sw_context, 1708c2ecf20Sopenharmony_ci bool backoff) 1718c2ecf20Sopenharmony_ci{ 1728c2ecf20Sopenharmony_ci struct vmw_ctx_validation_info *entry; 1738c2ecf20Sopenharmony_ci 1748c2ecf20Sopenharmony_ci list_for_each_entry(entry, &sw_context->ctx_list, head) { 1758c2ecf20Sopenharmony_ci if (!backoff) 1768c2ecf20Sopenharmony_ci vmw_binding_state_commit(entry->cur, entry->staged); 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_ci if (entry->staged != sw_context->staged_bindings) 1798c2ecf20Sopenharmony_ci vmw_binding_state_free(entry->staged); 1808c2ecf20Sopenharmony_ci else 1818c2ecf20Sopenharmony_ci sw_context->staged_bindings_inuse = false; 1828c2ecf20Sopenharmony_ci } 1838c2ecf20Sopenharmony_ci 1848c2ecf20Sopenharmony_ci /* List entries are freed with the validation context */ 1858c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&sw_context->ctx_list); 1868c2ecf20Sopenharmony_ci} 1878c2ecf20Sopenharmony_ci 1888c2ecf20Sopenharmony_ci/** 1898c2ecf20Sopenharmony_ci * vmw_bind_dx_query_mob - Bind the DX query MOB if referenced 1908c2ecf20Sopenharmony_ci * 1918c2ecf20Sopenharmony_ci * @sw_context: The command submission context 1928c2ecf20Sopenharmony_ci */ 1938c2ecf20Sopenharmony_cistatic void vmw_bind_dx_query_mob(struct vmw_sw_context *sw_context) 1948c2ecf20Sopenharmony_ci{ 1958c2ecf20Sopenharmony_ci if (sw_context->dx_query_mob) 1968c2ecf20Sopenharmony_ci vmw_context_bind_dx_query(sw_context->dx_query_ctx, 1978c2ecf20Sopenharmony_ci sw_context->dx_query_mob); 1988c2ecf20Sopenharmony_ci} 1998c2ecf20Sopenharmony_ci 2008c2ecf20Sopenharmony_ci/** 2018c2ecf20Sopenharmony_ci * vmw_cmd_ctx_first_setup - Perform the setup needed when a context is added to 2028c2ecf20Sopenharmony_ci * the validate list. 2038c2ecf20Sopenharmony_ci * 2048c2ecf20Sopenharmony_ci * @dev_priv: Pointer to the device private: 2058c2ecf20Sopenharmony_ci * @sw_context: The command submission context 2068c2ecf20Sopenharmony_ci * @node: The validation node holding the context resource metadata 2078c2ecf20Sopenharmony_ci */ 2088c2ecf20Sopenharmony_cistatic int vmw_cmd_ctx_first_setup(struct vmw_private *dev_priv, 2098c2ecf20Sopenharmony_ci struct vmw_sw_context *sw_context, 2108c2ecf20Sopenharmony_ci struct vmw_resource *res, 2118c2ecf20Sopenharmony_ci struct vmw_ctx_validation_info *node) 2128c2ecf20Sopenharmony_ci{ 2138c2ecf20Sopenharmony_ci int ret; 2148c2ecf20Sopenharmony_ci 2158c2ecf20Sopenharmony_ci ret = vmw_resource_context_res_add(dev_priv, sw_context, res); 2168c2ecf20Sopenharmony_ci if (unlikely(ret != 0)) 2178c2ecf20Sopenharmony_ci goto out_err; 2188c2ecf20Sopenharmony_ci 2198c2ecf20Sopenharmony_ci if (!sw_context->staged_bindings) { 2208c2ecf20Sopenharmony_ci sw_context->staged_bindings = vmw_binding_state_alloc(dev_priv); 2218c2ecf20Sopenharmony_ci if (IS_ERR(sw_context->staged_bindings)) { 2228c2ecf20Sopenharmony_ci ret = PTR_ERR(sw_context->staged_bindings); 2238c2ecf20Sopenharmony_ci sw_context->staged_bindings = NULL; 2248c2ecf20Sopenharmony_ci goto out_err; 2258c2ecf20Sopenharmony_ci } 2268c2ecf20Sopenharmony_ci } 2278c2ecf20Sopenharmony_ci 2288c2ecf20Sopenharmony_ci if (sw_context->staged_bindings_inuse) { 2298c2ecf20Sopenharmony_ci node->staged = vmw_binding_state_alloc(dev_priv); 2308c2ecf20Sopenharmony_ci if (IS_ERR(node->staged)) { 2318c2ecf20Sopenharmony_ci ret = PTR_ERR(node->staged); 2328c2ecf20Sopenharmony_ci node->staged = NULL; 2338c2ecf20Sopenharmony_ci goto out_err; 2348c2ecf20Sopenharmony_ci } 2358c2ecf20Sopenharmony_ci } else { 2368c2ecf20Sopenharmony_ci node->staged = sw_context->staged_bindings; 2378c2ecf20Sopenharmony_ci sw_context->staged_bindings_inuse = true; 2388c2ecf20Sopenharmony_ci } 2398c2ecf20Sopenharmony_ci 2408c2ecf20Sopenharmony_ci node->ctx = res; 2418c2ecf20Sopenharmony_ci node->cur = vmw_context_binding_state(res); 2428c2ecf20Sopenharmony_ci list_add_tail(&node->head, &sw_context->ctx_list); 2438c2ecf20Sopenharmony_ci 2448c2ecf20Sopenharmony_ci return 0; 2458c2ecf20Sopenharmony_ci 2468c2ecf20Sopenharmony_ciout_err: 2478c2ecf20Sopenharmony_ci return ret; 2488c2ecf20Sopenharmony_ci} 2498c2ecf20Sopenharmony_ci 2508c2ecf20Sopenharmony_ci/** 2518c2ecf20Sopenharmony_ci * vmw_execbuf_res_size - calculate extra size fore the resource validation node 2528c2ecf20Sopenharmony_ci * 2538c2ecf20Sopenharmony_ci * @dev_priv: Pointer to the device private struct. 2548c2ecf20Sopenharmony_ci * @res_type: The resource type. 2558c2ecf20Sopenharmony_ci * 2568c2ecf20Sopenharmony_ci * Guest-backed contexts and DX contexts require extra size to store execbuf 2578c2ecf20Sopenharmony_ci * private information in the validation node. Typically the binding manager 2588c2ecf20Sopenharmony_ci * associated data structures. 2598c2ecf20Sopenharmony_ci * 2608c2ecf20Sopenharmony_ci * Returns: The extra size requirement based on resource type. 2618c2ecf20Sopenharmony_ci */ 2628c2ecf20Sopenharmony_cistatic unsigned int vmw_execbuf_res_size(struct vmw_private *dev_priv, 2638c2ecf20Sopenharmony_ci enum vmw_res_type res_type) 2648c2ecf20Sopenharmony_ci{ 2658c2ecf20Sopenharmony_ci return (res_type == vmw_res_dx_context || 2668c2ecf20Sopenharmony_ci (res_type == vmw_res_context && dev_priv->has_mob)) ? 2678c2ecf20Sopenharmony_ci sizeof(struct vmw_ctx_validation_info) : 0; 2688c2ecf20Sopenharmony_ci} 2698c2ecf20Sopenharmony_ci 2708c2ecf20Sopenharmony_ci/** 2718c2ecf20Sopenharmony_ci * vmw_execbuf_rcache_update - Update a resource-node cache entry 2728c2ecf20Sopenharmony_ci * 2738c2ecf20Sopenharmony_ci * @rcache: Pointer to the entry to update. 2748c2ecf20Sopenharmony_ci * @res: Pointer to the resource. 2758c2ecf20Sopenharmony_ci * @private: Pointer to the execbuf-private space in the resource validation 2768c2ecf20Sopenharmony_ci * node. 2778c2ecf20Sopenharmony_ci */ 2788c2ecf20Sopenharmony_cistatic void vmw_execbuf_rcache_update(struct vmw_res_cache_entry *rcache, 2798c2ecf20Sopenharmony_ci struct vmw_resource *res, 2808c2ecf20Sopenharmony_ci void *private) 2818c2ecf20Sopenharmony_ci{ 2828c2ecf20Sopenharmony_ci rcache->res = res; 2838c2ecf20Sopenharmony_ci rcache->private = private; 2848c2ecf20Sopenharmony_ci rcache->valid = 1; 2858c2ecf20Sopenharmony_ci rcache->valid_handle = 0; 2868c2ecf20Sopenharmony_ci} 2878c2ecf20Sopenharmony_ci 2888c2ecf20Sopenharmony_ci/** 2898c2ecf20Sopenharmony_ci * vmw_execbuf_res_noref_val_add - Add a resource described by an unreferenced 2908c2ecf20Sopenharmony_ci * rcu-protected pointer to the validation list. 2918c2ecf20Sopenharmony_ci * 2928c2ecf20Sopenharmony_ci * @sw_context: Pointer to the software context. 2938c2ecf20Sopenharmony_ci * @res: Unreferenced rcu-protected pointer to the resource. 2948c2ecf20Sopenharmony_ci * @dirty: Whether to change dirty status. 2958c2ecf20Sopenharmony_ci * 2968c2ecf20Sopenharmony_ci * Returns: 0 on success. Negative error code on failure. Typical error codes 2978c2ecf20Sopenharmony_ci * are %-EINVAL on inconsistency and %-ESRCH if the resource was doomed. 2988c2ecf20Sopenharmony_ci */ 2998c2ecf20Sopenharmony_cistatic int vmw_execbuf_res_noref_val_add(struct vmw_sw_context *sw_context, 3008c2ecf20Sopenharmony_ci struct vmw_resource *res, 3018c2ecf20Sopenharmony_ci u32 dirty) 3028c2ecf20Sopenharmony_ci{ 3038c2ecf20Sopenharmony_ci struct vmw_private *dev_priv = res->dev_priv; 3048c2ecf20Sopenharmony_ci int ret; 3058c2ecf20Sopenharmony_ci enum vmw_res_type res_type = vmw_res_type(res); 3068c2ecf20Sopenharmony_ci struct vmw_res_cache_entry *rcache; 3078c2ecf20Sopenharmony_ci struct vmw_ctx_validation_info *ctx_info; 3088c2ecf20Sopenharmony_ci bool first_usage; 3098c2ecf20Sopenharmony_ci unsigned int priv_size; 3108c2ecf20Sopenharmony_ci 3118c2ecf20Sopenharmony_ci rcache = &sw_context->res_cache[res_type]; 3128c2ecf20Sopenharmony_ci if (likely(rcache->valid && rcache->res == res)) { 3138c2ecf20Sopenharmony_ci if (dirty) 3148c2ecf20Sopenharmony_ci vmw_validation_res_set_dirty(sw_context->ctx, 3158c2ecf20Sopenharmony_ci rcache->private, dirty); 3168c2ecf20Sopenharmony_ci vmw_user_resource_noref_release(); 3178c2ecf20Sopenharmony_ci return 0; 3188c2ecf20Sopenharmony_ci } 3198c2ecf20Sopenharmony_ci 3208c2ecf20Sopenharmony_ci priv_size = vmw_execbuf_res_size(dev_priv, res_type); 3218c2ecf20Sopenharmony_ci ret = vmw_validation_add_resource(sw_context->ctx, res, priv_size, 3228c2ecf20Sopenharmony_ci dirty, (void **)&ctx_info, 3238c2ecf20Sopenharmony_ci &first_usage); 3248c2ecf20Sopenharmony_ci vmw_user_resource_noref_release(); 3258c2ecf20Sopenharmony_ci if (ret) 3268c2ecf20Sopenharmony_ci return ret; 3278c2ecf20Sopenharmony_ci 3288c2ecf20Sopenharmony_ci if (priv_size && first_usage) { 3298c2ecf20Sopenharmony_ci ret = vmw_cmd_ctx_first_setup(dev_priv, sw_context, res, 3308c2ecf20Sopenharmony_ci ctx_info); 3318c2ecf20Sopenharmony_ci if (ret) { 3328c2ecf20Sopenharmony_ci VMW_DEBUG_USER("Failed first usage context setup.\n"); 3338c2ecf20Sopenharmony_ci return ret; 3348c2ecf20Sopenharmony_ci } 3358c2ecf20Sopenharmony_ci } 3368c2ecf20Sopenharmony_ci 3378c2ecf20Sopenharmony_ci vmw_execbuf_rcache_update(rcache, res, ctx_info); 3388c2ecf20Sopenharmony_ci return 0; 3398c2ecf20Sopenharmony_ci} 3408c2ecf20Sopenharmony_ci 3418c2ecf20Sopenharmony_ci/** 3428c2ecf20Sopenharmony_ci * vmw_execbuf_res_noctx_val_add - Add a non-context resource to the resource 3438c2ecf20Sopenharmony_ci * validation list if it's not already on it 3448c2ecf20Sopenharmony_ci * 3458c2ecf20Sopenharmony_ci * @sw_context: Pointer to the software context. 3468c2ecf20Sopenharmony_ci * @res: Pointer to the resource. 3478c2ecf20Sopenharmony_ci * @dirty: Whether to change dirty status. 3488c2ecf20Sopenharmony_ci * 3498c2ecf20Sopenharmony_ci * Returns: Zero on success. Negative error code on failure. 3508c2ecf20Sopenharmony_ci */ 3518c2ecf20Sopenharmony_cistatic int vmw_execbuf_res_noctx_val_add(struct vmw_sw_context *sw_context, 3528c2ecf20Sopenharmony_ci struct vmw_resource *res, 3538c2ecf20Sopenharmony_ci u32 dirty) 3548c2ecf20Sopenharmony_ci{ 3558c2ecf20Sopenharmony_ci struct vmw_res_cache_entry *rcache; 3568c2ecf20Sopenharmony_ci enum vmw_res_type res_type = vmw_res_type(res); 3578c2ecf20Sopenharmony_ci void *ptr; 3588c2ecf20Sopenharmony_ci int ret; 3598c2ecf20Sopenharmony_ci 3608c2ecf20Sopenharmony_ci rcache = &sw_context->res_cache[res_type]; 3618c2ecf20Sopenharmony_ci if (likely(rcache->valid && rcache->res == res)) { 3628c2ecf20Sopenharmony_ci if (dirty) 3638c2ecf20Sopenharmony_ci vmw_validation_res_set_dirty(sw_context->ctx, 3648c2ecf20Sopenharmony_ci rcache->private, dirty); 3658c2ecf20Sopenharmony_ci return 0; 3668c2ecf20Sopenharmony_ci } 3678c2ecf20Sopenharmony_ci 3688c2ecf20Sopenharmony_ci ret = vmw_validation_add_resource(sw_context->ctx, res, 0, dirty, 3698c2ecf20Sopenharmony_ci &ptr, NULL); 3708c2ecf20Sopenharmony_ci if (ret) 3718c2ecf20Sopenharmony_ci return ret; 3728c2ecf20Sopenharmony_ci 3738c2ecf20Sopenharmony_ci vmw_execbuf_rcache_update(rcache, res, ptr); 3748c2ecf20Sopenharmony_ci 3758c2ecf20Sopenharmony_ci return 0; 3768c2ecf20Sopenharmony_ci} 3778c2ecf20Sopenharmony_ci 3788c2ecf20Sopenharmony_ci/** 3798c2ecf20Sopenharmony_ci * vmw_view_res_val_add - Add a view and the surface it's pointing to to the 3808c2ecf20Sopenharmony_ci * validation list 3818c2ecf20Sopenharmony_ci * 3828c2ecf20Sopenharmony_ci * @sw_context: The software context holding the validation list. 3838c2ecf20Sopenharmony_ci * @view: Pointer to the view resource. 3848c2ecf20Sopenharmony_ci * 3858c2ecf20Sopenharmony_ci * Returns 0 if success, negative error code otherwise. 3868c2ecf20Sopenharmony_ci */ 3878c2ecf20Sopenharmony_cistatic int vmw_view_res_val_add(struct vmw_sw_context *sw_context, 3888c2ecf20Sopenharmony_ci struct vmw_resource *view) 3898c2ecf20Sopenharmony_ci{ 3908c2ecf20Sopenharmony_ci int ret; 3918c2ecf20Sopenharmony_ci 3928c2ecf20Sopenharmony_ci /* 3938c2ecf20Sopenharmony_ci * First add the resource the view is pointing to, otherwise it may be 3948c2ecf20Sopenharmony_ci * swapped out when the view is validated. 3958c2ecf20Sopenharmony_ci */ 3968c2ecf20Sopenharmony_ci ret = vmw_execbuf_res_noctx_val_add(sw_context, vmw_view_srf(view), 3978c2ecf20Sopenharmony_ci vmw_view_dirtying(view)); 3988c2ecf20Sopenharmony_ci if (ret) 3998c2ecf20Sopenharmony_ci return ret; 4008c2ecf20Sopenharmony_ci 4018c2ecf20Sopenharmony_ci return vmw_execbuf_res_noctx_val_add(sw_context, view, 4028c2ecf20Sopenharmony_ci VMW_RES_DIRTY_NONE); 4038c2ecf20Sopenharmony_ci} 4048c2ecf20Sopenharmony_ci 4058c2ecf20Sopenharmony_ci/** 4068c2ecf20Sopenharmony_ci * vmw_view_id_val_add - Look up a view and add it and the surface it's pointing 4078c2ecf20Sopenharmony_ci * to to the validation list. 4088c2ecf20Sopenharmony_ci * 4098c2ecf20Sopenharmony_ci * @sw_context: The software context holding the validation list. 4108c2ecf20Sopenharmony_ci * @view_type: The view type to look up. 4118c2ecf20Sopenharmony_ci * @id: view id of the view. 4128c2ecf20Sopenharmony_ci * 4138c2ecf20Sopenharmony_ci * The view is represented by a view id and the DX context it's created on, or 4148c2ecf20Sopenharmony_ci * scheduled for creation on. If there is no DX context set, the function will 4158c2ecf20Sopenharmony_ci * return an -EINVAL error pointer. 4168c2ecf20Sopenharmony_ci * 4178c2ecf20Sopenharmony_ci * Returns: Unreferenced pointer to the resource on success, negative error 4188c2ecf20Sopenharmony_ci * pointer on failure. 4198c2ecf20Sopenharmony_ci */ 4208c2ecf20Sopenharmony_cistatic struct vmw_resource * 4218c2ecf20Sopenharmony_civmw_view_id_val_add(struct vmw_sw_context *sw_context, 4228c2ecf20Sopenharmony_ci enum vmw_view_type view_type, u32 id) 4238c2ecf20Sopenharmony_ci{ 4248c2ecf20Sopenharmony_ci struct vmw_ctx_validation_info *ctx_node = sw_context->dx_ctx_node; 4258c2ecf20Sopenharmony_ci struct vmw_resource *view; 4268c2ecf20Sopenharmony_ci int ret; 4278c2ecf20Sopenharmony_ci 4288c2ecf20Sopenharmony_ci if (!ctx_node) 4298c2ecf20Sopenharmony_ci return ERR_PTR(-EINVAL); 4308c2ecf20Sopenharmony_ci 4318c2ecf20Sopenharmony_ci view = vmw_view_lookup(sw_context->man, view_type, id); 4328c2ecf20Sopenharmony_ci if (IS_ERR(view)) 4338c2ecf20Sopenharmony_ci return view; 4348c2ecf20Sopenharmony_ci 4358c2ecf20Sopenharmony_ci ret = vmw_view_res_val_add(sw_context, view); 4368c2ecf20Sopenharmony_ci if (ret) 4378c2ecf20Sopenharmony_ci return ERR_PTR(ret); 4388c2ecf20Sopenharmony_ci 4398c2ecf20Sopenharmony_ci return view; 4408c2ecf20Sopenharmony_ci} 4418c2ecf20Sopenharmony_ci 4428c2ecf20Sopenharmony_ci/** 4438c2ecf20Sopenharmony_ci * vmw_resource_context_res_add - Put resources previously bound to a context on 4448c2ecf20Sopenharmony_ci * the validation list 4458c2ecf20Sopenharmony_ci * 4468c2ecf20Sopenharmony_ci * @dev_priv: Pointer to a device private structure 4478c2ecf20Sopenharmony_ci * @sw_context: Pointer to a software context used for this command submission 4488c2ecf20Sopenharmony_ci * @ctx: Pointer to the context resource 4498c2ecf20Sopenharmony_ci * 4508c2ecf20Sopenharmony_ci * This function puts all resources that were previously bound to @ctx on the 4518c2ecf20Sopenharmony_ci * resource validation list. This is part of the context state reemission 4528c2ecf20Sopenharmony_ci */ 4538c2ecf20Sopenharmony_cistatic int vmw_resource_context_res_add(struct vmw_private *dev_priv, 4548c2ecf20Sopenharmony_ci struct vmw_sw_context *sw_context, 4558c2ecf20Sopenharmony_ci struct vmw_resource *ctx) 4568c2ecf20Sopenharmony_ci{ 4578c2ecf20Sopenharmony_ci struct list_head *binding_list; 4588c2ecf20Sopenharmony_ci struct vmw_ctx_bindinfo *entry; 4598c2ecf20Sopenharmony_ci int ret = 0; 4608c2ecf20Sopenharmony_ci struct vmw_resource *res; 4618c2ecf20Sopenharmony_ci u32 i; 4628c2ecf20Sopenharmony_ci u32 cotable_max = has_sm5_context(ctx->dev_priv) ? 4638c2ecf20Sopenharmony_ci SVGA_COTABLE_MAX : SVGA_COTABLE_DX10_MAX; 4648c2ecf20Sopenharmony_ci 4658c2ecf20Sopenharmony_ci /* Add all cotables to the validation list. */ 4668c2ecf20Sopenharmony_ci if (has_sm4_context(dev_priv) && 4678c2ecf20Sopenharmony_ci vmw_res_type(ctx) == vmw_res_dx_context) { 4688c2ecf20Sopenharmony_ci for (i = 0; i < cotable_max; ++i) { 4698c2ecf20Sopenharmony_ci res = vmw_context_cotable(ctx, i); 4708c2ecf20Sopenharmony_ci if (IS_ERR(res)) 4718c2ecf20Sopenharmony_ci continue; 4728c2ecf20Sopenharmony_ci 4738c2ecf20Sopenharmony_ci ret = vmw_execbuf_res_noctx_val_add(sw_context, res, 4748c2ecf20Sopenharmony_ci VMW_RES_DIRTY_SET); 4758c2ecf20Sopenharmony_ci if (unlikely(ret != 0)) 4768c2ecf20Sopenharmony_ci return ret; 4778c2ecf20Sopenharmony_ci } 4788c2ecf20Sopenharmony_ci } 4798c2ecf20Sopenharmony_ci 4808c2ecf20Sopenharmony_ci /* Add all resources bound to the context to the validation list */ 4818c2ecf20Sopenharmony_ci mutex_lock(&dev_priv->binding_mutex); 4828c2ecf20Sopenharmony_ci binding_list = vmw_context_binding_list(ctx); 4838c2ecf20Sopenharmony_ci 4848c2ecf20Sopenharmony_ci list_for_each_entry(entry, binding_list, ctx_list) { 4858c2ecf20Sopenharmony_ci if (vmw_res_type(entry->res) == vmw_res_view) 4868c2ecf20Sopenharmony_ci ret = vmw_view_res_val_add(sw_context, entry->res); 4878c2ecf20Sopenharmony_ci else 4888c2ecf20Sopenharmony_ci ret = vmw_execbuf_res_noctx_val_add 4898c2ecf20Sopenharmony_ci (sw_context, entry->res, 4908c2ecf20Sopenharmony_ci vmw_binding_dirtying(entry->bt)); 4918c2ecf20Sopenharmony_ci if (unlikely(ret != 0)) 4928c2ecf20Sopenharmony_ci break; 4938c2ecf20Sopenharmony_ci } 4948c2ecf20Sopenharmony_ci 4958c2ecf20Sopenharmony_ci if (has_sm4_context(dev_priv) && 4968c2ecf20Sopenharmony_ci vmw_res_type(ctx) == vmw_res_dx_context) { 4978c2ecf20Sopenharmony_ci struct vmw_buffer_object *dx_query_mob; 4988c2ecf20Sopenharmony_ci 4998c2ecf20Sopenharmony_ci dx_query_mob = vmw_context_get_dx_query_mob(ctx); 5008c2ecf20Sopenharmony_ci if (dx_query_mob) 5018c2ecf20Sopenharmony_ci ret = vmw_validation_add_bo(sw_context->ctx, 5028c2ecf20Sopenharmony_ci dx_query_mob, true, false); 5038c2ecf20Sopenharmony_ci } 5048c2ecf20Sopenharmony_ci 5058c2ecf20Sopenharmony_ci mutex_unlock(&dev_priv->binding_mutex); 5068c2ecf20Sopenharmony_ci return ret; 5078c2ecf20Sopenharmony_ci} 5088c2ecf20Sopenharmony_ci 5098c2ecf20Sopenharmony_ci/** 5108c2ecf20Sopenharmony_ci * vmw_resource_relocation_add - Add a relocation to the relocation list 5118c2ecf20Sopenharmony_ci * 5128c2ecf20Sopenharmony_ci * @list: Pointer to head of relocation list. 5138c2ecf20Sopenharmony_ci * @res: The resource. 5148c2ecf20Sopenharmony_ci * @offset: Offset into the command buffer currently being parsed where the id 5158c2ecf20Sopenharmony_ci * that needs fixup is located. Granularity is one byte. 5168c2ecf20Sopenharmony_ci * @rel_type: Relocation type. 5178c2ecf20Sopenharmony_ci */ 5188c2ecf20Sopenharmony_cistatic int vmw_resource_relocation_add(struct vmw_sw_context *sw_context, 5198c2ecf20Sopenharmony_ci const struct vmw_resource *res, 5208c2ecf20Sopenharmony_ci unsigned long offset, 5218c2ecf20Sopenharmony_ci enum vmw_resource_relocation_type 5228c2ecf20Sopenharmony_ci rel_type) 5238c2ecf20Sopenharmony_ci{ 5248c2ecf20Sopenharmony_ci struct vmw_resource_relocation *rel; 5258c2ecf20Sopenharmony_ci 5268c2ecf20Sopenharmony_ci rel = vmw_validation_mem_alloc(sw_context->ctx, sizeof(*rel)); 5278c2ecf20Sopenharmony_ci if (unlikely(!rel)) { 5288c2ecf20Sopenharmony_ci VMW_DEBUG_USER("Failed to allocate a resource relocation.\n"); 5298c2ecf20Sopenharmony_ci return -ENOMEM; 5308c2ecf20Sopenharmony_ci } 5318c2ecf20Sopenharmony_ci 5328c2ecf20Sopenharmony_ci rel->res = res; 5338c2ecf20Sopenharmony_ci rel->offset = offset; 5348c2ecf20Sopenharmony_ci rel->rel_type = rel_type; 5358c2ecf20Sopenharmony_ci list_add_tail(&rel->head, &sw_context->res_relocations); 5368c2ecf20Sopenharmony_ci 5378c2ecf20Sopenharmony_ci return 0; 5388c2ecf20Sopenharmony_ci} 5398c2ecf20Sopenharmony_ci 5408c2ecf20Sopenharmony_ci/** 5418c2ecf20Sopenharmony_ci * vmw_resource_relocations_free - Free all relocations on a list 5428c2ecf20Sopenharmony_ci * 5438c2ecf20Sopenharmony_ci * @list: Pointer to the head of the relocation list 5448c2ecf20Sopenharmony_ci */ 5458c2ecf20Sopenharmony_cistatic void vmw_resource_relocations_free(struct list_head *list) 5468c2ecf20Sopenharmony_ci{ 5478c2ecf20Sopenharmony_ci /* Memory is validation context memory, so no need to free it */ 5488c2ecf20Sopenharmony_ci INIT_LIST_HEAD(list); 5498c2ecf20Sopenharmony_ci} 5508c2ecf20Sopenharmony_ci 5518c2ecf20Sopenharmony_ci/** 5528c2ecf20Sopenharmony_ci * vmw_resource_relocations_apply - Apply all relocations on a list 5538c2ecf20Sopenharmony_ci * 5548c2ecf20Sopenharmony_ci * @cb: Pointer to the start of the command buffer bein patch. This need not be 5558c2ecf20Sopenharmony_ci * the same buffer as the one being parsed when the relocation list was built, 5568c2ecf20Sopenharmony_ci * but the contents must be the same modulo the resource ids. 5578c2ecf20Sopenharmony_ci * @list: Pointer to the head of the relocation list. 5588c2ecf20Sopenharmony_ci */ 5598c2ecf20Sopenharmony_cistatic void vmw_resource_relocations_apply(uint32_t *cb, 5608c2ecf20Sopenharmony_ci struct list_head *list) 5618c2ecf20Sopenharmony_ci{ 5628c2ecf20Sopenharmony_ci struct vmw_resource_relocation *rel; 5638c2ecf20Sopenharmony_ci 5648c2ecf20Sopenharmony_ci /* Validate the struct vmw_resource_relocation member size */ 5658c2ecf20Sopenharmony_ci BUILD_BUG_ON(SVGA_CB_MAX_SIZE >= (1 << 29)); 5668c2ecf20Sopenharmony_ci BUILD_BUG_ON(vmw_res_rel_max >= (1 << 3)); 5678c2ecf20Sopenharmony_ci 5688c2ecf20Sopenharmony_ci list_for_each_entry(rel, list, head) { 5698c2ecf20Sopenharmony_ci u32 *addr = (u32 *)((unsigned long) cb + rel->offset); 5708c2ecf20Sopenharmony_ci switch (rel->rel_type) { 5718c2ecf20Sopenharmony_ci case vmw_res_rel_normal: 5728c2ecf20Sopenharmony_ci *addr = rel->res->id; 5738c2ecf20Sopenharmony_ci break; 5748c2ecf20Sopenharmony_ci case vmw_res_rel_nop: 5758c2ecf20Sopenharmony_ci *addr = SVGA_3D_CMD_NOP; 5768c2ecf20Sopenharmony_ci break; 5778c2ecf20Sopenharmony_ci default: 5788c2ecf20Sopenharmony_ci if (rel->res->id == -1) 5798c2ecf20Sopenharmony_ci *addr = SVGA_3D_CMD_NOP; 5808c2ecf20Sopenharmony_ci break; 5818c2ecf20Sopenharmony_ci } 5828c2ecf20Sopenharmony_ci } 5838c2ecf20Sopenharmony_ci} 5848c2ecf20Sopenharmony_ci 5858c2ecf20Sopenharmony_cistatic int vmw_cmd_invalid(struct vmw_private *dev_priv, 5868c2ecf20Sopenharmony_ci struct vmw_sw_context *sw_context, 5878c2ecf20Sopenharmony_ci SVGA3dCmdHeader *header) 5888c2ecf20Sopenharmony_ci{ 5898c2ecf20Sopenharmony_ci return -EINVAL; 5908c2ecf20Sopenharmony_ci} 5918c2ecf20Sopenharmony_ci 5928c2ecf20Sopenharmony_cistatic int vmw_cmd_ok(struct vmw_private *dev_priv, 5938c2ecf20Sopenharmony_ci struct vmw_sw_context *sw_context, 5948c2ecf20Sopenharmony_ci SVGA3dCmdHeader *header) 5958c2ecf20Sopenharmony_ci{ 5968c2ecf20Sopenharmony_ci return 0; 5978c2ecf20Sopenharmony_ci} 5988c2ecf20Sopenharmony_ci 5998c2ecf20Sopenharmony_ci/** 6008c2ecf20Sopenharmony_ci * vmw_resources_reserve - Reserve all resources on the sw_context's resource 6018c2ecf20Sopenharmony_ci * list. 6028c2ecf20Sopenharmony_ci * 6038c2ecf20Sopenharmony_ci * @sw_context: Pointer to the software context. 6048c2ecf20Sopenharmony_ci * 6058c2ecf20Sopenharmony_ci * Note that since vmware's command submission currently is protected by the 6068c2ecf20Sopenharmony_ci * cmdbuf mutex, no fancy deadlock avoidance is required for resources, since 6078c2ecf20Sopenharmony_ci * only a single thread at once will attempt this. 6088c2ecf20Sopenharmony_ci */ 6098c2ecf20Sopenharmony_cistatic int vmw_resources_reserve(struct vmw_sw_context *sw_context) 6108c2ecf20Sopenharmony_ci{ 6118c2ecf20Sopenharmony_ci int ret; 6128c2ecf20Sopenharmony_ci 6138c2ecf20Sopenharmony_ci ret = vmw_validation_res_reserve(sw_context->ctx, true); 6148c2ecf20Sopenharmony_ci if (ret) 6158c2ecf20Sopenharmony_ci return ret; 6168c2ecf20Sopenharmony_ci 6178c2ecf20Sopenharmony_ci if (sw_context->dx_query_mob) { 6188c2ecf20Sopenharmony_ci struct vmw_buffer_object *expected_dx_query_mob; 6198c2ecf20Sopenharmony_ci 6208c2ecf20Sopenharmony_ci expected_dx_query_mob = 6218c2ecf20Sopenharmony_ci vmw_context_get_dx_query_mob(sw_context->dx_query_ctx); 6228c2ecf20Sopenharmony_ci if (expected_dx_query_mob && 6238c2ecf20Sopenharmony_ci expected_dx_query_mob != sw_context->dx_query_mob) { 6248c2ecf20Sopenharmony_ci ret = -EINVAL; 6258c2ecf20Sopenharmony_ci } 6268c2ecf20Sopenharmony_ci } 6278c2ecf20Sopenharmony_ci 6288c2ecf20Sopenharmony_ci return ret; 6298c2ecf20Sopenharmony_ci} 6308c2ecf20Sopenharmony_ci 6318c2ecf20Sopenharmony_ci/** 6328c2ecf20Sopenharmony_ci * vmw_cmd_res_check - Check that a resource is present and if so, put it on the 6338c2ecf20Sopenharmony_ci * resource validate list unless it's already there. 6348c2ecf20Sopenharmony_ci * 6358c2ecf20Sopenharmony_ci * @dev_priv: Pointer to a device private structure. 6368c2ecf20Sopenharmony_ci * @sw_context: Pointer to the software context. 6378c2ecf20Sopenharmony_ci * @res_type: Resource type. 6388c2ecf20Sopenharmony_ci * @dirty: Whether to change dirty status. 6398c2ecf20Sopenharmony_ci * @converter: User-space visisble type specific information. 6408c2ecf20Sopenharmony_ci * @id_loc: Pointer to the location in the command buffer currently being parsed 6418c2ecf20Sopenharmony_ci * from where the user-space resource id handle is located. 6428c2ecf20Sopenharmony_ci * @p_val: Pointer to pointer to resource validalidation node. Populated on 6438c2ecf20Sopenharmony_ci * exit. 6448c2ecf20Sopenharmony_ci */ 6458c2ecf20Sopenharmony_cistatic int 6468c2ecf20Sopenharmony_civmw_cmd_res_check(struct vmw_private *dev_priv, 6478c2ecf20Sopenharmony_ci struct vmw_sw_context *sw_context, 6488c2ecf20Sopenharmony_ci enum vmw_res_type res_type, 6498c2ecf20Sopenharmony_ci u32 dirty, 6508c2ecf20Sopenharmony_ci const struct vmw_user_resource_conv *converter, 6518c2ecf20Sopenharmony_ci uint32_t *id_loc, 6528c2ecf20Sopenharmony_ci struct vmw_resource **p_res) 6538c2ecf20Sopenharmony_ci{ 6548c2ecf20Sopenharmony_ci struct vmw_res_cache_entry *rcache = &sw_context->res_cache[res_type]; 6558c2ecf20Sopenharmony_ci struct vmw_resource *res; 6568c2ecf20Sopenharmony_ci int ret; 6578c2ecf20Sopenharmony_ci 6588c2ecf20Sopenharmony_ci if (p_res) 6598c2ecf20Sopenharmony_ci *p_res = NULL; 6608c2ecf20Sopenharmony_ci 6618c2ecf20Sopenharmony_ci if (*id_loc == SVGA3D_INVALID_ID) { 6628c2ecf20Sopenharmony_ci if (res_type == vmw_res_context) { 6638c2ecf20Sopenharmony_ci VMW_DEBUG_USER("Illegal context invalid id.\n"); 6648c2ecf20Sopenharmony_ci return -EINVAL; 6658c2ecf20Sopenharmony_ci } 6668c2ecf20Sopenharmony_ci return 0; 6678c2ecf20Sopenharmony_ci } 6688c2ecf20Sopenharmony_ci 6698c2ecf20Sopenharmony_ci if (likely(rcache->valid_handle && *id_loc == rcache->handle)) { 6708c2ecf20Sopenharmony_ci res = rcache->res; 6718c2ecf20Sopenharmony_ci if (dirty) 6728c2ecf20Sopenharmony_ci vmw_validation_res_set_dirty(sw_context->ctx, 6738c2ecf20Sopenharmony_ci rcache->private, dirty); 6748c2ecf20Sopenharmony_ci } else { 6758c2ecf20Sopenharmony_ci unsigned int size = vmw_execbuf_res_size(dev_priv, res_type); 6768c2ecf20Sopenharmony_ci 6778c2ecf20Sopenharmony_ci ret = vmw_validation_preload_res(sw_context->ctx, size); 6788c2ecf20Sopenharmony_ci if (ret) 6798c2ecf20Sopenharmony_ci return ret; 6808c2ecf20Sopenharmony_ci 6818c2ecf20Sopenharmony_ci res = vmw_user_resource_noref_lookup_handle 6828c2ecf20Sopenharmony_ci (dev_priv, sw_context->fp->tfile, *id_loc, converter); 6838c2ecf20Sopenharmony_ci if (IS_ERR(res)) { 6848c2ecf20Sopenharmony_ci VMW_DEBUG_USER("Could not find/use resource 0x%08x.\n", 6858c2ecf20Sopenharmony_ci (unsigned int) *id_loc); 6868c2ecf20Sopenharmony_ci return PTR_ERR(res); 6878c2ecf20Sopenharmony_ci } 6888c2ecf20Sopenharmony_ci 6898c2ecf20Sopenharmony_ci ret = vmw_execbuf_res_noref_val_add(sw_context, res, dirty); 6908c2ecf20Sopenharmony_ci if (unlikely(ret != 0)) 6918c2ecf20Sopenharmony_ci return ret; 6928c2ecf20Sopenharmony_ci 6938c2ecf20Sopenharmony_ci if (rcache->valid && rcache->res == res) { 6948c2ecf20Sopenharmony_ci rcache->valid_handle = true; 6958c2ecf20Sopenharmony_ci rcache->handle = *id_loc; 6968c2ecf20Sopenharmony_ci } 6978c2ecf20Sopenharmony_ci } 6988c2ecf20Sopenharmony_ci 6998c2ecf20Sopenharmony_ci ret = vmw_resource_relocation_add(sw_context, res, 7008c2ecf20Sopenharmony_ci vmw_ptr_diff(sw_context->buf_start, 7018c2ecf20Sopenharmony_ci id_loc), 7028c2ecf20Sopenharmony_ci vmw_res_rel_normal); 7038c2ecf20Sopenharmony_ci if (p_res) 7048c2ecf20Sopenharmony_ci *p_res = res; 7058c2ecf20Sopenharmony_ci 7068c2ecf20Sopenharmony_ci return 0; 7078c2ecf20Sopenharmony_ci} 7088c2ecf20Sopenharmony_ci 7098c2ecf20Sopenharmony_ci/** 7108c2ecf20Sopenharmony_ci * vmw_rebind_dx_query - Rebind DX query associated with the context 7118c2ecf20Sopenharmony_ci * 7128c2ecf20Sopenharmony_ci * @ctx_res: context the query belongs to 7138c2ecf20Sopenharmony_ci * 7148c2ecf20Sopenharmony_ci * This function assumes binding_mutex is held. 7158c2ecf20Sopenharmony_ci */ 7168c2ecf20Sopenharmony_cistatic int vmw_rebind_all_dx_query(struct vmw_resource *ctx_res) 7178c2ecf20Sopenharmony_ci{ 7188c2ecf20Sopenharmony_ci struct vmw_private *dev_priv = ctx_res->dev_priv; 7198c2ecf20Sopenharmony_ci struct vmw_buffer_object *dx_query_mob; 7208c2ecf20Sopenharmony_ci VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdDXBindAllQuery); 7218c2ecf20Sopenharmony_ci 7228c2ecf20Sopenharmony_ci dx_query_mob = vmw_context_get_dx_query_mob(ctx_res); 7238c2ecf20Sopenharmony_ci 7248c2ecf20Sopenharmony_ci if (!dx_query_mob || dx_query_mob->dx_query_ctx) 7258c2ecf20Sopenharmony_ci return 0; 7268c2ecf20Sopenharmony_ci 7278c2ecf20Sopenharmony_ci cmd = VMW_FIFO_RESERVE_DX(dev_priv, sizeof(*cmd), ctx_res->id); 7288c2ecf20Sopenharmony_ci if (cmd == NULL) 7298c2ecf20Sopenharmony_ci return -ENOMEM; 7308c2ecf20Sopenharmony_ci 7318c2ecf20Sopenharmony_ci cmd->header.id = SVGA_3D_CMD_DX_BIND_ALL_QUERY; 7328c2ecf20Sopenharmony_ci cmd->header.size = sizeof(cmd->body); 7338c2ecf20Sopenharmony_ci cmd->body.cid = ctx_res->id; 7348c2ecf20Sopenharmony_ci cmd->body.mobid = dx_query_mob->base.mem.start; 7358c2ecf20Sopenharmony_ci vmw_fifo_commit(dev_priv, sizeof(*cmd)); 7368c2ecf20Sopenharmony_ci 7378c2ecf20Sopenharmony_ci vmw_context_bind_dx_query(ctx_res, dx_query_mob); 7388c2ecf20Sopenharmony_ci 7398c2ecf20Sopenharmony_ci return 0; 7408c2ecf20Sopenharmony_ci} 7418c2ecf20Sopenharmony_ci 7428c2ecf20Sopenharmony_ci/** 7438c2ecf20Sopenharmony_ci * vmw_rebind_contexts - Rebind all resources previously bound to referenced 7448c2ecf20Sopenharmony_ci * contexts. 7458c2ecf20Sopenharmony_ci * 7468c2ecf20Sopenharmony_ci * @sw_context: Pointer to the software context. 7478c2ecf20Sopenharmony_ci * 7488c2ecf20Sopenharmony_ci * Rebind context binding points that have been scrubbed because of eviction. 7498c2ecf20Sopenharmony_ci */ 7508c2ecf20Sopenharmony_cistatic int vmw_rebind_contexts(struct vmw_sw_context *sw_context) 7518c2ecf20Sopenharmony_ci{ 7528c2ecf20Sopenharmony_ci struct vmw_ctx_validation_info *val; 7538c2ecf20Sopenharmony_ci int ret; 7548c2ecf20Sopenharmony_ci 7558c2ecf20Sopenharmony_ci list_for_each_entry(val, &sw_context->ctx_list, head) { 7568c2ecf20Sopenharmony_ci ret = vmw_binding_rebind_all(val->cur); 7578c2ecf20Sopenharmony_ci if (unlikely(ret != 0)) { 7588c2ecf20Sopenharmony_ci if (ret != -ERESTARTSYS) 7598c2ecf20Sopenharmony_ci VMW_DEBUG_USER("Failed to rebind context.\n"); 7608c2ecf20Sopenharmony_ci return ret; 7618c2ecf20Sopenharmony_ci } 7628c2ecf20Sopenharmony_ci 7638c2ecf20Sopenharmony_ci ret = vmw_rebind_all_dx_query(val->ctx); 7648c2ecf20Sopenharmony_ci if (ret != 0) { 7658c2ecf20Sopenharmony_ci VMW_DEBUG_USER("Failed to rebind queries.\n"); 7668c2ecf20Sopenharmony_ci return ret; 7678c2ecf20Sopenharmony_ci } 7688c2ecf20Sopenharmony_ci } 7698c2ecf20Sopenharmony_ci 7708c2ecf20Sopenharmony_ci return 0; 7718c2ecf20Sopenharmony_ci} 7728c2ecf20Sopenharmony_ci 7738c2ecf20Sopenharmony_ci/** 7748c2ecf20Sopenharmony_ci * vmw_view_bindings_add - Add an array of view bindings to a context binding 7758c2ecf20Sopenharmony_ci * state tracker. 7768c2ecf20Sopenharmony_ci * 7778c2ecf20Sopenharmony_ci * @sw_context: The execbuf state used for this command. 7788c2ecf20Sopenharmony_ci * @view_type: View type for the bindings. 7798c2ecf20Sopenharmony_ci * @binding_type: Binding type for the bindings. 7808c2ecf20Sopenharmony_ci * @shader_slot: The shader slot to user for the bindings. 7818c2ecf20Sopenharmony_ci * @view_ids: Array of view ids to be bound. 7828c2ecf20Sopenharmony_ci * @num_views: Number of view ids in @view_ids. 7838c2ecf20Sopenharmony_ci * @first_slot: The binding slot to be used for the first view id in @view_ids. 7848c2ecf20Sopenharmony_ci */ 7858c2ecf20Sopenharmony_cistatic int vmw_view_bindings_add(struct vmw_sw_context *sw_context, 7868c2ecf20Sopenharmony_ci enum vmw_view_type view_type, 7878c2ecf20Sopenharmony_ci enum vmw_ctx_binding_type binding_type, 7888c2ecf20Sopenharmony_ci uint32 shader_slot, 7898c2ecf20Sopenharmony_ci uint32 view_ids[], u32 num_views, 7908c2ecf20Sopenharmony_ci u32 first_slot) 7918c2ecf20Sopenharmony_ci{ 7928c2ecf20Sopenharmony_ci struct vmw_ctx_validation_info *ctx_node = VMW_GET_CTX_NODE(sw_context); 7938c2ecf20Sopenharmony_ci u32 i; 7948c2ecf20Sopenharmony_ci 7958c2ecf20Sopenharmony_ci if (!ctx_node) 7968c2ecf20Sopenharmony_ci return -EINVAL; 7978c2ecf20Sopenharmony_ci 7988c2ecf20Sopenharmony_ci for (i = 0; i < num_views; ++i) { 7998c2ecf20Sopenharmony_ci struct vmw_ctx_bindinfo_view binding; 8008c2ecf20Sopenharmony_ci struct vmw_resource *view = NULL; 8018c2ecf20Sopenharmony_ci 8028c2ecf20Sopenharmony_ci if (view_ids[i] != SVGA3D_INVALID_ID) { 8038c2ecf20Sopenharmony_ci view = vmw_view_id_val_add(sw_context, view_type, 8048c2ecf20Sopenharmony_ci view_ids[i]); 8058c2ecf20Sopenharmony_ci if (IS_ERR(view)) { 8068c2ecf20Sopenharmony_ci VMW_DEBUG_USER("View not found.\n"); 8078c2ecf20Sopenharmony_ci return PTR_ERR(view); 8088c2ecf20Sopenharmony_ci } 8098c2ecf20Sopenharmony_ci } 8108c2ecf20Sopenharmony_ci binding.bi.ctx = ctx_node->ctx; 8118c2ecf20Sopenharmony_ci binding.bi.res = view; 8128c2ecf20Sopenharmony_ci binding.bi.bt = binding_type; 8138c2ecf20Sopenharmony_ci binding.shader_slot = shader_slot; 8148c2ecf20Sopenharmony_ci binding.slot = first_slot + i; 8158c2ecf20Sopenharmony_ci vmw_binding_add(ctx_node->staged, &binding.bi, 8168c2ecf20Sopenharmony_ci shader_slot, binding.slot); 8178c2ecf20Sopenharmony_ci } 8188c2ecf20Sopenharmony_ci 8198c2ecf20Sopenharmony_ci return 0; 8208c2ecf20Sopenharmony_ci} 8218c2ecf20Sopenharmony_ci 8228c2ecf20Sopenharmony_ci/** 8238c2ecf20Sopenharmony_ci * vmw_cmd_cid_check - Check a command header for valid context information. 8248c2ecf20Sopenharmony_ci * 8258c2ecf20Sopenharmony_ci * @dev_priv: Pointer to a device private structure. 8268c2ecf20Sopenharmony_ci * @sw_context: Pointer to the software context. 8278c2ecf20Sopenharmony_ci * @header: A command header with an embedded user-space context handle. 8288c2ecf20Sopenharmony_ci * 8298c2ecf20Sopenharmony_ci * Convenience function: Call vmw_cmd_res_check with the user-space context 8308c2ecf20Sopenharmony_ci * handle embedded in @header. 8318c2ecf20Sopenharmony_ci */ 8328c2ecf20Sopenharmony_cistatic int vmw_cmd_cid_check(struct vmw_private *dev_priv, 8338c2ecf20Sopenharmony_ci struct vmw_sw_context *sw_context, 8348c2ecf20Sopenharmony_ci SVGA3dCmdHeader *header) 8358c2ecf20Sopenharmony_ci{ 8368c2ecf20Sopenharmony_ci VMW_DECLARE_CMD_VAR(*cmd, uint32_t) = 8378c2ecf20Sopenharmony_ci container_of(header, typeof(*cmd), header); 8388c2ecf20Sopenharmony_ci 8398c2ecf20Sopenharmony_ci return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_context, 8408c2ecf20Sopenharmony_ci VMW_RES_DIRTY_SET, user_context_converter, 8418c2ecf20Sopenharmony_ci &cmd->body, NULL); 8428c2ecf20Sopenharmony_ci} 8438c2ecf20Sopenharmony_ci 8448c2ecf20Sopenharmony_ci/** 8458c2ecf20Sopenharmony_ci * vmw_execbuf_info_from_res - Get the private validation metadata for a 8468c2ecf20Sopenharmony_ci * recently validated resource 8478c2ecf20Sopenharmony_ci * 8488c2ecf20Sopenharmony_ci * @sw_context: Pointer to the command submission context 8498c2ecf20Sopenharmony_ci * @res: The resource 8508c2ecf20Sopenharmony_ci * 8518c2ecf20Sopenharmony_ci * The resource pointed to by @res needs to be present in the command submission 8528c2ecf20Sopenharmony_ci * context's resource cache and hence the last resource of that type to be 8538c2ecf20Sopenharmony_ci * processed by the validation code. 8548c2ecf20Sopenharmony_ci * 8558c2ecf20Sopenharmony_ci * Return: a pointer to the private metadata of the resource, or NULL if it 8568c2ecf20Sopenharmony_ci * wasn't found 8578c2ecf20Sopenharmony_ci */ 8588c2ecf20Sopenharmony_cistatic struct vmw_ctx_validation_info * 8598c2ecf20Sopenharmony_civmw_execbuf_info_from_res(struct vmw_sw_context *sw_context, 8608c2ecf20Sopenharmony_ci struct vmw_resource *res) 8618c2ecf20Sopenharmony_ci{ 8628c2ecf20Sopenharmony_ci struct vmw_res_cache_entry *rcache = 8638c2ecf20Sopenharmony_ci &sw_context->res_cache[vmw_res_type(res)]; 8648c2ecf20Sopenharmony_ci 8658c2ecf20Sopenharmony_ci if (rcache->valid && rcache->res == res) 8668c2ecf20Sopenharmony_ci return rcache->private; 8678c2ecf20Sopenharmony_ci 8688c2ecf20Sopenharmony_ci WARN_ON_ONCE(true); 8698c2ecf20Sopenharmony_ci return NULL; 8708c2ecf20Sopenharmony_ci} 8718c2ecf20Sopenharmony_ci 8728c2ecf20Sopenharmony_cistatic int vmw_cmd_set_render_target_check(struct vmw_private *dev_priv, 8738c2ecf20Sopenharmony_ci struct vmw_sw_context *sw_context, 8748c2ecf20Sopenharmony_ci SVGA3dCmdHeader *header) 8758c2ecf20Sopenharmony_ci{ 8768c2ecf20Sopenharmony_ci VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdSetRenderTarget); 8778c2ecf20Sopenharmony_ci struct vmw_resource *ctx; 8788c2ecf20Sopenharmony_ci struct vmw_resource *res; 8798c2ecf20Sopenharmony_ci int ret; 8808c2ecf20Sopenharmony_ci 8818c2ecf20Sopenharmony_ci cmd = container_of(header, typeof(*cmd), header); 8828c2ecf20Sopenharmony_ci 8838c2ecf20Sopenharmony_ci if (cmd->body.type >= SVGA3D_RT_MAX) { 8848c2ecf20Sopenharmony_ci VMW_DEBUG_USER("Illegal render target type %u.\n", 8858c2ecf20Sopenharmony_ci (unsigned int) cmd->body.type); 8868c2ecf20Sopenharmony_ci return -EINVAL; 8878c2ecf20Sopenharmony_ci } 8888c2ecf20Sopenharmony_ci 8898c2ecf20Sopenharmony_ci ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_context, 8908c2ecf20Sopenharmony_ci VMW_RES_DIRTY_SET, user_context_converter, 8918c2ecf20Sopenharmony_ci &cmd->body.cid, &ctx); 8928c2ecf20Sopenharmony_ci if (unlikely(ret != 0)) 8938c2ecf20Sopenharmony_ci return ret; 8948c2ecf20Sopenharmony_ci 8958c2ecf20Sopenharmony_ci ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface, 8968c2ecf20Sopenharmony_ci VMW_RES_DIRTY_SET, user_surface_converter, 8978c2ecf20Sopenharmony_ci &cmd->body.target.sid, &res); 8988c2ecf20Sopenharmony_ci if (unlikely(ret)) 8998c2ecf20Sopenharmony_ci return ret; 9008c2ecf20Sopenharmony_ci 9018c2ecf20Sopenharmony_ci if (dev_priv->has_mob) { 9028c2ecf20Sopenharmony_ci struct vmw_ctx_bindinfo_view binding; 9038c2ecf20Sopenharmony_ci struct vmw_ctx_validation_info *node; 9048c2ecf20Sopenharmony_ci 9058c2ecf20Sopenharmony_ci node = vmw_execbuf_info_from_res(sw_context, ctx); 9068c2ecf20Sopenharmony_ci if (!node) 9078c2ecf20Sopenharmony_ci return -EINVAL; 9088c2ecf20Sopenharmony_ci 9098c2ecf20Sopenharmony_ci binding.bi.ctx = ctx; 9108c2ecf20Sopenharmony_ci binding.bi.res = res; 9118c2ecf20Sopenharmony_ci binding.bi.bt = vmw_ctx_binding_rt; 9128c2ecf20Sopenharmony_ci binding.slot = cmd->body.type; 9138c2ecf20Sopenharmony_ci vmw_binding_add(node->staged, &binding.bi, 0, binding.slot); 9148c2ecf20Sopenharmony_ci } 9158c2ecf20Sopenharmony_ci 9168c2ecf20Sopenharmony_ci return 0; 9178c2ecf20Sopenharmony_ci} 9188c2ecf20Sopenharmony_ci 9198c2ecf20Sopenharmony_cistatic int vmw_cmd_surface_copy_check(struct vmw_private *dev_priv, 9208c2ecf20Sopenharmony_ci struct vmw_sw_context *sw_context, 9218c2ecf20Sopenharmony_ci SVGA3dCmdHeader *header) 9228c2ecf20Sopenharmony_ci{ 9238c2ecf20Sopenharmony_ci VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdSurfaceCopy); 9248c2ecf20Sopenharmony_ci int ret; 9258c2ecf20Sopenharmony_ci 9268c2ecf20Sopenharmony_ci cmd = container_of(header, typeof(*cmd), header); 9278c2ecf20Sopenharmony_ci 9288c2ecf20Sopenharmony_ci ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface, 9298c2ecf20Sopenharmony_ci VMW_RES_DIRTY_NONE, user_surface_converter, 9308c2ecf20Sopenharmony_ci &cmd->body.src.sid, NULL); 9318c2ecf20Sopenharmony_ci if (ret) 9328c2ecf20Sopenharmony_ci return ret; 9338c2ecf20Sopenharmony_ci 9348c2ecf20Sopenharmony_ci return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface, 9358c2ecf20Sopenharmony_ci VMW_RES_DIRTY_SET, user_surface_converter, 9368c2ecf20Sopenharmony_ci &cmd->body.dest.sid, NULL); 9378c2ecf20Sopenharmony_ci} 9388c2ecf20Sopenharmony_ci 9398c2ecf20Sopenharmony_cistatic int vmw_cmd_buffer_copy_check(struct vmw_private *dev_priv, 9408c2ecf20Sopenharmony_ci struct vmw_sw_context *sw_context, 9418c2ecf20Sopenharmony_ci SVGA3dCmdHeader *header) 9428c2ecf20Sopenharmony_ci{ 9438c2ecf20Sopenharmony_ci VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdDXBufferCopy); 9448c2ecf20Sopenharmony_ci int ret; 9458c2ecf20Sopenharmony_ci 9468c2ecf20Sopenharmony_ci cmd = container_of(header, typeof(*cmd), header); 9478c2ecf20Sopenharmony_ci ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface, 9488c2ecf20Sopenharmony_ci VMW_RES_DIRTY_NONE, user_surface_converter, 9498c2ecf20Sopenharmony_ci &cmd->body.src, NULL); 9508c2ecf20Sopenharmony_ci if (ret != 0) 9518c2ecf20Sopenharmony_ci return ret; 9528c2ecf20Sopenharmony_ci 9538c2ecf20Sopenharmony_ci return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface, 9548c2ecf20Sopenharmony_ci VMW_RES_DIRTY_SET, user_surface_converter, 9558c2ecf20Sopenharmony_ci &cmd->body.dest, NULL); 9568c2ecf20Sopenharmony_ci} 9578c2ecf20Sopenharmony_ci 9588c2ecf20Sopenharmony_cistatic int vmw_cmd_pred_copy_check(struct vmw_private *dev_priv, 9598c2ecf20Sopenharmony_ci struct vmw_sw_context *sw_context, 9608c2ecf20Sopenharmony_ci SVGA3dCmdHeader *header) 9618c2ecf20Sopenharmony_ci{ 9628c2ecf20Sopenharmony_ci VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdDXPredCopyRegion); 9638c2ecf20Sopenharmony_ci int ret; 9648c2ecf20Sopenharmony_ci 9658c2ecf20Sopenharmony_ci cmd = container_of(header, typeof(*cmd), header); 9668c2ecf20Sopenharmony_ci ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface, 9678c2ecf20Sopenharmony_ci VMW_RES_DIRTY_NONE, user_surface_converter, 9688c2ecf20Sopenharmony_ci &cmd->body.srcSid, NULL); 9698c2ecf20Sopenharmony_ci if (ret != 0) 9708c2ecf20Sopenharmony_ci return ret; 9718c2ecf20Sopenharmony_ci 9728c2ecf20Sopenharmony_ci return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface, 9738c2ecf20Sopenharmony_ci VMW_RES_DIRTY_SET, user_surface_converter, 9748c2ecf20Sopenharmony_ci &cmd->body.dstSid, NULL); 9758c2ecf20Sopenharmony_ci} 9768c2ecf20Sopenharmony_ci 9778c2ecf20Sopenharmony_cistatic int vmw_cmd_stretch_blt_check(struct vmw_private *dev_priv, 9788c2ecf20Sopenharmony_ci struct vmw_sw_context *sw_context, 9798c2ecf20Sopenharmony_ci SVGA3dCmdHeader *header) 9808c2ecf20Sopenharmony_ci{ 9818c2ecf20Sopenharmony_ci VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdSurfaceStretchBlt); 9828c2ecf20Sopenharmony_ci int ret; 9838c2ecf20Sopenharmony_ci 9848c2ecf20Sopenharmony_ci cmd = container_of(header, typeof(*cmd), header); 9858c2ecf20Sopenharmony_ci ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface, 9868c2ecf20Sopenharmony_ci VMW_RES_DIRTY_NONE, user_surface_converter, 9878c2ecf20Sopenharmony_ci &cmd->body.src.sid, NULL); 9888c2ecf20Sopenharmony_ci if (unlikely(ret != 0)) 9898c2ecf20Sopenharmony_ci return ret; 9908c2ecf20Sopenharmony_ci 9918c2ecf20Sopenharmony_ci return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface, 9928c2ecf20Sopenharmony_ci VMW_RES_DIRTY_SET, user_surface_converter, 9938c2ecf20Sopenharmony_ci &cmd->body.dest.sid, NULL); 9948c2ecf20Sopenharmony_ci} 9958c2ecf20Sopenharmony_ci 9968c2ecf20Sopenharmony_cistatic int vmw_cmd_blt_surf_screen_check(struct vmw_private *dev_priv, 9978c2ecf20Sopenharmony_ci struct vmw_sw_context *sw_context, 9988c2ecf20Sopenharmony_ci SVGA3dCmdHeader *header) 9998c2ecf20Sopenharmony_ci{ 10008c2ecf20Sopenharmony_ci VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdBlitSurfaceToScreen) = 10018c2ecf20Sopenharmony_ci container_of(header, typeof(*cmd), header); 10028c2ecf20Sopenharmony_ci 10038c2ecf20Sopenharmony_ci return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface, 10048c2ecf20Sopenharmony_ci VMW_RES_DIRTY_NONE, user_surface_converter, 10058c2ecf20Sopenharmony_ci &cmd->body.srcImage.sid, NULL); 10068c2ecf20Sopenharmony_ci} 10078c2ecf20Sopenharmony_ci 10088c2ecf20Sopenharmony_cistatic int vmw_cmd_present_check(struct vmw_private *dev_priv, 10098c2ecf20Sopenharmony_ci struct vmw_sw_context *sw_context, 10108c2ecf20Sopenharmony_ci SVGA3dCmdHeader *header) 10118c2ecf20Sopenharmony_ci{ 10128c2ecf20Sopenharmony_ci VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdPresent) = 10138c2ecf20Sopenharmony_ci container_of(header, typeof(*cmd), header); 10148c2ecf20Sopenharmony_ci 10158c2ecf20Sopenharmony_ci return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface, 10168c2ecf20Sopenharmony_ci VMW_RES_DIRTY_NONE, user_surface_converter, 10178c2ecf20Sopenharmony_ci &cmd->body.sid, NULL); 10188c2ecf20Sopenharmony_ci} 10198c2ecf20Sopenharmony_ci 10208c2ecf20Sopenharmony_ci/** 10218c2ecf20Sopenharmony_ci * vmw_query_bo_switch_prepare - Prepare to switch pinned buffer for queries. 10228c2ecf20Sopenharmony_ci * 10238c2ecf20Sopenharmony_ci * @dev_priv: The device private structure. 10248c2ecf20Sopenharmony_ci * @new_query_bo: The new buffer holding query results. 10258c2ecf20Sopenharmony_ci * @sw_context: The software context used for this command submission. 10268c2ecf20Sopenharmony_ci * 10278c2ecf20Sopenharmony_ci * This function checks whether @new_query_bo is suitable for holding query 10288c2ecf20Sopenharmony_ci * results, and if another buffer currently is pinned for query results. If so, 10298c2ecf20Sopenharmony_ci * the function prepares the state of @sw_context for switching pinned buffers 10308c2ecf20Sopenharmony_ci * after successful submission of the current command batch. 10318c2ecf20Sopenharmony_ci */ 10328c2ecf20Sopenharmony_cistatic int vmw_query_bo_switch_prepare(struct vmw_private *dev_priv, 10338c2ecf20Sopenharmony_ci struct vmw_buffer_object *new_query_bo, 10348c2ecf20Sopenharmony_ci struct vmw_sw_context *sw_context) 10358c2ecf20Sopenharmony_ci{ 10368c2ecf20Sopenharmony_ci struct vmw_res_cache_entry *ctx_entry = 10378c2ecf20Sopenharmony_ci &sw_context->res_cache[vmw_res_context]; 10388c2ecf20Sopenharmony_ci int ret; 10398c2ecf20Sopenharmony_ci 10408c2ecf20Sopenharmony_ci BUG_ON(!ctx_entry->valid); 10418c2ecf20Sopenharmony_ci sw_context->last_query_ctx = ctx_entry->res; 10428c2ecf20Sopenharmony_ci 10438c2ecf20Sopenharmony_ci if (unlikely(new_query_bo != sw_context->cur_query_bo)) { 10448c2ecf20Sopenharmony_ci 10458c2ecf20Sopenharmony_ci if (unlikely(new_query_bo->base.num_pages > 4)) { 10468c2ecf20Sopenharmony_ci VMW_DEBUG_USER("Query buffer too large.\n"); 10478c2ecf20Sopenharmony_ci return -EINVAL; 10488c2ecf20Sopenharmony_ci } 10498c2ecf20Sopenharmony_ci 10508c2ecf20Sopenharmony_ci if (unlikely(sw_context->cur_query_bo != NULL)) { 10518c2ecf20Sopenharmony_ci sw_context->needs_post_query_barrier = true; 10528c2ecf20Sopenharmony_ci ret = vmw_validation_add_bo(sw_context->ctx, 10538c2ecf20Sopenharmony_ci sw_context->cur_query_bo, 10548c2ecf20Sopenharmony_ci dev_priv->has_mob, false); 10558c2ecf20Sopenharmony_ci if (unlikely(ret != 0)) 10568c2ecf20Sopenharmony_ci return ret; 10578c2ecf20Sopenharmony_ci } 10588c2ecf20Sopenharmony_ci sw_context->cur_query_bo = new_query_bo; 10598c2ecf20Sopenharmony_ci 10608c2ecf20Sopenharmony_ci ret = vmw_validation_add_bo(sw_context->ctx, 10618c2ecf20Sopenharmony_ci dev_priv->dummy_query_bo, 10628c2ecf20Sopenharmony_ci dev_priv->has_mob, false); 10638c2ecf20Sopenharmony_ci if (unlikely(ret != 0)) 10648c2ecf20Sopenharmony_ci return ret; 10658c2ecf20Sopenharmony_ci } 10668c2ecf20Sopenharmony_ci 10678c2ecf20Sopenharmony_ci return 0; 10688c2ecf20Sopenharmony_ci} 10698c2ecf20Sopenharmony_ci 10708c2ecf20Sopenharmony_ci/** 10718c2ecf20Sopenharmony_ci * vmw_query_bo_switch_commit - Finalize switching pinned query buffer 10728c2ecf20Sopenharmony_ci * 10738c2ecf20Sopenharmony_ci * @dev_priv: The device private structure. 10748c2ecf20Sopenharmony_ci * @sw_context: The software context used for this command submission batch. 10758c2ecf20Sopenharmony_ci * 10768c2ecf20Sopenharmony_ci * This function will check if we're switching query buffers, and will then, 10778c2ecf20Sopenharmony_ci * issue a dummy occlusion query wait used as a query barrier. When the fence 10788c2ecf20Sopenharmony_ci * object following that query wait has signaled, we are sure that all preceding 10798c2ecf20Sopenharmony_ci * queries have finished, and the old query buffer can be unpinned. However, 10808c2ecf20Sopenharmony_ci * since both the new query buffer and the old one are fenced with that fence, 10818c2ecf20Sopenharmony_ci * we can do an asynchronus unpin now, and be sure that the old query buffer 10828c2ecf20Sopenharmony_ci * won't be moved until the fence has signaled. 10838c2ecf20Sopenharmony_ci * 10848c2ecf20Sopenharmony_ci * As mentioned above, both the new - and old query buffers need to be fenced 10858c2ecf20Sopenharmony_ci * using a sequence emitted *after* calling this function. 10868c2ecf20Sopenharmony_ci */ 10878c2ecf20Sopenharmony_cistatic void vmw_query_bo_switch_commit(struct vmw_private *dev_priv, 10888c2ecf20Sopenharmony_ci struct vmw_sw_context *sw_context) 10898c2ecf20Sopenharmony_ci{ 10908c2ecf20Sopenharmony_ci /* 10918c2ecf20Sopenharmony_ci * The validate list should still hold references to all 10928c2ecf20Sopenharmony_ci * contexts here. 10938c2ecf20Sopenharmony_ci */ 10948c2ecf20Sopenharmony_ci if (sw_context->needs_post_query_barrier) { 10958c2ecf20Sopenharmony_ci struct vmw_res_cache_entry *ctx_entry = 10968c2ecf20Sopenharmony_ci &sw_context->res_cache[vmw_res_context]; 10978c2ecf20Sopenharmony_ci struct vmw_resource *ctx; 10988c2ecf20Sopenharmony_ci int ret; 10998c2ecf20Sopenharmony_ci 11008c2ecf20Sopenharmony_ci BUG_ON(!ctx_entry->valid); 11018c2ecf20Sopenharmony_ci ctx = ctx_entry->res; 11028c2ecf20Sopenharmony_ci 11038c2ecf20Sopenharmony_ci ret = vmw_fifo_emit_dummy_query(dev_priv, ctx->id); 11048c2ecf20Sopenharmony_ci 11058c2ecf20Sopenharmony_ci if (unlikely(ret != 0)) 11068c2ecf20Sopenharmony_ci VMW_DEBUG_USER("Out of fifo space for dummy query.\n"); 11078c2ecf20Sopenharmony_ci } 11088c2ecf20Sopenharmony_ci 11098c2ecf20Sopenharmony_ci if (dev_priv->pinned_bo != sw_context->cur_query_bo) { 11108c2ecf20Sopenharmony_ci if (dev_priv->pinned_bo) { 11118c2ecf20Sopenharmony_ci vmw_bo_pin_reserved(dev_priv->pinned_bo, false); 11128c2ecf20Sopenharmony_ci vmw_bo_unreference(&dev_priv->pinned_bo); 11138c2ecf20Sopenharmony_ci } 11148c2ecf20Sopenharmony_ci 11158c2ecf20Sopenharmony_ci if (!sw_context->needs_post_query_barrier) { 11168c2ecf20Sopenharmony_ci vmw_bo_pin_reserved(sw_context->cur_query_bo, true); 11178c2ecf20Sopenharmony_ci 11188c2ecf20Sopenharmony_ci /* 11198c2ecf20Sopenharmony_ci * We pin also the dummy_query_bo buffer so that we 11208c2ecf20Sopenharmony_ci * don't need to validate it when emitting dummy queries 11218c2ecf20Sopenharmony_ci * in context destroy paths. 11228c2ecf20Sopenharmony_ci */ 11238c2ecf20Sopenharmony_ci if (!dev_priv->dummy_query_bo_pinned) { 11248c2ecf20Sopenharmony_ci vmw_bo_pin_reserved(dev_priv->dummy_query_bo, 11258c2ecf20Sopenharmony_ci true); 11268c2ecf20Sopenharmony_ci dev_priv->dummy_query_bo_pinned = true; 11278c2ecf20Sopenharmony_ci } 11288c2ecf20Sopenharmony_ci 11298c2ecf20Sopenharmony_ci BUG_ON(sw_context->last_query_ctx == NULL); 11308c2ecf20Sopenharmony_ci dev_priv->query_cid = sw_context->last_query_ctx->id; 11318c2ecf20Sopenharmony_ci dev_priv->query_cid_valid = true; 11328c2ecf20Sopenharmony_ci dev_priv->pinned_bo = 11338c2ecf20Sopenharmony_ci vmw_bo_reference(sw_context->cur_query_bo); 11348c2ecf20Sopenharmony_ci } 11358c2ecf20Sopenharmony_ci } 11368c2ecf20Sopenharmony_ci} 11378c2ecf20Sopenharmony_ci 11388c2ecf20Sopenharmony_ci/** 11398c2ecf20Sopenharmony_ci * vmw_translate_mob_pointer - Prepare to translate a user-space buffer handle 11408c2ecf20Sopenharmony_ci * to a MOB id. 11418c2ecf20Sopenharmony_ci * 11428c2ecf20Sopenharmony_ci * @dev_priv: Pointer to a device private structure. 11438c2ecf20Sopenharmony_ci * @sw_context: The software context used for this command batch validation. 11448c2ecf20Sopenharmony_ci * @id: Pointer to the user-space handle to be translated. 11458c2ecf20Sopenharmony_ci * @vmw_bo_p: Points to a location that, on successful return will carry a 11468c2ecf20Sopenharmony_ci * non-reference-counted pointer to the buffer object identified by the 11478c2ecf20Sopenharmony_ci * user-space handle in @id. 11488c2ecf20Sopenharmony_ci * 11498c2ecf20Sopenharmony_ci * This function saves information needed to translate a user-space buffer 11508c2ecf20Sopenharmony_ci * handle to a MOB id. The translation does not take place immediately, but 11518c2ecf20Sopenharmony_ci * during a call to vmw_apply_relocations(). 11528c2ecf20Sopenharmony_ci * 11538c2ecf20Sopenharmony_ci * This function builds a relocation list and a list of buffers to validate. The 11548c2ecf20Sopenharmony_ci * former needs to be freed using either vmw_apply_relocations() or 11558c2ecf20Sopenharmony_ci * vmw_free_relocations(). The latter needs to be freed using 11568c2ecf20Sopenharmony_ci * vmw_clear_validations. 11578c2ecf20Sopenharmony_ci */ 11588c2ecf20Sopenharmony_cistatic int vmw_translate_mob_ptr(struct vmw_private *dev_priv, 11598c2ecf20Sopenharmony_ci struct vmw_sw_context *sw_context, 11608c2ecf20Sopenharmony_ci SVGAMobId *id, 11618c2ecf20Sopenharmony_ci struct vmw_buffer_object **vmw_bo_p) 11628c2ecf20Sopenharmony_ci{ 11638c2ecf20Sopenharmony_ci struct vmw_buffer_object *vmw_bo; 11648c2ecf20Sopenharmony_ci uint32_t handle = *id; 11658c2ecf20Sopenharmony_ci struct vmw_relocation *reloc; 11668c2ecf20Sopenharmony_ci int ret; 11678c2ecf20Sopenharmony_ci 11688c2ecf20Sopenharmony_ci vmw_validation_preload_bo(sw_context->ctx); 11698c2ecf20Sopenharmony_ci vmw_bo = vmw_user_bo_noref_lookup(sw_context->fp->tfile, handle); 11708c2ecf20Sopenharmony_ci if (IS_ERR(vmw_bo)) { 11718c2ecf20Sopenharmony_ci VMW_DEBUG_USER("Could not find or use MOB buffer.\n"); 11728c2ecf20Sopenharmony_ci return PTR_ERR(vmw_bo); 11738c2ecf20Sopenharmony_ci } 11748c2ecf20Sopenharmony_ci 11758c2ecf20Sopenharmony_ci ret = vmw_validation_add_bo(sw_context->ctx, vmw_bo, true, false); 11768c2ecf20Sopenharmony_ci vmw_user_bo_noref_release(); 11778c2ecf20Sopenharmony_ci if (unlikely(ret != 0)) 11788c2ecf20Sopenharmony_ci return ret; 11798c2ecf20Sopenharmony_ci 11808c2ecf20Sopenharmony_ci reloc = vmw_validation_mem_alloc(sw_context->ctx, sizeof(*reloc)); 11818c2ecf20Sopenharmony_ci if (!reloc) 11828c2ecf20Sopenharmony_ci return -ENOMEM; 11838c2ecf20Sopenharmony_ci 11848c2ecf20Sopenharmony_ci reloc->mob_loc = id; 11858c2ecf20Sopenharmony_ci reloc->vbo = vmw_bo; 11868c2ecf20Sopenharmony_ci 11878c2ecf20Sopenharmony_ci *vmw_bo_p = vmw_bo; 11888c2ecf20Sopenharmony_ci list_add_tail(&reloc->head, &sw_context->bo_relocations); 11898c2ecf20Sopenharmony_ci 11908c2ecf20Sopenharmony_ci return 0; 11918c2ecf20Sopenharmony_ci} 11928c2ecf20Sopenharmony_ci 11938c2ecf20Sopenharmony_ci/** 11948c2ecf20Sopenharmony_ci * vmw_translate_guest_pointer - Prepare to translate a user-space buffer handle 11958c2ecf20Sopenharmony_ci * to a valid SVGAGuestPtr 11968c2ecf20Sopenharmony_ci * 11978c2ecf20Sopenharmony_ci * @dev_priv: Pointer to a device private structure. 11988c2ecf20Sopenharmony_ci * @sw_context: The software context used for this command batch validation. 11998c2ecf20Sopenharmony_ci * @ptr: Pointer to the user-space handle to be translated. 12008c2ecf20Sopenharmony_ci * @vmw_bo_p: Points to a location that, on successful return will carry a 12018c2ecf20Sopenharmony_ci * non-reference-counted pointer to the DMA buffer identified by the user-space 12028c2ecf20Sopenharmony_ci * handle in @id. 12038c2ecf20Sopenharmony_ci * 12048c2ecf20Sopenharmony_ci * This function saves information needed to translate a user-space buffer 12058c2ecf20Sopenharmony_ci * handle to a valid SVGAGuestPtr. The translation does not take place 12068c2ecf20Sopenharmony_ci * immediately, but during a call to vmw_apply_relocations(). 12078c2ecf20Sopenharmony_ci * 12088c2ecf20Sopenharmony_ci * This function builds a relocation list and a list of buffers to validate. 12098c2ecf20Sopenharmony_ci * The former needs to be freed using either vmw_apply_relocations() or 12108c2ecf20Sopenharmony_ci * vmw_free_relocations(). The latter needs to be freed using 12118c2ecf20Sopenharmony_ci * vmw_clear_validations. 12128c2ecf20Sopenharmony_ci */ 12138c2ecf20Sopenharmony_cistatic int vmw_translate_guest_ptr(struct vmw_private *dev_priv, 12148c2ecf20Sopenharmony_ci struct vmw_sw_context *sw_context, 12158c2ecf20Sopenharmony_ci SVGAGuestPtr *ptr, 12168c2ecf20Sopenharmony_ci struct vmw_buffer_object **vmw_bo_p) 12178c2ecf20Sopenharmony_ci{ 12188c2ecf20Sopenharmony_ci struct vmw_buffer_object *vmw_bo; 12198c2ecf20Sopenharmony_ci uint32_t handle = ptr->gmrId; 12208c2ecf20Sopenharmony_ci struct vmw_relocation *reloc; 12218c2ecf20Sopenharmony_ci int ret; 12228c2ecf20Sopenharmony_ci 12238c2ecf20Sopenharmony_ci vmw_validation_preload_bo(sw_context->ctx); 12248c2ecf20Sopenharmony_ci vmw_bo = vmw_user_bo_noref_lookup(sw_context->fp->tfile, handle); 12258c2ecf20Sopenharmony_ci if (IS_ERR(vmw_bo)) { 12268c2ecf20Sopenharmony_ci VMW_DEBUG_USER("Could not find or use GMR region.\n"); 12278c2ecf20Sopenharmony_ci return PTR_ERR(vmw_bo); 12288c2ecf20Sopenharmony_ci } 12298c2ecf20Sopenharmony_ci 12308c2ecf20Sopenharmony_ci ret = vmw_validation_add_bo(sw_context->ctx, vmw_bo, false, false); 12318c2ecf20Sopenharmony_ci vmw_user_bo_noref_release(); 12328c2ecf20Sopenharmony_ci if (unlikely(ret != 0)) 12338c2ecf20Sopenharmony_ci return ret; 12348c2ecf20Sopenharmony_ci 12358c2ecf20Sopenharmony_ci reloc = vmw_validation_mem_alloc(sw_context->ctx, sizeof(*reloc)); 12368c2ecf20Sopenharmony_ci if (!reloc) 12378c2ecf20Sopenharmony_ci return -ENOMEM; 12388c2ecf20Sopenharmony_ci 12398c2ecf20Sopenharmony_ci reloc->location = ptr; 12408c2ecf20Sopenharmony_ci reloc->vbo = vmw_bo; 12418c2ecf20Sopenharmony_ci *vmw_bo_p = vmw_bo; 12428c2ecf20Sopenharmony_ci list_add_tail(&reloc->head, &sw_context->bo_relocations); 12438c2ecf20Sopenharmony_ci 12448c2ecf20Sopenharmony_ci return 0; 12458c2ecf20Sopenharmony_ci} 12468c2ecf20Sopenharmony_ci 12478c2ecf20Sopenharmony_ci/** 12488c2ecf20Sopenharmony_ci * vmw_cmd_dx_define_query - validate SVGA_3D_CMD_DX_DEFINE_QUERY command. 12498c2ecf20Sopenharmony_ci * 12508c2ecf20Sopenharmony_ci * @dev_priv: Pointer to a device private struct. 12518c2ecf20Sopenharmony_ci * @sw_context: The software context used for this command submission. 12528c2ecf20Sopenharmony_ci * @header: Pointer to the command header in the command stream. 12538c2ecf20Sopenharmony_ci * 12548c2ecf20Sopenharmony_ci * This function adds the new query into the query COTABLE 12558c2ecf20Sopenharmony_ci */ 12568c2ecf20Sopenharmony_cistatic int vmw_cmd_dx_define_query(struct vmw_private *dev_priv, 12578c2ecf20Sopenharmony_ci struct vmw_sw_context *sw_context, 12588c2ecf20Sopenharmony_ci SVGA3dCmdHeader *header) 12598c2ecf20Sopenharmony_ci{ 12608c2ecf20Sopenharmony_ci VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdDXDefineQuery); 12618c2ecf20Sopenharmony_ci struct vmw_ctx_validation_info *ctx_node = VMW_GET_CTX_NODE(sw_context); 12628c2ecf20Sopenharmony_ci struct vmw_resource *cotable_res; 12638c2ecf20Sopenharmony_ci int ret; 12648c2ecf20Sopenharmony_ci 12658c2ecf20Sopenharmony_ci if (!ctx_node) 12668c2ecf20Sopenharmony_ci return -EINVAL; 12678c2ecf20Sopenharmony_ci 12688c2ecf20Sopenharmony_ci cmd = container_of(header, typeof(*cmd), header); 12698c2ecf20Sopenharmony_ci 12708c2ecf20Sopenharmony_ci if (cmd->body.type < SVGA3D_QUERYTYPE_MIN || 12718c2ecf20Sopenharmony_ci cmd->body.type >= SVGA3D_QUERYTYPE_MAX) 12728c2ecf20Sopenharmony_ci return -EINVAL; 12738c2ecf20Sopenharmony_ci 12748c2ecf20Sopenharmony_ci cotable_res = vmw_context_cotable(ctx_node->ctx, SVGA_COTABLE_DXQUERY); 12758c2ecf20Sopenharmony_ci ret = vmw_cotable_notify(cotable_res, cmd->body.queryId); 12768c2ecf20Sopenharmony_ci 12778c2ecf20Sopenharmony_ci return ret; 12788c2ecf20Sopenharmony_ci} 12798c2ecf20Sopenharmony_ci 12808c2ecf20Sopenharmony_ci/** 12818c2ecf20Sopenharmony_ci * vmw_cmd_dx_bind_query - validate SVGA_3D_CMD_DX_BIND_QUERY command. 12828c2ecf20Sopenharmony_ci * 12838c2ecf20Sopenharmony_ci * @dev_priv: Pointer to a device private struct. 12848c2ecf20Sopenharmony_ci * @sw_context: The software context used for this command submission. 12858c2ecf20Sopenharmony_ci * @header: Pointer to the command header in the command stream. 12868c2ecf20Sopenharmony_ci * 12878c2ecf20Sopenharmony_ci * The query bind operation will eventually associate the query ID with its 12888c2ecf20Sopenharmony_ci * backing MOB. In this function, we take the user mode MOB ID and use 12898c2ecf20Sopenharmony_ci * vmw_translate_mob_ptr() to translate it to its kernel mode equivalent. 12908c2ecf20Sopenharmony_ci */ 12918c2ecf20Sopenharmony_cistatic int vmw_cmd_dx_bind_query(struct vmw_private *dev_priv, 12928c2ecf20Sopenharmony_ci struct vmw_sw_context *sw_context, 12938c2ecf20Sopenharmony_ci SVGA3dCmdHeader *header) 12948c2ecf20Sopenharmony_ci{ 12958c2ecf20Sopenharmony_ci VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdDXBindQuery); 12968c2ecf20Sopenharmony_ci struct vmw_buffer_object *vmw_bo; 12978c2ecf20Sopenharmony_ci int ret; 12988c2ecf20Sopenharmony_ci 12998c2ecf20Sopenharmony_ci cmd = container_of(header, typeof(*cmd), header); 13008c2ecf20Sopenharmony_ci 13018c2ecf20Sopenharmony_ci /* 13028c2ecf20Sopenharmony_ci * Look up the buffer pointed to by q.mobid, put it on the relocation 13038c2ecf20Sopenharmony_ci * list so its kernel mode MOB ID can be filled in later 13048c2ecf20Sopenharmony_ci */ 13058c2ecf20Sopenharmony_ci ret = vmw_translate_mob_ptr(dev_priv, sw_context, &cmd->body.mobid, 13068c2ecf20Sopenharmony_ci &vmw_bo); 13078c2ecf20Sopenharmony_ci 13088c2ecf20Sopenharmony_ci if (ret != 0) 13098c2ecf20Sopenharmony_ci return ret; 13108c2ecf20Sopenharmony_ci 13118c2ecf20Sopenharmony_ci sw_context->dx_query_mob = vmw_bo; 13128c2ecf20Sopenharmony_ci sw_context->dx_query_ctx = sw_context->dx_ctx_node->ctx; 13138c2ecf20Sopenharmony_ci return 0; 13148c2ecf20Sopenharmony_ci} 13158c2ecf20Sopenharmony_ci 13168c2ecf20Sopenharmony_ci/** 13178c2ecf20Sopenharmony_ci * vmw_cmd_begin_gb_query - validate SVGA_3D_CMD_BEGIN_GB_QUERY command. 13188c2ecf20Sopenharmony_ci * 13198c2ecf20Sopenharmony_ci * @dev_priv: Pointer to a device private struct. 13208c2ecf20Sopenharmony_ci * @sw_context: The software context used for this command submission. 13218c2ecf20Sopenharmony_ci * @header: Pointer to the command header in the command stream. 13228c2ecf20Sopenharmony_ci */ 13238c2ecf20Sopenharmony_cistatic int vmw_cmd_begin_gb_query(struct vmw_private *dev_priv, 13248c2ecf20Sopenharmony_ci struct vmw_sw_context *sw_context, 13258c2ecf20Sopenharmony_ci SVGA3dCmdHeader *header) 13268c2ecf20Sopenharmony_ci{ 13278c2ecf20Sopenharmony_ci VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdBeginGBQuery) = 13288c2ecf20Sopenharmony_ci container_of(header, typeof(*cmd), header); 13298c2ecf20Sopenharmony_ci 13308c2ecf20Sopenharmony_ci return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_context, 13318c2ecf20Sopenharmony_ci VMW_RES_DIRTY_SET, user_context_converter, 13328c2ecf20Sopenharmony_ci &cmd->body.cid, NULL); 13338c2ecf20Sopenharmony_ci} 13348c2ecf20Sopenharmony_ci 13358c2ecf20Sopenharmony_ci/** 13368c2ecf20Sopenharmony_ci * vmw_cmd_begin_query - validate SVGA_3D_CMD_BEGIN_QUERY command. 13378c2ecf20Sopenharmony_ci * 13388c2ecf20Sopenharmony_ci * @dev_priv: Pointer to a device private struct. 13398c2ecf20Sopenharmony_ci * @sw_context: The software context used for this command submission. 13408c2ecf20Sopenharmony_ci * @header: Pointer to the command header in the command stream. 13418c2ecf20Sopenharmony_ci */ 13428c2ecf20Sopenharmony_cistatic int vmw_cmd_begin_query(struct vmw_private *dev_priv, 13438c2ecf20Sopenharmony_ci struct vmw_sw_context *sw_context, 13448c2ecf20Sopenharmony_ci SVGA3dCmdHeader *header) 13458c2ecf20Sopenharmony_ci{ 13468c2ecf20Sopenharmony_ci VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdBeginQuery) = 13478c2ecf20Sopenharmony_ci container_of(header, typeof(*cmd), header); 13488c2ecf20Sopenharmony_ci 13498c2ecf20Sopenharmony_ci if (unlikely(dev_priv->has_mob)) { 13508c2ecf20Sopenharmony_ci VMW_DECLARE_CMD_VAR(gb_cmd, SVGA3dCmdBeginGBQuery); 13518c2ecf20Sopenharmony_ci 13528c2ecf20Sopenharmony_ci BUG_ON(sizeof(gb_cmd) != sizeof(*cmd)); 13538c2ecf20Sopenharmony_ci 13548c2ecf20Sopenharmony_ci gb_cmd.header.id = SVGA_3D_CMD_BEGIN_GB_QUERY; 13558c2ecf20Sopenharmony_ci gb_cmd.header.size = cmd->header.size; 13568c2ecf20Sopenharmony_ci gb_cmd.body.cid = cmd->body.cid; 13578c2ecf20Sopenharmony_ci gb_cmd.body.type = cmd->body.type; 13588c2ecf20Sopenharmony_ci 13598c2ecf20Sopenharmony_ci memcpy(cmd, &gb_cmd, sizeof(*cmd)); 13608c2ecf20Sopenharmony_ci return vmw_cmd_begin_gb_query(dev_priv, sw_context, header); 13618c2ecf20Sopenharmony_ci } 13628c2ecf20Sopenharmony_ci 13638c2ecf20Sopenharmony_ci return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_context, 13648c2ecf20Sopenharmony_ci VMW_RES_DIRTY_SET, user_context_converter, 13658c2ecf20Sopenharmony_ci &cmd->body.cid, NULL); 13668c2ecf20Sopenharmony_ci} 13678c2ecf20Sopenharmony_ci 13688c2ecf20Sopenharmony_ci/** 13698c2ecf20Sopenharmony_ci * vmw_cmd_end_gb_query - validate SVGA_3D_CMD_END_GB_QUERY command. 13708c2ecf20Sopenharmony_ci * 13718c2ecf20Sopenharmony_ci * @dev_priv: Pointer to a device private struct. 13728c2ecf20Sopenharmony_ci * @sw_context: The software context used for this command submission. 13738c2ecf20Sopenharmony_ci * @header: Pointer to the command header in the command stream. 13748c2ecf20Sopenharmony_ci */ 13758c2ecf20Sopenharmony_cistatic int vmw_cmd_end_gb_query(struct vmw_private *dev_priv, 13768c2ecf20Sopenharmony_ci struct vmw_sw_context *sw_context, 13778c2ecf20Sopenharmony_ci SVGA3dCmdHeader *header) 13788c2ecf20Sopenharmony_ci{ 13798c2ecf20Sopenharmony_ci struct vmw_buffer_object *vmw_bo; 13808c2ecf20Sopenharmony_ci VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdEndGBQuery); 13818c2ecf20Sopenharmony_ci int ret; 13828c2ecf20Sopenharmony_ci 13838c2ecf20Sopenharmony_ci cmd = container_of(header, typeof(*cmd), header); 13848c2ecf20Sopenharmony_ci ret = vmw_cmd_cid_check(dev_priv, sw_context, header); 13858c2ecf20Sopenharmony_ci if (unlikely(ret != 0)) 13868c2ecf20Sopenharmony_ci return ret; 13878c2ecf20Sopenharmony_ci 13888c2ecf20Sopenharmony_ci ret = vmw_translate_mob_ptr(dev_priv, sw_context, &cmd->body.mobid, 13898c2ecf20Sopenharmony_ci &vmw_bo); 13908c2ecf20Sopenharmony_ci if (unlikely(ret != 0)) 13918c2ecf20Sopenharmony_ci return ret; 13928c2ecf20Sopenharmony_ci 13938c2ecf20Sopenharmony_ci ret = vmw_query_bo_switch_prepare(dev_priv, vmw_bo, sw_context); 13948c2ecf20Sopenharmony_ci 13958c2ecf20Sopenharmony_ci return ret; 13968c2ecf20Sopenharmony_ci} 13978c2ecf20Sopenharmony_ci 13988c2ecf20Sopenharmony_ci/** 13998c2ecf20Sopenharmony_ci * vmw_cmd_end_query - validate SVGA_3D_CMD_END_QUERY command. 14008c2ecf20Sopenharmony_ci * 14018c2ecf20Sopenharmony_ci * @dev_priv: Pointer to a device private struct. 14028c2ecf20Sopenharmony_ci * @sw_context: The software context used for this command submission. 14038c2ecf20Sopenharmony_ci * @header: Pointer to the command header in the command stream. 14048c2ecf20Sopenharmony_ci */ 14058c2ecf20Sopenharmony_cistatic int vmw_cmd_end_query(struct vmw_private *dev_priv, 14068c2ecf20Sopenharmony_ci struct vmw_sw_context *sw_context, 14078c2ecf20Sopenharmony_ci SVGA3dCmdHeader *header) 14088c2ecf20Sopenharmony_ci{ 14098c2ecf20Sopenharmony_ci struct vmw_buffer_object *vmw_bo; 14108c2ecf20Sopenharmony_ci VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdEndQuery); 14118c2ecf20Sopenharmony_ci int ret; 14128c2ecf20Sopenharmony_ci 14138c2ecf20Sopenharmony_ci cmd = container_of(header, typeof(*cmd), header); 14148c2ecf20Sopenharmony_ci if (dev_priv->has_mob) { 14158c2ecf20Sopenharmony_ci VMW_DECLARE_CMD_VAR(gb_cmd, SVGA3dCmdEndGBQuery); 14168c2ecf20Sopenharmony_ci 14178c2ecf20Sopenharmony_ci BUG_ON(sizeof(gb_cmd) != sizeof(*cmd)); 14188c2ecf20Sopenharmony_ci 14198c2ecf20Sopenharmony_ci gb_cmd.header.id = SVGA_3D_CMD_END_GB_QUERY; 14208c2ecf20Sopenharmony_ci gb_cmd.header.size = cmd->header.size; 14218c2ecf20Sopenharmony_ci gb_cmd.body.cid = cmd->body.cid; 14228c2ecf20Sopenharmony_ci gb_cmd.body.type = cmd->body.type; 14238c2ecf20Sopenharmony_ci gb_cmd.body.mobid = cmd->body.guestResult.gmrId; 14248c2ecf20Sopenharmony_ci gb_cmd.body.offset = cmd->body.guestResult.offset; 14258c2ecf20Sopenharmony_ci 14268c2ecf20Sopenharmony_ci memcpy(cmd, &gb_cmd, sizeof(*cmd)); 14278c2ecf20Sopenharmony_ci return vmw_cmd_end_gb_query(dev_priv, sw_context, header); 14288c2ecf20Sopenharmony_ci } 14298c2ecf20Sopenharmony_ci 14308c2ecf20Sopenharmony_ci ret = vmw_cmd_cid_check(dev_priv, sw_context, header); 14318c2ecf20Sopenharmony_ci if (unlikely(ret != 0)) 14328c2ecf20Sopenharmony_ci return ret; 14338c2ecf20Sopenharmony_ci 14348c2ecf20Sopenharmony_ci ret = vmw_translate_guest_ptr(dev_priv, sw_context, 14358c2ecf20Sopenharmony_ci &cmd->body.guestResult, &vmw_bo); 14368c2ecf20Sopenharmony_ci if (unlikely(ret != 0)) 14378c2ecf20Sopenharmony_ci return ret; 14388c2ecf20Sopenharmony_ci 14398c2ecf20Sopenharmony_ci ret = vmw_query_bo_switch_prepare(dev_priv, vmw_bo, sw_context); 14408c2ecf20Sopenharmony_ci 14418c2ecf20Sopenharmony_ci return ret; 14428c2ecf20Sopenharmony_ci} 14438c2ecf20Sopenharmony_ci 14448c2ecf20Sopenharmony_ci/** 14458c2ecf20Sopenharmony_ci * vmw_cmd_wait_gb_query - validate SVGA_3D_CMD_WAIT_GB_QUERY command. 14468c2ecf20Sopenharmony_ci * 14478c2ecf20Sopenharmony_ci * @dev_priv: Pointer to a device private struct. 14488c2ecf20Sopenharmony_ci * @sw_context: The software context used for this command submission. 14498c2ecf20Sopenharmony_ci * @header: Pointer to the command header in the command stream. 14508c2ecf20Sopenharmony_ci */ 14518c2ecf20Sopenharmony_cistatic int vmw_cmd_wait_gb_query(struct vmw_private *dev_priv, 14528c2ecf20Sopenharmony_ci struct vmw_sw_context *sw_context, 14538c2ecf20Sopenharmony_ci SVGA3dCmdHeader *header) 14548c2ecf20Sopenharmony_ci{ 14558c2ecf20Sopenharmony_ci struct vmw_buffer_object *vmw_bo; 14568c2ecf20Sopenharmony_ci VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdWaitForGBQuery); 14578c2ecf20Sopenharmony_ci int ret; 14588c2ecf20Sopenharmony_ci 14598c2ecf20Sopenharmony_ci cmd = container_of(header, typeof(*cmd), header); 14608c2ecf20Sopenharmony_ci ret = vmw_cmd_cid_check(dev_priv, sw_context, header); 14618c2ecf20Sopenharmony_ci if (unlikely(ret != 0)) 14628c2ecf20Sopenharmony_ci return ret; 14638c2ecf20Sopenharmony_ci 14648c2ecf20Sopenharmony_ci ret = vmw_translate_mob_ptr(dev_priv, sw_context, &cmd->body.mobid, 14658c2ecf20Sopenharmony_ci &vmw_bo); 14668c2ecf20Sopenharmony_ci if (unlikely(ret != 0)) 14678c2ecf20Sopenharmony_ci return ret; 14688c2ecf20Sopenharmony_ci 14698c2ecf20Sopenharmony_ci return 0; 14708c2ecf20Sopenharmony_ci} 14718c2ecf20Sopenharmony_ci 14728c2ecf20Sopenharmony_ci/** 14738c2ecf20Sopenharmony_ci * vmw_cmd_wait_query - validate SVGA_3D_CMD_WAIT_QUERY command. 14748c2ecf20Sopenharmony_ci * 14758c2ecf20Sopenharmony_ci * @dev_priv: Pointer to a device private struct. 14768c2ecf20Sopenharmony_ci * @sw_context: The software context used for this command submission. 14778c2ecf20Sopenharmony_ci * @header: Pointer to the command header in the command stream. 14788c2ecf20Sopenharmony_ci */ 14798c2ecf20Sopenharmony_cistatic int vmw_cmd_wait_query(struct vmw_private *dev_priv, 14808c2ecf20Sopenharmony_ci struct vmw_sw_context *sw_context, 14818c2ecf20Sopenharmony_ci SVGA3dCmdHeader *header) 14828c2ecf20Sopenharmony_ci{ 14838c2ecf20Sopenharmony_ci struct vmw_buffer_object *vmw_bo; 14848c2ecf20Sopenharmony_ci VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdWaitForQuery); 14858c2ecf20Sopenharmony_ci int ret; 14868c2ecf20Sopenharmony_ci 14878c2ecf20Sopenharmony_ci cmd = container_of(header, typeof(*cmd), header); 14888c2ecf20Sopenharmony_ci if (dev_priv->has_mob) { 14898c2ecf20Sopenharmony_ci VMW_DECLARE_CMD_VAR(gb_cmd, SVGA3dCmdWaitForGBQuery); 14908c2ecf20Sopenharmony_ci 14918c2ecf20Sopenharmony_ci BUG_ON(sizeof(gb_cmd) != sizeof(*cmd)); 14928c2ecf20Sopenharmony_ci 14938c2ecf20Sopenharmony_ci gb_cmd.header.id = SVGA_3D_CMD_WAIT_FOR_GB_QUERY; 14948c2ecf20Sopenharmony_ci gb_cmd.header.size = cmd->header.size; 14958c2ecf20Sopenharmony_ci gb_cmd.body.cid = cmd->body.cid; 14968c2ecf20Sopenharmony_ci gb_cmd.body.type = cmd->body.type; 14978c2ecf20Sopenharmony_ci gb_cmd.body.mobid = cmd->body.guestResult.gmrId; 14988c2ecf20Sopenharmony_ci gb_cmd.body.offset = cmd->body.guestResult.offset; 14998c2ecf20Sopenharmony_ci 15008c2ecf20Sopenharmony_ci memcpy(cmd, &gb_cmd, sizeof(*cmd)); 15018c2ecf20Sopenharmony_ci return vmw_cmd_wait_gb_query(dev_priv, sw_context, header); 15028c2ecf20Sopenharmony_ci } 15038c2ecf20Sopenharmony_ci 15048c2ecf20Sopenharmony_ci ret = vmw_cmd_cid_check(dev_priv, sw_context, header); 15058c2ecf20Sopenharmony_ci if (unlikely(ret != 0)) 15068c2ecf20Sopenharmony_ci return ret; 15078c2ecf20Sopenharmony_ci 15088c2ecf20Sopenharmony_ci ret = vmw_translate_guest_ptr(dev_priv, sw_context, 15098c2ecf20Sopenharmony_ci &cmd->body.guestResult, &vmw_bo); 15108c2ecf20Sopenharmony_ci if (unlikely(ret != 0)) 15118c2ecf20Sopenharmony_ci return ret; 15128c2ecf20Sopenharmony_ci 15138c2ecf20Sopenharmony_ci return 0; 15148c2ecf20Sopenharmony_ci} 15158c2ecf20Sopenharmony_ci 15168c2ecf20Sopenharmony_cistatic int vmw_cmd_dma(struct vmw_private *dev_priv, 15178c2ecf20Sopenharmony_ci struct vmw_sw_context *sw_context, 15188c2ecf20Sopenharmony_ci SVGA3dCmdHeader *header) 15198c2ecf20Sopenharmony_ci{ 15208c2ecf20Sopenharmony_ci struct vmw_buffer_object *vmw_bo = NULL; 15218c2ecf20Sopenharmony_ci struct vmw_surface *srf = NULL; 15228c2ecf20Sopenharmony_ci VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdSurfaceDMA); 15238c2ecf20Sopenharmony_ci int ret; 15248c2ecf20Sopenharmony_ci SVGA3dCmdSurfaceDMASuffix *suffix; 15258c2ecf20Sopenharmony_ci uint32_t bo_size; 15268c2ecf20Sopenharmony_ci bool dirty; 15278c2ecf20Sopenharmony_ci 15288c2ecf20Sopenharmony_ci cmd = container_of(header, typeof(*cmd), header); 15298c2ecf20Sopenharmony_ci suffix = (SVGA3dCmdSurfaceDMASuffix *)((unsigned long) &cmd->body + 15308c2ecf20Sopenharmony_ci header->size - sizeof(*suffix)); 15318c2ecf20Sopenharmony_ci 15328c2ecf20Sopenharmony_ci /* Make sure device and verifier stays in sync. */ 15338c2ecf20Sopenharmony_ci if (unlikely(suffix->suffixSize != sizeof(*suffix))) { 15348c2ecf20Sopenharmony_ci VMW_DEBUG_USER("Invalid DMA suffix size.\n"); 15358c2ecf20Sopenharmony_ci return -EINVAL; 15368c2ecf20Sopenharmony_ci } 15378c2ecf20Sopenharmony_ci 15388c2ecf20Sopenharmony_ci ret = vmw_translate_guest_ptr(dev_priv, sw_context, 15398c2ecf20Sopenharmony_ci &cmd->body.guest.ptr, &vmw_bo); 15408c2ecf20Sopenharmony_ci if (unlikely(ret != 0)) 15418c2ecf20Sopenharmony_ci return ret; 15428c2ecf20Sopenharmony_ci 15438c2ecf20Sopenharmony_ci /* Make sure DMA doesn't cross BO boundaries. */ 15448c2ecf20Sopenharmony_ci bo_size = vmw_bo->base.num_pages * PAGE_SIZE; 15458c2ecf20Sopenharmony_ci if (unlikely(cmd->body.guest.ptr.offset > bo_size)) { 15468c2ecf20Sopenharmony_ci VMW_DEBUG_USER("Invalid DMA offset.\n"); 15478c2ecf20Sopenharmony_ci return -EINVAL; 15488c2ecf20Sopenharmony_ci } 15498c2ecf20Sopenharmony_ci 15508c2ecf20Sopenharmony_ci bo_size -= cmd->body.guest.ptr.offset; 15518c2ecf20Sopenharmony_ci if (unlikely(suffix->maximumOffset > bo_size)) 15528c2ecf20Sopenharmony_ci suffix->maximumOffset = bo_size; 15538c2ecf20Sopenharmony_ci 15548c2ecf20Sopenharmony_ci dirty = (cmd->body.transfer == SVGA3D_WRITE_HOST_VRAM) ? 15558c2ecf20Sopenharmony_ci VMW_RES_DIRTY_SET : 0; 15568c2ecf20Sopenharmony_ci ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface, 15578c2ecf20Sopenharmony_ci dirty, user_surface_converter, 15588c2ecf20Sopenharmony_ci &cmd->body.host.sid, NULL); 15598c2ecf20Sopenharmony_ci if (unlikely(ret != 0)) { 15608c2ecf20Sopenharmony_ci if (unlikely(ret != -ERESTARTSYS)) 15618c2ecf20Sopenharmony_ci VMW_DEBUG_USER("could not find surface for DMA.\n"); 15628c2ecf20Sopenharmony_ci return ret; 15638c2ecf20Sopenharmony_ci } 15648c2ecf20Sopenharmony_ci 15658c2ecf20Sopenharmony_ci srf = vmw_res_to_srf(sw_context->res_cache[vmw_res_surface].res); 15668c2ecf20Sopenharmony_ci 15678c2ecf20Sopenharmony_ci vmw_kms_cursor_snoop(srf, sw_context->fp->tfile, &vmw_bo->base, header); 15688c2ecf20Sopenharmony_ci 15698c2ecf20Sopenharmony_ci return 0; 15708c2ecf20Sopenharmony_ci} 15718c2ecf20Sopenharmony_ci 15728c2ecf20Sopenharmony_cistatic int vmw_cmd_draw(struct vmw_private *dev_priv, 15738c2ecf20Sopenharmony_ci struct vmw_sw_context *sw_context, 15748c2ecf20Sopenharmony_ci SVGA3dCmdHeader *header) 15758c2ecf20Sopenharmony_ci{ 15768c2ecf20Sopenharmony_ci VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdDrawPrimitives); 15778c2ecf20Sopenharmony_ci SVGA3dVertexDecl *decl = (SVGA3dVertexDecl *)( 15788c2ecf20Sopenharmony_ci (unsigned long)header + sizeof(*cmd)); 15798c2ecf20Sopenharmony_ci SVGA3dPrimitiveRange *range; 15808c2ecf20Sopenharmony_ci uint32_t i; 15818c2ecf20Sopenharmony_ci uint32_t maxnum; 15828c2ecf20Sopenharmony_ci int ret; 15838c2ecf20Sopenharmony_ci 15848c2ecf20Sopenharmony_ci ret = vmw_cmd_cid_check(dev_priv, sw_context, header); 15858c2ecf20Sopenharmony_ci if (unlikely(ret != 0)) 15868c2ecf20Sopenharmony_ci return ret; 15878c2ecf20Sopenharmony_ci 15888c2ecf20Sopenharmony_ci cmd = container_of(header, typeof(*cmd), header); 15898c2ecf20Sopenharmony_ci maxnum = (header->size - sizeof(cmd->body)) / sizeof(*decl); 15908c2ecf20Sopenharmony_ci 15918c2ecf20Sopenharmony_ci if (unlikely(cmd->body.numVertexDecls > maxnum)) { 15928c2ecf20Sopenharmony_ci VMW_DEBUG_USER("Illegal number of vertex declarations.\n"); 15938c2ecf20Sopenharmony_ci return -EINVAL; 15948c2ecf20Sopenharmony_ci } 15958c2ecf20Sopenharmony_ci 15968c2ecf20Sopenharmony_ci for (i = 0; i < cmd->body.numVertexDecls; ++i, ++decl) { 15978c2ecf20Sopenharmony_ci ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface, 15988c2ecf20Sopenharmony_ci VMW_RES_DIRTY_NONE, 15998c2ecf20Sopenharmony_ci user_surface_converter, 16008c2ecf20Sopenharmony_ci &decl->array.surfaceId, NULL); 16018c2ecf20Sopenharmony_ci if (unlikely(ret != 0)) 16028c2ecf20Sopenharmony_ci return ret; 16038c2ecf20Sopenharmony_ci } 16048c2ecf20Sopenharmony_ci 16058c2ecf20Sopenharmony_ci maxnum = (header->size - sizeof(cmd->body) - 16068c2ecf20Sopenharmony_ci cmd->body.numVertexDecls * sizeof(*decl)) / sizeof(*range); 16078c2ecf20Sopenharmony_ci if (unlikely(cmd->body.numRanges > maxnum)) { 16088c2ecf20Sopenharmony_ci VMW_DEBUG_USER("Illegal number of index ranges.\n"); 16098c2ecf20Sopenharmony_ci return -EINVAL; 16108c2ecf20Sopenharmony_ci } 16118c2ecf20Sopenharmony_ci 16128c2ecf20Sopenharmony_ci range = (SVGA3dPrimitiveRange *) decl; 16138c2ecf20Sopenharmony_ci for (i = 0; i < cmd->body.numRanges; ++i, ++range) { 16148c2ecf20Sopenharmony_ci ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface, 16158c2ecf20Sopenharmony_ci VMW_RES_DIRTY_NONE, 16168c2ecf20Sopenharmony_ci user_surface_converter, 16178c2ecf20Sopenharmony_ci &range->indexArray.surfaceId, NULL); 16188c2ecf20Sopenharmony_ci if (unlikely(ret != 0)) 16198c2ecf20Sopenharmony_ci return ret; 16208c2ecf20Sopenharmony_ci } 16218c2ecf20Sopenharmony_ci return 0; 16228c2ecf20Sopenharmony_ci} 16238c2ecf20Sopenharmony_ci 16248c2ecf20Sopenharmony_cistatic int vmw_cmd_tex_state(struct vmw_private *dev_priv, 16258c2ecf20Sopenharmony_ci struct vmw_sw_context *sw_context, 16268c2ecf20Sopenharmony_ci SVGA3dCmdHeader *header) 16278c2ecf20Sopenharmony_ci{ 16288c2ecf20Sopenharmony_ci VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdSetTextureState); 16298c2ecf20Sopenharmony_ci SVGA3dTextureState *last_state = (SVGA3dTextureState *) 16308c2ecf20Sopenharmony_ci ((unsigned long) header + header->size + sizeof(*header)); 16318c2ecf20Sopenharmony_ci SVGA3dTextureState *cur_state = (SVGA3dTextureState *) 16328c2ecf20Sopenharmony_ci ((unsigned long) header + sizeof(*cmd)); 16338c2ecf20Sopenharmony_ci struct vmw_resource *ctx; 16348c2ecf20Sopenharmony_ci struct vmw_resource *res; 16358c2ecf20Sopenharmony_ci int ret; 16368c2ecf20Sopenharmony_ci 16378c2ecf20Sopenharmony_ci cmd = container_of(header, typeof(*cmd), header); 16388c2ecf20Sopenharmony_ci 16398c2ecf20Sopenharmony_ci ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_context, 16408c2ecf20Sopenharmony_ci VMW_RES_DIRTY_SET, user_context_converter, 16418c2ecf20Sopenharmony_ci &cmd->body.cid, &ctx); 16428c2ecf20Sopenharmony_ci if (unlikely(ret != 0)) 16438c2ecf20Sopenharmony_ci return ret; 16448c2ecf20Sopenharmony_ci 16458c2ecf20Sopenharmony_ci for (; cur_state < last_state; ++cur_state) { 16468c2ecf20Sopenharmony_ci if (likely(cur_state->name != SVGA3D_TS_BIND_TEXTURE)) 16478c2ecf20Sopenharmony_ci continue; 16488c2ecf20Sopenharmony_ci 16498c2ecf20Sopenharmony_ci if (cur_state->stage >= SVGA3D_NUM_TEXTURE_UNITS) { 16508c2ecf20Sopenharmony_ci VMW_DEBUG_USER("Illegal texture/sampler unit %u.\n", 16518c2ecf20Sopenharmony_ci (unsigned int) cur_state->stage); 16528c2ecf20Sopenharmony_ci return -EINVAL; 16538c2ecf20Sopenharmony_ci } 16548c2ecf20Sopenharmony_ci 16558c2ecf20Sopenharmony_ci ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface, 16568c2ecf20Sopenharmony_ci VMW_RES_DIRTY_NONE, 16578c2ecf20Sopenharmony_ci user_surface_converter, 16588c2ecf20Sopenharmony_ci &cur_state->value, &res); 16598c2ecf20Sopenharmony_ci if (unlikely(ret != 0)) 16608c2ecf20Sopenharmony_ci return ret; 16618c2ecf20Sopenharmony_ci 16628c2ecf20Sopenharmony_ci if (dev_priv->has_mob) { 16638c2ecf20Sopenharmony_ci struct vmw_ctx_bindinfo_tex binding; 16648c2ecf20Sopenharmony_ci struct vmw_ctx_validation_info *node; 16658c2ecf20Sopenharmony_ci 16668c2ecf20Sopenharmony_ci node = vmw_execbuf_info_from_res(sw_context, ctx); 16678c2ecf20Sopenharmony_ci if (!node) 16688c2ecf20Sopenharmony_ci return -EINVAL; 16698c2ecf20Sopenharmony_ci 16708c2ecf20Sopenharmony_ci binding.bi.ctx = ctx; 16718c2ecf20Sopenharmony_ci binding.bi.res = res; 16728c2ecf20Sopenharmony_ci binding.bi.bt = vmw_ctx_binding_tex; 16738c2ecf20Sopenharmony_ci binding.texture_stage = cur_state->stage; 16748c2ecf20Sopenharmony_ci vmw_binding_add(node->staged, &binding.bi, 0, 16758c2ecf20Sopenharmony_ci binding.texture_stage); 16768c2ecf20Sopenharmony_ci } 16778c2ecf20Sopenharmony_ci } 16788c2ecf20Sopenharmony_ci 16798c2ecf20Sopenharmony_ci return 0; 16808c2ecf20Sopenharmony_ci} 16818c2ecf20Sopenharmony_ci 16828c2ecf20Sopenharmony_cistatic int vmw_cmd_check_define_gmrfb(struct vmw_private *dev_priv, 16838c2ecf20Sopenharmony_ci struct vmw_sw_context *sw_context, 16848c2ecf20Sopenharmony_ci void *buf) 16858c2ecf20Sopenharmony_ci{ 16868c2ecf20Sopenharmony_ci struct vmw_buffer_object *vmw_bo; 16878c2ecf20Sopenharmony_ci 16888c2ecf20Sopenharmony_ci struct { 16898c2ecf20Sopenharmony_ci uint32_t header; 16908c2ecf20Sopenharmony_ci SVGAFifoCmdDefineGMRFB body; 16918c2ecf20Sopenharmony_ci } *cmd = buf; 16928c2ecf20Sopenharmony_ci 16938c2ecf20Sopenharmony_ci return vmw_translate_guest_ptr(dev_priv, sw_context, &cmd->body.ptr, 16948c2ecf20Sopenharmony_ci &vmw_bo); 16958c2ecf20Sopenharmony_ci} 16968c2ecf20Sopenharmony_ci 16978c2ecf20Sopenharmony_ci/** 16988c2ecf20Sopenharmony_ci * vmw_cmd_res_switch_backup - Utility function to handle backup buffer 16998c2ecf20Sopenharmony_ci * switching 17008c2ecf20Sopenharmony_ci * 17018c2ecf20Sopenharmony_ci * @dev_priv: Pointer to a device private struct. 17028c2ecf20Sopenharmony_ci * @sw_context: The software context being used for this batch. 17038c2ecf20Sopenharmony_ci * @val_node: The validation node representing the resource. 17048c2ecf20Sopenharmony_ci * @buf_id: Pointer to the user-space backup buffer handle in the command 17058c2ecf20Sopenharmony_ci * stream. 17068c2ecf20Sopenharmony_ci * @backup_offset: Offset of backup into MOB. 17078c2ecf20Sopenharmony_ci * 17088c2ecf20Sopenharmony_ci * This function prepares for registering a switch of backup buffers in the 17098c2ecf20Sopenharmony_ci * resource metadata just prior to unreserving. It's basically a wrapper around 17108c2ecf20Sopenharmony_ci * vmw_cmd_res_switch_backup with a different interface. 17118c2ecf20Sopenharmony_ci */ 17128c2ecf20Sopenharmony_cistatic int vmw_cmd_res_switch_backup(struct vmw_private *dev_priv, 17138c2ecf20Sopenharmony_ci struct vmw_sw_context *sw_context, 17148c2ecf20Sopenharmony_ci struct vmw_resource *res, uint32_t *buf_id, 17158c2ecf20Sopenharmony_ci unsigned long backup_offset) 17168c2ecf20Sopenharmony_ci{ 17178c2ecf20Sopenharmony_ci struct vmw_buffer_object *vbo; 17188c2ecf20Sopenharmony_ci void *info; 17198c2ecf20Sopenharmony_ci int ret; 17208c2ecf20Sopenharmony_ci 17218c2ecf20Sopenharmony_ci info = vmw_execbuf_info_from_res(sw_context, res); 17228c2ecf20Sopenharmony_ci if (!info) 17238c2ecf20Sopenharmony_ci return -EINVAL; 17248c2ecf20Sopenharmony_ci 17258c2ecf20Sopenharmony_ci ret = vmw_translate_mob_ptr(dev_priv, sw_context, buf_id, &vbo); 17268c2ecf20Sopenharmony_ci if (ret) 17278c2ecf20Sopenharmony_ci return ret; 17288c2ecf20Sopenharmony_ci 17298c2ecf20Sopenharmony_ci vmw_validation_res_switch_backup(sw_context->ctx, info, vbo, 17308c2ecf20Sopenharmony_ci backup_offset); 17318c2ecf20Sopenharmony_ci return 0; 17328c2ecf20Sopenharmony_ci} 17338c2ecf20Sopenharmony_ci 17348c2ecf20Sopenharmony_ci/** 17358c2ecf20Sopenharmony_ci * vmw_cmd_switch_backup - Utility function to handle backup buffer switching 17368c2ecf20Sopenharmony_ci * 17378c2ecf20Sopenharmony_ci * @dev_priv: Pointer to a device private struct. 17388c2ecf20Sopenharmony_ci * @sw_context: The software context being used for this batch. 17398c2ecf20Sopenharmony_ci * @res_type: The resource type. 17408c2ecf20Sopenharmony_ci * @converter: Information about user-space binding for this resource type. 17418c2ecf20Sopenharmony_ci * @res_id: Pointer to the user-space resource handle in the command stream. 17428c2ecf20Sopenharmony_ci * @buf_id: Pointer to the user-space backup buffer handle in the command 17438c2ecf20Sopenharmony_ci * stream. 17448c2ecf20Sopenharmony_ci * @backup_offset: Offset of backup into MOB. 17458c2ecf20Sopenharmony_ci * 17468c2ecf20Sopenharmony_ci * This function prepares for registering a switch of backup buffers in the 17478c2ecf20Sopenharmony_ci * resource metadata just prior to unreserving. It's basically a wrapper around 17488c2ecf20Sopenharmony_ci * vmw_cmd_res_switch_backup with a different interface. 17498c2ecf20Sopenharmony_ci */ 17508c2ecf20Sopenharmony_cistatic int vmw_cmd_switch_backup(struct vmw_private *dev_priv, 17518c2ecf20Sopenharmony_ci struct vmw_sw_context *sw_context, 17528c2ecf20Sopenharmony_ci enum vmw_res_type res_type, 17538c2ecf20Sopenharmony_ci const struct vmw_user_resource_conv 17548c2ecf20Sopenharmony_ci *converter, uint32_t *res_id, uint32_t *buf_id, 17558c2ecf20Sopenharmony_ci unsigned long backup_offset) 17568c2ecf20Sopenharmony_ci{ 17578c2ecf20Sopenharmony_ci struct vmw_resource *res; 17588c2ecf20Sopenharmony_ci int ret; 17598c2ecf20Sopenharmony_ci 17608c2ecf20Sopenharmony_ci ret = vmw_cmd_res_check(dev_priv, sw_context, res_type, 17618c2ecf20Sopenharmony_ci VMW_RES_DIRTY_NONE, converter, res_id, &res); 17628c2ecf20Sopenharmony_ci if (ret) 17638c2ecf20Sopenharmony_ci return ret; 17648c2ecf20Sopenharmony_ci 17658c2ecf20Sopenharmony_ci return vmw_cmd_res_switch_backup(dev_priv, sw_context, res, buf_id, 17668c2ecf20Sopenharmony_ci backup_offset); 17678c2ecf20Sopenharmony_ci} 17688c2ecf20Sopenharmony_ci 17698c2ecf20Sopenharmony_ci/** 17708c2ecf20Sopenharmony_ci * vmw_cmd_bind_gb_surface - Validate SVGA_3D_CMD_BIND_GB_SURFACE command 17718c2ecf20Sopenharmony_ci * 17728c2ecf20Sopenharmony_ci * @dev_priv: Pointer to a device private struct. 17738c2ecf20Sopenharmony_ci * @sw_context: The software context being used for this batch. 17748c2ecf20Sopenharmony_ci * @header: Pointer to the command header in the command stream. 17758c2ecf20Sopenharmony_ci */ 17768c2ecf20Sopenharmony_cistatic int vmw_cmd_bind_gb_surface(struct vmw_private *dev_priv, 17778c2ecf20Sopenharmony_ci struct vmw_sw_context *sw_context, 17788c2ecf20Sopenharmony_ci SVGA3dCmdHeader *header) 17798c2ecf20Sopenharmony_ci{ 17808c2ecf20Sopenharmony_ci VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdBindGBSurface) = 17818c2ecf20Sopenharmony_ci container_of(header, typeof(*cmd), header); 17828c2ecf20Sopenharmony_ci 17838c2ecf20Sopenharmony_ci return vmw_cmd_switch_backup(dev_priv, sw_context, vmw_res_surface, 17848c2ecf20Sopenharmony_ci user_surface_converter, &cmd->body.sid, 17858c2ecf20Sopenharmony_ci &cmd->body.mobid, 0); 17868c2ecf20Sopenharmony_ci} 17878c2ecf20Sopenharmony_ci 17888c2ecf20Sopenharmony_ci/** 17898c2ecf20Sopenharmony_ci * vmw_cmd_update_gb_image - Validate SVGA_3D_CMD_UPDATE_GB_IMAGE command 17908c2ecf20Sopenharmony_ci * 17918c2ecf20Sopenharmony_ci * @dev_priv: Pointer to a device private struct. 17928c2ecf20Sopenharmony_ci * @sw_context: The software context being used for this batch. 17938c2ecf20Sopenharmony_ci * @header: Pointer to the command header in the command stream. 17948c2ecf20Sopenharmony_ci */ 17958c2ecf20Sopenharmony_cistatic int vmw_cmd_update_gb_image(struct vmw_private *dev_priv, 17968c2ecf20Sopenharmony_ci struct vmw_sw_context *sw_context, 17978c2ecf20Sopenharmony_ci SVGA3dCmdHeader *header) 17988c2ecf20Sopenharmony_ci{ 17998c2ecf20Sopenharmony_ci VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdUpdateGBImage) = 18008c2ecf20Sopenharmony_ci container_of(header, typeof(*cmd), header); 18018c2ecf20Sopenharmony_ci 18028c2ecf20Sopenharmony_ci return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface, 18038c2ecf20Sopenharmony_ci VMW_RES_DIRTY_NONE, user_surface_converter, 18048c2ecf20Sopenharmony_ci &cmd->body.image.sid, NULL); 18058c2ecf20Sopenharmony_ci} 18068c2ecf20Sopenharmony_ci 18078c2ecf20Sopenharmony_ci/** 18088c2ecf20Sopenharmony_ci * vmw_cmd_update_gb_surface - Validate SVGA_3D_CMD_UPDATE_GB_SURFACE command 18098c2ecf20Sopenharmony_ci * 18108c2ecf20Sopenharmony_ci * @dev_priv: Pointer to a device private struct. 18118c2ecf20Sopenharmony_ci * @sw_context: The software context being used for this batch. 18128c2ecf20Sopenharmony_ci * @header: Pointer to the command header in the command stream. 18138c2ecf20Sopenharmony_ci */ 18148c2ecf20Sopenharmony_cistatic int vmw_cmd_update_gb_surface(struct vmw_private *dev_priv, 18158c2ecf20Sopenharmony_ci struct vmw_sw_context *sw_context, 18168c2ecf20Sopenharmony_ci SVGA3dCmdHeader *header) 18178c2ecf20Sopenharmony_ci{ 18188c2ecf20Sopenharmony_ci VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdUpdateGBSurface) = 18198c2ecf20Sopenharmony_ci container_of(header, typeof(*cmd), header); 18208c2ecf20Sopenharmony_ci 18218c2ecf20Sopenharmony_ci return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface, 18228c2ecf20Sopenharmony_ci VMW_RES_DIRTY_CLEAR, user_surface_converter, 18238c2ecf20Sopenharmony_ci &cmd->body.sid, NULL); 18248c2ecf20Sopenharmony_ci} 18258c2ecf20Sopenharmony_ci 18268c2ecf20Sopenharmony_ci/** 18278c2ecf20Sopenharmony_ci * vmw_cmd_readback_gb_image - Validate SVGA_3D_CMD_READBACK_GB_IMAGE command 18288c2ecf20Sopenharmony_ci * 18298c2ecf20Sopenharmony_ci * @dev_priv: Pointer to a device private struct. 18308c2ecf20Sopenharmony_ci * @sw_context: The software context being used for this batch. 18318c2ecf20Sopenharmony_ci * @header: Pointer to the command header in the command stream. 18328c2ecf20Sopenharmony_ci */ 18338c2ecf20Sopenharmony_cistatic int vmw_cmd_readback_gb_image(struct vmw_private *dev_priv, 18348c2ecf20Sopenharmony_ci struct vmw_sw_context *sw_context, 18358c2ecf20Sopenharmony_ci SVGA3dCmdHeader *header) 18368c2ecf20Sopenharmony_ci{ 18378c2ecf20Sopenharmony_ci VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdReadbackGBImage) = 18388c2ecf20Sopenharmony_ci container_of(header, typeof(*cmd), header); 18398c2ecf20Sopenharmony_ci 18408c2ecf20Sopenharmony_ci return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface, 18418c2ecf20Sopenharmony_ci VMW_RES_DIRTY_NONE, user_surface_converter, 18428c2ecf20Sopenharmony_ci &cmd->body.image.sid, NULL); 18438c2ecf20Sopenharmony_ci} 18448c2ecf20Sopenharmony_ci 18458c2ecf20Sopenharmony_ci/** 18468c2ecf20Sopenharmony_ci * vmw_cmd_readback_gb_surface - Validate SVGA_3D_CMD_READBACK_GB_SURFACE 18478c2ecf20Sopenharmony_ci * command 18488c2ecf20Sopenharmony_ci * 18498c2ecf20Sopenharmony_ci * @dev_priv: Pointer to a device private struct. 18508c2ecf20Sopenharmony_ci * @sw_context: The software context being used for this batch. 18518c2ecf20Sopenharmony_ci * @header: Pointer to the command header in the command stream. 18528c2ecf20Sopenharmony_ci */ 18538c2ecf20Sopenharmony_cistatic int vmw_cmd_readback_gb_surface(struct vmw_private *dev_priv, 18548c2ecf20Sopenharmony_ci struct vmw_sw_context *sw_context, 18558c2ecf20Sopenharmony_ci SVGA3dCmdHeader *header) 18568c2ecf20Sopenharmony_ci{ 18578c2ecf20Sopenharmony_ci VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdReadbackGBSurface) = 18588c2ecf20Sopenharmony_ci container_of(header, typeof(*cmd), header); 18598c2ecf20Sopenharmony_ci 18608c2ecf20Sopenharmony_ci return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface, 18618c2ecf20Sopenharmony_ci VMW_RES_DIRTY_CLEAR, user_surface_converter, 18628c2ecf20Sopenharmony_ci &cmd->body.sid, NULL); 18638c2ecf20Sopenharmony_ci} 18648c2ecf20Sopenharmony_ci 18658c2ecf20Sopenharmony_ci/** 18668c2ecf20Sopenharmony_ci * vmw_cmd_invalidate_gb_image - Validate SVGA_3D_CMD_INVALIDATE_GB_IMAGE 18678c2ecf20Sopenharmony_ci * command 18688c2ecf20Sopenharmony_ci * 18698c2ecf20Sopenharmony_ci * @dev_priv: Pointer to a device private struct. 18708c2ecf20Sopenharmony_ci * @sw_context: The software context being used for this batch. 18718c2ecf20Sopenharmony_ci * @header: Pointer to the command header in the command stream. 18728c2ecf20Sopenharmony_ci */ 18738c2ecf20Sopenharmony_cistatic int vmw_cmd_invalidate_gb_image(struct vmw_private *dev_priv, 18748c2ecf20Sopenharmony_ci struct vmw_sw_context *sw_context, 18758c2ecf20Sopenharmony_ci SVGA3dCmdHeader *header) 18768c2ecf20Sopenharmony_ci{ 18778c2ecf20Sopenharmony_ci VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdInvalidateGBImage) = 18788c2ecf20Sopenharmony_ci container_of(header, typeof(*cmd), header); 18798c2ecf20Sopenharmony_ci 18808c2ecf20Sopenharmony_ci return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface, 18818c2ecf20Sopenharmony_ci VMW_RES_DIRTY_NONE, user_surface_converter, 18828c2ecf20Sopenharmony_ci &cmd->body.image.sid, NULL); 18838c2ecf20Sopenharmony_ci} 18848c2ecf20Sopenharmony_ci 18858c2ecf20Sopenharmony_ci/** 18868c2ecf20Sopenharmony_ci * vmw_cmd_invalidate_gb_surface - Validate SVGA_3D_CMD_INVALIDATE_GB_SURFACE 18878c2ecf20Sopenharmony_ci * command 18888c2ecf20Sopenharmony_ci * 18898c2ecf20Sopenharmony_ci * @dev_priv: Pointer to a device private struct. 18908c2ecf20Sopenharmony_ci * @sw_context: The software context being used for this batch. 18918c2ecf20Sopenharmony_ci * @header: Pointer to the command header in the command stream. 18928c2ecf20Sopenharmony_ci */ 18938c2ecf20Sopenharmony_cistatic int vmw_cmd_invalidate_gb_surface(struct vmw_private *dev_priv, 18948c2ecf20Sopenharmony_ci struct vmw_sw_context *sw_context, 18958c2ecf20Sopenharmony_ci SVGA3dCmdHeader *header) 18968c2ecf20Sopenharmony_ci{ 18978c2ecf20Sopenharmony_ci VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdInvalidateGBSurface) = 18988c2ecf20Sopenharmony_ci container_of(header, typeof(*cmd), header); 18998c2ecf20Sopenharmony_ci 19008c2ecf20Sopenharmony_ci return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface, 19018c2ecf20Sopenharmony_ci VMW_RES_DIRTY_CLEAR, user_surface_converter, 19028c2ecf20Sopenharmony_ci &cmd->body.sid, NULL); 19038c2ecf20Sopenharmony_ci} 19048c2ecf20Sopenharmony_ci 19058c2ecf20Sopenharmony_ci/** 19068c2ecf20Sopenharmony_ci * vmw_cmd_shader_define - Validate SVGA_3D_CMD_SHADER_DEFINE command 19078c2ecf20Sopenharmony_ci * 19088c2ecf20Sopenharmony_ci * @dev_priv: Pointer to a device private struct. 19098c2ecf20Sopenharmony_ci * @sw_context: The software context being used for this batch. 19108c2ecf20Sopenharmony_ci * @header: Pointer to the command header in the command stream. 19118c2ecf20Sopenharmony_ci */ 19128c2ecf20Sopenharmony_cistatic int vmw_cmd_shader_define(struct vmw_private *dev_priv, 19138c2ecf20Sopenharmony_ci struct vmw_sw_context *sw_context, 19148c2ecf20Sopenharmony_ci SVGA3dCmdHeader *header) 19158c2ecf20Sopenharmony_ci{ 19168c2ecf20Sopenharmony_ci VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdDefineShader); 19178c2ecf20Sopenharmony_ci int ret; 19188c2ecf20Sopenharmony_ci size_t size; 19198c2ecf20Sopenharmony_ci struct vmw_resource *ctx; 19208c2ecf20Sopenharmony_ci 19218c2ecf20Sopenharmony_ci cmd = container_of(header, typeof(*cmd), header); 19228c2ecf20Sopenharmony_ci 19238c2ecf20Sopenharmony_ci ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_context, 19248c2ecf20Sopenharmony_ci VMW_RES_DIRTY_SET, user_context_converter, 19258c2ecf20Sopenharmony_ci &cmd->body.cid, &ctx); 19268c2ecf20Sopenharmony_ci if (unlikely(ret != 0)) 19278c2ecf20Sopenharmony_ci return ret; 19288c2ecf20Sopenharmony_ci 19298c2ecf20Sopenharmony_ci if (unlikely(!dev_priv->has_mob)) 19308c2ecf20Sopenharmony_ci return 0; 19318c2ecf20Sopenharmony_ci 19328c2ecf20Sopenharmony_ci size = cmd->header.size - sizeof(cmd->body); 19338c2ecf20Sopenharmony_ci ret = vmw_compat_shader_add(dev_priv, vmw_context_res_man(ctx), 19348c2ecf20Sopenharmony_ci cmd->body.shid, cmd + 1, cmd->body.type, 19358c2ecf20Sopenharmony_ci size, &sw_context->staged_cmd_res); 19368c2ecf20Sopenharmony_ci if (unlikely(ret != 0)) 19378c2ecf20Sopenharmony_ci return ret; 19388c2ecf20Sopenharmony_ci 19398c2ecf20Sopenharmony_ci return vmw_resource_relocation_add(sw_context, NULL, 19408c2ecf20Sopenharmony_ci vmw_ptr_diff(sw_context->buf_start, 19418c2ecf20Sopenharmony_ci &cmd->header.id), 19428c2ecf20Sopenharmony_ci vmw_res_rel_nop); 19438c2ecf20Sopenharmony_ci} 19448c2ecf20Sopenharmony_ci 19458c2ecf20Sopenharmony_ci/** 19468c2ecf20Sopenharmony_ci * vmw_cmd_shader_destroy - Validate SVGA_3D_CMD_SHADER_DESTROY command 19478c2ecf20Sopenharmony_ci * 19488c2ecf20Sopenharmony_ci * @dev_priv: Pointer to a device private struct. 19498c2ecf20Sopenharmony_ci * @sw_context: The software context being used for this batch. 19508c2ecf20Sopenharmony_ci * @header: Pointer to the command header in the command stream. 19518c2ecf20Sopenharmony_ci */ 19528c2ecf20Sopenharmony_cistatic int vmw_cmd_shader_destroy(struct vmw_private *dev_priv, 19538c2ecf20Sopenharmony_ci struct vmw_sw_context *sw_context, 19548c2ecf20Sopenharmony_ci SVGA3dCmdHeader *header) 19558c2ecf20Sopenharmony_ci{ 19568c2ecf20Sopenharmony_ci VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdDestroyShader); 19578c2ecf20Sopenharmony_ci int ret; 19588c2ecf20Sopenharmony_ci struct vmw_resource *ctx; 19598c2ecf20Sopenharmony_ci 19608c2ecf20Sopenharmony_ci cmd = container_of(header, typeof(*cmd), header); 19618c2ecf20Sopenharmony_ci 19628c2ecf20Sopenharmony_ci ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_context, 19638c2ecf20Sopenharmony_ci VMW_RES_DIRTY_SET, user_context_converter, 19648c2ecf20Sopenharmony_ci &cmd->body.cid, &ctx); 19658c2ecf20Sopenharmony_ci if (unlikely(ret != 0)) 19668c2ecf20Sopenharmony_ci return ret; 19678c2ecf20Sopenharmony_ci 19688c2ecf20Sopenharmony_ci if (unlikely(!dev_priv->has_mob)) 19698c2ecf20Sopenharmony_ci return 0; 19708c2ecf20Sopenharmony_ci 19718c2ecf20Sopenharmony_ci ret = vmw_shader_remove(vmw_context_res_man(ctx), cmd->body.shid, 19728c2ecf20Sopenharmony_ci cmd->body.type, &sw_context->staged_cmd_res); 19738c2ecf20Sopenharmony_ci if (unlikely(ret != 0)) 19748c2ecf20Sopenharmony_ci return ret; 19758c2ecf20Sopenharmony_ci 19768c2ecf20Sopenharmony_ci return vmw_resource_relocation_add(sw_context, NULL, 19778c2ecf20Sopenharmony_ci vmw_ptr_diff(sw_context->buf_start, 19788c2ecf20Sopenharmony_ci &cmd->header.id), 19798c2ecf20Sopenharmony_ci vmw_res_rel_nop); 19808c2ecf20Sopenharmony_ci} 19818c2ecf20Sopenharmony_ci 19828c2ecf20Sopenharmony_ci/** 19838c2ecf20Sopenharmony_ci * vmw_cmd_set_shader - Validate SVGA_3D_CMD_SET_SHADER command 19848c2ecf20Sopenharmony_ci * 19858c2ecf20Sopenharmony_ci * @dev_priv: Pointer to a device private struct. 19868c2ecf20Sopenharmony_ci * @sw_context: The software context being used for this batch. 19878c2ecf20Sopenharmony_ci * @header: Pointer to the command header in the command stream. 19888c2ecf20Sopenharmony_ci */ 19898c2ecf20Sopenharmony_cistatic int vmw_cmd_set_shader(struct vmw_private *dev_priv, 19908c2ecf20Sopenharmony_ci struct vmw_sw_context *sw_context, 19918c2ecf20Sopenharmony_ci SVGA3dCmdHeader *header) 19928c2ecf20Sopenharmony_ci{ 19938c2ecf20Sopenharmony_ci VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdSetShader); 19948c2ecf20Sopenharmony_ci struct vmw_ctx_bindinfo_shader binding; 19958c2ecf20Sopenharmony_ci struct vmw_resource *ctx, *res = NULL; 19968c2ecf20Sopenharmony_ci struct vmw_ctx_validation_info *ctx_info; 19978c2ecf20Sopenharmony_ci int ret; 19988c2ecf20Sopenharmony_ci 19998c2ecf20Sopenharmony_ci cmd = container_of(header, typeof(*cmd), header); 20008c2ecf20Sopenharmony_ci 20018c2ecf20Sopenharmony_ci if (!vmw_shadertype_is_valid(VMW_SM_LEGACY, cmd->body.type)) { 20028c2ecf20Sopenharmony_ci VMW_DEBUG_USER("Illegal shader type %u.\n", 20038c2ecf20Sopenharmony_ci (unsigned int) cmd->body.type); 20048c2ecf20Sopenharmony_ci return -EINVAL; 20058c2ecf20Sopenharmony_ci } 20068c2ecf20Sopenharmony_ci 20078c2ecf20Sopenharmony_ci ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_context, 20088c2ecf20Sopenharmony_ci VMW_RES_DIRTY_SET, user_context_converter, 20098c2ecf20Sopenharmony_ci &cmd->body.cid, &ctx); 20108c2ecf20Sopenharmony_ci if (unlikely(ret != 0)) 20118c2ecf20Sopenharmony_ci return ret; 20128c2ecf20Sopenharmony_ci 20138c2ecf20Sopenharmony_ci if (!dev_priv->has_mob) 20148c2ecf20Sopenharmony_ci return 0; 20158c2ecf20Sopenharmony_ci 20168c2ecf20Sopenharmony_ci if (cmd->body.shid != SVGA3D_INVALID_ID) { 20178c2ecf20Sopenharmony_ci /* 20188c2ecf20Sopenharmony_ci * This is the compat shader path - Per device guest-backed 20198c2ecf20Sopenharmony_ci * shaders, but user-space thinks it's per context host- 20208c2ecf20Sopenharmony_ci * backed shaders. 20218c2ecf20Sopenharmony_ci */ 20228c2ecf20Sopenharmony_ci res = vmw_shader_lookup(vmw_context_res_man(ctx), 20238c2ecf20Sopenharmony_ci cmd->body.shid, cmd->body.type); 20248c2ecf20Sopenharmony_ci if (!IS_ERR(res)) { 20258c2ecf20Sopenharmony_ci ret = vmw_execbuf_res_noctx_val_add(sw_context, res, 20268c2ecf20Sopenharmony_ci VMW_RES_DIRTY_NONE); 20278c2ecf20Sopenharmony_ci if (unlikely(ret != 0)) 20288c2ecf20Sopenharmony_ci return ret; 20298c2ecf20Sopenharmony_ci 20308c2ecf20Sopenharmony_ci ret = vmw_resource_relocation_add 20318c2ecf20Sopenharmony_ci (sw_context, res, 20328c2ecf20Sopenharmony_ci vmw_ptr_diff(sw_context->buf_start, 20338c2ecf20Sopenharmony_ci &cmd->body.shid), 20348c2ecf20Sopenharmony_ci vmw_res_rel_normal); 20358c2ecf20Sopenharmony_ci if (unlikely(ret != 0)) 20368c2ecf20Sopenharmony_ci return ret; 20378c2ecf20Sopenharmony_ci } 20388c2ecf20Sopenharmony_ci } 20398c2ecf20Sopenharmony_ci 20408c2ecf20Sopenharmony_ci if (IS_ERR_OR_NULL(res)) { 20418c2ecf20Sopenharmony_ci ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_shader, 20428c2ecf20Sopenharmony_ci VMW_RES_DIRTY_NONE, 20438c2ecf20Sopenharmony_ci user_shader_converter, &cmd->body.shid, 20448c2ecf20Sopenharmony_ci &res); 20458c2ecf20Sopenharmony_ci if (unlikely(ret != 0)) 20468c2ecf20Sopenharmony_ci return ret; 20478c2ecf20Sopenharmony_ci } 20488c2ecf20Sopenharmony_ci 20498c2ecf20Sopenharmony_ci ctx_info = vmw_execbuf_info_from_res(sw_context, ctx); 20508c2ecf20Sopenharmony_ci if (!ctx_info) 20518c2ecf20Sopenharmony_ci return -EINVAL; 20528c2ecf20Sopenharmony_ci 20538c2ecf20Sopenharmony_ci binding.bi.ctx = ctx; 20548c2ecf20Sopenharmony_ci binding.bi.res = res; 20558c2ecf20Sopenharmony_ci binding.bi.bt = vmw_ctx_binding_shader; 20568c2ecf20Sopenharmony_ci binding.shader_slot = cmd->body.type - SVGA3D_SHADERTYPE_MIN; 20578c2ecf20Sopenharmony_ci vmw_binding_add(ctx_info->staged, &binding.bi, binding.shader_slot, 0); 20588c2ecf20Sopenharmony_ci 20598c2ecf20Sopenharmony_ci return 0; 20608c2ecf20Sopenharmony_ci} 20618c2ecf20Sopenharmony_ci 20628c2ecf20Sopenharmony_ci/** 20638c2ecf20Sopenharmony_ci * vmw_cmd_set_shader_const - Validate SVGA_3D_CMD_SET_SHADER_CONST command 20648c2ecf20Sopenharmony_ci * 20658c2ecf20Sopenharmony_ci * @dev_priv: Pointer to a device private struct. 20668c2ecf20Sopenharmony_ci * @sw_context: The software context being used for this batch. 20678c2ecf20Sopenharmony_ci * @header: Pointer to the command header in the command stream. 20688c2ecf20Sopenharmony_ci */ 20698c2ecf20Sopenharmony_cistatic int vmw_cmd_set_shader_const(struct vmw_private *dev_priv, 20708c2ecf20Sopenharmony_ci struct vmw_sw_context *sw_context, 20718c2ecf20Sopenharmony_ci SVGA3dCmdHeader *header) 20728c2ecf20Sopenharmony_ci{ 20738c2ecf20Sopenharmony_ci VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdSetShaderConst); 20748c2ecf20Sopenharmony_ci int ret; 20758c2ecf20Sopenharmony_ci 20768c2ecf20Sopenharmony_ci cmd = container_of(header, typeof(*cmd), header); 20778c2ecf20Sopenharmony_ci 20788c2ecf20Sopenharmony_ci ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_context, 20798c2ecf20Sopenharmony_ci VMW_RES_DIRTY_SET, user_context_converter, 20808c2ecf20Sopenharmony_ci &cmd->body.cid, NULL); 20818c2ecf20Sopenharmony_ci if (unlikely(ret != 0)) 20828c2ecf20Sopenharmony_ci return ret; 20838c2ecf20Sopenharmony_ci 20848c2ecf20Sopenharmony_ci if (dev_priv->has_mob) 20858c2ecf20Sopenharmony_ci header->id = SVGA_3D_CMD_SET_GB_SHADERCONSTS_INLINE; 20868c2ecf20Sopenharmony_ci 20878c2ecf20Sopenharmony_ci return 0; 20888c2ecf20Sopenharmony_ci} 20898c2ecf20Sopenharmony_ci 20908c2ecf20Sopenharmony_ci/** 20918c2ecf20Sopenharmony_ci * vmw_cmd_bind_gb_shader - Validate SVGA_3D_CMD_BIND_GB_SHADER command 20928c2ecf20Sopenharmony_ci * 20938c2ecf20Sopenharmony_ci * @dev_priv: Pointer to a device private struct. 20948c2ecf20Sopenharmony_ci * @sw_context: The software context being used for this batch. 20958c2ecf20Sopenharmony_ci * @header: Pointer to the command header in the command stream. 20968c2ecf20Sopenharmony_ci */ 20978c2ecf20Sopenharmony_cistatic int vmw_cmd_bind_gb_shader(struct vmw_private *dev_priv, 20988c2ecf20Sopenharmony_ci struct vmw_sw_context *sw_context, 20998c2ecf20Sopenharmony_ci SVGA3dCmdHeader *header) 21008c2ecf20Sopenharmony_ci{ 21018c2ecf20Sopenharmony_ci VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdBindGBShader) = 21028c2ecf20Sopenharmony_ci container_of(header, typeof(*cmd), header); 21038c2ecf20Sopenharmony_ci 21048c2ecf20Sopenharmony_ci return vmw_cmd_switch_backup(dev_priv, sw_context, vmw_res_shader, 21058c2ecf20Sopenharmony_ci user_shader_converter, &cmd->body.shid, 21068c2ecf20Sopenharmony_ci &cmd->body.mobid, cmd->body.offsetInBytes); 21078c2ecf20Sopenharmony_ci} 21088c2ecf20Sopenharmony_ci 21098c2ecf20Sopenharmony_ci/** 21108c2ecf20Sopenharmony_ci * vmw_cmd_dx_set_single_constant_buffer - Validate 21118c2ecf20Sopenharmony_ci * SVGA_3D_CMD_DX_SET_SINGLE_CONSTANT_BUFFER command. 21128c2ecf20Sopenharmony_ci * 21138c2ecf20Sopenharmony_ci * @dev_priv: Pointer to a device private struct. 21148c2ecf20Sopenharmony_ci * @sw_context: The software context being used for this batch. 21158c2ecf20Sopenharmony_ci * @header: Pointer to the command header in the command stream. 21168c2ecf20Sopenharmony_ci */ 21178c2ecf20Sopenharmony_cistatic int 21188c2ecf20Sopenharmony_civmw_cmd_dx_set_single_constant_buffer(struct vmw_private *dev_priv, 21198c2ecf20Sopenharmony_ci struct vmw_sw_context *sw_context, 21208c2ecf20Sopenharmony_ci SVGA3dCmdHeader *header) 21218c2ecf20Sopenharmony_ci{ 21228c2ecf20Sopenharmony_ci VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdDXSetSingleConstantBuffer); 21238c2ecf20Sopenharmony_ci 21248c2ecf20Sopenharmony_ci struct vmw_resource *res = NULL; 21258c2ecf20Sopenharmony_ci struct vmw_ctx_validation_info *ctx_node = VMW_GET_CTX_NODE(sw_context); 21268c2ecf20Sopenharmony_ci struct vmw_ctx_bindinfo_cb binding; 21278c2ecf20Sopenharmony_ci int ret; 21288c2ecf20Sopenharmony_ci 21298c2ecf20Sopenharmony_ci if (!ctx_node) 21308c2ecf20Sopenharmony_ci return -EINVAL; 21318c2ecf20Sopenharmony_ci 21328c2ecf20Sopenharmony_ci cmd = container_of(header, typeof(*cmd), header); 21338c2ecf20Sopenharmony_ci ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface, 21348c2ecf20Sopenharmony_ci VMW_RES_DIRTY_NONE, user_surface_converter, 21358c2ecf20Sopenharmony_ci &cmd->body.sid, &res); 21368c2ecf20Sopenharmony_ci if (unlikely(ret != 0)) 21378c2ecf20Sopenharmony_ci return ret; 21388c2ecf20Sopenharmony_ci 21398c2ecf20Sopenharmony_ci if (!vmw_shadertype_is_valid(dev_priv->sm_type, cmd->body.type) || 21408c2ecf20Sopenharmony_ci cmd->body.slot >= SVGA3D_DX_MAX_CONSTBUFFERS) { 21418c2ecf20Sopenharmony_ci VMW_DEBUG_USER("Illegal const buffer shader %u slot %u.\n", 21428c2ecf20Sopenharmony_ci (unsigned int) cmd->body.type, 21438c2ecf20Sopenharmony_ci (unsigned int) cmd->body.slot); 21448c2ecf20Sopenharmony_ci return -EINVAL; 21458c2ecf20Sopenharmony_ci } 21468c2ecf20Sopenharmony_ci 21478c2ecf20Sopenharmony_ci binding.bi.ctx = ctx_node->ctx; 21488c2ecf20Sopenharmony_ci binding.bi.res = res; 21498c2ecf20Sopenharmony_ci binding.bi.bt = vmw_ctx_binding_cb; 21508c2ecf20Sopenharmony_ci binding.shader_slot = cmd->body.type - SVGA3D_SHADERTYPE_MIN; 21518c2ecf20Sopenharmony_ci binding.offset = cmd->body.offsetInBytes; 21528c2ecf20Sopenharmony_ci binding.size = cmd->body.sizeInBytes; 21538c2ecf20Sopenharmony_ci binding.slot = cmd->body.slot; 21548c2ecf20Sopenharmony_ci 21558c2ecf20Sopenharmony_ci vmw_binding_add(ctx_node->staged, &binding.bi, binding.shader_slot, 21568c2ecf20Sopenharmony_ci binding.slot); 21578c2ecf20Sopenharmony_ci 21588c2ecf20Sopenharmony_ci return 0; 21598c2ecf20Sopenharmony_ci} 21608c2ecf20Sopenharmony_ci 21618c2ecf20Sopenharmony_ci/** 21628c2ecf20Sopenharmony_ci * vmw_cmd_dx_set_shader_res - Validate SVGA_3D_CMD_DX_SET_SHADER_RESOURCES 21638c2ecf20Sopenharmony_ci * command 21648c2ecf20Sopenharmony_ci * 21658c2ecf20Sopenharmony_ci * @dev_priv: Pointer to a device private struct. 21668c2ecf20Sopenharmony_ci * @sw_context: The software context being used for this batch. 21678c2ecf20Sopenharmony_ci * @header: Pointer to the command header in the command stream. 21688c2ecf20Sopenharmony_ci */ 21698c2ecf20Sopenharmony_cistatic int vmw_cmd_dx_set_shader_res(struct vmw_private *dev_priv, 21708c2ecf20Sopenharmony_ci struct vmw_sw_context *sw_context, 21718c2ecf20Sopenharmony_ci SVGA3dCmdHeader *header) 21728c2ecf20Sopenharmony_ci{ 21738c2ecf20Sopenharmony_ci VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdDXSetShaderResources) = 21748c2ecf20Sopenharmony_ci container_of(header, typeof(*cmd), header); 21758c2ecf20Sopenharmony_ci 21768c2ecf20Sopenharmony_ci u32 num_sr_view = (cmd->header.size - sizeof(cmd->body)) / 21778c2ecf20Sopenharmony_ci sizeof(SVGA3dShaderResourceViewId); 21788c2ecf20Sopenharmony_ci 21798c2ecf20Sopenharmony_ci if ((u64) cmd->body.startView + (u64) num_sr_view > 21808c2ecf20Sopenharmony_ci (u64) SVGA3D_DX_MAX_SRVIEWS || 21818c2ecf20Sopenharmony_ci !vmw_shadertype_is_valid(dev_priv->sm_type, cmd->body.type)) { 21828c2ecf20Sopenharmony_ci VMW_DEBUG_USER("Invalid shader binding.\n"); 21838c2ecf20Sopenharmony_ci return -EINVAL; 21848c2ecf20Sopenharmony_ci } 21858c2ecf20Sopenharmony_ci 21868c2ecf20Sopenharmony_ci return vmw_view_bindings_add(sw_context, vmw_view_sr, 21878c2ecf20Sopenharmony_ci vmw_ctx_binding_sr, 21888c2ecf20Sopenharmony_ci cmd->body.type - SVGA3D_SHADERTYPE_MIN, 21898c2ecf20Sopenharmony_ci (void *) &cmd[1], num_sr_view, 21908c2ecf20Sopenharmony_ci cmd->body.startView); 21918c2ecf20Sopenharmony_ci} 21928c2ecf20Sopenharmony_ci 21938c2ecf20Sopenharmony_ci/** 21948c2ecf20Sopenharmony_ci * vmw_cmd_dx_set_shader - Validate SVGA_3D_CMD_DX_SET_SHADER command 21958c2ecf20Sopenharmony_ci * 21968c2ecf20Sopenharmony_ci * @dev_priv: Pointer to a device private struct. 21978c2ecf20Sopenharmony_ci * @sw_context: The software context being used for this batch. 21988c2ecf20Sopenharmony_ci * @header: Pointer to the command header in the command stream. 21998c2ecf20Sopenharmony_ci */ 22008c2ecf20Sopenharmony_cistatic int vmw_cmd_dx_set_shader(struct vmw_private *dev_priv, 22018c2ecf20Sopenharmony_ci struct vmw_sw_context *sw_context, 22028c2ecf20Sopenharmony_ci SVGA3dCmdHeader *header) 22038c2ecf20Sopenharmony_ci{ 22048c2ecf20Sopenharmony_ci VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdDXSetShader); 22058c2ecf20Sopenharmony_ci struct vmw_resource *res = NULL; 22068c2ecf20Sopenharmony_ci struct vmw_ctx_validation_info *ctx_node = VMW_GET_CTX_NODE(sw_context); 22078c2ecf20Sopenharmony_ci struct vmw_ctx_bindinfo_shader binding; 22088c2ecf20Sopenharmony_ci int ret = 0; 22098c2ecf20Sopenharmony_ci 22108c2ecf20Sopenharmony_ci if (!ctx_node) 22118c2ecf20Sopenharmony_ci return -EINVAL; 22128c2ecf20Sopenharmony_ci 22138c2ecf20Sopenharmony_ci cmd = container_of(header, typeof(*cmd), header); 22148c2ecf20Sopenharmony_ci 22158c2ecf20Sopenharmony_ci if (!vmw_shadertype_is_valid(dev_priv->sm_type, cmd->body.type)) { 22168c2ecf20Sopenharmony_ci VMW_DEBUG_USER("Illegal shader type %u.\n", 22178c2ecf20Sopenharmony_ci (unsigned int) cmd->body.type); 22188c2ecf20Sopenharmony_ci return -EINVAL; 22198c2ecf20Sopenharmony_ci } 22208c2ecf20Sopenharmony_ci 22218c2ecf20Sopenharmony_ci if (cmd->body.shaderId != SVGA3D_INVALID_ID) { 22228c2ecf20Sopenharmony_ci res = vmw_shader_lookup(sw_context->man, cmd->body.shaderId, 0); 22238c2ecf20Sopenharmony_ci if (IS_ERR(res)) { 22248c2ecf20Sopenharmony_ci VMW_DEBUG_USER("Could not find shader for binding.\n"); 22258c2ecf20Sopenharmony_ci return PTR_ERR(res); 22268c2ecf20Sopenharmony_ci } 22278c2ecf20Sopenharmony_ci 22288c2ecf20Sopenharmony_ci ret = vmw_execbuf_res_noctx_val_add(sw_context, res, 22298c2ecf20Sopenharmony_ci VMW_RES_DIRTY_NONE); 22308c2ecf20Sopenharmony_ci if (ret) 22318c2ecf20Sopenharmony_ci return ret; 22328c2ecf20Sopenharmony_ci } 22338c2ecf20Sopenharmony_ci 22348c2ecf20Sopenharmony_ci binding.bi.ctx = ctx_node->ctx; 22358c2ecf20Sopenharmony_ci binding.bi.res = res; 22368c2ecf20Sopenharmony_ci binding.bi.bt = vmw_ctx_binding_dx_shader; 22378c2ecf20Sopenharmony_ci binding.shader_slot = cmd->body.type - SVGA3D_SHADERTYPE_MIN; 22388c2ecf20Sopenharmony_ci 22398c2ecf20Sopenharmony_ci vmw_binding_add(ctx_node->staged, &binding.bi, binding.shader_slot, 0); 22408c2ecf20Sopenharmony_ci 22418c2ecf20Sopenharmony_ci return 0; 22428c2ecf20Sopenharmony_ci} 22438c2ecf20Sopenharmony_ci 22448c2ecf20Sopenharmony_ci/** 22458c2ecf20Sopenharmony_ci * vmw_cmd_dx_set_vertex_buffers - Validates SVGA_3D_CMD_DX_SET_VERTEX_BUFFERS 22468c2ecf20Sopenharmony_ci * command 22478c2ecf20Sopenharmony_ci * 22488c2ecf20Sopenharmony_ci * @dev_priv: Pointer to a device private struct. 22498c2ecf20Sopenharmony_ci * @sw_context: The software context being used for this batch. 22508c2ecf20Sopenharmony_ci * @header: Pointer to the command header in the command stream. 22518c2ecf20Sopenharmony_ci */ 22528c2ecf20Sopenharmony_cistatic int vmw_cmd_dx_set_vertex_buffers(struct vmw_private *dev_priv, 22538c2ecf20Sopenharmony_ci struct vmw_sw_context *sw_context, 22548c2ecf20Sopenharmony_ci SVGA3dCmdHeader *header) 22558c2ecf20Sopenharmony_ci{ 22568c2ecf20Sopenharmony_ci struct vmw_ctx_validation_info *ctx_node = VMW_GET_CTX_NODE(sw_context); 22578c2ecf20Sopenharmony_ci struct vmw_ctx_bindinfo_vb binding; 22588c2ecf20Sopenharmony_ci struct vmw_resource *res; 22598c2ecf20Sopenharmony_ci struct { 22608c2ecf20Sopenharmony_ci SVGA3dCmdHeader header; 22618c2ecf20Sopenharmony_ci SVGA3dCmdDXSetVertexBuffers body; 22628c2ecf20Sopenharmony_ci SVGA3dVertexBuffer buf[]; 22638c2ecf20Sopenharmony_ci } *cmd; 22648c2ecf20Sopenharmony_ci int i, ret, num; 22658c2ecf20Sopenharmony_ci 22668c2ecf20Sopenharmony_ci if (!ctx_node) 22678c2ecf20Sopenharmony_ci return -EINVAL; 22688c2ecf20Sopenharmony_ci 22698c2ecf20Sopenharmony_ci cmd = container_of(header, typeof(*cmd), header); 22708c2ecf20Sopenharmony_ci num = (cmd->header.size - sizeof(cmd->body)) / 22718c2ecf20Sopenharmony_ci sizeof(SVGA3dVertexBuffer); 22728c2ecf20Sopenharmony_ci if ((u64)num + (u64)cmd->body.startBuffer > 22738c2ecf20Sopenharmony_ci (u64)SVGA3D_DX_MAX_VERTEXBUFFERS) { 22748c2ecf20Sopenharmony_ci VMW_DEBUG_USER("Invalid number of vertex buffers.\n"); 22758c2ecf20Sopenharmony_ci return -EINVAL; 22768c2ecf20Sopenharmony_ci } 22778c2ecf20Sopenharmony_ci 22788c2ecf20Sopenharmony_ci for (i = 0; i < num; i++) { 22798c2ecf20Sopenharmony_ci ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface, 22808c2ecf20Sopenharmony_ci VMW_RES_DIRTY_NONE, 22818c2ecf20Sopenharmony_ci user_surface_converter, 22828c2ecf20Sopenharmony_ci &cmd->buf[i].sid, &res); 22838c2ecf20Sopenharmony_ci if (unlikely(ret != 0)) 22848c2ecf20Sopenharmony_ci return ret; 22858c2ecf20Sopenharmony_ci 22868c2ecf20Sopenharmony_ci binding.bi.ctx = ctx_node->ctx; 22878c2ecf20Sopenharmony_ci binding.bi.bt = vmw_ctx_binding_vb; 22888c2ecf20Sopenharmony_ci binding.bi.res = res; 22898c2ecf20Sopenharmony_ci binding.offset = cmd->buf[i].offset; 22908c2ecf20Sopenharmony_ci binding.stride = cmd->buf[i].stride; 22918c2ecf20Sopenharmony_ci binding.slot = i + cmd->body.startBuffer; 22928c2ecf20Sopenharmony_ci 22938c2ecf20Sopenharmony_ci vmw_binding_add(ctx_node->staged, &binding.bi, 0, binding.slot); 22948c2ecf20Sopenharmony_ci } 22958c2ecf20Sopenharmony_ci 22968c2ecf20Sopenharmony_ci return 0; 22978c2ecf20Sopenharmony_ci} 22988c2ecf20Sopenharmony_ci 22998c2ecf20Sopenharmony_ci/** 23008c2ecf20Sopenharmony_ci * vmw_cmd_dx_ia_set_vertex_buffers - Validate 23018c2ecf20Sopenharmony_ci * SVGA_3D_CMD_DX_IA_SET_INDEX_BUFFER command. 23028c2ecf20Sopenharmony_ci * 23038c2ecf20Sopenharmony_ci * @dev_priv: Pointer to a device private struct. 23048c2ecf20Sopenharmony_ci * @sw_context: The software context being used for this batch. 23058c2ecf20Sopenharmony_ci * @header: Pointer to the command header in the command stream. 23068c2ecf20Sopenharmony_ci */ 23078c2ecf20Sopenharmony_cistatic int vmw_cmd_dx_set_index_buffer(struct vmw_private *dev_priv, 23088c2ecf20Sopenharmony_ci struct vmw_sw_context *sw_context, 23098c2ecf20Sopenharmony_ci SVGA3dCmdHeader *header) 23108c2ecf20Sopenharmony_ci{ 23118c2ecf20Sopenharmony_ci struct vmw_ctx_validation_info *ctx_node = VMW_GET_CTX_NODE(sw_context); 23128c2ecf20Sopenharmony_ci struct vmw_ctx_bindinfo_ib binding; 23138c2ecf20Sopenharmony_ci struct vmw_resource *res; 23148c2ecf20Sopenharmony_ci VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdDXSetIndexBuffer); 23158c2ecf20Sopenharmony_ci int ret; 23168c2ecf20Sopenharmony_ci 23178c2ecf20Sopenharmony_ci if (!ctx_node) 23188c2ecf20Sopenharmony_ci return -EINVAL; 23198c2ecf20Sopenharmony_ci 23208c2ecf20Sopenharmony_ci cmd = container_of(header, typeof(*cmd), header); 23218c2ecf20Sopenharmony_ci ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface, 23228c2ecf20Sopenharmony_ci VMW_RES_DIRTY_NONE, user_surface_converter, 23238c2ecf20Sopenharmony_ci &cmd->body.sid, &res); 23248c2ecf20Sopenharmony_ci if (unlikely(ret != 0)) 23258c2ecf20Sopenharmony_ci return ret; 23268c2ecf20Sopenharmony_ci 23278c2ecf20Sopenharmony_ci binding.bi.ctx = ctx_node->ctx; 23288c2ecf20Sopenharmony_ci binding.bi.res = res; 23298c2ecf20Sopenharmony_ci binding.bi.bt = vmw_ctx_binding_ib; 23308c2ecf20Sopenharmony_ci binding.offset = cmd->body.offset; 23318c2ecf20Sopenharmony_ci binding.format = cmd->body.format; 23328c2ecf20Sopenharmony_ci 23338c2ecf20Sopenharmony_ci vmw_binding_add(ctx_node->staged, &binding.bi, 0, 0); 23348c2ecf20Sopenharmony_ci 23358c2ecf20Sopenharmony_ci return 0; 23368c2ecf20Sopenharmony_ci} 23378c2ecf20Sopenharmony_ci 23388c2ecf20Sopenharmony_ci/** 23398c2ecf20Sopenharmony_ci * vmw_cmd_dx_set_rendertarget - Validate SVGA_3D_CMD_DX_SET_RENDERTARGETS 23408c2ecf20Sopenharmony_ci * command 23418c2ecf20Sopenharmony_ci * 23428c2ecf20Sopenharmony_ci * @dev_priv: Pointer to a device private struct. 23438c2ecf20Sopenharmony_ci * @sw_context: The software context being used for this batch. 23448c2ecf20Sopenharmony_ci * @header: Pointer to the command header in the command stream. 23458c2ecf20Sopenharmony_ci */ 23468c2ecf20Sopenharmony_cistatic int vmw_cmd_dx_set_rendertargets(struct vmw_private *dev_priv, 23478c2ecf20Sopenharmony_ci struct vmw_sw_context *sw_context, 23488c2ecf20Sopenharmony_ci SVGA3dCmdHeader *header) 23498c2ecf20Sopenharmony_ci{ 23508c2ecf20Sopenharmony_ci VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdDXSetRenderTargets) = 23518c2ecf20Sopenharmony_ci container_of(header, typeof(*cmd), header); 23528c2ecf20Sopenharmony_ci u32 num_rt_view = (cmd->header.size - sizeof(cmd->body)) / 23538c2ecf20Sopenharmony_ci sizeof(SVGA3dRenderTargetViewId); 23548c2ecf20Sopenharmony_ci int ret; 23558c2ecf20Sopenharmony_ci 23568c2ecf20Sopenharmony_ci if (num_rt_view > SVGA3D_MAX_SIMULTANEOUS_RENDER_TARGETS) { 23578c2ecf20Sopenharmony_ci VMW_DEBUG_USER("Invalid DX Rendertarget binding.\n"); 23588c2ecf20Sopenharmony_ci return -EINVAL; 23598c2ecf20Sopenharmony_ci } 23608c2ecf20Sopenharmony_ci 23618c2ecf20Sopenharmony_ci ret = vmw_view_bindings_add(sw_context, vmw_view_ds, vmw_ctx_binding_ds, 23628c2ecf20Sopenharmony_ci 0, &cmd->body.depthStencilViewId, 1, 0); 23638c2ecf20Sopenharmony_ci if (ret) 23648c2ecf20Sopenharmony_ci return ret; 23658c2ecf20Sopenharmony_ci 23668c2ecf20Sopenharmony_ci return vmw_view_bindings_add(sw_context, vmw_view_rt, 23678c2ecf20Sopenharmony_ci vmw_ctx_binding_dx_rt, 0, (void *)&cmd[1], 23688c2ecf20Sopenharmony_ci num_rt_view, 0); 23698c2ecf20Sopenharmony_ci} 23708c2ecf20Sopenharmony_ci 23718c2ecf20Sopenharmony_ci/** 23728c2ecf20Sopenharmony_ci * vmw_cmd_dx_clear_rendertarget_view - Validate 23738c2ecf20Sopenharmony_ci * SVGA_3D_CMD_DX_CLEAR_RENDERTARGET_VIEW command 23748c2ecf20Sopenharmony_ci * 23758c2ecf20Sopenharmony_ci * @dev_priv: Pointer to a device private struct. 23768c2ecf20Sopenharmony_ci * @sw_context: The software context being used for this batch. 23778c2ecf20Sopenharmony_ci * @header: Pointer to the command header in the command stream. 23788c2ecf20Sopenharmony_ci */ 23798c2ecf20Sopenharmony_cistatic int vmw_cmd_dx_clear_rendertarget_view(struct vmw_private *dev_priv, 23808c2ecf20Sopenharmony_ci struct vmw_sw_context *sw_context, 23818c2ecf20Sopenharmony_ci SVGA3dCmdHeader *header) 23828c2ecf20Sopenharmony_ci{ 23838c2ecf20Sopenharmony_ci VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdDXClearRenderTargetView) = 23848c2ecf20Sopenharmony_ci container_of(header, typeof(*cmd), header); 23858c2ecf20Sopenharmony_ci struct vmw_resource *ret; 23868c2ecf20Sopenharmony_ci 23878c2ecf20Sopenharmony_ci ret = vmw_view_id_val_add(sw_context, vmw_view_rt, 23888c2ecf20Sopenharmony_ci cmd->body.renderTargetViewId); 23898c2ecf20Sopenharmony_ci 23908c2ecf20Sopenharmony_ci return PTR_ERR_OR_ZERO(ret); 23918c2ecf20Sopenharmony_ci} 23928c2ecf20Sopenharmony_ci 23938c2ecf20Sopenharmony_ci/** 23948c2ecf20Sopenharmony_ci * vmw_cmd_dx_clear_rendertarget_view - Validate 23958c2ecf20Sopenharmony_ci * SVGA_3D_CMD_DX_CLEAR_DEPTHSTENCIL_VIEW command 23968c2ecf20Sopenharmony_ci * 23978c2ecf20Sopenharmony_ci * @dev_priv: Pointer to a device private struct. 23988c2ecf20Sopenharmony_ci * @sw_context: The software context being used for this batch. 23998c2ecf20Sopenharmony_ci * @header: Pointer to the command header in the command stream. 24008c2ecf20Sopenharmony_ci */ 24018c2ecf20Sopenharmony_cistatic int vmw_cmd_dx_clear_depthstencil_view(struct vmw_private *dev_priv, 24028c2ecf20Sopenharmony_ci struct vmw_sw_context *sw_context, 24038c2ecf20Sopenharmony_ci SVGA3dCmdHeader *header) 24048c2ecf20Sopenharmony_ci{ 24058c2ecf20Sopenharmony_ci VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdDXClearDepthStencilView) = 24068c2ecf20Sopenharmony_ci container_of(header, typeof(*cmd), header); 24078c2ecf20Sopenharmony_ci struct vmw_resource *ret; 24088c2ecf20Sopenharmony_ci 24098c2ecf20Sopenharmony_ci ret = vmw_view_id_val_add(sw_context, vmw_view_ds, 24108c2ecf20Sopenharmony_ci cmd->body.depthStencilViewId); 24118c2ecf20Sopenharmony_ci 24128c2ecf20Sopenharmony_ci return PTR_ERR_OR_ZERO(ret); 24138c2ecf20Sopenharmony_ci} 24148c2ecf20Sopenharmony_ci 24158c2ecf20Sopenharmony_cistatic int vmw_cmd_dx_view_define(struct vmw_private *dev_priv, 24168c2ecf20Sopenharmony_ci struct vmw_sw_context *sw_context, 24178c2ecf20Sopenharmony_ci SVGA3dCmdHeader *header) 24188c2ecf20Sopenharmony_ci{ 24198c2ecf20Sopenharmony_ci struct vmw_ctx_validation_info *ctx_node = VMW_GET_CTX_NODE(sw_context); 24208c2ecf20Sopenharmony_ci struct vmw_resource *srf; 24218c2ecf20Sopenharmony_ci struct vmw_resource *res; 24228c2ecf20Sopenharmony_ci enum vmw_view_type view_type; 24238c2ecf20Sopenharmony_ci int ret; 24248c2ecf20Sopenharmony_ci /* 24258c2ecf20Sopenharmony_ci * This is based on the fact that all affected define commands have the 24268c2ecf20Sopenharmony_ci * same initial command body layout. 24278c2ecf20Sopenharmony_ci */ 24288c2ecf20Sopenharmony_ci struct { 24298c2ecf20Sopenharmony_ci SVGA3dCmdHeader header; 24308c2ecf20Sopenharmony_ci uint32 defined_id; 24318c2ecf20Sopenharmony_ci uint32 sid; 24328c2ecf20Sopenharmony_ci } *cmd; 24338c2ecf20Sopenharmony_ci 24348c2ecf20Sopenharmony_ci if (!ctx_node) 24358c2ecf20Sopenharmony_ci return -EINVAL; 24368c2ecf20Sopenharmony_ci 24378c2ecf20Sopenharmony_ci view_type = vmw_view_cmd_to_type(header->id); 24388c2ecf20Sopenharmony_ci if (view_type == vmw_view_max) 24398c2ecf20Sopenharmony_ci return -EINVAL; 24408c2ecf20Sopenharmony_ci 24418c2ecf20Sopenharmony_ci cmd = container_of(header, typeof(*cmd), header); 24428c2ecf20Sopenharmony_ci if (unlikely(cmd->sid == SVGA3D_INVALID_ID)) { 24438c2ecf20Sopenharmony_ci VMW_DEBUG_USER("Invalid surface id.\n"); 24448c2ecf20Sopenharmony_ci return -EINVAL; 24458c2ecf20Sopenharmony_ci } 24468c2ecf20Sopenharmony_ci ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface, 24478c2ecf20Sopenharmony_ci VMW_RES_DIRTY_NONE, user_surface_converter, 24488c2ecf20Sopenharmony_ci &cmd->sid, &srf); 24498c2ecf20Sopenharmony_ci if (unlikely(ret != 0)) 24508c2ecf20Sopenharmony_ci return ret; 24518c2ecf20Sopenharmony_ci 24528c2ecf20Sopenharmony_ci res = vmw_context_cotable(ctx_node->ctx, vmw_view_cotables[view_type]); 24538c2ecf20Sopenharmony_ci ret = vmw_cotable_notify(res, cmd->defined_id); 24548c2ecf20Sopenharmony_ci if (unlikely(ret != 0)) 24558c2ecf20Sopenharmony_ci return ret; 24568c2ecf20Sopenharmony_ci 24578c2ecf20Sopenharmony_ci return vmw_view_add(sw_context->man, ctx_node->ctx, srf, view_type, 24588c2ecf20Sopenharmony_ci cmd->defined_id, header, 24598c2ecf20Sopenharmony_ci header->size + sizeof(*header), 24608c2ecf20Sopenharmony_ci &sw_context->staged_cmd_res); 24618c2ecf20Sopenharmony_ci} 24628c2ecf20Sopenharmony_ci 24638c2ecf20Sopenharmony_ci/** 24648c2ecf20Sopenharmony_ci * vmw_cmd_dx_set_so_targets - Validate SVGA_3D_CMD_DX_SET_SOTARGETS command. 24658c2ecf20Sopenharmony_ci * 24668c2ecf20Sopenharmony_ci * @dev_priv: Pointer to a device private struct. 24678c2ecf20Sopenharmony_ci * @sw_context: The software context being used for this batch. 24688c2ecf20Sopenharmony_ci * @header: Pointer to the command header in the command stream. 24698c2ecf20Sopenharmony_ci */ 24708c2ecf20Sopenharmony_cistatic int vmw_cmd_dx_set_so_targets(struct vmw_private *dev_priv, 24718c2ecf20Sopenharmony_ci struct vmw_sw_context *sw_context, 24728c2ecf20Sopenharmony_ci SVGA3dCmdHeader *header) 24738c2ecf20Sopenharmony_ci{ 24748c2ecf20Sopenharmony_ci struct vmw_ctx_validation_info *ctx_node = VMW_GET_CTX_NODE(sw_context); 24758c2ecf20Sopenharmony_ci struct vmw_ctx_bindinfo_so_target binding; 24768c2ecf20Sopenharmony_ci struct vmw_resource *res; 24778c2ecf20Sopenharmony_ci struct { 24788c2ecf20Sopenharmony_ci SVGA3dCmdHeader header; 24798c2ecf20Sopenharmony_ci SVGA3dCmdDXSetSOTargets body; 24808c2ecf20Sopenharmony_ci SVGA3dSoTarget targets[]; 24818c2ecf20Sopenharmony_ci } *cmd; 24828c2ecf20Sopenharmony_ci int i, ret, num; 24838c2ecf20Sopenharmony_ci 24848c2ecf20Sopenharmony_ci if (!ctx_node) 24858c2ecf20Sopenharmony_ci return -EINVAL; 24868c2ecf20Sopenharmony_ci 24878c2ecf20Sopenharmony_ci cmd = container_of(header, typeof(*cmd), header); 24888c2ecf20Sopenharmony_ci num = (cmd->header.size - sizeof(cmd->body)) / sizeof(SVGA3dSoTarget); 24898c2ecf20Sopenharmony_ci 24908c2ecf20Sopenharmony_ci if (num > SVGA3D_DX_MAX_SOTARGETS) { 24918c2ecf20Sopenharmony_ci VMW_DEBUG_USER("Invalid DX SO binding.\n"); 24928c2ecf20Sopenharmony_ci return -EINVAL; 24938c2ecf20Sopenharmony_ci } 24948c2ecf20Sopenharmony_ci 24958c2ecf20Sopenharmony_ci for (i = 0; i < num; i++) { 24968c2ecf20Sopenharmony_ci ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface, 24978c2ecf20Sopenharmony_ci VMW_RES_DIRTY_SET, 24988c2ecf20Sopenharmony_ci user_surface_converter, 24998c2ecf20Sopenharmony_ci &cmd->targets[i].sid, &res); 25008c2ecf20Sopenharmony_ci if (unlikely(ret != 0)) 25018c2ecf20Sopenharmony_ci return ret; 25028c2ecf20Sopenharmony_ci 25038c2ecf20Sopenharmony_ci binding.bi.ctx = ctx_node->ctx; 25048c2ecf20Sopenharmony_ci binding.bi.res = res; 25058c2ecf20Sopenharmony_ci binding.bi.bt = vmw_ctx_binding_so_target, 25068c2ecf20Sopenharmony_ci binding.offset = cmd->targets[i].offset; 25078c2ecf20Sopenharmony_ci binding.size = cmd->targets[i].sizeInBytes; 25088c2ecf20Sopenharmony_ci binding.slot = i; 25098c2ecf20Sopenharmony_ci 25108c2ecf20Sopenharmony_ci vmw_binding_add(ctx_node->staged, &binding.bi, 0, binding.slot); 25118c2ecf20Sopenharmony_ci } 25128c2ecf20Sopenharmony_ci 25138c2ecf20Sopenharmony_ci return 0; 25148c2ecf20Sopenharmony_ci} 25158c2ecf20Sopenharmony_ci 25168c2ecf20Sopenharmony_cistatic int vmw_cmd_dx_so_define(struct vmw_private *dev_priv, 25178c2ecf20Sopenharmony_ci struct vmw_sw_context *sw_context, 25188c2ecf20Sopenharmony_ci SVGA3dCmdHeader *header) 25198c2ecf20Sopenharmony_ci{ 25208c2ecf20Sopenharmony_ci struct vmw_ctx_validation_info *ctx_node = VMW_GET_CTX_NODE(sw_context); 25218c2ecf20Sopenharmony_ci struct vmw_resource *res; 25228c2ecf20Sopenharmony_ci /* 25238c2ecf20Sopenharmony_ci * This is based on the fact that all affected define commands have 25248c2ecf20Sopenharmony_ci * the same initial command body layout. 25258c2ecf20Sopenharmony_ci */ 25268c2ecf20Sopenharmony_ci struct { 25278c2ecf20Sopenharmony_ci SVGA3dCmdHeader header; 25288c2ecf20Sopenharmony_ci uint32 defined_id; 25298c2ecf20Sopenharmony_ci } *cmd; 25308c2ecf20Sopenharmony_ci enum vmw_so_type so_type; 25318c2ecf20Sopenharmony_ci int ret; 25328c2ecf20Sopenharmony_ci 25338c2ecf20Sopenharmony_ci if (!ctx_node) 25348c2ecf20Sopenharmony_ci return -EINVAL; 25358c2ecf20Sopenharmony_ci 25368c2ecf20Sopenharmony_ci so_type = vmw_so_cmd_to_type(header->id); 25378c2ecf20Sopenharmony_ci res = vmw_context_cotable(ctx_node->ctx, vmw_so_cotables[so_type]); 25388c2ecf20Sopenharmony_ci cmd = container_of(header, typeof(*cmd), header); 25398c2ecf20Sopenharmony_ci ret = vmw_cotable_notify(res, cmd->defined_id); 25408c2ecf20Sopenharmony_ci 25418c2ecf20Sopenharmony_ci return ret; 25428c2ecf20Sopenharmony_ci} 25438c2ecf20Sopenharmony_ci 25448c2ecf20Sopenharmony_ci/** 25458c2ecf20Sopenharmony_ci * vmw_cmd_dx_check_subresource - Validate SVGA_3D_CMD_DX_[X]_SUBRESOURCE 25468c2ecf20Sopenharmony_ci * command 25478c2ecf20Sopenharmony_ci * 25488c2ecf20Sopenharmony_ci * @dev_priv: Pointer to a device private struct. 25498c2ecf20Sopenharmony_ci * @sw_context: The software context being used for this batch. 25508c2ecf20Sopenharmony_ci * @header: Pointer to the command header in the command stream. 25518c2ecf20Sopenharmony_ci */ 25528c2ecf20Sopenharmony_cistatic int vmw_cmd_dx_check_subresource(struct vmw_private *dev_priv, 25538c2ecf20Sopenharmony_ci struct vmw_sw_context *sw_context, 25548c2ecf20Sopenharmony_ci SVGA3dCmdHeader *header) 25558c2ecf20Sopenharmony_ci{ 25568c2ecf20Sopenharmony_ci struct { 25578c2ecf20Sopenharmony_ci SVGA3dCmdHeader header; 25588c2ecf20Sopenharmony_ci union { 25598c2ecf20Sopenharmony_ci SVGA3dCmdDXReadbackSubResource r_body; 25608c2ecf20Sopenharmony_ci SVGA3dCmdDXInvalidateSubResource i_body; 25618c2ecf20Sopenharmony_ci SVGA3dCmdDXUpdateSubResource u_body; 25628c2ecf20Sopenharmony_ci SVGA3dSurfaceId sid; 25638c2ecf20Sopenharmony_ci }; 25648c2ecf20Sopenharmony_ci } *cmd; 25658c2ecf20Sopenharmony_ci 25668c2ecf20Sopenharmony_ci BUILD_BUG_ON(offsetof(typeof(*cmd), r_body.sid) != 25678c2ecf20Sopenharmony_ci offsetof(typeof(*cmd), sid)); 25688c2ecf20Sopenharmony_ci BUILD_BUG_ON(offsetof(typeof(*cmd), i_body.sid) != 25698c2ecf20Sopenharmony_ci offsetof(typeof(*cmd), sid)); 25708c2ecf20Sopenharmony_ci BUILD_BUG_ON(offsetof(typeof(*cmd), u_body.sid) != 25718c2ecf20Sopenharmony_ci offsetof(typeof(*cmd), sid)); 25728c2ecf20Sopenharmony_ci 25738c2ecf20Sopenharmony_ci cmd = container_of(header, typeof(*cmd), header); 25748c2ecf20Sopenharmony_ci return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface, 25758c2ecf20Sopenharmony_ci VMW_RES_DIRTY_NONE, user_surface_converter, 25768c2ecf20Sopenharmony_ci &cmd->sid, NULL); 25778c2ecf20Sopenharmony_ci} 25788c2ecf20Sopenharmony_ci 25798c2ecf20Sopenharmony_cistatic int vmw_cmd_dx_cid_check(struct vmw_private *dev_priv, 25808c2ecf20Sopenharmony_ci struct vmw_sw_context *sw_context, 25818c2ecf20Sopenharmony_ci SVGA3dCmdHeader *header) 25828c2ecf20Sopenharmony_ci{ 25838c2ecf20Sopenharmony_ci struct vmw_ctx_validation_info *ctx_node = VMW_GET_CTX_NODE(sw_context); 25848c2ecf20Sopenharmony_ci 25858c2ecf20Sopenharmony_ci if (!ctx_node) 25868c2ecf20Sopenharmony_ci return -EINVAL; 25878c2ecf20Sopenharmony_ci 25888c2ecf20Sopenharmony_ci return 0; 25898c2ecf20Sopenharmony_ci} 25908c2ecf20Sopenharmony_ci 25918c2ecf20Sopenharmony_ci/** 25928c2ecf20Sopenharmony_ci * vmw_cmd_dx_view_remove - validate a view remove command and schedule the view 25938c2ecf20Sopenharmony_ci * resource for removal. 25948c2ecf20Sopenharmony_ci * 25958c2ecf20Sopenharmony_ci * @dev_priv: Pointer to a device private struct. 25968c2ecf20Sopenharmony_ci * @sw_context: The software context being used for this batch. 25978c2ecf20Sopenharmony_ci * @header: Pointer to the command header in the command stream. 25988c2ecf20Sopenharmony_ci * 25998c2ecf20Sopenharmony_ci * Check that the view exists, and if it was not created using this command 26008c2ecf20Sopenharmony_ci * batch, conditionally make this command a NOP. 26018c2ecf20Sopenharmony_ci */ 26028c2ecf20Sopenharmony_cistatic int vmw_cmd_dx_view_remove(struct vmw_private *dev_priv, 26038c2ecf20Sopenharmony_ci struct vmw_sw_context *sw_context, 26048c2ecf20Sopenharmony_ci SVGA3dCmdHeader *header) 26058c2ecf20Sopenharmony_ci{ 26068c2ecf20Sopenharmony_ci struct vmw_ctx_validation_info *ctx_node = VMW_GET_CTX_NODE(sw_context); 26078c2ecf20Sopenharmony_ci struct { 26088c2ecf20Sopenharmony_ci SVGA3dCmdHeader header; 26098c2ecf20Sopenharmony_ci union vmw_view_destroy body; 26108c2ecf20Sopenharmony_ci } *cmd = container_of(header, typeof(*cmd), header); 26118c2ecf20Sopenharmony_ci enum vmw_view_type view_type = vmw_view_cmd_to_type(header->id); 26128c2ecf20Sopenharmony_ci struct vmw_resource *view; 26138c2ecf20Sopenharmony_ci int ret; 26148c2ecf20Sopenharmony_ci 26158c2ecf20Sopenharmony_ci if (!ctx_node) 26168c2ecf20Sopenharmony_ci return -EINVAL; 26178c2ecf20Sopenharmony_ci 26188c2ecf20Sopenharmony_ci ret = vmw_view_remove(sw_context->man, cmd->body.view_id, view_type, 26198c2ecf20Sopenharmony_ci &sw_context->staged_cmd_res, &view); 26208c2ecf20Sopenharmony_ci if (ret || !view) 26218c2ecf20Sopenharmony_ci return ret; 26228c2ecf20Sopenharmony_ci 26238c2ecf20Sopenharmony_ci /* 26248c2ecf20Sopenharmony_ci * If the view wasn't created during this command batch, it might 26258c2ecf20Sopenharmony_ci * have been removed due to a context swapout, so add a 26268c2ecf20Sopenharmony_ci * relocation to conditionally make this command a NOP to avoid 26278c2ecf20Sopenharmony_ci * device errors. 26288c2ecf20Sopenharmony_ci */ 26298c2ecf20Sopenharmony_ci return vmw_resource_relocation_add(sw_context, view, 26308c2ecf20Sopenharmony_ci vmw_ptr_diff(sw_context->buf_start, 26318c2ecf20Sopenharmony_ci &cmd->header.id), 26328c2ecf20Sopenharmony_ci vmw_res_rel_cond_nop); 26338c2ecf20Sopenharmony_ci} 26348c2ecf20Sopenharmony_ci 26358c2ecf20Sopenharmony_ci/** 26368c2ecf20Sopenharmony_ci * vmw_cmd_dx_define_shader - Validate SVGA_3D_CMD_DX_DEFINE_SHADER command 26378c2ecf20Sopenharmony_ci * 26388c2ecf20Sopenharmony_ci * @dev_priv: Pointer to a device private struct. 26398c2ecf20Sopenharmony_ci * @sw_context: The software context being used for this batch. 26408c2ecf20Sopenharmony_ci * @header: Pointer to the command header in the command stream. 26418c2ecf20Sopenharmony_ci */ 26428c2ecf20Sopenharmony_cistatic int vmw_cmd_dx_define_shader(struct vmw_private *dev_priv, 26438c2ecf20Sopenharmony_ci struct vmw_sw_context *sw_context, 26448c2ecf20Sopenharmony_ci SVGA3dCmdHeader *header) 26458c2ecf20Sopenharmony_ci{ 26468c2ecf20Sopenharmony_ci struct vmw_ctx_validation_info *ctx_node = VMW_GET_CTX_NODE(sw_context); 26478c2ecf20Sopenharmony_ci struct vmw_resource *res; 26488c2ecf20Sopenharmony_ci VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdDXDefineShader) = 26498c2ecf20Sopenharmony_ci container_of(header, typeof(*cmd), header); 26508c2ecf20Sopenharmony_ci int ret; 26518c2ecf20Sopenharmony_ci 26528c2ecf20Sopenharmony_ci if (!ctx_node) 26538c2ecf20Sopenharmony_ci return -EINVAL; 26548c2ecf20Sopenharmony_ci 26558c2ecf20Sopenharmony_ci res = vmw_context_cotable(ctx_node->ctx, SVGA_COTABLE_DXSHADER); 26568c2ecf20Sopenharmony_ci ret = vmw_cotable_notify(res, cmd->body.shaderId); 26578c2ecf20Sopenharmony_ci if (ret) 26588c2ecf20Sopenharmony_ci return ret; 26598c2ecf20Sopenharmony_ci 26608c2ecf20Sopenharmony_ci return vmw_dx_shader_add(sw_context->man, ctx_node->ctx, 26618c2ecf20Sopenharmony_ci cmd->body.shaderId, cmd->body.type, 26628c2ecf20Sopenharmony_ci &sw_context->staged_cmd_res); 26638c2ecf20Sopenharmony_ci} 26648c2ecf20Sopenharmony_ci 26658c2ecf20Sopenharmony_ci/** 26668c2ecf20Sopenharmony_ci * vmw_cmd_dx_destroy_shader - Validate SVGA_3D_CMD_DX_DESTROY_SHADER command 26678c2ecf20Sopenharmony_ci * 26688c2ecf20Sopenharmony_ci * @dev_priv: Pointer to a device private struct. 26698c2ecf20Sopenharmony_ci * @sw_context: The software context being used for this batch. 26708c2ecf20Sopenharmony_ci * @header: Pointer to the command header in the command stream. 26718c2ecf20Sopenharmony_ci */ 26728c2ecf20Sopenharmony_cistatic int vmw_cmd_dx_destroy_shader(struct vmw_private *dev_priv, 26738c2ecf20Sopenharmony_ci struct vmw_sw_context *sw_context, 26748c2ecf20Sopenharmony_ci SVGA3dCmdHeader *header) 26758c2ecf20Sopenharmony_ci{ 26768c2ecf20Sopenharmony_ci struct vmw_ctx_validation_info *ctx_node = VMW_GET_CTX_NODE(sw_context); 26778c2ecf20Sopenharmony_ci VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdDXDestroyShader) = 26788c2ecf20Sopenharmony_ci container_of(header, typeof(*cmd), header); 26798c2ecf20Sopenharmony_ci int ret; 26808c2ecf20Sopenharmony_ci 26818c2ecf20Sopenharmony_ci if (!ctx_node) 26828c2ecf20Sopenharmony_ci return -EINVAL; 26838c2ecf20Sopenharmony_ci 26848c2ecf20Sopenharmony_ci ret = vmw_shader_remove(sw_context->man, cmd->body.shaderId, 0, 26858c2ecf20Sopenharmony_ci &sw_context->staged_cmd_res); 26868c2ecf20Sopenharmony_ci 26878c2ecf20Sopenharmony_ci return ret; 26888c2ecf20Sopenharmony_ci} 26898c2ecf20Sopenharmony_ci 26908c2ecf20Sopenharmony_ci/** 26918c2ecf20Sopenharmony_ci * vmw_cmd_dx_bind_shader - Validate SVGA_3D_CMD_DX_BIND_SHADER command 26928c2ecf20Sopenharmony_ci * 26938c2ecf20Sopenharmony_ci * @dev_priv: Pointer to a device private struct. 26948c2ecf20Sopenharmony_ci * @sw_context: The software context being used for this batch. 26958c2ecf20Sopenharmony_ci * @header: Pointer to the command header in the command stream. 26968c2ecf20Sopenharmony_ci */ 26978c2ecf20Sopenharmony_cistatic int vmw_cmd_dx_bind_shader(struct vmw_private *dev_priv, 26988c2ecf20Sopenharmony_ci struct vmw_sw_context *sw_context, 26998c2ecf20Sopenharmony_ci SVGA3dCmdHeader *header) 27008c2ecf20Sopenharmony_ci{ 27018c2ecf20Sopenharmony_ci struct vmw_resource *ctx; 27028c2ecf20Sopenharmony_ci struct vmw_resource *res; 27038c2ecf20Sopenharmony_ci VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdDXBindShader) = 27048c2ecf20Sopenharmony_ci container_of(header, typeof(*cmd), header); 27058c2ecf20Sopenharmony_ci int ret; 27068c2ecf20Sopenharmony_ci 27078c2ecf20Sopenharmony_ci if (cmd->body.cid != SVGA3D_INVALID_ID) { 27088c2ecf20Sopenharmony_ci ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_context, 27098c2ecf20Sopenharmony_ci VMW_RES_DIRTY_SET, 27108c2ecf20Sopenharmony_ci user_context_converter, &cmd->body.cid, 27118c2ecf20Sopenharmony_ci &ctx); 27128c2ecf20Sopenharmony_ci if (ret) 27138c2ecf20Sopenharmony_ci return ret; 27148c2ecf20Sopenharmony_ci } else { 27158c2ecf20Sopenharmony_ci struct vmw_ctx_validation_info *ctx_node = 27168c2ecf20Sopenharmony_ci VMW_GET_CTX_NODE(sw_context); 27178c2ecf20Sopenharmony_ci 27188c2ecf20Sopenharmony_ci if (!ctx_node) 27198c2ecf20Sopenharmony_ci return -EINVAL; 27208c2ecf20Sopenharmony_ci 27218c2ecf20Sopenharmony_ci ctx = ctx_node->ctx; 27228c2ecf20Sopenharmony_ci } 27238c2ecf20Sopenharmony_ci 27248c2ecf20Sopenharmony_ci res = vmw_shader_lookup(vmw_context_res_man(ctx), cmd->body.shid, 0); 27258c2ecf20Sopenharmony_ci if (IS_ERR(res)) { 27268c2ecf20Sopenharmony_ci VMW_DEBUG_USER("Could not find shader to bind.\n"); 27278c2ecf20Sopenharmony_ci return PTR_ERR(res); 27288c2ecf20Sopenharmony_ci } 27298c2ecf20Sopenharmony_ci 27308c2ecf20Sopenharmony_ci ret = vmw_execbuf_res_noctx_val_add(sw_context, res, 27318c2ecf20Sopenharmony_ci VMW_RES_DIRTY_NONE); 27328c2ecf20Sopenharmony_ci if (ret) { 27338c2ecf20Sopenharmony_ci VMW_DEBUG_USER("Error creating resource validation node.\n"); 27348c2ecf20Sopenharmony_ci return ret; 27358c2ecf20Sopenharmony_ci } 27368c2ecf20Sopenharmony_ci 27378c2ecf20Sopenharmony_ci return vmw_cmd_res_switch_backup(dev_priv, sw_context, res, 27388c2ecf20Sopenharmony_ci &cmd->body.mobid, 27398c2ecf20Sopenharmony_ci cmd->body.offsetInBytes); 27408c2ecf20Sopenharmony_ci} 27418c2ecf20Sopenharmony_ci 27428c2ecf20Sopenharmony_ci/** 27438c2ecf20Sopenharmony_ci * vmw_cmd_dx_genmips - Validate SVGA_3D_CMD_DX_GENMIPS command 27448c2ecf20Sopenharmony_ci * 27458c2ecf20Sopenharmony_ci * @dev_priv: Pointer to a device private struct. 27468c2ecf20Sopenharmony_ci * @sw_context: The software context being used for this batch. 27478c2ecf20Sopenharmony_ci * @header: Pointer to the command header in the command stream. 27488c2ecf20Sopenharmony_ci */ 27498c2ecf20Sopenharmony_cistatic int vmw_cmd_dx_genmips(struct vmw_private *dev_priv, 27508c2ecf20Sopenharmony_ci struct vmw_sw_context *sw_context, 27518c2ecf20Sopenharmony_ci SVGA3dCmdHeader *header) 27528c2ecf20Sopenharmony_ci{ 27538c2ecf20Sopenharmony_ci VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdDXGenMips) = 27548c2ecf20Sopenharmony_ci container_of(header, typeof(*cmd), header); 27558c2ecf20Sopenharmony_ci struct vmw_resource *view; 27568c2ecf20Sopenharmony_ci struct vmw_res_cache_entry *rcache; 27578c2ecf20Sopenharmony_ci 27588c2ecf20Sopenharmony_ci view = vmw_view_id_val_add(sw_context, vmw_view_sr, 27598c2ecf20Sopenharmony_ci cmd->body.shaderResourceViewId); 27608c2ecf20Sopenharmony_ci if (IS_ERR(view)) 27618c2ecf20Sopenharmony_ci return PTR_ERR(view); 27628c2ecf20Sopenharmony_ci 27638c2ecf20Sopenharmony_ci /* 27648c2ecf20Sopenharmony_ci * Normally the shader-resource view is not gpu-dirtying, but for 27658c2ecf20Sopenharmony_ci * this particular command it is... 27668c2ecf20Sopenharmony_ci * So mark the last looked-up surface, which is the surface 27678c2ecf20Sopenharmony_ci * the view points to, gpu-dirty. 27688c2ecf20Sopenharmony_ci */ 27698c2ecf20Sopenharmony_ci rcache = &sw_context->res_cache[vmw_res_surface]; 27708c2ecf20Sopenharmony_ci vmw_validation_res_set_dirty(sw_context->ctx, rcache->private, 27718c2ecf20Sopenharmony_ci VMW_RES_DIRTY_SET); 27728c2ecf20Sopenharmony_ci return 0; 27738c2ecf20Sopenharmony_ci} 27748c2ecf20Sopenharmony_ci 27758c2ecf20Sopenharmony_ci/** 27768c2ecf20Sopenharmony_ci * vmw_cmd_dx_transfer_from_buffer - Validate 27778c2ecf20Sopenharmony_ci * SVGA_3D_CMD_DX_TRANSFER_FROM_BUFFER command 27788c2ecf20Sopenharmony_ci * 27798c2ecf20Sopenharmony_ci * @dev_priv: Pointer to a device private struct. 27808c2ecf20Sopenharmony_ci * @sw_context: The software context being used for this batch. 27818c2ecf20Sopenharmony_ci * @header: Pointer to the command header in the command stream. 27828c2ecf20Sopenharmony_ci */ 27838c2ecf20Sopenharmony_cistatic int vmw_cmd_dx_transfer_from_buffer(struct vmw_private *dev_priv, 27848c2ecf20Sopenharmony_ci struct vmw_sw_context *sw_context, 27858c2ecf20Sopenharmony_ci SVGA3dCmdHeader *header) 27868c2ecf20Sopenharmony_ci{ 27878c2ecf20Sopenharmony_ci VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdDXTransferFromBuffer) = 27888c2ecf20Sopenharmony_ci container_of(header, typeof(*cmd), header); 27898c2ecf20Sopenharmony_ci int ret; 27908c2ecf20Sopenharmony_ci 27918c2ecf20Sopenharmony_ci ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface, 27928c2ecf20Sopenharmony_ci VMW_RES_DIRTY_NONE, user_surface_converter, 27938c2ecf20Sopenharmony_ci &cmd->body.srcSid, NULL); 27948c2ecf20Sopenharmony_ci if (ret != 0) 27958c2ecf20Sopenharmony_ci return ret; 27968c2ecf20Sopenharmony_ci 27978c2ecf20Sopenharmony_ci return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface, 27988c2ecf20Sopenharmony_ci VMW_RES_DIRTY_SET, user_surface_converter, 27998c2ecf20Sopenharmony_ci &cmd->body.destSid, NULL); 28008c2ecf20Sopenharmony_ci} 28018c2ecf20Sopenharmony_ci 28028c2ecf20Sopenharmony_ci/** 28038c2ecf20Sopenharmony_ci * vmw_cmd_intra_surface_copy - Validate SVGA_3D_CMD_INTRA_SURFACE_COPY command 28048c2ecf20Sopenharmony_ci * 28058c2ecf20Sopenharmony_ci * @dev_priv: Pointer to a device private struct. 28068c2ecf20Sopenharmony_ci * @sw_context: The software context being used for this batch. 28078c2ecf20Sopenharmony_ci * @header: Pointer to the command header in the command stream. 28088c2ecf20Sopenharmony_ci */ 28098c2ecf20Sopenharmony_cistatic int vmw_cmd_intra_surface_copy(struct vmw_private *dev_priv, 28108c2ecf20Sopenharmony_ci struct vmw_sw_context *sw_context, 28118c2ecf20Sopenharmony_ci SVGA3dCmdHeader *header) 28128c2ecf20Sopenharmony_ci{ 28138c2ecf20Sopenharmony_ci VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdIntraSurfaceCopy) = 28148c2ecf20Sopenharmony_ci container_of(header, typeof(*cmd), header); 28158c2ecf20Sopenharmony_ci 28168c2ecf20Sopenharmony_ci if (!(dev_priv->capabilities2 & SVGA_CAP2_INTRA_SURFACE_COPY)) 28178c2ecf20Sopenharmony_ci return -EINVAL; 28188c2ecf20Sopenharmony_ci 28198c2ecf20Sopenharmony_ci return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface, 28208c2ecf20Sopenharmony_ci VMW_RES_DIRTY_SET, user_surface_converter, 28218c2ecf20Sopenharmony_ci &cmd->body.surface.sid, NULL); 28228c2ecf20Sopenharmony_ci} 28238c2ecf20Sopenharmony_ci 28248c2ecf20Sopenharmony_cistatic int vmw_cmd_sm5(struct vmw_private *dev_priv, 28258c2ecf20Sopenharmony_ci struct vmw_sw_context *sw_context, 28268c2ecf20Sopenharmony_ci SVGA3dCmdHeader *header) 28278c2ecf20Sopenharmony_ci{ 28288c2ecf20Sopenharmony_ci if (!has_sm5_context(dev_priv)) 28298c2ecf20Sopenharmony_ci return -EINVAL; 28308c2ecf20Sopenharmony_ci 28318c2ecf20Sopenharmony_ci return 0; 28328c2ecf20Sopenharmony_ci} 28338c2ecf20Sopenharmony_ci 28348c2ecf20Sopenharmony_cistatic int vmw_cmd_sm5_view_define(struct vmw_private *dev_priv, 28358c2ecf20Sopenharmony_ci struct vmw_sw_context *sw_context, 28368c2ecf20Sopenharmony_ci SVGA3dCmdHeader *header) 28378c2ecf20Sopenharmony_ci{ 28388c2ecf20Sopenharmony_ci if (!has_sm5_context(dev_priv)) 28398c2ecf20Sopenharmony_ci return -EINVAL; 28408c2ecf20Sopenharmony_ci 28418c2ecf20Sopenharmony_ci return vmw_cmd_dx_view_define(dev_priv, sw_context, header); 28428c2ecf20Sopenharmony_ci} 28438c2ecf20Sopenharmony_ci 28448c2ecf20Sopenharmony_cistatic int vmw_cmd_sm5_view_remove(struct vmw_private *dev_priv, 28458c2ecf20Sopenharmony_ci struct vmw_sw_context *sw_context, 28468c2ecf20Sopenharmony_ci SVGA3dCmdHeader *header) 28478c2ecf20Sopenharmony_ci{ 28488c2ecf20Sopenharmony_ci if (!has_sm5_context(dev_priv)) 28498c2ecf20Sopenharmony_ci return -EINVAL; 28508c2ecf20Sopenharmony_ci 28518c2ecf20Sopenharmony_ci return vmw_cmd_dx_view_remove(dev_priv, sw_context, header); 28528c2ecf20Sopenharmony_ci} 28538c2ecf20Sopenharmony_ci 28548c2ecf20Sopenharmony_cistatic int vmw_cmd_clear_uav_uint(struct vmw_private *dev_priv, 28558c2ecf20Sopenharmony_ci struct vmw_sw_context *sw_context, 28568c2ecf20Sopenharmony_ci SVGA3dCmdHeader *header) 28578c2ecf20Sopenharmony_ci{ 28588c2ecf20Sopenharmony_ci struct { 28598c2ecf20Sopenharmony_ci SVGA3dCmdHeader header; 28608c2ecf20Sopenharmony_ci SVGA3dCmdDXClearUAViewUint body; 28618c2ecf20Sopenharmony_ci } *cmd = container_of(header, typeof(*cmd), header); 28628c2ecf20Sopenharmony_ci struct vmw_resource *ret; 28638c2ecf20Sopenharmony_ci 28648c2ecf20Sopenharmony_ci if (!has_sm5_context(dev_priv)) 28658c2ecf20Sopenharmony_ci return -EINVAL; 28668c2ecf20Sopenharmony_ci 28678c2ecf20Sopenharmony_ci ret = vmw_view_id_val_add(sw_context, vmw_view_ua, 28688c2ecf20Sopenharmony_ci cmd->body.uaViewId); 28698c2ecf20Sopenharmony_ci 28708c2ecf20Sopenharmony_ci return PTR_ERR_OR_ZERO(ret); 28718c2ecf20Sopenharmony_ci} 28728c2ecf20Sopenharmony_ci 28738c2ecf20Sopenharmony_cistatic int vmw_cmd_clear_uav_float(struct vmw_private *dev_priv, 28748c2ecf20Sopenharmony_ci struct vmw_sw_context *sw_context, 28758c2ecf20Sopenharmony_ci SVGA3dCmdHeader *header) 28768c2ecf20Sopenharmony_ci{ 28778c2ecf20Sopenharmony_ci struct { 28788c2ecf20Sopenharmony_ci SVGA3dCmdHeader header; 28798c2ecf20Sopenharmony_ci SVGA3dCmdDXClearUAViewFloat body; 28808c2ecf20Sopenharmony_ci } *cmd = container_of(header, typeof(*cmd), header); 28818c2ecf20Sopenharmony_ci struct vmw_resource *ret; 28828c2ecf20Sopenharmony_ci 28838c2ecf20Sopenharmony_ci if (!has_sm5_context(dev_priv)) 28848c2ecf20Sopenharmony_ci return -EINVAL; 28858c2ecf20Sopenharmony_ci 28868c2ecf20Sopenharmony_ci ret = vmw_view_id_val_add(sw_context, vmw_view_ua, 28878c2ecf20Sopenharmony_ci cmd->body.uaViewId); 28888c2ecf20Sopenharmony_ci 28898c2ecf20Sopenharmony_ci return PTR_ERR_OR_ZERO(ret); 28908c2ecf20Sopenharmony_ci} 28918c2ecf20Sopenharmony_ci 28928c2ecf20Sopenharmony_cistatic int vmw_cmd_set_uav(struct vmw_private *dev_priv, 28938c2ecf20Sopenharmony_ci struct vmw_sw_context *sw_context, 28948c2ecf20Sopenharmony_ci SVGA3dCmdHeader *header) 28958c2ecf20Sopenharmony_ci{ 28968c2ecf20Sopenharmony_ci struct { 28978c2ecf20Sopenharmony_ci SVGA3dCmdHeader header; 28988c2ecf20Sopenharmony_ci SVGA3dCmdDXSetUAViews body; 28998c2ecf20Sopenharmony_ci } *cmd = container_of(header, typeof(*cmd), header); 29008c2ecf20Sopenharmony_ci u32 num_uav = (cmd->header.size - sizeof(cmd->body)) / 29018c2ecf20Sopenharmony_ci sizeof(SVGA3dUAViewId); 29028c2ecf20Sopenharmony_ci int ret; 29038c2ecf20Sopenharmony_ci 29048c2ecf20Sopenharmony_ci if (!has_sm5_context(dev_priv)) 29058c2ecf20Sopenharmony_ci return -EINVAL; 29068c2ecf20Sopenharmony_ci 29078c2ecf20Sopenharmony_ci if (num_uav > SVGA3D_MAX_UAVIEWS) { 29088c2ecf20Sopenharmony_ci VMW_DEBUG_USER("Invalid UAV binding.\n"); 29098c2ecf20Sopenharmony_ci return -EINVAL; 29108c2ecf20Sopenharmony_ci } 29118c2ecf20Sopenharmony_ci 29128c2ecf20Sopenharmony_ci ret = vmw_view_bindings_add(sw_context, vmw_view_ua, 29138c2ecf20Sopenharmony_ci vmw_ctx_binding_uav, 0, (void *)&cmd[1], 29148c2ecf20Sopenharmony_ci num_uav, 0); 29158c2ecf20Sopenharmony_ci if (ret) 29168c2ecf20Sopenharmony_ci return ret; 29178c2ecf20Sopenharmony_ci 29188c2ecf20Sopenharmony_ci vmw_binding_add_uav_index(sw_context->dx_ctx_node->staged, 0, 29198c2ecf20Sopenharmony_ci cmd->body.uavSpliceIndex); 29208c2ecf20Sopenharmony_ci 29218c2ecf20Sopenharmony_ci return ret; 29228c2ecf20Sopenharmony_ci} 29238c2ecf20Sopenharmony_ci 29248c2ecf20Sopenharmony_cistatic int vmw_cmd_set_cs_uav(struct vmw_private *dev_priv, 29258c2ecf20Sopenharmony_ci struct vmw_sw_context *sw_context, 29268c2ecf20Sopenharmony_ci SVGA3dCmdHeader *header) 29278c2ecf20Sopenharmony_ci{ 29288c2ecf20Sopenharmony_ci struct { 29298c2ecf20Sopenharmony_ci SVGA3dCmdHeader header; 29308c2ecf20Sopenharmony_ci SVGA3dCmdDXSetCSUAViews body; 29318c2ecf20Sopenharmony_ci } *cmd = container_of(header, typeof(*cmd), header); 29328c2ecf20Sopenharmony_ci u32 num_uav = (cmd->header.size - sizeof(cmd->body)) / 29338c2ecf20Sopenharmony_ci sizeof(SVGA3dUAViewId); 29348c2ecf20Sopenharmony_ci int ret; 29358c2ecf20Sopenharmony_ci 29368c2ecf20Sopenharmony_ci if (!has_sm5_context(dev_priv)) 29378c2ecf20Sopenharmony_ci return -EINVAL; 29388c2ecf20Sopenharmony_ci 29398c2ecf20Sopenharmony_ci if (num_uav > SVGA3D_MAX_UAVIEWS) { 29408c2ecf20Sopenharmony_ci VMW_DEBUG_USER("Invalid UAV binding.\n"); 29418c2ecf20Sopenharmony_ci return -EINVAL; 29428c2ecf20Sopenharmony_ci } 29438c2ecf20Sopenharmony_ci 29448c2ecf20Sopenharmony_ci ret = vmw_view_bindings_add(sw_context, vmw_view_ua, 29458c2ecf20Sopenharmony_ci vmw_ctx_binding_cs_uav, 0, (void *)&cmd[1], 29468c2ecf20Sopenharmony_ci num_uav, 0); 29478c2ecf20Sopenharmony_ci if (ret) 29488c2ecf20Sopenharmony_ci return ret; 29498c2ecf20Sopenharmony_ci 29508c2ecf20Sopenharmony_ci vmw_binding_add_uav_index(sw_context->dx_ctx_node->staged, 1, 29518c2ecf20Sopenharmony_ci cmd->body.startIndex); 29528c2ecf20Sopenharmony_ci 29538c2ecf20Sopenharmony_ci return ret; 29548c2ecf20Sopenharmony_ci} 29558c2ecf20Sopenharmony_ci 29568c2ecf20Sopenharmony_cistatic int vmw_cmd_dx_define_streamoutput(struct vmw_private *dev_priv, 29578c2ecf20Sopenharmony_ci struct vmw_sw_context *sw_context, 29588c2ecf20Sopenharmony_ci SVGA3dCmdHeader *header) 29598c2ecf20Sopenharmony_ci{ 29608c2ecf20Sopenharmony_ci struct vmw_ctx_validation_info *ctx_node = sw_context->dx_ctx_node; 29618c2ecf20Sopenharmony_ci struct vmw_resource *res; 29628c2ecf20Sopenharmony_ci struct { 29638c2ecf20Sopenharmony_ci SVGA3dCmdHeader header; 29648c2ecf20Sopenharmony_ci SVGA3dCmdDXDefineStreamOutputWithMob body; 29658c2ecf20Sopenharmony_ci } *cmd = container_of(header, typeof(*cmd), header); 29668c2ecf20Sopenharmony_ci int ret; 29678c2ecf20Sopenharmony_ci 29688c2ecf20Sopenharmony_ci if (!has_sm5_context(dev_priv)) 29698c2ecf20Sopenharmony_ci return -EINVAL; 29708c2ecf20Sopenharmony_ci 29718c2ecf20Sopenharmony_ci if (!ctx_node) { 29728c2ecf20Sopenharmony_ci DRM_ERROR("DX Context not set.\n"); 29738c2ecf20Sopenharmony_ci return -EINVAL; 29748c2ecf20Sopenharmony_ci } 29758c2ecf20Sopenharmony_ci 29768c2ecf20Sopenharmony_ci res = vmw_context_cotable(ctx_node->ctx, SVGA_COTABLE_STREAMOUTPUT); 29778c2ecf20Sopenharmony_ci ret = vmw_cotable_notify(res, cmd->body.soid); 29788c2ecf20Sopenharmony_ci if (ret) 29798c2ecf20Sopenharmony_ci return ret; 29808c2ecf20Sopenharmony_ci 29818c2ecf20Sopenharmony_ci return vmw_dx_streamoutput_add(sw_context->man, ctx_node->ctx, 29828c2ecf20Sopenharmony_ci cmd->body.soid, 29838c2ecf20Sopenharmony_ci &sw_context->staged_cmd_res); 29848c2ecf20Sopenharmony_ci} 29858c2ecf20Sopenharmony_ci 29868c2ecf20Sopenharmony_cistatic int vmw_cmd_dx_destroy_streamoutput(struct vmw_private *dev_priv, 29878c2ecf20Sopenharmony_ci struct vmw_sw_context *sw_context, 29888c2ecf20Sopenharmony_ci SVGA3dCmdHeader *header) 29898c2ecf20Sopenharmony_ci{ 29908c2ecf20Sopenharmony_ci struct vmw_ctx_validation_info *ctx_node = sw_context->dx_ctx_node; 29918c2ecf20Sopenharmony_ci struct vmw_resource *res; 29928c2ecf20Sopenharmony_ci struct { 29938c2ecf20Sopenharmony_ci SVGA3dCmdHeader header; 29948c2ecf20Sopenharmony_ci SVGA3dCmdDXDestroyStreamOutput body; 29958c2ecf20Sopenharmony_ci } *cmd = container_of(header, typeof(*cmd), header); 29968c2ecf20Sopenharmony_ci 29978c2ecf20Sopenharmony_ci if (!ctx_node) { 29988c2ecf20Sopenharmony_ci DRM_ERROR("DX Context not set.\n"); 29998c2ecf20Sopenharmony_ci return -EINVAL; 30008c2ecf20Sopenharmony_ci } 30018c2ecf20Sopenharmony_ci 30028c2ecf20Sopenharmony_ci /* 30038c2ecf20Sopenharmony_ci * When device does not support SM5 then streamoutput with mob command is 30048c2ecf20Sopenharmony_ci * not available to user-space. Simply return in this case. 30058c2ecf20Sopenharmony_ci */ 30068c2ecf20Sopenharmony_ci if (!has_sm5_context(dev_priv)) 30078c2ecf20Sopenharmony_ci return 0; 30088c2ecf20Sopenharmony_ci 30098c2ecf20Sopenharmony_ci /* 30108c2ecf20Sopenharmony_ci * With SM5 capable device if lookup fails then user-space probably used 30118c2ecf20Sopenharmony_ci * old streamoutput define command. Return without an error. 30128c2ecf20Sopenharmony_ci */ 30138c2ecf20Sopenharmony_ci res = vmw_dx_streamoutput_lookup(vmw_context_res_man(ctx_node->ctx), 30148c2ecf20Sopenharmony_ci cmd->body.soid); 30158c2ecf20Sopenharmony_ci if (IS_ERR(res)) 30168c2ecf20Sopenharmony_ci return 0; 30178c2ecf20Sopenharmony_ci 30188c2ecf20Sopenharmony_ci return vmw_dx_streamoutput_remove(sw_context->man, cmd->body.soid, 30198c2ecf20Sopenharmony_ci &sw_context->staged_cmd_res); 30208c2ecf20Sopenharmony_ci} 30218c2ecf20Sopenharmony_ci 30228c2ecf20Sopenharmony_cistatic int vmw_cmd_dx_bind_streamoutput(struct vmw_private *dev_priv, 30238c2ecf20Sopenharmony_ci struct vmw_sw_context *sw_context, 30248c2ecf20Sopenharmony_ci SVGA3dCmdHeader *header) 30258c2ecf20Sopenharmony_ci{ 30268c2ecf20Sopenharmony_ci struct vmw_ctx_validation_info *ctx_node = sw_context->dx_ctx_node; 30278c2ecf20Sopenharmony_ci struct vmw_resource *res; 30288c2ecf20Sopenharmony_ci struct { 30298c2ecf20Sopenharmony_ci SVGA3dCmdHeader header; 30308c2ecf20Sopenharmony_ci SVGA3dCmdDXBindStreamOutput body; 30318c2ecf20Sopenharmony_ci } *cmd = container_of(header, typeof(*cmd), header); 30328c2ecf20Sopenharmony_ci int ret; 30338c2ecf20Sopenharmony_ci 30348c2ecf20Sopenharmony_ci if (!has_sm5_context(dev_priv)) 30358c2ecf20Sopenharmony_ci return -EINVAL; 30368c2ecf20Sopenharmony_ci 30378c2ecf20Sopenharmony_ci if (!ctx_node) { 30388c2ecf20Sopenharmony_ci DRM_ERROR("DX Context not set.\n"); 30398c2ecf20Sopenharmony_ci return -EINVAL; 30408c2ecf20Sopenharmony_ci } 30418c2ecf20Sopenharmony_ci 30428c2ecf20Sopenharmony_ci res = vmw_dx_streamoutput_lookup(vmw_context_res_man(ctx_node->ctx), 30438c2ecf20Sopenharmony_ci cmd->body.soid); 30448c2ecf20Sopenharmony_ci if (IS_ERR(res)) { 30458c2ecf20Sopenharmony_ci DRM_ERROR("Could not find streamoutput to bind.\n"); 30468c2ecf20Sopenharmony_ci return PTR_ERR(res); 30478c2ecf20Sopenharmony_ci } 30488c2ecf20Sopenharmony_ci 30498c2ecf20Sopenharmony_ci vmw_dx_streamoutput_set_size(res, cmd->body.sizeInBytes); 30508c2ecf20Sopenharmony_ci 30518c2ecf20Sopenharmony_ci ret = vmw_execbuf_res_noctx_val_add(sw_context, res, 30528c2ecf20Sopenharmony_ci VMW_RES_DIRTY_NONE); 30538c2ecf20Sopenharmony_ci if (ret) { 30548c2ecf20Sopenharmony_ci DRM_ERROR("Error creating resource validation node.\n"); 30558c2ecf20Sopenharmony_ci return ret; 30568c2ecf20Sopenharmony_ci } 30578c2ecf20Sopenharmony_ci 30588c2ecf20Sopenharmony_ci return vmw_cmd_res_switch_backup(dev_priv, sw_context, res, 30598c2ecf20Sopenharmony_ci &cmd->body.mobid, 30608c2ecf20Sopenharmony_ci cmd->body.offsetInBytes); 30618c2ecf20Sopenharmony_ci} 30628c2ecf20Sopenharmony_ci 30638c2ecf20Sopenharmony_cistatic int vmw_cmd_dx_set_streamoutput(struct vmw_private *dev_priv, 30648c2ecf20Sopenharmony_ci struct vmw_sw_context *sw_context, 30658c2ecf20Sopenharmony_ci SVGA3dCmdHeader *header) 30668c2ecf20Sopenharmony_ci{ 30678c2ecf20Sopenharmony_ci struct vmw_ctx_validation_info *ctx_node = sw_context->dx_ctx_node; 30688c2ecf20Sopenharmony_ci struct vmw_resource *res; 30698c2ecf20Sopenharmony_ci struct vmw_ctx_bindinfo_so binding; 30708c2ecf20Sopenharmony_ci struct { 30718c2ecf20Sopenharmony_ci SVGA3dCmdHeader header; 30728c2ecf20Sopenharmony_ci SVGA3dCmdDXSetStreamOutput body; 30738c2ecf20Sopenharmony_ci } *cmd = container_of(header, typeof(*cmd), header); 30748c2ecf20Sopenharmony_ci int ret; 30758c2ecf20Sopenharmony_ci 30768c2ecf20Sopenharmony_ci if (!ctx_node) { 30778c2ecf20Sopenharmony_ci DRM_ERROR("DX Context not set.\n"); 30788c2ecf20Sopenharmony_ci return -EINVAL; 30798c2ecf20Sopenharmony_ci } 30808c2ecf20Sopenharmony_ci 30818c2ecf20Sopenharmony_ci if (cmd->body.soid == SVGA3D_INVALID_ID) 30828c2ecf20Sopenharmony_ci return 0; 30838c2ecf20Sopenharmony_ci 30848c2ecf20Sopenharmony_ci /* 30858c2ecf20Sopenharmony_ci * When device does not support SM5 then streamoutput with mob command is 30868c2ecf20Sopenharmony_ci * not available to user-space. Simply return in this case. 30878c2ecf20Sopenharmony_ci */ 30888c2ecf20Sopenharmony_ci if (!has_sm5_context(dev_priv)) 30898c2ecf20Sopenharmony_ci return 0; 30908c2ecf20Sopenharmony_ci 30918c2ecf20Sopenharmony_ci /* 30928c2ecf20Sopenharmony_ci * With SM5 capable device if lookup fails then user-space probably used 30938c2ecf20Sopenharmony_ci * old streamoutput define command. Return without an error. 30948c2ecf20Sopenharmony_ci */ 30958c2ecf20Sopenharmony_ci res = vmw_dx_streamoutput_lookup(vmw_context_res_man(ctx_node->ctx), 30968c2ecf20Sopenharmony_ci cmd->body.soid); 30978c2ecf20Sopenharmony_ci if (IS_ERR(res)) { 30988c2ecf20Sopenharmony_ci return 0; 30998c2ecf20Sopenharmony_ci } 31008c2ecf20Sopenharmony_ci 31018c2ecf20Sopenharmony_ci ret = vmw_execbuf_res_noctx_val_add(sw_context, res, 31028c2ecf20Sopenharmony_ci VMW_RES_DIRTY_NONE); 31038c2ecf20Sopenharmony_ci if (ret) { 31048c2ecf20Sopenharmony_ci DRM_ERROR("Error creating resource validation node.\n"); 31058c2ecf20Sopenharmony_ci return ret; 31068c2ecf20Sopenharmony_ci } 31078c2ecf20Sopenharmony_ci 31088c2ecf20Sopenharmony_ci binding.bi.ctx = ctx_node->ctx; 31098c2ecf20Sopenharmony_ci binding.bi.res = res; 31108c2ecf20Sopenharmony_ci binding.bi.bt = vmw_ctx_binding_so; 31118c2ecf20Sopenharmony_ci binding.slot = 0; /* Only one SO set to context at a time. */ 31128c2ecf20Sopenharmony_ci 31138c2ecf20Sopenharmony_ci vmw_binding_add(sw_context->dx_ctx_node->staged, &binding.bi, 0, 31148c2ecf20Sopenharmony_ci binding.slot); 31158c2ecf20Sopenharmony_ci 31168c2ecf20Sopenharmony_ci return ret; 31178c2ecf20Sopenharmony_ci} 31188c2ecf20Sopenharmony_ci 31198c2ecf20Sopenharmony_cistatic int vmw_cmd_indexed_instanced_indirect(struct vmw_private *dev_priv, 31208c2ecf20Sopenharmony_ci struct vmw_sw_context *sw_context, 31218c2ecf20Sopenharmony_ci SVGA3dCmdHeader *header) 31228c2ecf20Sopenharmony_ci{ 31238c2ecf20Sopenharmony_ci struct vmw_draw_indexed_instanced_indirect_cmd { 31248c2ecf20Sopenharmony_ci SVGA3dCmdHeader header; 31258c2ecf20Sopenharmony_ci SVGA3dCmdDXDrawIndexedInstancedIndirect body; 31268c2ecf20Sopenharmony_ci } *cmd = container_of(header, typeof(*cmd), header); 31278c2ecf20Sopenharmony_ci 31288c2ecf20Sopenharmony_ci if (!has_sm5_context(dev_priv)) 31298c2ecf20Sopenharmony_ci return -EINVAL; 31308c2ecf20Sopenharmony_ci 31318c2ecf20Sopenharmony_ci return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface, 31328c2ecf20Sopenharmony_ci VMW_RES_DIRTY_NONE, user_surface_converter, 31338c2ecf20Sopenharmony_ci &cmd->body.argsBufferSid, NULL); 31348c2ecf20Sopenharmony_ci} 31358c2ecf20Sopenharmony_ci 31368c2ecf20Sopenharmony_cistatic int vmw_cmd_instanced_indirect(struct vmw_private *dev_priv, 31378c2ecf20Sopenharmony_ci struct vmw_sw_context *sw_context, 31388c2ecf20Sopenharmony_ci SVGA3dCmdHeader *header) 31398c2ecf20Sopenharmony_ci{ 31408c2ecf20Sopenharmony_ci struct vmw_draw_instanced_indirect_cmd { 31418c2ecf20Sopenharmony_ci SVGA3dCmdHeader header; 31428c2ecf20Sopenharmony_ci SVGA3dCmdDXDrawInstancedIndirect body; 31438c2ecf20Sopenharmony_ci } *cmd = container_of(header, typeof(*cmd), header); 31448c2ecf20Sopenharmony_ci 31458c2ecf20Sopenharmony_ci if (!has_sm5_context(dev_priv)) 31468c2ecf20Sopenharmony_ci return -EINVAL; 31478c2ecf20Sopenharmony_ci 31488c2ecf20Sopenharmony_ci return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface, 31498c2ecf20Sopenharmony_ci VMW_RES_DIRTY_NONE, user_surface_converter, 31508c2ecf20Sopenharmony_ci &cmd->body.argsBufferSid, NULL); 31518c2ecf20Sopenharmony_ci} 31528c2ecf20Sopenharmony_ci 31538c2ecf20Sopenharmony_cistatic int vmw_cmd_dispatch_indirect(struct vmw_private *dev_priv, 31548c2ecf20Sopenharmony_ci struct vmw_sw_context *sw_context, 31558c2ecf20Sopenharmony_ci SVGA3dCmdHeader *header) 31568c2ecf20Sopenharmony_ci{ 31578c2ecf20Sopenharmony_ci struct vmw_dispatch_indirect_cmd { 31588c2ecf20Sopenharmony_ci SVGA3dCmdHeader header; 31598c2ecf20Sopenharmony_ci SVGA3dCmdDXDispatchIndirect body; 31608c2ecf20Sopenharmony_ci } *cmd = container_of(header, typeof(*cmd), header); 31618c2ecf20Sopenharmony_ci 31628c2ecf20Sopenharmony_ci if (!has_sm5_context(dev_priv)) 31638c2ecf20Sopenharmony_ci return -EINVAL; 31648c2ecf20Sopenharmony_ci 31658c2ecf20Sopenharmony_ci return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface, 31668c2ecf20Sopenharmony_ci VMW_RES_DIRTY_NONE, user_surface_converter, 31678c2ecf20Sopenharmony_ci &cmd->body.argsBufferSid, NULL); 31688c2ecf20Sopenharmony_ci} 31698c2ecf20Sopenharmony_ci 31708c2ecf20Sopenharmony_cistatic int vmw_cmd_check_not_3d(struct vmw_private *dev_priv, 31718c2ecf20Sopenharmony_ci struct vmw_sw_context *sw_context, 31728c2ecf20Sopenharmony_ci void *buf, uint32_t *size) 31738c2ecf20Sopenharmony_ci{ 31748c2ecf20Sopenharmony_ci uint32_t size_remaining = *size; 31758c2ecf20Sopenharmony_ci uint32_t cmd_id; 31768c2ecf20Sopenharmony_ci 31778c2ecf20Sopenharmony_ci cmd_id = ((uint32_t *)buf)[0]; 31788c2ecf20Sopenharmony_ci switch (cmd_id) { 31798c2ecf20Sopenharmony_ci case SVGA_CMD_UPDATE: 31808c2ecf20Sopenharmony_ci *size = sizeof(uint32_t) + sizeof(SVGAFifoCmdUpdate); 31818c2ecf20Sopenharmony_ci break; 31828c2ecf20Sopenharmony_ci case SVGA_CMD_DEFINE_GMRFB: 31838c2ecf20Sopenharmony_ci *size = sizeof(uint32_t) + sizeof(SVGAFifoCmdDefineGMRFB); 31848c2ecf20Sopenharmony_ci break; 31858c2ecf20Sopenharmony_ci case SVGA_CMD_BLIT_GMRFB_TO_SCREEN: 31868c2ecf20Sopenharmony_ci *size = sizeof(uint32_t) + sizeof(SVGAFifoCmdBlitGMRFBToScreen); 31878c2ecf20Sopenharmony_ci break; 31888c2ecf20Sopenharmony_ci case SVGA_CMD_BLIT_SCREEN_TO_GMRFB: 31898c2ecf20Sopenharmony_ci *size = sizeof(uint32_t) + sizeof(SVGAFifoCmdBlitGMRFBToScreen); 31908c2ecf20Sopenharmony_ci break; 31918c2ecf20Sopenharmony_ci default: 31928c2ecf20Sopenharmony_ci VMW_DEBUG_USER("Unsupported SVGA command: %u.\n", cmd_id); 31938c2ecf20Sopenharmony_ci return -EINVAL; 31948c2ecf20Sopenharmony_ci } 31958c2ecf20Sopenharmony_ci 31968c2ecf20Sopenharmony_ci if (*size > size_remaining) { 31978c2ecf20Sopenharmony_ci VMW_DEBUG_USER("Invalid SVGA command (size mismatch): %u.\n", 31988c2ecf20Sopenharmony_ci cmd_id); 31998c2ecf20Sopenharmony_ci return -EINVAL; 32008c2ecf20Sopenharmony_ci } 32018c2ecf20Sopenharmony_ci 32028c2ecf20Sopenharmony_ci if (unlikely(!sw_context->kernel)) { 32038c2ecf20Sopenharmony_ci VMW_DEBUG_USER("Kernel only SVGA command: %u.\n", cmd_id); 32048c2ecf20Sopenharmony_ci return -EPERM; 32058c2ecf20Sopenharmony_ci } 32068c2ecf20Sopenharmony_ci 32078c2ecf20Sopenharmony_ci if (cmd_id == SVGA_CMD_DEFINE_GMRFB) 32088c2ecf20Sopenharmony_ci return vmw_cmd_check_define_gmrfb(dev_priv, sw_context, buf); 32098c2ecf20Sopenharmony_ci 32108c2ecf20Sopenharmony_ci return 0; 32118c2ecf20Sopenharmony_ci} 32128c2ecf20Sopenharmony_ci 32138c2ecf20Sopenharmony_cistatic const struct vmw_cmd_entry vmw_cmd_entries[SVGA_3D_CMD_MAX] = { 32148c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_SURFACE_DEFINE, &vmw_cmd_invalid, 32158c2ecf20Sopenharmony_ci false, false, false), 32168c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_SURFACE_DESTROY, &vmw_cmd_invalid, 32178c2ecf20Sopenharmony_ci false, false, false), 32188c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_SURFACE_COPY, &vmw_cmd_surface_copy_check, 32198c2ecf20Sopenharmony_ci true, false, false), 32208c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_SURFACE_STRETCHBLT, &vmw_cmd_stretch_blt_check, 32218c2ecf20Sopenharmony_ci true, false, false), 32228c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_SURFACE_DMA, &vmw_cmd_dma, 32238c2ecf20Sopenharmony_ci true, false, false), 32248c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_CONTEXT_DEFINE, &vmw_cmd_invalid, 32258c2ecf20Sopenharmony_ci false, false, false), 32268c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_CONTEXT_DESTROY, &vmw_cmd_invalid, 32278c2ecf20Sopenharmony_ci false, false, false), 32288c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_SETTRANSFORM, &vmw_cmd_cid_check, 32298c2ecf20Sopenharmony_ci true, false, false), 32308c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_SETZRANGE, &vmw_cmd_cid_check, 32318c2ecf20Sopenharmony_ci true, false, false), 32328c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_SETRENDERSTATE, &vmw_cmd_cid_check, 32338c2ecf20Sopenharmony_ci true, false, false), 32348c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_SETRENDERTARGET, 32358c2ecf20Sopenharmony_ci &vmw_cmd_set_render_target_check, true, false, false), 32368c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_SETTEXTURESTATE, &vmw_cmd_tex_state, 32378c2ecf20Sopenharmony_ci true, false, false), 32388c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_SETMATERIAL, &vmw_cmd_cid_check, 32398c2ecf20Sopenharmony_ci true, false, false), 32408c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_SETLIGHTDATA, &vmw_cmd_cid_check, 32418c2ecf20Sopenharmony_ci true, false, false), 32428c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_SETLIGHTENABLED, &vmw_cmd_cid_check, 32438c2ecf20Sopenharmony_ci true, false, false), 32448c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_SETVIEWPORT, &vmw_cmd_cid_check, 32458c2ecf20Sopenharmony_ci true, false, false), 32468c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_SETCLIPPLANE, &vmw_cmd_cid_check, 32478c2ecf20Sopenharmony_ci true, false, false), 32488c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_CLEAR, &vmw_cmd_cid_check, 32498c2ecf20Sopenharmony_ci true, false, false), 32508c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_PRESENT, &vmw_cmd_present_check, 32518c2ecf20Sopenharmony_ci false, false, false), 32528c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_SHADER_DEFINE, &vmw_cmd_shader_define, 32538c2ecf20Sopenharmony_ci true, false, false), 32548c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_SHADER_DESTROY, &vmw_cmd_shader_destroy, 32558c2ecf20Sopenharmony_ci true, false, false), 32568c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_SET_SHADER, &vmw_cmd_set_shader, 32578c2ecf20Sopenharmony_ci true, false, false), 32588c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_SET_SHADER_CONST, &vmw_cmd_set_shader_const, 32598c2ecf20Sopenharmony_ci true, false, false), 32608c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DRAW_PRIMITIVES, &vmw_cmd_draw, 32618c2ecf20Sopenharmony_ci true, false, false), 32628c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_SETSCISSORRECT, &vmw_cmd_cid_check, 32638c2ecf20Sopenharmony_ci true, false, false), 32648c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_BEGIN_QUERY, &vmw_cmd_begin_query, 32658c2ecf20Sopenharmony_ci true, false, false), 32668c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_END_QUERY, &vmw_cmd_end_query, 32678c2ecf20Sopenharmony_ci true, false, false), 32688c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_WAIT_FOR_QUERY, &vmw_cmd_wait_query, 32698c2ecf20Sopenharmony_ci true, false, false), 32708c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_PRESENT_READBACK, &vmw_cmd_ok, 32718c2ecf20Sopenharmony_ci true, false, false), 32728c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_BLIT_SURFACE_TO_SCREEN, 32738c2ecf20Sopenharmony_ci &vmw_cmd_blt_surf_screen_check, false, false, false), 32748c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_SURFACE_DEFINE_V2, &vmw_cmd_invalid, 32758c2ecf20Sopenharmony_ci false, false, false), 32768c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_GENERATE_MIPMAPS, &vmw_cmd_invalid, 32778c2ecf20Sopenharmony_ci false, false, false), 32788c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_ACTIVATE_SURFACE, &vmw_cmd_invalid, 32798c2ecf20Sopenharmony_ci false, false, false), 32808c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DEACTIVATE_SURFACE, &vmw_cmd_invalid, 32818c2ecf20Sopenharmony_ci false, false, false), 32828c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_SCREEN_DMA, &vmw_cmd_invalid, 32838c2ecf20Sopenharmony_ci false, false, false), 32848c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DEAD1, &vmw_cmd_invalid, 32858c2ecf20Sopenharmony_ci false, false, false), 32868c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DEAD2, &vmw_cmd_invalid, 32878c2ecf20Sopenharmony_ci false, false, false), 32888c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DEAD12, &vmw_cmd_invalid, false, false, false), 32898c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DEAD13, &vmw_cmd_invalid, false, false, false), 32908c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DEAD14, &vmw_cmd_invalid, false, false, false), 32918c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DEAD15, &vmw_cmd_invalid, false, false, false), 32928c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DEAD16, &vmw_cmd_invalid, false, false, false), 32938c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DEAD17, &vmw_cmd_invalid, false, false, false), 32948c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_SET_OTABLE_BASE, &vmw_cmd_invalid, 32958c2ecf20Sopenharmony_ci false, false, true), 32968c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_READBACK_OTABLE, &vmw_cmd_invalid, 32978c2ecf20Sopenharmony_ci false, false, true), 32988c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DEFINE_GB_MOB, &vmw_cmd_invalid, 32998c2ecf20Sopenharmony_ci false, false, true), 33008c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DESTROY_GB_MOB, &vmw_cmd_invalid, 33018c2ecf20Sopenharmony_ci false, false, true), 33028c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_REDEFINE_GB_MOB64, &vmw_cmd_invalid, 33038c2ecf20Sopenharmony_ci false, false, true), 33048c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_UPDATE_GB_MOB_MAPPING, &vmw_cmd_invalid, 33058c2ecf20Sopenharmony_ci false, false, true), 33068c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DEFINE_GB_SURFACE, &vmw_cmd_invalid, 33078c2ecf20Sopenharmony_ci false, false, true), 33088c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DESTROY_GB_SURFACE, &vmw_cmd_invalid, 33098c2ecf20Sopenharmony_ci false, false, true), 33108c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_BIND_GB_SURFACE, &vmw_cmd_bind_gb_surface, 33118c2ecf20Sopenharmony_ci true, false, true), 33128c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_COND_BIND_GB_SURFACE, &vmw_cmd_invalid, 33138c2ecf20Sopenharmony_ci false, false, true), 33148c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_UPDATE_GB_IMAGE, &vmw_cmd_update_gb_image, 33158c2ecf20Sopenharmony_ci true, false, true), 33168c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_UPDATE_GB_SURFACE, 33178c2ecf20Sopenharmony_ci &vmw_cmd_update_gb_surface, true, false, true), 33188c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_READBACK_GB_IMAGE, 33198c2ecf20Sopenharmony_ci &vmw_cmd_readback_gb_image, true, false, true), 33208c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_READBACK_GB_SURFACE, 33218c2ecf20Sopenharmony_ci &vmw_cmd_readback_gb_surface, true, false, true), 33228c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_INVALIDATE_GB_IMAGE, 33238c2ecf20Sopenharmony_ci &vmw_cmd_invalidate_gb_image, true, false, true), 33248c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_INVALIDATE_GB_SURFACE, 33258c2ecf20Sopenharmony_ci &vmw_cmd_invalidate_gb_surface, true, false, true), 33268c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DEFINE_GB_CONTEXT, &vmw_cmd_invalid, 33278c2ecf20Sopenharmony_ci false, false, true), 33288c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DESTROY_GB_CONTEXT, &vmw_cmd_invalid, 33298c2ecf20Sopenharmony_ci false, false, true), 33308c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_BIND_GB_CONTEXT, &vmw_cmd_invalid, 33318c2ecf20Sopenharmony_ci false, false, true), 33328c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_READBACK_GB_CONTEXT, &vmw_cmd_invalid, 33338c2ecf20Sopenharmony_ci false, false, true), 33348c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_INVALIDATE_GB_CONTEXT, &vmw_cmd_invalid, 33358c2ecf20Sopenharmony_ci false, false, true), 33368c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DEFINE_GB_SHADER, &vmw_cmd_invalid, 33378c2ecf20Sopenharmony_ci false, false, true), 33388c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_BIND_GB_SHADER, &vmw_cmd_bind_gb_shader, 33398c2ecf20Sopenharmony_ci true, false, true), 33408c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DESTROY_GB_SHADER, &vmw_cmd_invalid, 33418c2ecf20Sopenharmony_ci false, false, true), 33428c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_SET_OTABLE_BASE64, &vmw_cmd_invalid, 33438c2ecf20Sopenharmony_ci false, false, false), 33448c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_BEGIN_GB_QUERY, &vmw_cmd_begin_gb_query, 33458c2ecf20Sopenharmony_ci true, false, true), 33468c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_END_GB_QUERY, &vmw_cmd_end_gb_query, 33478c2ecf20Sopenharmony_ci true, false, true), 33488c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_WAIT_FOR_GB_QUERY, &vmw_cmd_wait_gb_query, 33498c2ecf20Sopenharmony_ci true, false, true), 33508c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_NOP, &vmw_cmd_ok, 33518c2ecf20Sopenharmony_ci true, false, true), 33528c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_NOP_ERROR, &vmw_cmd_ok, 33538c2ecf20Sopenharmony_ci true, false, true), 33548c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_ENABLE_GART, &vmw_cmd_invalid, 33558c2ecf20Sopenharmony_ci false, false, true), 33568c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DISABLE_GART, &vmw_cmd_invalid, 33578c2ecf20Sopenharmony_ci false, false, true), 33588c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_MAP_MOB_INTO_GART, &vmw_cmd_invalid, 33598c2ecf20Sopenharmony_ci false, false, true), 33608c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_UNMAP_GART_RANGE, &vmw_cmd_invalid, 33618c2ecf20Sopenharmony_ci false, false, true), 33628c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DEFINE_GB_SCREENTARGET, &vmw_cmd_invalid, 33638c2ecf20Sopenharmony_ci false, false, true), 33648c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DESTROY_GB_SCREENTARGET, &vmw_cmd_invalid, 33658c2ecf20Sopenharmony_ci false, false, true), 33668c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_BIND_GB_SCREENTARGET, &vmw_cmd_invalid, 33678c2ecf20Sopenharmony_ci false, false, true), 33688c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_UPDATE_GB_SCREENTARGET, &vmw_cmd_invalid, 33698c2ecf20Sopenharmony_ci false, false, true), 33708c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_READBACK_GB_IMAGE_PARTIAL, &vmw_cmd_invalid, 33718c2ecf20Sopenharmony_ci false, false, true), 33728c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_INVALIDATE_GB_IMAGE_PARTIAL, &vmw_cmd_invalid, 33738c2ecf20Sopenharmony_ci false, false, true), 33748c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_SET_GB_SHADERCONSTS_INLINE, &vmw_cmd_cid_check, 33758c2ecf20Sopenharmony_ci true, false, true), 33768c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_GB_SCREEN_DMA, &vmw_cmd_invalid, 33778c2ecf20Sopenharmony_ci false, false, true), 33788c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_BIND_GB_SURFACE_WITH_PITCH, &vmw_cmd_invalid, 33798c2ecf20Sopenharmony_ci false, false, true), 33808c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_GB_MOB_FENCE, &vmw_cmd_invalid, 33818c2ecf20Sopenharmony_ci false, false, true), 33828c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DEFINE_GB_SURFACE_V2, &vmw_cmd_invalid, 33838c2ecf20Sopenharmony_ci false, false, true), 33848c2ecf20Sopenharmony_ci 33858c2ecf20Sopenharmony_ci /* SM commands */ 33868c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_DEFINE_CONTEXT, &vmw_cmd_invalid, 33878c2ecf20Sopenharmony_ci false, false, true), 33888c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_DESTROY_CONTEXT, &vmw_cmd_invalid, 33898c2ecf20Sopenharmony_ci false, false, true), 33908c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_BIND_CONTEXT, &vmw_cmd_invalid, 33918c2ecf20Sopenharmony_ci false, false, true), 33928c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_READBACK_CONTEXT, &vmw_cmd_invalid, 33938c2ecf20Sopenharmony_ci false, false, true), 33948c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_INVALIDATE_CONTEXT, &vmw_cmd_invalid, 33958c2ecf20Sopenharmony_ci false, false, true), 33968c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_SET_SINGLE_CONSTANT_BUFFER, 33978c2ecf20Sopenharmony_ci &vmw_cmd_dx_set_single_constant_buffer, true, false, true), 33988c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_SET_SHADER_RESOURCES, 33998c2ecf20Sopenharmony_ci &vmw_cmd_dx_set_shader_res, true, false, true), 34008c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_SET_SHADER, &vmw_cmd_dx_set_shader, 34018c2ecf20Sopenharmony_ci true, false, true), 34028c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_SET_SAMPLERS, &vmw_cmd_dx_cid_check, 34038c2ecf20Sopenharmony_ci true, false, true), 34048c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_DRAW, &vmw_cmd_dx_cid_check, 34058c2ecf20Sopenharmony_ci true, false, true), 34068c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_DRAW_INDEXED, &vmw_cmd_dx_cid_check, 34078c2ecf20Sopenharmony_ci true, false, true), 34088c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_DRAW_INSTANCED, &vmw_cmd_dx_cid_check, 34098c2ecf20Sopenharmony_ci true, false, true), 34108c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_DRAW_INDEXED_INSTANCED, 34118c2ecf20Sopenharmony_ci &vmw_cmd_dx_cid_check, true, false, true), 34128c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_DRAW_AUTO, &vmw_cmd_dx_cid_check, 34138c2ecf20Sopenharmony_ci true, false, true), 34148c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_SET_VERTEX_BUFFERS, 34158c2ecf20Sopenharmony_ci &vmw_cmd_dx_set_vertex_buffers, true, false, true), 34168c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_SET_INDEX_BUFFER, 34178c2ecf20Sopenharmony_ci &vmw_cmd_dx_set_index_buffer, true, false, true), 34188c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_SET_RENDERTARGETS, 34198c2ecf20Sopenharmony_ci &vmw_cmd_dx_set_rendertargets, true, false, true), 34208c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_SET_BLEND_STATE, &vmw_cmd_dx_cid_check, 34218c2ecf20Sopenharmony_ci true, false, true), 34228c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_SET_DEPTHSTENCIL_STATE, 34238c2ecf20Sopenharmony_ci &vmw_cmd_dx_cid_check, true, false, true), 34248c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_SET_RASTERIZER_STATE, 34258c2ecf20Sopenharmony_ci &vmw_cmd_dx_cid_check, true, false, true), 34268c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_DEFINE_QUERY, &vmw_cmd_dx_define_query, 34278c2ecf20Sopenharmony_ci true, false, true), 34288c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_DESTROY_QUERY, &vmw_cmd_dx_cid_check, 34298c2ecf20Sopenharmony_ci true, false, true), 34308c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_BIND_QUERY, &vmw_cmd_dx_bind_query, 34318c2ecf20Sopenharmony_ci true, false, true), 34328c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_SET_QUERY_OFFSET, 34338c2ecf20Sopenharmony_ci &vmw_cmd_dx_cid_check, true, false, true), 34348c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_BEGIN_QUERY, &vmw_cmd_dx_cid_check, 34358c2ecf20Sopenharmony_ci true, false, true), 34368c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_END_QUERY, &vmw_cmd_dx_cid_check, 34378c2ecf20Sopenharmony_ci true, false, true), 34388c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_READBACK_QUERY, &vmw_cmd_invalid, 34398c2ecf20Sopenharmony_ci true, false, true), 34408c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_SET_PREDICATION, &vmw_cmd_dx_cid_check, 34418c2ecf20Sopenharmony_ci true, false, true), 34428c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_SET_VIEWPORTS, &vmw_cmd_dx_cid_check, 34438c2ecf20Sopenharmony_ci true, false, true), 34448c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_SET_SCISSORRECTS, &vmw_cmd_dx_cid_check, 34458c2ecf20Sopenharmony_ci true, false, true), 34468c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_CLEAR_RENDERTARGET_VIEW, 34478c2ecf20Sopenharmony_ci &vmw_cmd_dx_clear_rendertarget_view, true, false, true), 34488c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_CLEAR_DEPTHSTENCIL_VIEW, 34498c2ecf20Sopenharmony_ci &vmw_cmd_dx_clear_depthstencil_view, true, false, true), 34508c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_PRED_COPY, &vmw_cmd_invalid, 34518c2ecf20Sopenharmony_ci true, false, true), 34528c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_GENMIPS, &vmw_cmd_dx_genmips, 34538c2ecf20Sopenharmony_ci true, false, true), 34548c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_UPDATE_SUBRESOURCE, 34558c2ecf20Sopenharmony_ci &vmw_cmd_dx_check_subresource, true, false, true), 34568c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_READBACK_SUBRESOURCE, 34578c2ecf20Sopenharmony_ci &vmw_cmd_dx_check_subresource, true, false, true), 34588c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_INVALIDATE_SUBRESOURCE, 34598c2ecf20Sopenharmony_ci &vmw_cmd_dx_check_subresource, true, false, true), 34608c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_DEFINE_SHADERRESOURCE_VIEW, 34618c2ecf20Sopenharmony_ci &vmw_cmd_dx_view_define, true, false, true), 34628c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_DESTROY_SHADERRESOURCE_VIEW, 34638c2ecf20Sopenharmony_ci &vmw_cmd_dx_view_remove, true, false, true), 34648c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_DEFINE_RENDERTARGET_VIEW, 34658c2ecf20Sopenharmony_ci &vmw_cmd_dx_view_define, true, false, true), 34668c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_DESTROY_RENDERTARGET_VIEW, 34678c2ecf20Sopenharmony_ci &vmw_cmd_dx_view_remove, true, false, true), 34688c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_DEFINE_DEPTHSTENCIL_VIEW, 34698c2ecf20Sopenharmony_ci &vmw_cmd_dx_view_define, true, false, true), 34708c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_DESTROY_DEPTHSTENCIL_VIEW, 34718c2ecf20Sopenharmony_ci &vmw_cmd_dx_view_remove, true, false, true), 34728c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_DEFINE_ELEMENTLAYOUT, 34738c2ecf20Sopenharmony_ci &vmw_cmd_dx_so_define, true, false, true), 34748c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_DESTROY_ELEMENTLAYOUT, 34758c2ecf20Sopenharmony_ci &vmw_cmd_dx_cid_check, true, false, true), 34768c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_DEFINE_BLEND_STATE, 34778c2ecf20Sopenharmony_ci &vmw_cmd_dx_so_define, true, false, true), 34788c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_DESTROY_BLEND_STATE, 34798c2ecf20Sopenharmony_ci &vmw_cmd_dx_cid_check, true, false, true), 34808c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_DEFINE_DEPTHSTENCIL_STATE, 34818c2ecf20Sopenharmony_ci &vmw_cmd_dx_so_define, true, false, true), 34828c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_DESTROY_DEPTHSTENCIL_STATE, 34838c2ecf20Sopenharmony_ci &vmw_cmd_dx_cid_check, true, false, true), 34848c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_DEFINE_RASTERIZER_STATE, 34858c2ecf20Sopenharmony_ci &vmw_cmd_dx_so_define, true, false, true), 34868c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_DESTROY_RASTERIZER_STATE, 34878c2ecf20Sopenharmony_ci &vmw_cmd_dx_cid_check, true, false, true), 34888c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_DEFINE_SAMPLER_STATE, 34898c2ecf20Sopenharmony_ci &vmw_cmd_dx_so_define, true, false, true), 34908c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_DESTROY_SAMPLER_STATE, 34918c2ecf20Sopenharmony_ci &vmw_cmd_dx_cid_check, true, false, true), 34928c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_DEFINE_SHADER, 34938c2ecf20Sopenharmony_ci &vmw_cmd_dx_define_shader, true, false, true), 34948c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_DESTROY_SHADER, 34958c2ecf20Sopenharmony_ci &vmw_cmd_dx_destroy_shader, true, false, true), 34968c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_BIND_SHADER, 34978c2ecf20Sopenharmony_ci &vmw_cmd_dx_bind_shader, true, false, true), 34988c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_DEFINE_STREAMOUTPUT, 34998c2ecf20Sopenharmony_ci &vmw_cmd_dx_so_define, true, false, true), 35008c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_DESTROY_STREAMOUTPUT, 35018c2ecf20Sopenharmony_ci &vmw_cmd_dx_destroy_streamoutput, true, false, true), 35028c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_SET_STREAMOUTPUT, 35038c2ecf20Sopenharmony_ci &vmw_cmd_dx_set_streamoutput, true, false, true), 35048c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_SET_SOTARGETS, 35058c2ecf20Sopenharmony_ci &vmw_cmd_dx_set_so_targets, true, false, true), 35068c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_SET_INPUT_LAYOUT, 35078c2ecf20Sopenharmony_ci &vmw_cmd_dx_cid_check, true, false, true), 35088c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_SET_TOPOLOGY, 35098c2ecf20Sopenharmony_ci &vmw_cmd_dx_cid_check, true, false, true), 35108c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_BUFFER_COPY, 35118c2ecf20Sopenharmony_ci &vmw_cmd_buffer_copy_check, true, false, true), 35128c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_PRED_COPY_REGION, 35138c2ecf20Sopenharmony_ci &vmw_cmd_pred_copy_check, true, false, true), 35148c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_TRANSFER_FROM_BUFFER, 35158c2ecf20Sopenharmony_ci &vmw_cmd_dx_transfer_from_buffer, 35168c2ecf20Sopenharmony_ci true, false, true), 35178c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_INTRA_SURFACE_COPY, &vmw_cmd_intra_surface_copy, 35188c2ecf20Sopenharmony_ci true, false, true), 35198c2ecf20Sopenharmony_ci 35208c2ecf20Sopenharmony_ci /* 35218c2ecf20Sopenharmony_ci * SM5 commands 35228c2ecf20Sopenharmony_ci */ 35238c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_DEFINE_UA_VIEW, &vmw_cmd_sm5_view_define, 35248c2ecf20Sopenharmony_ci true, false, true), 35258c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_DESTROY_UA_VIEW, &vmw_cmd_sm5_view_remove, 35268c2ecf20Sopenharmony_ci true, false, true), 35278c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_CLEAR_UA_VIEW_UINT, &vmw_cmd_clear_uav_uint, 35288c2ecf20Sopenharmony_ci true, false, true), 35298c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_CLEAR_UA_VIEW_FLOAT, 35308c2ecf20Sopenharmony_ci &vmw_cmd_clear_uav_float, true, false, true), 35318c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_COPY_STRUCTURE_COUNT, &vmw_cmd_invalid, true, 35328c2ecf20Sopenharmony_ci false, true), 35338c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_SET_UA_VIEWS, &vmw_cmd_set_uav, true, false, 35348c2ecf20Sopenharmony_ci true), 35358c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_DRAW_INDEXED_INSTANCED_INDIRECT, 35368c2ecf20Sopenharmony_ci &vmw_cmd_indexed_instanced_indirect, true, false, true), 35378c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_DRAW_INSTANCED_INDIRECT, 35388c2ecf20Sopenharmony_ci &vmw_cmd_instanced_indirect, true, false, true), 35398c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_DISPATCH, &vmw_cmd_sm5, true, false, true), 35408c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_DISPATCH_INDIRECT, 35418c2ecf20Sopenharmony_ci &vmw_cmd_dispatch_indirect, true, false, true), 35428c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_SET_CS_UA_VIEWS, &vmw_cmd_set_cs_uav, true, 35438c2ecf20Sopenharmony_ci false, true), 35448c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_DEFINE_DEPTHSTENCIL_VIEW_V2, 35458c2ecf20Sopenharmony_ci &vmw_cmd_sm5_view_define, true, false, true), 35468c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_DEFINE_STREAMOUTPUT_WITH_MOB, 35478c2ecf20Sopenharmony_ci &vmw_cmd_dx_define_streamoutput, true, false, true), 35488c2ecf20Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_BIND_STREAMOUTPUT, 35498c2ecf20Sopenharmony_ci &vmw_cmd_dx_bind_streamoutput, true, false, true), 35508c2ecf20Sopenharmony_ci}; 35518c2ecf20Sopenharmony_ci 35528c2ecf20Sopenharmony_cibool vmw_cmd_describe(const void *buf, u32 *size, char const **cmd) 35538c2ecf20Sopenharmony_ci{ 35548c2ecf20Sopenharmony_ci u32 cmd_id = ((u32 *) buf)[0]; 35558c2ecf20Sopenharmony_ci 35568c2ecf20Sopenharmony_ci if (cmd_id >= SVGA_CMD_MAX) { 35578c2ecf20Sopenharmony_ci SVGA3dCmdHeader *header = (SVGA3dCmdHeader *) buf; 35588c2ecf20Sopenharmony_ci const struct vmw_cmd_entry *entry; 35598c2ecf20Sopenharmony_ci 35608c2ecf20Sopenharmony_ci *size = header->size + sizeof(SVGA3dCmdHeader); 35618c2ecf20Sopenharmony_ci cmd_id = header->id; 35628c2ecf20Sopenharmony_ci if (cmd_id >= SVGA_3D_CMD_MAX) 35638c2ecf20Sopenharmony_ci return false; 35648c2ecf20Sopenharmony_ci 35658c2ecf20Sopenharmony_ci cmd_id -= SVGA_3D_CMD_BASE; 35668c2ecf20Sopenharmony_ci entry = &vmw_cmd_entries[cmd_id]; 35678c2ecf20Sopenharmony_ci *cmd = entry->cmd_name; 35688c2ecf20Sopenharmony_ci return true; 35698c2ecf20Sopenharmony_ci } 35708c2ecf20Sopenharmony_ci 35718c2ecf20Sopenharmony_ci switch (cmd_id) { 35728c2ecf20Sopenharmony_ci case SVGA_CMD_UPDATE: 35738c2ecf20Sopenharmony_ci *cmd = "SVGA_CMD_UPDATE"; 35748c2ecf20Sopenharmony_ci *size = sizeof(u32) + sizeof(SVGAFifoCmdUpdate); 35758c2ecf20Sopenharmony_ci break; 35768c2ecf20Sopenharmony_ci case SVGA_CMD_DEFINE_GMRFB: 35778c2ecf20Sopenharmony_ci *cmd = "SVGA_CMD_DEFINE_GMRFB"; 35788c2ecf20Sopenharmony_ci *size = sizeof(u32) + sizeof(SVGAFifoCmdDefineGMRFB); 35798c2ecf20Sopenharmony_ci break; 35808c2ecf20Sopenharmony_ci case SVGA_CMD_BLIT_GMRFB_TO_SCREEN: 35818c2ecf20Sopenharmony_ci *cmd = "SVGA_CMD_BLIT_GMRFB_TO_SCREEN"; 35828c2ecf20Sopenharmony_ci *size = sizeof(u32) + sizeof(SVGAFifoCmdBlitGMRFBToScreen); 35838c2ecf20Sopenharmony_ci break; 35848c2ecf20Sopenharmony_ci case SVGA_CMD_BLIT_SCREEN_TO_GMRFB: 35858c2ecf20Sopenharmony_ci *cmd = "SVGA_CMD_BLIT_SCREEN_TO_GMRFB"; 35868c2ecf20Sopenharmony_ci *size = sizeof(u32) + sizeof(SVGAFifoCmdBlitGMRFBToScreen); 35878c2ecf20Sopenharmony_ci break; 35888c2ecf20Sopenharmony_ci default: 35898c2ecf20Sopenharmony_ci *cmd = "UNKNOWN"; 35908c2ecf20Sopenharmony_ci *size = 0; 35918c2ecf20Sopenharmony_ci return false; 35928c2ecf20Sopenharmony_ci } 35938c2ecf20Sopenharmony_ci 35948c2ecf20Sopenharmony_ci return true; 35958c2ecf20Sopenharmony_ci} 35968c2ecf20Sopenharmony_ci 35978c2ecf20Sopenharmony_cistatic int vmw_cmd_check(struct vmw_private *dev_priv, 35988c2ecf20Sopenharmony_ci struct vmw_sw_context *sw_context, void *buf, 35998c2ecf20Sopenharmony_ci uint32_t *size) 36008c2ecf20Sopenharmony_ci{ 36018c2ecf20Sopenharmony_ci uint32_t cmd_id; 36028c2ecf20Sopenharmony_ci uint32_t size_remaining = *size; 36038c2ecf20Sopenharmony_ci SVGA3dCmdHeader *header = (SVGA3dCmdHeader *) buf; 36048c2ecf20Sopenharmony_ci int ret; 36058c2ecf20Sopenharmony_ci const struct vmw_cmd_entry *entry; 36068c2ecf20Sopenharmony_ci bool gb = dev_priv->capabilities & SVGA_CAP_GBOBJECTS; 36078c2ecf20Sopenharmony_ci 36088c2ecf20Sopenharmony_ci cmd_id = ((uint32_t *)buf)[0]; 36098c2ecf20Sopenharmony_ci /* Handle any none 3D commands */ 36108c2ecf20Sopenharmony_ci if (unlikely(cmd_id < SVGA_CMD_MAX)) 36118c2ecf20Sopenharmony_ci return vmw_cmd_check_not_3d(dev_priv, sw_context, buf, size); 36128c2ecf20Sopenharmony_ci 36138c2ecf20Sopenharmony_ci 36148c2ecf20Sopenharmony_ci cmd_id = header->id; 36158c2ecf20Sopenharmony_ci *size = header->size + sizeof(SVGA3dCmdHeader); 36168c2ecf20Sopenharmony_ci 36178c2ecf20Sopenharmony_ci cmd_id -= SVGA_3D_CMD_BASE; 36188c2ecf20Sopenharmony_ci if (unlikely(*size > size_remaining)) 36198c2ecf20Sopenharmony_ci goto out_invalid; 36208c2ecf20Sopenharmony_ci 36218c2ecf20Sopenharmony_ci if (unlikely(cmd_id >= SVGA_3D_CMD_MAX - SVGA_3D_CMD_BASE)) 36228c2ecf20Sopenharmony_ci goto out_invalid; 36238c2ecf20Sopenharmony_ci 36248c2ecf20Sopenharmony_ci entry = &vmw_cmd_entries[cmd_id]; 36258c2ecf20Sopenharmony_ci if (unlikely(!entry->func)) 36268c2ecf20Sopenharmony_ci goto out_invalid; 36278c2ecf20Sopenharmony_ci 36288c2ecf20Sopenharmony_ci if (unlikely(!entry->user_allow && !sw_context->kernel)) 36298c2ecf20Sopenharmony_ci goto out_privileged; 36308c2ecf20Sopenharmony_ci 36318c2ecf20Sopenharmony_ci if (unlikely(entry->gb_disable && gb)) 36328c2ecf20Sopenharmony_ci goto out_old; 36338c2ecf20Sopenharmony_ci 36348c2ecf20Sopenharmony_ci if (unlikely(entry->gb_enable && !gb)) 36358c2ecf20Sopenharmony_ci goto out_new; 36368c2ecf20Sopenharmony_ci 36378c2ecf20Sopenharmony_ci ret = entry->func(dev_priv, sw_context, header); 36388c2ecf20Sopenharmony_ci if (unlikely(ret != 0)) { 36398c2ecf20Sopenharmony_ci VMW_DEBUG_USER("SVGA3D command: %d failed with error %d\n", 36408c2ecf20Sopenharmony_ci cmd_id + SVGA_3D_CMD_BASE, ret); 36418c2ecf20Sopenharmony_ci return ret; 36428c2ecf20Sopenharmony_ci } 36438c2ecf20Sopenharmony_ci 36448c2ecf20Sopenharmony_ci return 0; 36458c2ecf20Sopenharmony_ciout_invalid: 36468c2ecf20Sopenharmony_ci VMW_DEBUG_USER("Invalid SVGA3D command: %d\n", 36478c2ecf20Sopenharmony_ci cmd_id + SVGA_3D_CMD_BASE); 36488c2ecf20Sopenharmony_ci return -EINVAL; 36498c2ecf20Sopenharmony_ciout_privileged: 36508c2ecf20Sopenharmony_ci VMW_DEBUG_USER("Privileged SVGA3D command: %d\n", 36518c2ecf20Sopenharmony_ci cmd_id + SVGA_3D_CMD_BASE); 36528c2ecf20Sopenharmony_ci return -EPERM; 36538c2ecf20Sopenharmony_ciout_old: 36548c2ecf20Sopenharmony_ci VMW_DEBUG_USER("Deprecated (disallowed) SVGA3D command: %d\n", 36558c2ecf20Sopenharmony_ci cmd_id + SVGA_3D_CMD_BASE); 36568c2ecf20Sopenharmony_ci return -EINVAL; 36578c2ecf20Sopenharmony_ciout_new: 36588c2ecf20Sopenharmony_ci VMW_DEBUG_USER("SVGA3D command: %d not supported by virtual device.\n", 36598c2ecf20Sopenharmony_ci cmd_id + SVGA_3D_CMD_BASE); 36608c2ecf20Sopenharmony_ci return -EINVAL; 36618c2ecf20Sopenharmony_ci} 36628c2ecf20Sopenharmony_ci 36638c2ecf20Sopenharmony_cistatic int vmw_cmd_check_all(struct vmw_private *dev_priv, 36648c2ecf20Sopenharmony_ci struct vmw_sw_context *sw_context, void *buf, 36658c2ecf20Sopenharmony_ci uint32_t size) 36668c2ecf20Sopenharmony_ci{ 36678c2ecf20Sopenharmony_ci int32_t cur_size = size; 36688c2ecf20Sopenharmony_ci int ret; 36698c2ecf20Sopenharmony_ci 36708c2ecf20Sopenharmony_ci sw_context->buf_start = buf; 36718c2ecf20Sopenharmony_ci 36728c2ecf20Sopenharmony_ci while (cur_size > 0) { 36738c2ecf20Sopenharmony_ci size = cur_size; 36748c2ecf20Sopenharmony_ci ret = vmw_cmd_check(dev_priv, sw_context, buf, &size); 36758c2ecf20Sopenharmony_ci if (unlikely(ret != 0)) 36768c2ecf20Sopenharmony_ci return ret; 36778c2ecf20Sopenharmony_ci buf = (void *)((unsigned long) buf + size); 36788c2ecf20Sopenharmony_ci cur_size -= size; 36798c2ecf20Sopenharmony_ci } 36808c2ecf20Sopenharmony_ci 36818c2ecf20Sopenharmony_ci if (unlikely(cur_size != 0)) { 36828c2ecf20Sopenharmony_ci VMW_DEBUG_USER("Command verifier out of sync.\n"); 36838c2ecf20Sopenharmony_ci return -EINVAL; 36848c2ecf20Sopenharmony_ci } 36858c2ecf20Sopenharmony_ci 36868c2ecf20Sopenharmony_ci return 0; 36878c2ecf20Sopenharmony_ci} 36888c2ecf20Sopenharmony_ci 36898c2ecf20Sopenharmony_cistatic void vmw_free_relocations(struct vmw_sw_context *sw_context) 36908c2ecf20Sopenharmony_ci{ 36918c2ecf20Sopenharmony_ci /* Memory is validation context memory, so no need to free it */ 36928c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&sw_context->bo_relocations); 36938c2ecf20Sopenharmony_ci} 36948c2ecf20Sopenharmony_ci 36958c2ecf20Sopenharmony_cistatic void vmw_apply_relocations(struct vmw_sw_context *sw_context) 36968c2ecf20Sopenharmony_ci{ 36978c2ecf20Sopenharmony_ci struct vmw_relocation *reloc; 36988c2ecf20Sopenharmony_ci struct ttm_buffer_object *bo; 36998c2ecf20Sopenharmony_ci 37008c2ecf20Sopenharmony_ci list_for_each_entry(reloc, &sw_context->bo_relocations, head) { 37018c2ecf20Sopenharmony_ci bo = &reloc->vbo->base; 37028c2ecf20Sopenharmony_ci switch (bo->mem.mem_type) { 37038c2ecf20Sopenharmony_ci case TTM_PL_VRAM: 37048c2ecf20Sopenharmony_ci reloc->location->offset += bo->mem.start << PAGE_SHIFT; 37058c2ecf20Sopenharmony_ci reloc->location->gmrId = SVGA_GMR_FRAMEBUFFER; 37068c2ecf20Sopenharmony_ci break; 37078c2ecf20Sopenharmony_ci case VMW_PL_GMR: 37088c2ecf20Sopenharmony_ci reloc->location->gmrId = bo->mem.start; 37098c2ecf20Sopenharmony_ci break; 37108c2ecf20Sopenharmony_ci case VMW_PL_MOB: 37118c2ecf20Sopenharmony_ci *reloc->mob_loc = bo->mem.start; 37128c2ecf20Sopenharmony_ci break; 37138c2ecf20Sopenharmony_ci default: 37148c2ecf20Sopenharmony_ci BUG(); 37158c2ecf20Sopenharmony_ci } 37168c2ecf20Sopenharmony_ci } 37178c2ecf20Sopenharmony_ci vmw_free_relocations(sw_context); 37188c2ecf20Sopenharmony_ci} 37198c2ecf20Sopenharmony_ci 37208c2ecf20Sopenharmony_cistatic int vmw_resize_cmd_bounce(struct vmw_sw_context *sw_context, 37218c2ecf20Sopenharmony_ci uint32_t size) 37228c2ecf20Sopenharmony_ci{ 37238c2ecf20Sopenharmony_ci if (likely(sw_context->cmd_bounce_size >= size)) 37248c2ecf20Sopenharmony_ci return 0; 37258c2ecf20Sopenharmony_ci 37268c2ecf20Sopenharmony_ci if (sw_context->cmd_bounce_size == 0) 37278c2ecf20Sopenharmony_ci sw_context->cmd_bounce_size = VMWGFX_CMD_BOUNCE_INIT_SIZE; 37288c2ecf20Sopenharmony_ci 37298c2ecf20Sopenharmony_ci while (sw_context->cmd_bounce_size < size) { 37308c2ecf20Sopenharmony_ci sw_context->cmd_bounce_size = 37318c2ecf20Sopenharmony_ci PAGE_ALIGN(sw_context->cmd_bounce_size + 37328c2ecf20Sopenharmony_ci (sw_context->cmd_bounce_size >> 1)); 37338c2ecf20Sopenharmony_ci } 37348c2ecf20Sopenharmony_ci 37358c2ecf20Sopenharmony_ci vfree(sw_context->cmd_bounce); 37368c2ecf20Sopenharmony_ci sw_context->cmd_bounce = vmalloc(sw_context->cmd_bounce_size); 37378c2ecf20Sopenharmony_ci 37388c2ecf20Sopenharmony_ci if (sw_context->cmd_bounce == NULL) { 37398c2ecf20Sopenharmony_ci VMW_DEBUG_USER("Failed to allocate command bounce buffer.\n"); 37408c2ecf20Sopenharmony_ci sw_context->cmd_bounce_size = 0; 37418c2ecf20Sopenharmony_ci return -ENOMEM; 37428c2ecf20Sopenharmony_ci } 37438c2ecf20Sopenharmony_ci 37448c2ecf20Sopenharmony_ci return 0; 37458c2ecf20Sopenharmony_ci} 37468c2ecf20Sopenharmony_ci 37478c2ecf20Sopenharmony_ci/** 37488c2ecf20Sopenharmony_ci * vmw_execbuf_fence_commands - create and submit a command stream fence 37498c2ecf20Sopenharmony_ci * 37508c2ecf20Sopenharmony_ci * Creates a fence object and submits a command stream marker. 37518c2ecf20Sopenharmony_ci * If this fails for some reason, We sync the fifo and return NULL. 37528c2ecf20Sopenharmony_ci * It is then safe to fence buffers with a NULL pointer. 37538c2ecf20Sopenharmony_ci * 37548c2ecf20Sopenharmony_ci * If @p_handle is not NULL @file_priv must also not be NULL. Creates a 37558c2ecf20Sopenharmony_ci * userspace handle if @p_handle is not NULL, otherwise not. 37568c2ecf20Sopenharmony_ci */ 37578c2ecf20Sopenharmony_ci 37588c2ecf20Sopenharmony_ciint vmw_execbuf_fence_commands(struct drm_file *file_priv, 37598c2ecf20Sopenharmony_ci struct vmw_private *dev_priv, 37608c2ecf20Sopenharmony_ci struct vmw_fence_obj **p_fence, 37618c2ecf20Sopenharmony_ci uint32_t *p_handle) 37628c2ecf20Sopenharmony_ci{ 37638c2ecf20Sopenharmony_ci uint32_t sequence; 37648c2ecf20Sopenharmony_ci int ret; 37658c2ecf20Sopenharmony_ci bool synced = false; 37668c2ecf20Sopenharmony_ci 37678c2ecf20Sopenharmony_ci /* p_handle implies file_priv. */ 37688c2ecf20Sopenharmony_ci BUG_ON(p_handle != NULL && file_priv == NULL); 37698c2ecf20Sopenharmony_ci 37708c2ecf20Sopenharmony_ci ret = vmw_fifo_send_fence(dev_priv, &sequence); 37718c2ecf20Sopenharmony_ci if (unlikely(ret != 0)) { 37728c2ecf20Sopenharmony_ci VMW_DEBUG_USER("Fence submission error. Syncing.\n"); 37738c2ecf20Sopenharmony_ci synced = true; 37748c2ecf20Sopenharmony_ci } 37758c2ecf20Sopenharmony_ci 37768c2ecf20Sopenharmony_ci if (p_handle != NULL) 37778c2ecf20Sopenharmony_ci ret = vmw_user_fence_create(file_priv, dev_priv->fman, 37788c2ecf20Sopenharmony_ci sequence, p_fence, p_handle); 37798c2ecf20Sopenharmony_ci else 37808c2ecf20Sopenharmony_ci ret = vmw_fence_create(dev_priv->fman, sequence, p_fence); 37818c2ecf20Sopenharmony_ci 37828c2ecf20Sopenharmony_ci if (unlikely(ret != 0 && !synced)) { 37838c2ecf20Sopenharmony_ci (void) vmw_fallback_wait(dev_priv, false, false, sequence, 37848c2ecf20Sopenharmony_ci false, VMW_FENCE_WAIT_TIMEOUT); 37858c2ecf20Sopenharmony_ci *p_fence = NULL; 37868c2ecf20Sopenharmony_ci } 37878c2ecf20Sopenharmony_ci 37888c2ecf20Sopenharmony_ci return ret; 37898c2ecf20Sopenharmony_ci} 37908c2ecf20Sopenharmony_ci 37918c2ecf20Sopenharmony_ci/** 37928c2ecf20Sopenharmony_ci * vmw_execbuf_copy_fence_user - copy fence object information to user-space. 37938c2ecf20Sopenharmony_ci * 37948c2ecf20Sopenharmony_ci * @dev_priv: Pointer to a vmw_private struct. 37958c2ecf20Sopenharmony_ci * @vmw_fp: Pointer to the struct vmw_fpriv representing the calling file. 37968c2ecf20Sopenharmony_ci * @ret: Return value from fence object creation. 37978c2ecf20Sopenharmony_ci * @user_fence_rep: User space address of a struct drm_vmw_fence_rep to which 37988c2ecf20Sopenharmony_ci * the information should be copied. 37998c2ecf20Sopenharmony_ci * @fence: Pointer to the fenc object. 38008c2ecf20Sopenharmony_ci * @fence_handle: User-space fence handle. 38018c2ecf20Sopenharmony_ci * @out_fence_fd: exported file descriptor for the fence. -1 if not used 38028c2ecf20Sopenharmony_ci * @sync_file: Only used to clean up in case of an error in this function. 38038c2ecf20Sopenharmony_ci * 38048c2ecf20Sopenharmony_ci * This function copies fence information to user-space. If copying fails, the 38058c2ecf20Sopenharmony_ci * user-space struct drm_vmw_fence_rep::error member is hopefully left 38068c2ecf20Sopenharmony_ci * untouched, and if it's preloaded with an -EFAULT by user-space, the error 38078c2ecf20Sopenharmony_ci * will hopefully be detected. 38088c2ecf20Sopenharmony_ci * 38098c2ecf20Sopenharmony_ci * Also if copying fails, user-space will be unable to signal the fence object 38108c2ecf20Sopenharmony_ci * so we wait for it immediately, and then unreference the user-space reference. 38118c2ecf20Sopenharmony_ci */ 38128c2ecf20Sopenharmony_ciint 38138c2ecf20Sopenharmony_civmw_execbuf_copy_fence_user(struct vmw_private *dev_priv, 38148c2ecf20Sopenharmony_ci struct vmw_fpriv *vmw_fp, int ret, 38158c2ecf20Sopenharmony_ci struct drm_vmw_fence_rep __user *user_fence_rep, 38168c2ecf20Sopenharmony_ci struct vmw_fence_obj *fence, uint32_t fence_handle, 38178c2ecf20Sopenharmony_ci int32_t out_fence_fd) 38188c2ecf20Sopenharmony_ci{ 38198c2ecf20Sopenharmony_ci struct drm_vmw_fence_rep fence_rep; 38208c2ecf20Sopenharmony_ci 38218c2ecf20Sopenharmony_ci if (user_fence_rep == NULL) 38228c2ecf20Sopenharmony_ci return 0; 38238c2ecf20Sopenharmony_ci 38248c2ecf20Sopenharmony_ci memset(&fence_rep, 0, sizeof(fence_rep)); 38258c2ecf20Sopenharmony_ci 38268c2ecf20Sopenharmony_ci fence_rep.error = ret; 38278c2ecf20Sopenharmony_ci fence_rep.fd = out_fence_fd; 38288c2ecf20Sopenharmony_ci if (ret == 0) { 38298c2ecf20Sopenharmony_ci BUG_ON(fence == NULL); 38308c2ecf20Sopenharmony_ci 38318c2ecf20Sopenharmony_ci fence_rep.handle = fence_handle; 38328c2ecf20Sopenharmony_ci fence_rep.seqno = fence->base.seqno; 38338c2ecf20Sopenharmony_ci vmw_update_seqno(dev_priv, &dev_priv->fifo); 38348c2ecf20Sopenharmony_ci fence_rep.passed_seqno = dev_priv->last_read_seqno; 38358c2ecf20Sopenharmony_ci } 38368c2ecf20Sopenharmony_ci 38378c2ecf20Sopenharmony_ci /* 38388c2ecf20Sopenharmony_ci * copy_to_user errors will be detected by user space not seeing 38398c2ecf20Sopenharmony_ci * fence_rep::error filled in. Typically user-space would have pre-set 38408c2ecf20Sopenharmony_ci * that member to -EFAULT. 38418c2ecf20Sopenharmony_ci */ 38428c2ecf20Sopenharmony_ci ret = copy_to_user(user_fence_rep, &fence_rep, 38438c2ecf20Sopenharmony_ci sizeof(fence_rep)); 38448c2ecf20Sopenharmony_ci 38458c2ecf20Sopenharmony_ci /* 38468c2ecf20Sopenharmony_ci * User-space lost the fence object. We need to sync and unreference the 38478c2ecf20Sopenharmony_ci * handle. 38488c2ecf20Sopenharmony_ci */ 38498c2ecf20Sopenharmony_ci if (unlikely(ret != 0) && (fence_rep.error == 0)) { 38508c2ecf20Sopenharmony_ci ttm_ref_object_base_unref(vmw_fp->tfile, fence_handle, 38518c2ecf20Sopenharmony_ci TTM_REF_USAGE); 38528c2ecf20Sopenharmony_ci VMW_DEBUG_USER("Fence copy error. Syncing.\n"); 38538c2ecf20Sopenharmony_ci (void) vmw_fence_obj_wait(fence, false, false, 38548c2ecf20Sopenharmony_ci VMW_FENCE_WAIT_TIMEOUT); 38558c2ecf20Sopenharmony_ci } 38568c2ecf20Sopenharmony_ci 38578c2ecf20Sopenharmony_ci return ret ? -EFAULT : 0; 38588c2ecf20Sopenharmony_ci} 38598c2ecf20Sopenharmony_ci 38608c2ecf20Sopenharmony_ci/** 38618c2ecf20Sopenharmony_ci * vmw_execbuf_submit_fifo - Patch a command batch and submit it using the fifo. 38628c2ecf20Sopenharmony_ci * 38638c2ecf20Sopenharmony_ci * @dev_priv: Pointer to a device private structure. 38648c2ecf20Sopenharmony_ci * @kernel_commands: Pointer to the unpatched command batch. 38658c2ecf20Sopenharmony_ci * @command_size: Size of the unpatched command batch. 38668c2ecf20Sopenharmony_ci * @sw_context: Structure holding the relocation lists. 38678c2ecf20Sopenharmony_ci * 38688c2ecf20Sopenharmony_ci * Side effects: If this function returns 0, then the command batch pointed to 38698c2ecf20Sopenharmony_ci * by @kernel_commands will have been modified. 38708c2ecf20Sopenharmony_ci */ 38718c2ecf20Sopenharmony_cistatic int vmw_execbuf_submit_fifo(struct vmw_private *dev_priv, 38728c2ecf20Sopenharmony_ci void *kernel_commands, u32 command_size, 38738c2ecf20Sopenharmony_ci struct vmw_sw_context *sw_context) 38748c2ecf20Sopenharmony_ci{ 38758c2ecf20Sopenharmony_ci void *cmd; 38768c2ecf20Sopenharmony_ci 38778c2ecf20Sopenharmony_ci if (sw_context->dx_ctx_node) 38788c2ecf20Sopenharmony_ci cmd = VMW_FIFO_RESERVE_DX(dev_priv, command_size, 38798c2ecf20Sopenharmony_ci sw_context->dx_ctx_node->ctx->id); 38808c2ecf20Sopenharmony_ci else 38818c2ecf20Sopenharmony_ci cmd = VMW_FIFO_RESERVE(dev_priv, command_size); 38828c2ecf20Sopenharmony_ci 38838c2ecf20Sopenharmony_ci if (!cmd) 38848c2ecf20Sopenharmony_ci return -ENOMEM; 38858c2ecf20Sopenharmony_ci 38868c2ecf20Sopenharmony_ci vmw_apply_relocations(sw_context); 38878c2ecf20Sopenharmony_ci memcpy(cmd, kernel_commands, command_size); 38888c2ecf20Sopenharmony_ci vmw_resource_relocations_apply(cmd, &sw_context->res_relocations); 38898c2ecf20Sopenharmony_ci vmw_resource_relocations_free(&sw_context->res_relocations); 38908c2ecf20Sopenharmony_ci vmw_fifo_commit(dev_priv, command_size); 38918c2ecf20Sopenharmony_ci 38928c2ecf20Sopenharmony_ci return 0; 38938c2ecf20Sopenharmony_ci} 38948c2ecf20Sopenharmony_ci 38958c2ecf20Sopenharmony_ci/** 38968c2ecf20Sopenharmony_ci * vmw_execbuf_submit_cmdbuf - Patch a command batch and submit it using the 38978c2ecf20Sopenharmony_ci * command buffer manager. 38988c2ecf20Sopenharmony_ci * 38998c2ecf20Sopenharmony_ci * @dev_priv: Pointer to a device private structure. 39008c2ecf20Sopenharmony_ci * @header: Opaque handle to the command buffer allocation. 39018c2ecf20Sopenharmony_ci * @command_size: Size of the unpatched command batch. 39028c2ecf20Sopenharmony_ci * @sw_context: Structure holding the relocation lists. 39038c2ecf20Sopenharmony_ci * 39048c2ecf20Sopenharmony_ci * Side effects: If this function returns 0, then the command buffer represented 39058c2ecf20Sopenharmony_ci * by @header will have been modified. 39068c2ecf20Sopenharmony_ci */ 39078c2ecf20Sopenharmony_cistatic int vmw_execbuf_submit_cmdbuf(struct vmw_private *dev_priv, 39088c2ecf20Sopenharmony_ci struct vmw_cmdbuf_header *header, 39098c2ecf20Sopenharmony_ci u32 command_size, 39108c2ecf20Sopenharmony_ci struct vmw_sw_context *sw_context) 39118c2ecf20Sopenharmony_ci{ 39128c2ecf20Sopenharmony_ci u32 id = ((sw_context->dx_ctx_node) ? sw_context->dx_ctx_node->ctx->id : 39138c2ecf20Sopenharmony_ci SVGA3D_INVALID_ID); 39148c2ecf20Sopenharmony_ci void *cmd = vmw_cmdbuf_reserve(dev_priv->cman, command_size, id, false, 39158c2ecf20Sopenharmony_ci header); 39168c2ecf20Sopenharmony_ci 39178c2ecf20Sopenharmony_ci vmw_apply_relocations(sw_context); 39188c2ecf20Sopenharmony_ci vmw_resource_relocations_apply(cmd, &sw_context->res_relocations); 39198c2ecf20Sopenharmony_ci vmw_resource_relocations_free(&sw_context->res_relocations); 39208c2ecf20Sopenharmony_ci vmw_cmdbuf_commit(dev_priv->cman, command_size, header, false); 39218c2ecf20Sopenharmony_ci 39228c2ecf20Sopenharmony_ci return 0; 39238c2ecf20Sopenharmony_ci} 39248c2ecf20Sopenharmony_ci 39258c2ecf20Sopenharmony_ci/** 39268c2ecf20Sopenharmony_ci * vmw_execbuf_cmdbuf - Prepare, if possible, a user-space command batch for 39278c2ecf20Sopenharmony_ci * submission using a command buffer. 39288c2ecf20Sopenharmony_ci * 39298c2ecf20Sopenharmony_ci * @dev_priv: Pointer to a device private structure. 39308c2ecf20Sopenharmony_ci * @user_commands: User-space pointer to the commands to be submitted. 39318c2ecf20Sopenharmony_ci * @command_size: Size of the unpatched command batch. 39328c2ecf20Sopenharmony_ci * @header: Out parameter returning the opaque pointer to the command buffer. 39338c2ecf20Sopenharmony_ci * 39348c2ecf20Sopenharmony_ci * This function checks whether we can use the command buffer manager for 39358c2ecf20Sopenharmony_ci * submission and if so, creates a command buffer of suitable size and copies 39368c2ecf20Sopenharmony_ci * the user data into that buffer. 39378c2ecf20Sopenharmony_ci * 39388c2ecf20Sopenharmony_ci * On successful return, the function returns a pointer to the data in the 39398c2ecf20Sopenharmony_ci * command buffer and *@header is set to non-NULL. 39408c2ecf20Sopenharmony_ci * 39418c2ecf20Sopenharmony_ci * If command buffers could not be used, the function will return the value of 39428c2ecf20Sopenharmony_ci * @kernel_commands on function call. That value may be NULL. In that case, the 39438c2ecf20Sopenharmony_ci * value of *@header will be set to NULL. 39448c2ecf20Sopenharmony_ci * 39458c2ecf20Sopenharmony_ci * If an error is encountered, the function will return a pointer error value. 39468c2ecf20Sopenharmony_ci * If the function is interrupted by a signal while sleeping, it will return 39478c2ecf20Sopenharmony_ci * -ERESTARTSYS casted to a pointer error value. 39488c2ecf20Sopenharmony_ci */ 39498c2ecf20Sopenharmony_cistatic void *vmw_execbuf_cmdbuf(struct vmw_private *dev_priv, 39508c2ecf20Sopenharmony_ci void __user *user_commands, 39518c2ecf20Sopenharmony_ci void *kernel_commands, u32 command_size, 39528c2ecf20Sopenharmony_ci struct vmw_cmdbuf_header **header) 39538c2ecf20Sopenharmony_ci{ 39548c2ecf20Sopenharmony_ci size_t cmdbuf_size; 39558c2ecf20Sopenharmony_ci int ret; 39568c2ecf20Sopenharmony_ci 39578c2ecf20Sopenharmony_ci *header = NULL; 39588c2ecf20Sopenharmony_ci if (command_size > SVGA_CB_MAX_SIZE) { 39598c2ecf20Sopenharmony_ci VMW_DEBUG_USER("Command buffer is too large.\n"); 39608c2ecf20Sopenharmony_ci return ERR_PTR(-EINVAL); 39618c2ecf20Sopenharmony_ci } 39628c2ecf20Sopenharmony_ci 39638c2ecf20Sopenharmony_ci if (!dev_priv->cman || kernel_commands) 39648c2ecf20Sopenharmony_ci return kernel_commands; 39658c2ecf20Sopenharmony_ci 39668c2ecf20Sopenharmony_ci /* If possible, add a little space for fencing. */ 39678c2ecf20Sopenharmony_ci cmdbuf_size = command_size + 512; 39688c2ecf20Sopenharmony_ci cmdbuf_size = min_t(size_t, cmdbuf_size, SVGA_CB_MAX_SIZE); 39698c2ecf20Sopenharmony_ci kernel_commands = vmw_cmdbuf_alloc(dev_priv->cman, cmdbuf_size, true, 39708c2ecf20Sopenharmony_ci header); 39718c2ecf20Sopenharmony_ci if (IS_ERR(kernel_commands)) 39728c2ecf20Sopenharmony_ci return kernel_commands; 39738c2ecf20Sopenharmony_ci 39748c2ecf20Sopenharmony_ci ret = copy_from_user(kernel_commands, user_commands, command_size); 39758c2ecf20Sopenharmony_ci if (ret) { 39768c2ecf20Sopenharmony_ci VMW_DEBUG_USER("Failed copying commands.\n"); 39778c2ecf20Sopenharmony_ci vmw_cmdbuf_header_free(*header); 39788c2ecf20Sopenharmony_ci *header = NULL; 39798c2ecf20Sopenharmony_ci return ERR_PTR(-EFAULT); 39808c2ecf20Sopenharmony_ci } 39818c2ecf20Sopenharmony_ci 39828c2ecf20Sopenharmony_ci return kernel_commands; 39838c2ecf20Sopenharmony_ci} 39848c2ecf20Sopenharmony_ci 39858c2ecf20Sopenharmony_cistatic int vmw_execbuf_tie_context(struct vmw_private *dev_priv, 39868c2ecf20Sopenharmony_ci struct vmw_sw_context *sw_context, 39878c2ecf20Sopenharmony_ci uint32_t handle) 39888c2ecf20Sopenharmony_ci{ 39898c2ecf20Sopenharmony_ci struct vmw_resource *res; 39908c2ecf20Sopenharmony_ci int ret; 39918c2ecf20Sopenharmony_ci unsigned int size; 39928c2ecf20Sopenharmony_ci 39938c2ecf20Sopenharmony_ci if (handle == SVGA3D_INVALID_ID) 39948c2ecf20Sopenharmony_ci return 0; 39958c2ecf20Sopenharmony_ci 39968c2ecf20Sopenharmony_ci size = vmw_execbuf_res_size(dev_priv, vmw_res_dx_context); 39978c2ecf20Sopenharmony_ci ret = vmw_validation_preload_res(sw_context->ctx, size); 39988c2ecf20Sopenharmony_ci if (ret) 39998c2ecf20Sopenharmony_ci return ret; 40008c2ecf20Sopenharmony_ci 40018c2ecf20Sopenharmony_ci res = vmw_user_resource_noref_lookup_handle 40028c2ecf20Sopenharmony_ci (dev_priv, sw_context->fp->tfile, handle, 40038c2ecf20Sopenharmony_ci user_context_converter); 40048c2ecf20Sopenharmony_ci if (IS_ERR(res)) { 40058c2ecf20Sopenharmony_ci VMW_DEBUG_USER("Could not find or user DX context 0x%08x.\n", 40068c2ecf20Sopenharmony_ci (unsigned int) handle); 40078c2ecf20Sopenharmony_ci return PTR_ERR(res); 40088c2ecf20Sopenharmony_ci } 40098c2ecf20Sopenharmony_ci 40108c2ecf20Sopenharmony_ci ret = vmw_execbuf_res_noref_val_add(sw_context, res, VMW_RES_DIRTY_SET); 40118c2ecf20Sopenharmony_ci if (unlikely(ret != 0)) 40128c2ecf20Sopenharmony_ci return ret; 40138c2ecf20Sopenharmony_ci 40148c2ecf20Sopenharmony_ci sw_context->dx_ctx_node = vmw_execbuf_info_from_res(sw_context, res); 40158c2ecf20Sopenharmony_ci sw_context->man = vmw_context_res_man(res); 40168c2ecf20Sopenharmony_ci 40178c2ecf20Sopenharmony_ci return 0; 40188c2ecf20Sopenharmony_ci} 40198c2ecf20Sopenharmony_ci 40208c2ecf20Sopenharmony_ciint vmw_execbuf_process(struct drm_file *file_priv, 40218c2ecf20Sopenharmony_ci struct vmw_private *dev_priv, 40228c2ecf20Sopenharmony_ci void __user *user_commands, void *kernel_commands, 40238c2ecf20Sopenharmony_ci uint32_t command_size, uint64_t throttle_us, 40248c2ecf20Sopenharmony_ci uint32_t dx_context_handle, 40258c2ecf20Sopenharmony_ci struct drm_vmw_fence_rep __user *user_fence_rep, 40268c2ecf20Sopenharmony_ci struct vmw_fence_obj **out_fence, uint32_t flags) 40278c2ecf20Sopenharmony_ci{ 40288c2ecf20Sopenharmony_ci struct vmw_sw_context *sw_context = &dev_priv->ctx; 40298c2ecf20Sopenharmony_ci struct vmw_fence_obj *fence = NULL; 40308c2ecf20Sopenharmony_ci struct vmw_cmdbuf_header *header; 40318c2ecf20Sopenharmony_ci uint32_t handle = 0; 40328c2ecf20Sopenharmony_ci int ret; 40338c2ecf20Sopenharmony_ci int32_t out_fence_fd = -1; 40348c2ecf20Sopenharmony_ci struct sync_file *sync_file = NULL; 40358c2ecf20Sopenharmony_ci DECLARE_VAL_CONTEXT(val_ctx, &sw_context->res_ht, 1); 40368c2ecf20Sopenharmony_ci 40378c2ecf20Sopenharmony_ci vmw_validation_set_val_mem(&val_ctx, &dev_priv->vvm); 40388c2ecf20Sopenharmony_ci 40398c2ecf20Sopenharmony_ci if (flags & DRM_VMW_EXECBUF_FLAG_EXPORT_FENCE_FD) { 40408c2ecf20Sopenharmony_ci out_fence_fd = get_unused_fd_flags(O_CLOEXEC); 40418c2ecf20Sopenharmony_ci if (out_fence_fd < 0) { 40428c2ecf20Sopenharmony_ci VMW_DEBUG_USER("Failed to get a fence fd.\n"); 40438c2ecf20Sopenharmony_ci return out_fence_fd; 40448c2ecf20Sopenharmony_ci } 40458c2ecf20Sopenharmony_ci } 40468c2ecf20Sopenharmony_ci 40478c2ecf20Sopenharmony_ci if (throttle_us) { 40488c2ecf20Sopenharmony_ci ret = vmw_wait_lag(dev_priv, &dev_priv->fifo.marker_queue, 40498c2ecf20Sopenharmony_ci throttle_us); 40508c2ecf20Sopenharmony_ci 40518c2ecf20Sopenharmony_ci if (ret) 40528c2ecf20Sopenharmony_ci goto out_free_fence_fd; 40538c2ecf20Sopenharmony_ci } 40548c2ecf20Sopenharmony_ci 40558c2ecf20Sopenharmony_ci kernel_commands = vmw_execbuf_cmdbuf(dev_priv, user_commands, 40568c2ecf20Sopenharmony_ci kernel_commands, command_size, 40578c2ecf20Sopenharmony_ci &header); 40588c2ecf20Sopenharmony_ci if (IS_ERR(kernel_commands)) { 40598c2ecf20Sopenharmony_ci ret = PTR_ERR(kernel_commands); 40608c2ecf20Sopenharmony_ci goto out_free_fence_fd; 40618c2ecf20Sopenharmony_ci } 40628c2ecf20Sopenharmony_ci 40638c2ecf20Sopenharmony_ci ret = mutex_lock_interruptible(&dev_priv->cmdbuf_mutex); 40648c2ecf20Sopenharmony_ci if (ret) { 40658c2ecf20Sopenharmony_ci ret = -ERESTARTSYS; 40668c2ecf20Sopenharmony_ci goto out_free_header; 40678c2ecf20Sopenharmony_ci } 40688c2ecf20Sopenharmony_ci 40698c2ecf20Sopenharmony_ci sw_context->kernel = false; 40708c2ecf20Sopenharmony_ci if (kernel_commands == NULL) { 40718c2ecf20Sopenharmony_ci ret = vmw_resize_cmd_bounce(sw_context, command_size); 40728c2ecf20Sopenharmony_ci if (unlikely(ret != 0)) 40738c2ecf20Sopenharmony_ci goto out_unlock; 40748c2ecf20Sopenharmony_ci 40758c2ecf20Sopenharmony_ci ret = copy_from_user(sw_context->cmd_bounce, user_commands, 40768c2ecf20Sopenharmony_ci command_size); 40778c2ecf20Sopenharmony_ci if (unlikely(ret != 0)) { 40788c2ecf20Sopenharmony_ci ret = -EFAULT; 40798c2ecf20Sopenharmony_ci VMW_DEBUG_USER("Failed copying commands.\n"); 40808c2ecf20Sopenharmony_ci goto out_unlock; 40818c2ecf20Sopenharmony_ci } 40828c2ecf20Sopenharmony_ci 40838c2ecf20Sopenharmony_ci kernel_commands = sw_context->cmd_bounce; 40848c2ecf20Sopenharmony_ci } else if (!header) { 40858c2ecf20Sopenharmony_ci sw_context->kernel = true; 40868c2ecf20Sopenharmony_ci } 40878c2ecf20Sopenharmony_ci 40888c2ecf20Sopenharmony_ci sw_context->fp = vmw_fpriv(file_priv); 40898c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&sw_context->ctx_list); 40908c2ecf20Sopenharmony_ci sw_context->cur_query_bo = dev_priv->pinned_bo; 40918c2ecf20Sopenharmony_ci sw_context->last_query_ctx = NULL; 40928c2ecf20Sopenharmony_ci sw_context->needs_post_query_barrier = false; 40938c2ecf20Sopenharmony_ci sw_context->dx_ctx_node = NULL; 40948c2ecf20Sopenharmony_ci sw_context->dx_query_mob = NULL; 40958c2ecf20Sopenharmony_ci sw_context->dx_query_ctx = NULL; 40968c2ecf20Sopenharmony_ci memset(sw_context->res_cache, 0, sizeof(sw_context->res_cache)); 40978c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&sw_context->res_relocations); 40988c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&sw_context->bo_relocations); 40998c2ecf20Sopenharmony_ci 41008c2ecf20Sopenharmony_ci if (sw_context->staged_bindings) 41018c2ecf20Sopenharmony_ci vmw_binding_state_reset(sw_context->staged_bindings); 41028c2ecf20Sopenharmony_ci 41038c2ecf20Sopenharmony_ci if (!sw_context->res_ht_initialized) { 41048c2ecf20Sopenharmony_ci ret = drm_ht_create(&sw_context->res_ht, VMW_RES_HT_ORDER); 41058c2ecf20Sopenharmony_ci if (unlikely(ret != 0)) 41068c2ecf20Sopenharmony_ci goto out_unlock; 41078c2ecf20Sopenharmony_ci 41088c2ecf20Sopenharmony_ci sw_context->res_ht_initialized = true; 41098c2ecf20Sopenharmony_ci } 41108c2ecf20Sopenharmony_ci 41118c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&sw_context->staged_cmd_res); 41128c2ecf20Sopenharmony_ci sw_context->ctx = &val_ctx; 41138c2ecf20Sopenharmony_ci ret = vmw_execbuf_tie_context(dev_priv, sw_context, dx_context_handle); 41148c2ecf20Sopenharmony_ci if (unlikely(ret != 0)) 41158c2ecf20Sopenharmony_ci goto out_err_nores; 41168c2ecf20Sopenharmony_ci 41178c2ecf20Sopenharmony_ci ret = vmw_cmd_check_all(dev_priv, sw_context, kernel_commands, 41188c2ecf20Sopenharmony_ci command_size); 41198c2ecf20Sopenharmony_ci if (unlikely(ret != 0)) 41208c2ecf20Sopenharmony_ci goto out_err_nores; 41218c2ecf20Sopenharmony_ci 41228c2ecf20Sopenharmony_ci ret = vmw_resources_reserve(sw_context); 41238c2ecf20Sopenharmony_ci if (unlikely(ret != 0)) 41248c2ecf20Sopenharmony_ci goto out_err_nores; 41258c2ecf20Sopenharmony_ci 41268c2ecf20Sopenharmony_ci ret = vmw_validation_bo_reserve(&val_ctx, true); 41278c2ecf20Sopenharmony_ci if (unlikely(ret != 0)) 41288c2ecf20Sopenharmony_ci goto out_err_nores; 41298c2ecf20Sopenharmony_ci 41308c2ecf20Sopenharmony_ci ret = vmw_validation_bo_validate(&val_ctx, true); 41318c2ecf20Sopenharmony_ci if (unlikely(ret != 0)) 41328c2ecf20Sopenharmony_ci goto out_err; 41338c2ecf20Sopenharmony_ci 41348c2ecf20Sopenharmony_ci ret = vmw_validation_res_validate(&val_ctx, true); 41358c2ecf20Sopenharmony_ci if (unlikely(ret != 0)) 41368c2ecf20Sopenharmony_ci goto out_err; 41378c2ecf20Sopenharmony_ci 41388c2ecf20Sopenharmony_ci vmw_validation_drop_ht(&val_ctx); 41398c2ecf20Sopenharmony_ci 41408c2ecf20Sopenharmony_ci ret = mutex_lock_interruptible(&dev_priv->binding_mutex); 41418c2ecf20Sopenharmony_ci if (unlikely(ret != 0)) { 41428c2ecf20Sopenharmony_ci ret = -ERESTARTSYS; 41438c2ecf20Sopenharmony_ci goto out_err; 41448c2ecf20Sopenharmony_ci } 41458c2ecf20Sopenharmony_ci 41468c2ecf20Sopenharmony_ci if (dev_priv->has_mob) { 41478c2ecf20Sopenharmony_ci ret = vmw_rebind_contexts(sw_context); 41488c2ecf20Sopenharmony_ci if (unlikely(ret != 0)) 41498c2ecf20Sopenharmony_ci goto out_unlock_binding; 41508c2ecf20Sopenharmony_ci } 41518c2ecf20Sopenharmony_ci 41528c2ecf20Sopenharmony_ci if (!header) { 41538c2ecf20Sopenharmony_ci ret = vmw_execbuf_submit_fifo(dev_priv, kernel_commands, 41548c2ecf20Sopenharmony_ci command_size, sw_context); 41558c2ecf20Sopenharmony_ci } else { 41568c2ecf20Sopenharmony_ci ret = vmw_execbuf_submit_cmdbuf(dev_priv, header, command_size, 41578c2ecf20Sopenharmony_ci sw_context); 41588c2ecf20Sopenharmony_ci header = NULL; 41598c2ecf20Sopenharmony_ci } 41608c2ecf20Sopenharmony_ci mutex_unlock(&dev_priv->binding_mutex); 41618c2ecf20Sopenharmony_ci if (ret) 41628c2ecf20Sopenharmony_ci goto out_err; 41638c2ecf20Sopenharmony_ci 41648c2ecf20Sopenharmony_ci vmw_query_bo_switch_commit(dev_priv, sw_context); 41658c2ecf20Sopenharmony_ci ret = vmw_execbuf_fence_commands(file_priv, dev_priv, &fence, 41668c2ecf20Sopenharmony_ci (user_fence_rep) ? &handle : NULL); 41678c2ecf20Sopenharmony_ci /* 41688c2ecf20Sopenharmony_ci * This error is harmless, because if fence submission fails, 41698c2ecf20Sopenharmony_ci * vmw_fifo_send_fence will sync. The error will be propagated to 41708c2ecf20Sopenharmony_ci * user-space in @fence_rep 41718c2ecf20Sopenharmony_ci */ 41728c2ecf20Sopenharmony_ci if (ret != 0) 41738c2ecf20Sopenharmony_ci VMW_DEBUG_USER("Fence submission error. Syncing.\n"); 41748c2ecf20Sopenharmony_ci 41758c2ecf20Sopenharmony_ci vmw_execbuf_bindings_commit(sw_context, false); 41768c2ecf20Sopenharmony_ci vmw_bind_dx_query_mob(sw_context); 41778c2ecf20Sopenharmony_ci vmw_validation_res_unreserve(&val_ctx, false); 41788c2ecf20Sopenharmony_ci 41798c2ecf20Sopenharmony_ci vmw_validation_bo_fence(sw_context->ctx, fence); 41808c2ecf20Sopenharmony_ci 41818c2ecf20Sopenharmony_ci if (unlikely(dev_priv->pinned_bo != NULL && !dev_priv->query_cid_valid)) 41828c2ecf20Sopenharmony_ci __vmw_execbuf_release_pinned_bo(dev_priv, fence); 41838c2ecf20Sopenharmony_ci 41848c2ecf20Sopenharmony_ci /* 41858c2ecf20Sopenharmony_ci * If anything fails here, give up trying to export the fence and do a 41868c2ecf20Sopenharmony_ci * sync since the user mode will not be able to sync the fence itself. 41878c2ecf20Sopenharmony_ci * This ensures we are still functionally correct. 41888c2ecf20Sopenharmony_ci */ 41898c2ecf20Sopenharmony_ci if (flags & DRM_VMW_EXECBUF_FLAG_EXPORT_FENCE_FD) { 41908c2ecf20Sopenharmony_ci 41918c2ecf20Sopenharmony_ci sync_file = sync_file_create(&fence->base); 41928c2ecf20Sopenharmony_ci if (!sync_file) { 41938c2ecf20Sopenharmony_ci VMW_DEBUG_USER("Sync file create failed for fence\n"); 41948c2ecf20Sopenharmony_ci put_unused_fd(out_fence_fd); 41958c2ecf20Sopenharmony_ci out_fence_fd = -1; 41968c2ecf20Sopenharmony_ci 41978c2ecf20Sopenharmony_ci (void) vmw_fence_obj_wait(fence, false, false, 41988c2ecf20Sopenharmony_ci VMW_FENCE_WAIT_TIMEOUT); 41998c2ecf20Sopenharmony_ci } 42008c2ecf20Sopenharmony_ci } 42018c2ecf20Sopenharmony_ci 42028c2ecf20Sopenharmony_ci ret = vmw_execbuf_copy_fence_user(dev_priv, vmw_fpriv(file_priv), ret, 42038c2ecf20Sopenharmony_ci user_fence_rep, fence, handle, out_fence_fd); 42048c2ecf20Sopenharmony_ci 42058c2ecf20Sopenharmony_ci if (sync_file) { 42068c2ecf20Sopenharmony_ci if (ret) { 42078c2ecf20Sopenharmony_ci /* usercopy of fence failed, put the file object */ 42088c2ecf20Sopenharmony_ci fput(sync_file->file); 42098c2ecf20Sopenharmony_ci put_unused_fd(out_fence_fd); 42108c2ecf20Sopenharmony_ci } else { 42118c2ecf20Sopenharmony_ci /* Link the fence with the FD created earlier */ 42128c2ecf20Sopenharmony_ci fd_install(out_fence_fd, sync_file->file); 42138c2ecf20Sopenharmony_ci } 42148c2ecf20Sopenharmony_ci } 42158c2ecf20Sopenharmony_ci 42168c2ecf20Sopenharmony_ci /* Don't unreference when handing fence out */ 42178c2ecf20Sopenharmony_ci if (unlikely(out_fence != NULL)) { 42188c2ecf20Sopenharmony_ci *out_fence = fence; 42198c2ecf20Sopenharmony_ci fence = NULL; 42208c2ecf20Sopenharmony_ci } else if (likely(fence != NULL)) { 42218c2ecf20Sopenharmony_ci vmw_fence_obj_unreference(&fence); 42228c2ecf20Sopenharmony_ci } 42238c2ecf20Sopenharmony_ci 42248c2ecf20Sopenharmony_ci vmw_cmdbuf_res_commit(&sw_context->staged_cmd_res); 42258c2ecf20Sopenharmony_ci mutex_unlock(&dev_priv->cmdbuf_mutex); 42268c2ecf20Sopenharmony_ci 42278c2ecf20Sopenharmony_ci /* 42288c2ecf20Sopenharmony_ci * Unreference resources outside of the cmdbuf_mutex to avoid deadlocks 42298c2ecf20Sopenharmony_ci * in resource destruction paths. 42308c2ecf20Sopenharmony_ci */ 42318c2ecf20Sopenharmony_ci vmw_validation_unref_lists(&val_ctx); 42328c2ecf20Sopenharmony_ci 42338c2ecf20Sopenharmony_ci return ret; 42348c2ecf20Sopenharmony_ci 42358c2ecf20Sopenharmony_ciout_unlock_binding: 42368c2ecf20Sopenharmony_ci mutex_unlock(&dev_priv->binding_mutex); 42378c2ecf20Sopenharmony_ciout_err: 42388c2ecf20Sopenharmony_ci vmw_validation_bo_backoff(&val_ctx); 42398c2ecf20Sopenharmony_ciout_err_nores: 42408c2ecf20Sopenharmony_ci vmw_execbuf_bindings_commit(sw_context, true); 42418c2ecf20Sopenharmony_ci vmw_validation_res_unreserve(&val_ctx, true); 42428c2ecf20Sopenharmony_ci vmw_resource_relocations_free(&sw_context->res_relocations); 42438c2ecf20Sopenharmony_ci vmw_free_relocations(sw_context); 42448c2ecf20Sopenharmony_ci if (unlikely(dev_priv->pinned_bo != NULL && !dev_priv->query_cid_valid)) 42458c2ecf20Sopenharmony_ci __vmw_execbuf_release_pinned_bo(dev_priv, NULL); 42468c2ecf20Sopenharmony_ciout_unlock: 42478c2ecf20Sopenharmony_ci vmw_cmdbuf_res_revert(&sw_context->staged_cmd_res); 42488c2ecf20Sopenharmony_ci vmw_validation_drop_ht(&val_ctx); 42498c2ecf20Sopenharmony_ci WARN_ON(!list_empty(&sw_context->ctx_list)); 42508c2ecf20Sopenharmony_ci mutex_unlock(&dev_priv->cmdbuf_mutex); 42518c2ecf20Sopenharmony_ci 42528c2ecf20Sopenharmony_ci /* 42538c2ecf20Sopenharmony_ci * Unreference resources outside of the cmdbuf_mutex to avoid deadlocks 42548c2ecf20Sopenharmony_ci * in resource destruction paths. 42558c2ecf20Sopenharmony_ci */ 42568c2ecf20Sopenharmony_ci vmw_validation_unref_lists(&val_ctx); 42578c2ecf20Sopenharmony_ciout_free_header: 42588c2ecf20Sopenharmony_ci if (header) 42598c2ecf20Sopenharmony_ci vmw_cmdbuf_header_free(header); 42608c2ecf20Sopenharmony_ciout_free_fence_fd: 42618c2ecf20Sopenharmony_ci if (out_fence_fd >= 0) 42628c2ecf20Sopenharmony_ci put_unused_fd(out_fence_fd); 42638c2ecf20Sopenharmony_ci 42648c2ecf20Sopenharmony_ci return ret; 42658c2ecf20Sopenharmony_ci} 42668c2ecf20Sopenharmony_ci 42678c2ecf20Sopenharmony_ci/** 42688c2ecf20Sopenharmony_ci * vmw_execbuf_unpin_panic - Idle the fifo and unpin the query buffer. 42698c2ecf20Sopenharmony_ci * 42708c2ecf20Sopenharmony_ci * @dev_priv: The device private structure. 42718c2ecf20Sopenharmony_ci * 42728c2ecf20Sopenharmony_ci * This function is called to idle the fifo and unpin the query buffer if the 42738c2ecf20Sopenharmony_ci * normal way to do this hits an error, which should typically be extremely 42748c2ecf20Sopenharmony_ci * rare. 42758c2ecf20Sopenharmony_ci */ 42768c2ecf20Sopenharmony_cistatic void vmw_execbuf_unpin_panic(struct vmw_private *dev_priv) 42778c2ecf20Sopenharmony_ci{ 42788c2ecf20Sopenharmony_ci VMW_DEBUG_USER("Can't unpin query buffer. Trying to recover.\n"); 42798c2ecf20Sopenharmony_ci 42808c2ecf20Sopenharmony_ci (void) vmw_fallback_wait(dev_priv, false, true, 0, false, 10*HZ); 42818c2ecf20Sopenharmony_ci vmw_bo_pin_reserved(dev_priv->pinned_bo, false); 42828c2ecf20Sopenharmony_ci if (dev_priv->dummy_query_bo_pinned) { 42838c2ecf20Sopenharmony_ci vmw_bo_pin_reserved(dev_priv->dummy_query_bo, false); 42848c2ecf20Sopenharmony_ci dev_priv->dummy_query_bo_pinned = false; 42858c2ecf20Sopenharmony_ci } 42868c2ecf20Sopenharmony_ci} 42878c2ecf20Sopenharmony_ci 42888c2ecf20Sopenharmony_ci 42898c2ecf20Sopenharmony_ci/** 42908c2ecf20Sopenharmony_ci * __vmw_execbuf_release_pinned_bo - Flush queries and unpin the pinned query 42918c2ecf20Sopenharmony_ci * bo. 42928c2ecf20Sopenharmony_ci * 42938c2ecf20Sopenharmony_ci * @dev_priv: The device private structure. 42948c2ecf20Sopenharmony_ci * @fence: If non-NULL should point to a struct vmw_fence_obj issued _after_ a 42958c2ecf20Sopenharmony_ci * query barrier that flushes all queries touching the current buffer pointed to 42968c2ecf20Sopenharmony_ci * by @dev_priv->pinned_bo 42978c2ecf20Sopenharmony_ci * 42988c2ecf20Sopenharmony_ci * This function should be used to unpin the pinned query bo, or as a query 42998c2ecf20Sopenharmony_ci * barrier when we need to make sure that all queries have finished before the 43008c2ecf20Sopenharmony_ci * next fifo command. (For example on hardware context destructions where the 43018c2ecf20Sopenharmony_ci * hardware may otherwise leak unfinished queries). 43028c2ecf20Sopenharmony_ci * 43038c2ecf20Sopenharmony_ci * This function does not return any failure codes, but make attempts to do safe 43048c2ecf20Sopenharmony_ci * unpinning in case of errors. 43058c2ecf20Sopenharmony_ci * 43068c2ecf20Sopenharmony_ci * The function will synchronize on the previous query barrier, and will thus 43078c2ecf20Sopenharmony_ci * not finish until that barrier has executed. 43088c2ecf20Sopenharmony_ci * 43098c2ecf20Sopenharmony_ci * the @dev_priv->cmdbuf_mutex needs to be held by the current thread before 43108c2ecf20Sopenharmony_ci * calling this function. 43118c2ecf20Sopenharmony_ci */ 43128c2ecf20Sopenharmony_civoid __vmw_execbuf_release_pinned_bo(struct vmw_private *dev_priv, 43138c2ecf20Sopenharmony_ci struct vmw_fence_obj *fence) 43148c2ecf20Sopenharmony_ci{ 43158c2ecf20Sopenharmony_ci int ret = 0; 43168c2ecf20Sopenharmony_ci struct vmw_fence_obj *lfence = NULL; 43178c2ecf20Sopenharmony_ci DECLARE_VAL_CONTEXT(val_ctx, NULL, 0); 43188c2ecf20Sopenharmony_ci 43198c2ecf20Sopenharmony_ci if (dev_priv->pinned_bo == NULL) 43208c2ecf20Sopenharmony_ci goto out_unlock; 43218c2ecf20Sopenharmony_ci 43228c2ecf20Sopenharmony_ci ret = vmw_validation_add_bo(&val_ctx, dev_priv->pinned_bo, false, 43238c2ecf20Sopenharmony_ci false); 43248c2ecf20Sopenharmony_ci if (ret) 43258c2ecf20Sopenharmony_ci goto out_no_reserve; 43268c2ecf20Sopenharmony_ci 43278c2ecf20Sopenharmony_ci ret = vmw_validation_add_bo(&val_ctx, dev_priv->dummy_query_bo, false, 43288c2ecf20Sopenharmony_ci false); 43298c2ecf20Sopenharmony_ci if (ret) 43308c2ecf20Sopenharmony_ci goto out_no_reserve; 43318c2ecf20Sopenharmony_ci 43328c2ecf20Sopenharmony_ci ret = vmw_validation_bo_reserve(&val_ctx, false); 43338c2ecf20Sopenharmony_ci if (ret) 43348c2ecf20Sopenharmony_ci goto out_no_reserve; 43358c2ecf20Sopenharmony_ci 43368c2ecf20Sopenharmony_ci if (dev_priv->query_cid_valid) { 43378c2ecf20Sopenharmony_ci BUG_ON(fence != NULL); 43388c2ecf20Sopenharmony_ci ret = vmw_fifo_emit_dummy_query(dev_priv, dev_priv->query_cid); 43398c2ecf20Sopenharmony_ci if (ret) 43408c2ecf20Sopenharmony_ci goto out_no_emit; 43418c2ecf20Sopenharmony_ci dev_priv->query_cid_valid = false; 43428c2ecf20Sopenharmony_ci } 43438c2ecf20Sopenharmony_ci 43448c2ecf20Sopenharmony_ci vmw_bo_pin_reserved(dev_priv->pinned_bo, false); 43458c2ecf20Sopenharmony_ci if (dev_priv->dummy_query_bo_pinned) { 43468c2ecf20Sopenharmony_ci vmw_bo_pin_reserved(dev_priv->dummy_query_bo, false); 43478c2ecf20Sopenharmony_ci dev_priv->dummy_query_bo_pinned = false; 43488c2ecf20Sopenharmony_ci } 43498c2ecf20Sopenharmony_ci if (fence == NULL) { 43508c2ecf20Sopenharmony_ci (void) vmw_execbuf_fence_commands(NULL, dev_priv, &lfence, 43518c2ecf20Sopenharmony_ci NULL); 43528c2ecf20Sopenharmony_ci fence = lfence; 43538c2ecf20Sopenharmony_ci } 43548c2ecf20Sopenharmony_ci vmw_validation_bo_fence(&val_ctx, fence); 43558c2ecf20Sopenharmony_ci if (lfence != NULL) 43568c2ecf20Sopenharmony_ci vmw_fence_obj_unreference(&lfence); 43578c2ecf20Sopenharmony_ci 43588c2ecf20Sopenharmony_ci vmw_validation_unref_lists(&val_ctx); 43598c2ecf20Sopenharmony_ci vmw_bo_unreference(&dev_priv->pinned_bo); 43608c2ecf20Sopenharmony_ci 43618c2ecf20Sopenharmony_ciout_unlock: 43628c2ecf20Sopenharmony_ci return; 43638c2ecf20Sopenharmony_ciout_no_emit: 43648c2ecf20Sopenharmony_ci vmw_validation_bo_backoff(&val_ctx); 43658c2ecf20Sopenharmony_ciout_no_reserve: 43668c2ecf20Sopenharmony_ci vmw_validation_unref_lists(&val_ctx); 43678c2ecf20Sopenharmony_ci vmw_execbuf_unpin_panic(dev_priv); 43688c2ecf20Sopenharmony_ci vmw_bo_unreference(&dev_priv->pinned_bo); 43698c2ecf20Sopenharmony_ci} 43708c2ecf20Sopenharmony_ci 43718c2ecf20Sopenharmony_ci/** 43728c2ecf20Sopenharmony_ci * vmw_execbuf_release_pinned_bo - Flush queries and unpin the pinned query bo. 43738c2ecf20Sopenharmony_ci * 43748c2ecf20Sopenharmony_ci * @dev_priv: The device private structure. 43758c2ecf20Sopenharmony_ci * 43768c2ecf20Sopenharmony_ci * This function should be used to unpin the pinned query bo, or as a query 43778c2ecf20Sopenharmony_ci * barrier when we need to make sure that all queries have finished before the 43788c2ecf20Sopenharmony_ci * next fifo command. (For example on hardware context destructions where the 43798c2ecf20Sopenharmony_ci * hardware may otherwise leak unfinished queries). 43808c2ecf20Sopenharmony_ci * 43818c2ecf20Sopenharmony_ci * This function does not return any failure codes, but make attempts to do safe 43828c2ecf20Sopenharmony_ci * unpinning in case of errors. 43838c2ecf20Sopenharmony_ci * 43848c2ecf20Sopenharmony_ci * The function will synchronize on the previous query barrier, and will thus 43858c2ecf20Sopenharmony_ci * not finish until that barrier has executed. 43868c2ecf20Sopenharmony_ci */ 43878c2ecf20Sopenharmony_civoid vmw_execbuf_release_pinned_bo(struct vmw_private *dev_priv) 43888c2ecf20Sopenharmony_ci{ 43898c2ecf20Sopenharmony_ci mutex_lock(&dev_priv->cmdbuf_mutex); 43908c2ecf20Sopenharmony_ci if (dev_priv->query_cid_valid) 43918c2ecf20Sopenharmony_ci __vmw_execbuf_release_pinned_bo(dev_priv, NULL); 43928c2ecf20Sopenharmony_ci mutex_unlock(&dev_priv->cmdbuf_mutex); 43938c2ecf20Sopenharmony_ci} 43948c2ecf20Sopenharmony_ci 43958c2ecf20Sopenharmony_ciint vmw_execbuf_ioctl(struct drm_device *dev, void *data, 43968c2ecf20Sopenharmony_ci struct drm_file *file_priv) 43978c2ecf20Sopenharmony_ci{ 43988c2ecf20Sopenharmony_ci struct vmw_private *dev_priv = vmw_priv(dev); 43998c2ecf20Sopenharmony_ci struct drm_vmw_execbuf_arg *arg = data; 44008c2ecf20Sopenharmony_ci int ret; 44018c2ecf20Sopenharmony_ci struct dma_fence *in_fence = NULL; 44028c2ecf20Sopenharmony_ci 44038c2ecf20Sopenharmony_ci /* 44048c2ecf20Sopenharmony_ci * Extend the ioctl argument while maintaining backwards compatibility: 44058c2ecf20Sopenharmony_ci * We take different code paths depending on the value of arg->version. 44068c2ecf20Sopenharmony_ci * 44078c2ecf20Sopenharmony_ci * Note: The ioctl argument is extended and zeropadded by core DRM. 44088c2ecf20Sopenharmony_ci */ 44098c2ecf20Sopenharmony_ci if (unlikely(arg->version > DRM_VMW_EXECBUF_VERSION || 44108c2ecf20Sopenharmony_ci arg->version == 0)) { 44118c2ecf20Sopenharmony_ci VMW_DEBUG_USER("Incorrect execbuf version.\n"); 44128c2ecf20Sopenharmony_ci return -EINVAL; 44138c2ecf20Sopenharmony_ci } 44148c2ecf20Sopenharmony_ci 44158c2ecf20Sopenharmony_ci switch (arg->version) { 44168c2ecf20Sopenharmony_ci case 1: 44178c2ecf20Sopenharmony_ci /* For v1 core DRM have extended + zeropadded the data */ 44188c2ecf20Sopenharmony_ci arg->context_handle = (uint32_t) -1; 44198c2ecf20Sopenharmony_ci break; 44208c2ecf20Sopenharmony_ci case 2: 44218c2ecf20Sopenharmony_ci default: 44228c2ecf20Sopenharmony_ci /* For v2 and later core DRM would have correctly copied it */ 44238c2ecf20Sopenharmony_ci break; 44248c2ecf20Sopenharmony_ci } 44258c2ecf20Sopenharmony_ci 44268c2ecf20Sopenharmony_ci /* If imported a fence FD from elsewhere, then wait on it */ 44278c2ecf20Sopenharmony_ci if (arg->flags & DRM_VMW_EXECBUF_FLAG_IMPORT_FENCE_FD) { 44288c2ecf20Sopenharmony_ci in_fence = sync_file_get_fence(arg->imported_fence_fd); 44298c2ecf20Sopenharmony_ci 44308c2ecf20Sopenharmony_ci if (!in_fence) { 44318c2ecf20Sopenharmony_ci VMW_DEBUG_USER("Cannot get imported fence\n"); 44328c2ecf20Sopenharmony_ci return -EINVAL; 44338c2ecf20Sopenharmony_ci } 44348c2ecf20Sopenharmony_ci 44358c2ecf20Sopenharmony_ci ret = vmw_wait_dma_fence(dev_priv->fman, in_fence); 44368c2ecf20Sopenharmony_ci if (ret) 44378c2ecf20Sopenharmony_ci goto out; 44388c2ecf20Sopenharmony_ci } 44398c2ecf20Sopenharmony_ci 44408c2ecf20Sopenharmony_ci ret = ttm_read_lock(&dev_priv->reservation_sem, true); 44418c2ecf20Sopenharmony_ci if (unlikely(ret != 0)) 44428c2ecf20Sopenharmony_ci return ret; 44438c2ecf20Sopenharmony_ci 44448c2ecf20Sopenharmony_ci ret = vmw_execbuf_process(file_priv, dev_priv, 44458c2ecf20Sopenharmony_ci (void __user *)(unsigned long)arg->commands, 44468c2ecf20Sopenharmony_ci NULL, arg->command_size, arg->throttle_us, 44478c2ecf20Sopenharmony_ci arg->context_handle, 44488c2ecf20Sopenharmony_ci (void __user *)(unsigned long)arg->fence_rep, 44498c2ecf20Sopenharmony_ci NULL, arg->flags); 44508c2ecf20Sopenharmony_ci 44518c2ecf20Sopenharmony_ci ttm_read_unlock(&dev_priv->reservation_sem); 44528c2ecf20Sopenharmony_ci if (unlikely(ret != 0)) 44538c2ecf20Sopenharmony_ci goto out; 44548c2ecf20Sopenharmony_ci 44558c2ecf20Sopenharmony_ci vmw_kms_cursor_post_execbuf(dev_priv); 44568c2ecf20Sopenharmony_ci 44578c2ecf20Sopenharmony_ciout: 44588c2ecf20Sopenharmony_ci if (in_fence) 44598c2ecf20Sopenharmony_ci dma_fence_put(in_fence); 44608c2ecf20Sopenharmony_ci return ret; 44618c2ecf20Sopenharmony_ci} 4462