162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 OR MIT 262306a36Sopenharmony_ci/************************************************************************** 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Copyright 2009 - 2023 VMware, Inc., Palo Alto, CA., USA 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 762306a36Sopenharmony_ci * copy of this software and associated documentation files (the 862306a36Sopenharmony_ci * "Software"), to deal in the Software without restriction, including 962306a36Sopenharmony_ci * without limitation the rights to use, copy, modify, merge, publish, 1062306a36Sopenharmony_ci * distribute, sub license, and/or sell copies of the Software, and to 1162306a36Sopenharmony_ci * permit persons to whom the Software is furnished to do so, subject to 1262306a36Sopenharmony_ci * the following conditions: 1362306a36Sopenharmony_ci * 1462306a36Sopenharmony_ci * The above copyright notice and this permission notice (including the 1562306a36Sopenharmony_ci * next paragraph) shall be included in all copies or substantial portions 1662306a36Sopenharmony_ci * of the Software. 1762306a36Sopenharmony_ci * 1862306a36Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1962306a36Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 2062306a36Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 2162306a36Sopenharmony_ci * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, 2262306a36Sopenharmony_ci * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 2362306a36Sopenharmony_ci * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 2462306a36Sopenharmony_ci * USE OR OTHER DEALINGS IN THE SOFTWARE. 2562306a36Sopenharmony_ci * 2662306a36Sopenharmony_ci **************************************************************************/ 2762306a36Sopenharmony_ci#include "vmwgfx_binding.h" 2862306a36Sopenharmony_ci#include "vmwgfx_bo.h" 2962306a36Sopenharmony_ci#include "vmwgfx_drv.h" 3062306a36Sopenharmony_ci#include "vmwgfx_mksstat.h" 3162306a36Sopenharmony_ci#include "vmwgfx_so.h" 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci#include <drm/ttm/ttm_bo.h> 3462306a36Sopenharmony_ci#include <drm/ttm/ttm_placement.h> 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ci#include <linux/sync_file.h> 3762306a36Sopenharmony_ci#include <linux/hashtable.h> 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ci/* 4062306a36Sopenharmony_ci * Helper macro to get dx_ctx_node if available otherwise print an error 4162306a36Sopenharmony_ci * message. This is for use in command verifier function where if dx_ctx_node 4262306a36Sopenharmony_ci * is not set then command is invalid. 4362306a36Sopenharmony_ci */ 4462306a36Sopenharmony_ci#define VMW_GET_CTX_NODE(__sw_context) \ 4562306a36Sopenharmony_ci({ \ 4662306a36Sopenharmony_ci __sw_context->dx_ctx_node ? __sw_context->dx_ctx_node : ({ \ 4762306a36Sopenharmony_ci VMW_DEBUG_USER("SM context is not set at %s\n", __func__); \ 4862306a36Sopenharmony_ci __sw_context->dx_ctx_node; \ 4962306a36Sopenharmony_ci }); \ 5062306a36Sopenharmony_ci}) 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ci#define VMW_DECLARE_CMD_VAR(__var, __type) \ 5362306a36Sopenharmony_ci struct { \ 5462306a36Sopenharmony_ci SVGA3dCmdHeader header; \ 5562306a36Sopenharmony_ci __type body; \ 5662306a36Sopenharmony_ci } __var 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_ci/** 5962306a36Sopenharmony_ci * struct vmw_relocation - Buffer object relocation 6062306a36Sopenharmony_ci * 6162306a36Sopenharmony_ci * @head: List head for the command submission context's relocation list 6262306a36Sopenharmony_ci * @vbo: Non ref-counted pointer to buffer object 6362306a36Sopenharmony_ci * @mob_loc: Pointer to location for mob id to be modified 6462306a36Sopenharmony_ci * @location: Pointer to location for guest pointer to be modified 6562306a36Sopenharmony_ci */ 6662306a36Sopenharmony_cistruct vmw_relocation { 6762306a36Sopenharmony_ci struct list_head head; 6862306a36Sopenharmony_ci struct vmw_bo *vbo; 6962306a36Sopenharmony_ci union { 7062306a36Sopenharmony_ci SVGAMobId *mob_loc; 7162306a36Sopenharmony_ci SVGAGuestPtr *location; 7262306a36Sopenharmony_ci }; 7362306a36Sopenharmony_ci}; 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_ci/** 7662306a36Sopenharmony_ci * enum vmw_resource_relocation_type - Relocation type for resources 7762306a36Sopenharmony_ci * 7862306a36Sopenharmony_ci * @vmw_res_rel_normal: Traditional relocation. The resource id in the 7962306a36Sopenharmony_ci * command stream is replaced with the actual id after validation. 8062306a36Sopenharmony_ci * @vmw_res_rel_nop: NOP relocation. The command is unconditionally replaced 8162306a36Sopenharmony_ci * with a NOP. 8262306a36Sopenharmony_ci * @vmw_res_rel_cond_nop: Conditional NOP relocation. If the resource id after 8362306a36Sopenharmony_ci * validation is -1, the command is replaced with a NOP. Otherwise no action. 8462306a36Sopenharmony_ci * @vmw_res_rel_max: Last value in the enum - used for error checking 8562306a36Sopenharmony_ci*/ 8662306a36Sopenharmony_cienum vmw_resource_relocation_type { 8762306a36Sopenharmony_ci vmw_res_rel_normal, 8862306a36Sopenharmony_ci vmw_res_rel_nop, 8962306a36Sopenharmony_ci vmw_res_rel_cond_nop, 9062306a36Sopenharmony_ci vmw_res_rel_max 9162306a36Sopenharmony_ci}; 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci/** 9462306a36Sopenharmony_ci * struct vmw_resource_relocation - Relocation info for resources 9562306a36Sopenharmony_ci * 9662306a36Sopenharmony_ci * @head: List head for the software context's relocation list. 9762306a36Sopenharmony_ci * @res: Non-ref-counted pointer to the resource. 9862306a36Sopenharmony_ci * @offset: Offset of single byte entries into the command buffer where the id 9962306a36Sopenharmony_ci * that needs fixup is located. 10062306a36Sopenharmony_ci * @rel_type: Type of relocation. 10162306a36Sopenharmony_ci */ 10262306a36Sopenharmony_cistruct vmw_resource_relocation { 10362306a36Sopenharmony_ci struct list_head head; 10462306a36Sopenharmony_ci const struct vmw_resource *res; 10562306a36Sopenharmony_ci u32 offset:29; 10662306a36Sopenharmony_ci enum vmw_resource_relocation_type rel_type:3; 10762306a36Sopenharmony_ci}; 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ci/** 11062306a36Sopenharmony_ci * struct vmw_ctx_validation_info - Extra validation metadata for contexts 11162306a36Sopenharmony_ci * 11262306a36Sopenharmony_ci * @head: List head of context list 11362306a36Sopenharmony_ci * @ctx: The context resource 11462306a36Sopenharmony_ci * @cur: The context's persistent binding state 11562306a36Sopenharmony_ci * @staged: The binding state changes of this command buffer 11662306a36Sopenharmony_ci */ 11762306a36Sopenharmony_cistruct vmw_ctx_validation_info { 11862306a36Sopenharmony_ci struct list_head head; 11962306a36Sopenharmony_ci struct vmw_resource *ctx; 12062306a36Sopenharmony_ci struct vmw_ctx_binding_state *cur; 12162306a36Sopenharmony_ci struct vmw_ctx_binding_state *staged; 12262306a36Sopenharmony_ci}; 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ci/** 12562306a36Sopenharmony_ci * struct vmw_cmd_entry - Describe a command for the verifier 12662306a36Sopenharmony_ci * 12762306a36Sopenharmony_ci * @func: Call-back to handle the command. 12862306a36Sopenharmony_ci * @user_allow: Whether allowed from the execbuf ioctl. 12962306a36Sopenharmony_ci * @gb_disable: Whether disabled if guest-backed objects are available. 13062306a36Sopenharmony_ci * @gb_enable: Whether enabled iff guest-backed objects are available. 13162306a36Sopenharmony_ci * @cmd_name: Name of the command. 13262306a36Sopenharmony_ci */ 13362306a36Sopenharmony_cistruct vmw_cmd_entry { 13462306a36Sopenharmony_ci int (*func) (struct vmw_private *, struct vmw_sw_context *, 13562306a36Sopenharmony_ci SVGA3dCmdHeader *); 13662306a36Sopenharmony_ci bool user_allow; 13762306a36Sopenharmony_ci bool gb_disable; 13862306a36Sopenharmony_ci bool gb_enable; 13962306a36Sopenharmony_ci const char *cmd_name; 14062306a36Sopenharmony_ci}; 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_ci#define VMW_CMD_DEF(_cmd, _func, _user_allow, _gb_disable, _gb_enable) \ 14362306a36Sopenharmony_ci [(_cmd) - SVGA_3D_CMD_BASE] = {(_func), (_user_allow),\ 14462306a36Sopenharmony_ci (_gb_disable), (_gb_enable), #_cmd} 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_cistatic int vmw_resource_context_res_add(struct vmw_private *dev_priv, 14762306a36Sopenharmony_ci struct vmw_sw_context *sw_context, 14862306a36Sopenharmony_ci struct vmw_resource *ctx); 14962306a36Sopenharmony_cistatic int vmw_translate_mob_ptr(struct vmw_private *dev_priv, 15062306a36Sopenharmony_ci struct vmw_sw_context *sw_context, 15162306a36Sopenharmony_ci SVGAMobId *id, 15262306a36Sopenharmony_ci struct vmw_bo **vmw_bo_p); 15362306a36Sopenharmony_ci/** 15462306a36Sopenharmony_ci * vmw_ptr_diff - Compute the offset from a to b in bytes 15562306a36Sopenharmony_ci * 15662306a36Sopenharmony_ci * @a: A starting pointer. 15762306a36Sopenharmony_ci * @b: A pointer offset in the same address space. 15862306a36Sopenharmony_ci * 15962306a36Sopenharmony_ci * Returns: The offset in bytes between the two pointers. 16062306a36Sopenharmony_ci */ 16162306a36Sopenharmony_cistatic size_t vmw_ptr_diff(void *a, void *b) 16262306a36Sopenharmony_ci{ 16362306a36Sopenharmony_ci return (unsigned long) b - (unsigned long) a; 16462306a36Sopenharmony_ci} 16562306a36Sopenharmony_ci 16662306a36Sopenharmony_ci/** 16762306a36Sopenharmony_ci * vmw_execbuf_bindings_commit - Commit modified binding state 16862306a36Sopenharmony_ci * 16962306a36Sopenharmony_ci * @sw_context: The command submission context 17062306a36Sopenharmony_ci * @backoff: Whether this is part of the error path and binding state changes 17162306a36Sopenharmony_ci * should be ignored 17262306a36Sopenharmony_ci */ 17362306a36Sopenharmony_cistatic void vmw_execbuf_bindings_commit(struct vmw_sw_context *sw_context, 17462306a36Sopenharmony_ci bool backoff) 17562306a36Sopenharmony_ci{ 17662306a36Sopenharmony_ci struct vmw_ctx_validation_info *entry; 17762306a36Sopenharmony_ci 17862306a36Sopenharmony_ci list_for_each_entry(entry, &sw_context->ctx_list, head) { 17962306a36Sopenharmony_ci if (!backoff) 18062306a36Sopenharmony_ci vmw_binding_state_commit(entry->cur, entry->staged); 18162306a36Sopenharmony_ci 18262306a36Sopenharmony_ci if (entry->staged != sw_context->staged_bindings) 18362306a36Sopenharmony_ci vmw_binding_state_free(entry->staged); 18462306a36Sopenharmony_ci else 18562306a36Sopenharmony_ci sw_context->staged_bindings_inuse = false; 18662306a36Sopenharmony_ci } 18762306a36Sopenharmony_ci 18862306a36Sopenharmony_ci /* List entries are freed with the validation context */ 18962306a36Sopenharmony_ci INIT_LIST_HEAD(&sw_context->ctx_list); 19062306a36Sopenharmony_ci} 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_ci/** 19362306a36Sopenharmony_ci * vmw_bind_dx_query_mob - Bind the DX query MOB if referenced 19462306a36Sopenharmony_ci * 19562306a36Sopenharmony_ci * @sw_context: The command submission context 19662306a36Sopenharmony_ci */ 19762306a36Sopenharmony_cistatic void vmw_bind_dx_query_mob(struct vmw_sw_context *sw_context) 19862306a36Sopenharmony_ci{ 19962306a36Sopenharmony_ci if (sw_context->dx_query_mob) 20062306a36Sopenharmony_ci vmw_context_bind_dx_query(sw_context->dx_query_ctx, 20162306a36Sopenharmony_ci sw_context->dx_query_mob); 20262306a36Sopenharmony_ci} 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_ci/** 20562306a36Sopenharmony_ci * vmw_cmd_ctx_first_setup - Perform the setup needed when a context is added to 20662306a36Sopenharmony_ci * the validate list. 20762306a36Sopenharmony_ci * 20862306a36Sopenharmony_ci * @dev_priv: Pointer to the device private: 20962306a36Sopenharmony_ci * @sw_context: The command submission context 21062306a36Sopenharmony_ci * @res: Pointer to the resource 21162306a36Sopenharmony_ci * @node: The validation node holding the context resource metadata 21262306a36Sopenharmony_ci */ 21362306a36Sopenharmony_cistatic int vmw_cmd_ctx_first_setup(struct vmw_private *dev_priv, 21462306a36Sopenharmony_ci struct vmw_sw_context *sw_context, 21562306a36Sopenharmony_ci struct vmw_resource *res, 21662306a36Sopenharmony_ci struct vmw_ctx_validation_info *node) 21762306a36Sopenharmony_ci{ 21862306a36Sopenharmony_ci int ret; 21962306a36Sopenharmony_ci 22062306a36Sopenharmony_ci ret = vmw_resource_context_res_add(dev_priv, sw_context, res); 22162306a36Sopenharmony_ci if (unlikely(ret != 0)) 22262306a36Sopenharmony_ci goto out_err; 22362306a36Sopenharmony_ci 22462306a36Sopenharmony_ci if (!sw_context->staged_bindings) { 22562306a36Sopenharmony_ci sw_context->staged_bindings = vmw_binding_state_alloc(dev_priv); 22662306a36Sopenharmony_ci if (IS_ERR(sw_context->staged_bindings)) { 22762306a36Sopenharmony_ci ret = PTR_ERR(sw_context->staged_bindings); 22862306a36Sopenharmony_ci sw_context->staged_bindings = NULL; 22962306a36Sopenharmony_ci goto out_err; 23062306a36Sopenharmony_ci } 23162306a36Sopenharmony_ci } 23262306a36Sopenharmony_ci 23362306a36Sopenharmony_ci if (sw_context->staged_bindings_inuse) { 23462306a36Sopenharmony_ci node->staged = vmw_binding_state_alloc(dev_priv); 23562306a36Sopenharmony_ci if (IS_ERR(node->staged)) { 23662306a36Sopenharmony_ci ret = PTR_ERR(node->staged); 23762306a36Sopenharmony_ci node->staged = NULL; 23862306a36Sopenharmony_ci goto out_err; 23962306a36Sopenharmony_ci } 24062306a36Sopenharmony_ci } else { 24162306a36Sopenharmony_ci node->staged = sw_context->staged_bindings; 24262306a36Sopenharmony_ci sw_context->staged_bindings_inuse = true; 24362306a36Sopenharmony_ci } 24462306a36Sopenharmony_ci 24562306a36Sopenharmony_ci node->ctx = res; 24662306a36Sopenharmony_ci node->cur = vmw_context_binding_state(res); 24762306a36Sopenharmony_ci list_add_tail(&node->head, &sw_context->ctx_list); 24862306a36Sopenharmony_ci 24962306a36Sopenharmony_ci return 0; 25062306a36Sopenharmony_ci 25162306a36Sopenharmony_ciout_err: 25262306a36Sopenharmony_ci return ret; 25362306a36Sopenharmony_ci} 25462306a36Sopenharmony_ci 25562306a36Sopenharmony_ci/** 25662306a36Sopenharmony_ci * vmw_execbuf_res_size - calculate extra size fore the resource validation node 25762306a36Sopenharmony_ci * 25862306a36Sopenharmony_ci * @dev_priv: Pointer to the device private struct. 25962306a36Sopenharmony_ci * @res_type: The resource type. 26062306a36Sopenharmony_ci * 26162306a36Sopenharmony_ci * Guest-backed contexts and DX contexts require extra size to store execbuf 26262306a36Sopenharmony_ci * private information in the validation node. Typically the binding manager 26362306a36Sopenharmony_ci * associated data structures. 26462306a36Sopenharmony_ci * 26562306a36Sopenharmony_ci * Returns: The extra size requirement based on resource type. 26662306a36Sopenharmony_ci */ 26762306a36Sopenharmony_cistatic unsigned int vmw_execbuf_res_size(struct vmw_private *dev_priv, 26862306a36Sopenharmony_ci enum vmw_res_type res_type) 26962306a36Sopenharmony_ci{ 27062306a36Sopenharmony_ci return (res_type == vmw_res_dx_context || 27162306a36Sopenharmony_ci (res_type == vmw_res_context && dev_priv->has_mob)) ? 27262306a36Sopenharmony_ci sizeof(struct vmw_ctx_validation_info) : 0; 27362306a36Sopenharmony_ci} 27462306a36Sopenharmony_ci 27562306a36Sopenharmony_ci/** 27662306a36Sopenharmony_ci * vmw_execbuf_rcache_update - Update a resource-node cache entry 27762306a36Sopenharmony_ci * 27862306a36Sopenharmony_ci * @rcache: Pointer to the entry to update. 27962306a36Sopenharmony_ci * @res: Pointer to the resource. 28062306a36Sopenharmony_ci * @private: Pointer to the execbuf-private space in the resource validation 28162306a36Sopenharmony_ci * node. 28262306a36Sopenharmony_ci */ 28362306a36Sopenharmony_cistatic void vmw_execbuf_rcache_update(struct vmw_res_cache_entry *rcache, 28462306a36Sopenharmony_ci struct vmw_resource *res, 28562306a36Sopenharmony_ci void *private) 28662306a36Sopenharmony_ci{ 28762306a36Sopenharmony_ci rcache->res = res; 28862306a36Sopenharmony_ci rcache->private = private; 28962306a36Sopenharmony_ci rcache->valid = 1; 29062306a36Sopenharmony_ci rcache->valid_handle = 0; 29162306a36Sopenharmony_ci} 29262306a36Sopenharmony_ci 29362306a36Sopenharmony_cienum vmw_val_add_flags { 29462306a36Sopenharmony_ci vmw_val_add_flag_none = 0, 29562306a36Sopenharmony_ci vmw_val_add_flag_noctx = 1 << 0, 29662306a36Sopenharmony_ci}; 29762306a36Sopenharmony_ci 29862306a36Sopenharmony_ci/** 29962306a36Sopenharmony_ci * vmw_execbuf_res_val_add - Add a resource to the validation list. 30062306a36Sopenharmony_ci * 30162306a36Sopenharmony_ci * @sw_context: Pointer to the software context. 30262306a36Sopenharmony_ci * @res: Unreferenced rcu-protected pointer to the resource. 30362306a36Sopenharmony_ci * @dirty: Whether to change dirty status. 30462306a36Sopenharmony_ci * @flags: specifies whether to use the context or not 30562306a36Sopenharmony_ci * 30662306a36Sopenharmony_ci * Returns: 0 on success. Negative error code on failure. Typical error codes 30762306a36Sopenharmony_ci * are %-EINVAL on inconsistency and %-ESRCH if the resource was doomed. 30862306a36Sopenharmony_ci */ 30962306a36Sopenharmony_cistatic int vmw_execbuf_res_val_add(struct vmw_sw_context *sw_context, 31062306a36Sopenharmony_ci struct vmw_resource *res, 31162306a36Sopenharmony_ci u32 dirty, 31262306a36Sopenharmony_ci u32 flags) 31362306a36Sopenharmony_ci{ 31462306a36Sopenharmony_ci struct vmw_private *dev_priv = res->dev_priv; 31562306a36Sopenharmony_ci int ret; 31662306a36Sopenharmony_ci enum vmw_res_type res_type = vmw_res_type(res); 31762306a36Sopenharmony_ci struct vmw_res_cache_entry *rcache; 31862306a36Sopenharmony_ci struct vmw_ctx_validation_info *ctx_info; 31962306a36Sopenharmony_ci bool first_usage; 32062306a36Sopenharmony_ci unsigned int priv_size; 32162306a36Sopenharmony_ci 32262306a36Sopenharmony_ci rcache = &sw_context->res_cache[res_type]; 32362306a36Sopenharmony_ci if (likely(rcache->valid && rcache->res == res)) { 32462306a36Sopenharmony_ci if (dirty) 32562306a36Sopenharmony_ci vmw_validation_res_set_dirty(sw_context->ctx, 32662306a36Sopenharmony_ci rcache->private, dirty); 32762306a36Sopenharmony_ci return 0; 32862306a36Sopenharmony_ci } 32962306a36Sopenharmony_ci 33062306a36Sopenharmony_ci if ((flags & vmw_val_add_flag_noctx) != 0) { 33162306a36Sopenharmony_ci ret = vmw_validation_add_resource(sw_context->ctx, res, 0, dirty, 33262306a36Sopenharmony_ci (void **)&ctx_info, NULL); 33362306a36Sopenharmony_ci if (ret) 33462306a36Sopenharmony_ci return ret; 33562306a36Sopenharmony_ci 33662306a36Sopenharmony_ci } else { 33762306a36Sopenharmony_ci priv_size = vmw_execbuf_res_size(dev_priv, res_type); 33862306a36Sopenharmony_ci ret = vmw_validation_add_resource(sw_context->ctx, res, priv_size, 33962306a36Sopenharmony_ci dirty, (void **)&ctx_info, 34062306a36Sopenharmony_ci &first_usage); 34162306a36Sopenharmony_ci if (ret) 34262306a36Sopenharmony_ci return ret; 34362306a36Sopenharmony_ci 34462306a36Sopenharmony_ci if (priv_size && first_usage) { 34562306a36Sopenharmony_ci ret = vmw_cmd_ctx_first_setup(dev_priv, sw_context, res, 34662306a36Sopenharmony_ci ctx_info); 34762306a36Sopenharmony_ci if (ret) { 34862306a36Sopenharmony_ci VMW_DEBUG_USER("Failed first usage context setup.\n"); 34962306a36Sopenharmony_ci return ret; 35062306a36Sopenharmony_ci } 35162306a36Sopenharmony_ci } 35262306a36Sopenharmony_ci } 35362306a36Sopenharmony_ci 35462306a36Sopenharmony_ci vmw_execbuf_rcache_update(rcache, res, ctx_info); 35562306a36Sopenharmony_ci return 0; 35662306a36Sopenharmony_ci} 35762306a36Sopenharmony_ci 35862306a36Sopenharmony_ci/** 35962306a36Sopenharmony_ci * vmw_view_res_val_add - Add a view and the surface it's pointing to to the 36062306a36Sopenharmony_ci * validation list 36162306a36Sopenharmony_ci * 36262306a36Sopenharmony_ci * @sw_context: The software context holding the validation list. 36362306a36Sopenharmony_ci * @view: Pointer to the view resource. 36462306a36Sopenharmony_ci * 36562306a36Sopenharmony_ci * Returns 0 if success, negative error code otherwise. 36662306a36Sopenharmony_ci */ 36762306a36Sopenharmony_cistatic int vmw_view_res_val_add(struct vmw_sw_context *sw_context, 36862306a36Sopenharmony_ci struct vmw_resource *view) 36962306a36Sopenharmony_ci{ 37062306a36Sopenharmony_ci int ret; 37162306a36Sopenharmony_ci 37262306a36Sopenharmony_ci /* 37362306a36Sopenharmony_ci * First add the resource the view is pointing to, otherwise it may be 37462306a36Sopenharmony_ci * swapped out when the view is validated. 37562306a36Sopenharmony_ci */ 37662306a36Sopenharmony_ci ret = vmw_execbuf_res_val_add(sw_context, vmw_view_srf(view), 37762306a36Sopenharmony_ci vmw_view_dirtying(view), vmw_val_add_flag_noctx); 37862306a36Sopenharmony_ci if (ret) 37962306a36Sopenharmony_ci return ret; 38062306a36Sopenharmony_ci 38162306a36Sopenharmony_ci return vmw_execbuf_res_val_add(sw_context, view, VMW_RES_DIRTY_NONE, 38262306a36Sopenharmony_ci vmw_val_add_flag_noctx); 38362306a36Sopenharmony_ci} 38462306a36Sopenharmony_ci 38562306a36Sopenharmony_ci/** 38662306a36Sopenharmony_ci * vmw_view_id_val_add - Look up a view and add it and the surface it's pointing 38762306a36Sopenharmony_ci * to to the validation list. 38862306a36Sopenharmony_ci * 38962306a36Sopenharmony_ci * @sw_context: The software context holding the validation list. 39062306a36Sopenharmony_ci * @view_type: The view type to look up. 39162306a36Sopenharmony_ci * @id: view id of the view. 39262306a36Sopenharmony_ci * 39362306a36Sopenharmony_ci * The view is represented by a view id and the DX context it's created on, or 39462306a36Sopenharmony_ci * scheduled for creation on. If there is no DX context set, the function will 39562306a36Sopenharmony_ci * return an -EINVAL error pointer. 39662306a36Sopenharmony_ci * 39762306a36Sopenharmony_ci * Returns: Unreferenced pointer to the resource on success, negative error 39862306a36Sopenharmony_ci * pointer on failure. 39962306a36Sopenharmony_ci */ 40062306a36Sopenharmony_cistatic struct vmw_resource * 40162306a36Sopenharmony_civmw_view_id_val_add(struct vmw_sw_context *sw_context, 40262306a36Sopenharmony_ci enum vmw_view_type view_type, u32 id) 40362306a36Sopenharmony_ci{ 40462306a36Sopenharmony_ci struct vmw_ctx_validation_info *ctx_node = sw_context->dx_ctx_node; 40562306a36Sopenharmony_ci struct vmw_resource *view; 40662306a36Sopenharmony_ci int ret; 40762306a36Sopenharmony_ci 40862306a36Sopenharmony_ci if (!ctx_node) 40962306a36Sopenharmony_ci return ERR_PTR(-EINVAL); 41062306a36Sopenharmony_ci 41162306a36Sopenharmony_ci view = vmw_view_lookup(sw_context->man, view_type, id); 41262306a36Sopenharmony_ci if (IS_ERR(view)) 41362306a36Sopenharmony_ci return view; 41462306a36Sopenharmony_ci 41562306a36Sopenharmony_ci ret = vmw_view_res_val_add(sw_context, view); 41662306a36Sopenharmony_ci if (ret) 41762306a36Sopenharmony_ci return ERR_PTR(ret); 41862306a36Sopenharmony_ci 41962306a36Sopenharmony_ci return view; 42062306a36Sopenharmony_ci} 42162306a36Sopenharmony_ci 42262306a36Sopenharmony_ci/** 42362306a36Sopenharmony_ci * vmw_resource_context_res_add - Put resources previously bound to a context on 42462306a36Sopenharmony_ci * the validation list 42562306a36Sopenharmony_ci * 42662306a36Sopenharmony_ci * @dev_priv: Pointer to a device private structure 42762306a36Sopenharmony_ci * @sw_context: Pointer to a software context used for this command submission 42862306a36Sopenharmony_ci * @ctx: Pointer to the context resource 42962306a36Sopenharmony_ci * 43062306a36Sopenharmony_ci * This function puts all resources that were previously bound to @ctx on the 43162306a36Sopenharmony_ci * resource validation list. This is part of the context state reemission 43262306a36Sopenharmony_ci */ 43362306a36Sopenharmony_cistatic int vmw_resource_context_res_add(struct vmw_private *dev_priv, 43462306a36Sopenharmony_ci struct vmw_sw_context *sw_context, 43562306a36Sopenharmony_ci struct vmw_resource *ctx) 43662306a36Sopenharmony_ci{ 43762306a36Sopenharmony_ci struct list_head *binding_list; 43862306a36Sopenharmony_ci struct vmw_ctx_bindinfo *entry; 43962306a36Sopenharmony_ci int ret = 0; 44062306a36Sopenharmony_ci struct vmw_resource *res; 44162306a36Sopenharmony_ci u32 i; 44262306a36Sopenharmony_ci u32 cotable_max = has_sm5_context(ctx->dev_priv) ? 44362306a36Sopenharmony_ci SVGA_COTABLE_MAX : SVGA_COTABLE_DX10_MAX; 44462306a36Sopenharmony_ci 44562306a36Sopenharmony_ci /* Add all cotables to the validation list. */ 44662306a36Sopenharmony_ci if (has_sm4_context(dev_priv) && 44762306a36Sopenharmony_ci vmw_res_type(ctx) == vmw_res_dx_context) { 44862306a36Sopenharmony_ci for (i = 0; i < cotable_max; ++i) { 44962306a36Sopenharmony_ci res = vmw_context_cotable(ctx, i); 45062306a36Sopenharmony_ci if (IS_ERR_OR_NULL(res)) 45162306a36Sopenharmony_ci continue; 45262306a36Sopenharmony_ci 45362306a36Sopenharmony_ci ret = vmw_execbuf_res_val_add(sw_context, res, 45462306a36Sopenharmony_ci VMW_RES_DIRTY_SET, 45562306a36Sopenharmony_ci vmw_val_add_flag_noctx); 45662306a36Sopenharmony_ci if (unlikely(ret != 0)) 45762306a36Sopenharmony_ci return ret; 45862306a36Sopenharmony_ci } 45962306a36Sopenharmony_ci } 46062306a36Sopenharmony_ci 46162306a36Sopenharmony_ci /* Add all resources bound to the context to the validation list */ 46262306a36Sopenharmony_ci mutex_lock(&dev_priv->binding_mutex); 46362306a36Sopenharmony_ci binding_list = vmw_context_binding_list(ctx); 46462306a36Sopenharmony_ci 46562306a36Sopenharmony_ci list_for_each_entry(entry, binding_list, ctx_list) { 46662306a36Sopenharmony_ci if (vmw_res_type(entry->res) == vmw_res_view) 46762306a36Sopenharmony_ci ret = vmw_view_res_val_add(sw_context, entry->res); 46862306a36Sopenharmony_ci else 46962306a36Sopenharmony_ci ret = vmw_execbuf_res_val_add(sw_context, entry->res, 47062306a36Sopenharmony_ci vmw_binding_dirtying(entry->bt), 47162306a36Sopenharmony_ci vmw_val_add_flag_noctx); 47262306a36Sopenharmony_ci if (unlikely(ret != 0)) 47362306a36Sopenharmony_ci break; 47462306a36Sopenharmony_ci } 47562306a36Sopenharmony_ci 47662306a36Sopenharmony_ci if (has_sm4_context(dev_priv) && 47762306a36Sopenharmony_ci vmw_res_type(ctx) == vmw_res_dx_context) { 47862306a36Sopenharmony_ci struct vmw_bo *dx_query_mob; 47962306a36Sopenharmony_ci 48062306a36Sopenharmony_ci dx_query_mob = vmw_context_get_dx_query_mob(ctx); 48162306a36Sopenharmony_ci if (dx_query_mob) { 48262306a36Sopenharmony_ci vmw_bo_placement_set(dx_query_mob, 48362306a36Sopenharmony_ci VMW_BO_DOMAIN_MOB, 48462306a36Sopenharmony_ci VMW_BO_DOMAIN_MOB); 48562306a36Sopenharmony_ci ret = vmw_validation_add_bo(sw_context->ctx, 48662306a36Sopenharmony_ci dx_query_mob); 48762306a36Sopenharmony_ci } 48862306a36Sopenharmony_ci } 48962306a36Sopenharmony_ci 49062306a36Sopenharmony_ci mutex_unlock(&dev_priv->binding_mutex); 49162306a36Sopenharmony_ci return ret; 49262306a36Sopenharmony_ci} 49362306a36Sopenharmony_ci 49462306a36Sopenharmony_ci/** 49562306a36Sopenharmony_ci * vmw_resource_relocation_add - Add a relocation to the relocation list 49662306a36Sopenharmony_ci * 49762306a36Sopenharmony_ci * @sw_context: Pointer to the software context. 49862306a36Sopenharmony_ci * @res: The resource. 49962306a36Sopenharmony_ci * @offset: Offset into the command buffer currently being parsed where the id 50062306a36Sopenharmony_ci * that needs fixup is located. Granularity is one byte. 50162306a36Sopenharmony_ci * @rel_type: Relocation type. 50262306a36Sopenharmony_ci */ 50362306a36Sopenharmony_cistatic int vmw_resource_relocation_add(struct vmw_sw_context *sw_context, 50462306a36Sopenharmony_ci const struct vmw_resource *res, 50562306a36Sopenharmony_ci unsigned long offset, 50662306a36Sopenharmony_ci enum vmw_resource_relocation_type 50762306a36Sopenharmony_ci rel_type) 50862306a36Sopenharmony_ci{ 50962306a36Sopenharmony_ci struct vmw_resource_relocation *rel; 51062306a36Sopenharmony_ci 51162306a36Sopenharmony_ci rel = vmw_validation_mem_alloc(sw_context->ctx, sizeof(*rel)); 51262306a36Sopenharmony_ci if (unlikely(!rel)) { 51362306a36Sopenharmony_ci VMW_DEBUG_USER("Failed to allocate a resource relocation.\n"); 51462306a36Sopenharmony_ci return -ENOMEM; 51562306a36Sopenharmony_ci } 51662306a36Sopenharmony_ci 51762306a36Sopenharmony_ci rel->res = res; 51862306a36Sopenharmony_ci rel->offset = offset; 51962306a36Sopenharmony_ci rel->rel_type = rel_type; 52062306a36Sopenharmony_ci list_add_tail(&rel->head, &sw_context->res_relocations); 52162306a36Sopenharmony_ci 52262306a36Sopenharmony_ci return 0; 52362306a36Sopenharmony_ci} 52462306a36Sopenharmony_ci 52562306a36Sopenharmony_ci/** 52662306a36Sopenharmony_ci * vmw_resource_relocations_free - Free all relocations on a list 52762306a36Sopenharmony_ci * 52862306a36Sopenharmony_ci * @list: Pointer to the head of the relocation list 52962306a36Sopenharmony_ci */ 53062306a36Sopenharmony_cistatic void vmw_resource_relocations_free(struct list_head *list) 53162306a36Sopenharmony_ci{ 53262306a36Sopenharmony_ci /* Memory is validation context memory, so no need to free it */ 53362306a36Sopenharmony_ci INIT_LIST_HEAD(list); 53462306a36Sopenharmony_ci} 53562306a36Sopenharmony_ci 53662306a36Sopenharmony_ci/** 53762306a36Sopenharmony_ci * vmw_resource_relocations_apply - Apply all relocations on a list 53862306a36Sopenharmony_ci * 53962306a36Sopenharmony_ci * @cb: Pointer to the start of the command buffer bein patch. This need not be 54062306a36Sopenharmony_ci * the same buffer as the one being parsed when the relocation list was built, 54162306a36Sopenharmony_ci * but the contents must be the same modulo the resource ids. 54262306a36Sopenharmony_ci * @list: Pointer to the head of the relocation list. 54362306a36Sopenharmony_ci */ 54462306a36Sopenharmony_cistatic void vmw_resource_relocations_apply(uint32_t *cb, 54562306a36Sopenharmony_ci struct list_head *list) 54662306a36Sopenharmony_ci{ 54762306a36Sopenharmony_ci struct vmw_resource_relocation *rel; 54862306a36Sopenharmony_ci 54962306a36Sopenharmony_ci /* Validate the struct vmw_resource_relocation member size */ 55062306a36Sopenharmony_ci BUILD_BUG_ON(SVGA_CB_MAX_SIZE >= (1 << 29)); 55162306a36Sopenharmony_ci BUILD_BUG_ON(vmw_res_rel_max >= (1 << 3)); 55262306a36Sopenharmony_ci 55362306a36Sopenharmony_ci list_for_each_entry(rel, list, head) { 55462306a36Sopenharmony_ci u32 *addr = (u32 *)((unsigned long) cb + rel->offset); 55562306a36Sopenharmony_ci switch (rel->rel_type) { 55662306a36Sopenharmony_ci case vmw_res_rel_normal: 55762306a36Sopenharmony_ci *addr = rel->res->id; 55862306a36Sopenharmony_ci break; 55962306a36Sopenharmony_ci case vmw_res_rel_nop: 56062306a36Sopenharmony_ci *addr = SVGA_3D_CMD_NOP; 56162306a36Sopenharmony_ci break; 56262306a36Sopenharmony_ci default: 56362306a36Sopenharmony_ci if (rel->res->id == -1) 56462306a36Sopenharmony_ci *addr = SVGA_3D_CMD_NOP; 56562306a36Sopenharmony_ci break; 56662306a36Sopenharmony_ci } 56762306a36Sopenharmony_ci } 56862306a36Sopenharmony_ci} 56962306a36Sopenharmony_ci 57062306a36Sopenharmony_cistatic int vmw_cmd_invalid(struct vmw_private *dev_priv, 57162306a36Sopenharmony_ci struct vmw_sw_context *sw_context, 57262306a36Sopenharmony_ci SVGA3dCmdHeader *header) 57362306a36Sopenharmony_ci{ 57462306a36Sopenharmony_ci return -EINVAL; 57562306a36Sopenharmony_ci} 57662306a36Sopenharmony_ci 57762306a36Sopenharmony_cistatic int vmw_cmd_ok(struct vmw_private *dev_priv, 57862306a36Sopenharmony_ci struct vmw_sw_context *sw_context, 57962306a36Sopenharmony_ci SVGA3dCmdHeader *header) 58062306a36Sopenharmony_ci{ 58162306a36Sopenharmony_ci return 0; 58262306a36Sopenharmony_ci} 58362306a36Sopenharmony_ci 58462306a36Sopenharmony_ci/** 58562306a36Sopenharmony_ci * vmw_resources_reserve - Reserve all resources on the sw_context's resource 58662306a36Sopenharmony_ci * list. 58762306a36Sopenharmony_ci * 58862306a36Sopenharmony_ci * @sw_context: Pointer to the software context. 58962306a36Sopenharmony_ci * 59062306a36Sopenharmony_ci * Note that since vmware's command submission currently is protected by the 59162306a36Sopenharmony_ci * cmdbuf mutex, no fancy deadlock avoidance is required for resources, since 59262306a36Sopenharmony_ci * only a single thread at once will attempt this. 59362306a36Sopenharmony_ci */ 59462306a36Sopenharmony_cistatic int vmw_resources_reserve(struct vmw_sw_context *sw_context) 59562306a36Sopenharmony_ci{ 59662306a36Sopenharmony_ci int ret; 59762306a36Sopenharmony_ci 59862306a36Sopenharmony_ci ret = vmw_validation_res_reserve(sw_context->ctx, true); 59962306a36Sopenharmony_ci if (ret) 60062306a36Sopenharmony_ci return ret; 60162306a36Sopenharmony_ci 60262306a36Sopenharmony_ci if (sw_context->dx_query_mob) { 60362306a36Sopenharmony_ci struct vmw_bo *expected_dx_query_mob; 60462306a36Sopenharmony_ci 60562306a36Sopenharmony_ci expected_dx_query_mob = 60662306a36Sopenharmony_ci vmw_context_get_dx_query_mob(sw_context->dx_query_ctx); 60762306a36Sopenharmony_ci if (expected_dx_query_mob && 60862306a36Sopenharmony_ci expected_dx_query_mob != sw_context->dx_query_mob) { 60962306a36Sopenharmony_ci ret = -EINVAL; 61062306a36Sopenharmony_ci } 61162306a36Sopenharmony_ci } 61262306a36Sopenharmony_ci 61362306a36Sopenharmony_ci return ret; 61462306a36Sopenharmony_ci} 61562306a36Sopenharmony_ci 61662306a36Sopenharmony_ci/** 61762306a36Sopenharmony_ci * vmw_cmd_res_check - Check that a resource is present and if so, put it on the 61862306a36Sopenharmony_ci * resource validate list unless it's already there. 61962306a36Sopenharmony_ci * 62062306a36Sopenharmony_ci * @dev_priv: Pointer to a device private structure. 62162306a36Sopenharmony_ci * @sw_context: Pointer to the software context. 62262306a36Sopenharmony_ci * @res_type: Resource type. 62362306a36Sopenharmony_ci * @dirty: Whether to change dirty status. 62462306a36Sopenharmony_ci * @converter: User-space visisble type specific information. 62562306a36Sopenharmony_ci * @id_loc: Pointer to the location in the command buffer currently being parsed 62662306a36Sopenharmony_ci * from where the user-space resource id handle is located. 62762306a36Sopenharmony_ci * @p_res: Pointer to pointer to resource validalidation node. Populated on 62862306a36Sopenharmony_ci * exit. 62962306a36Sopenharmony_ci */ 63062306a36Sopenharmony_cistatic int 63162306a36Sopenharmony_civmw_cmd_res_check(struct vmw_private *dev_priv, 63262306a36Sopenharmony_ci struct vmw_sw_context *sw_context, 63362306a36Sopenharmony_ci enum vmw_res_type res_type, 63462306a36Sopenharmony_ci u32 dirty, 63562306a36Sopenharmony_ci const struct vmw_user_resource_conv *converter, 63662306a36Sopenharmony_ci uint32_t *id_loc, 63762306a36Sopenharmony_ci struct vmw_resource **p_res) 63862306a36Sopenharmony_ci{ 63962306a36Sopenharmony_ci struct vmw_res_cache_entry *rcache = &sw_context->res_cache[res_type]; 64062306a36Sopenharmony_ci struct vmw_resource *res; 64162306a36Sopenharmony_ci int ret = 0; 64262306a36Sopenharmony_ci bool needs_unref = false; 64362306a36Sopenharmony_ci 64462306a36Sopenharmony_ci if (p_res) 64562306a36Sopenharmony_ci *p_res = NULL; 64662306a36Sopenharmony_ci 64762306a36Sopenharmony_ci if (*id_loc == SVGA3D_INVALID_ID) { 64862306a36Sopenharmony_ci if (res_type == vmw_res_context) { 64962306a36Sopenharmony_ci VMW_DEBUG_USER("Illegal context invalid id.\n"); 65062306a36Sopenharmony_ci return -EINVAL; 65162306a36Sopenharmony_ci } 65262306a36Sopenharmony_ci return 0; 65362306a36Sopenharmony_ci } 65462306a36Sopenharmony_ci 65562306a36Sopenharmony_ci if (likely(rcache->valid_handle && *id_loc == rcache->handle)) { 65662306a36Sopenharmony_ci res = rcache->res; 65762306a36Sopenharmony_ci if (dirty) 65862306a36Sopenharmony_ci vmw_validation_res_set_dirty(sw_context->ctx, 65962306a36Sopenharmony_ci rcache->private, dirty); 66062306a36Sopenharmony_ci } else { 66162306a36Sopenharmony_ci unsigned int size = vmw_execbuf_res_size(dev_priv, res_type); 66262306a36Sopenharmony_ci 66362306a36Sopenharmony_ci ret = vmw_validation_preload_res(sw_context->ctx, size); 66462306a36Sopenharmony_ci if (ret) 66562306a36Sopenharmony_ci return ret; 66662306a36Sopenharmony_ci 66762306a36Sopenharmony_ci ret = vmw_user_resource_lookup_handle 66862306a36Sopenharmony_ci (dev_priv, sw_context->fp->tfile, *id_loc, converter, &res); 66962306a36Sopenharmony_ci if (ret != 0) { 67062306a36Sopenharmony_ci VMW_DEBUG_USER("Could not find/use resource 0x%08x.\n", 67162306a36Sopenharmony_ci (unsigned int) *id_loc); 67262306a36Sopenharmony_ci return ret; 67362306a36Sopenharmony_ci } 67462306a36Sopenharmony_ci needs_unref = true; 67562306a36Sopenharmony_ci 67662306a36Sopenharmony_ci ret = vmw_execbuf_res_val_add(sw_context, res, dirty, vmw_val_add_flag_none); 67762306a36Sopenharmony_ci if (unlikely(ret != 0)) 67862306a36Sopenharmony_ci goto res_check_done; 67962306a36Sopenharmony_ci 68062306a36Sopenharmony_ci if (rcache->valid && rcache->res == res) { 68162306a36Sopenharmony_ci rcache->valid_handle = true; 68262306a36Sopenharmony_ci rcache->handle = *id_loc; 68362306a36Sopenharmony_ci } 68462306a36Sopenharmony_ci } 68562306a36Sopenharmony_ci 68662306a36Sopenharmony_ci ret = vmw_resource_relocation_add(sw_context, res, 68762306a36Sopenharmony_ci vmw_ptr_diff(sw_context->buf_start, 68862306a36Sopenharmony_ci id_loc), 68962306a36Sopenharmony_ci vmw_res_rel_normal); 69062306a36Sopenharmony_ci if (p_res) 69162306a36Sopenharmony_ci *p_res = res; 69262306a36Sopenharmony_ci 69362306a36Sopenharmony_cires_check_done: 69462306a36Sopenharmony_ci if (needs_unref) 69562306a36Sopenharmony_ci vmw_resource_unreference(&res); 69662306a36Sopenharmony_ci 69762306a36Sopenharmony_ci return ret; 69862306a36Sopenharmony_ci} 69962306a36Sopenharmony_ci 70062306a36Sopenharmony_ci/** 70162306a36Sopenharmony_ci * vmw_rebind_all_dx_query - Rebind DX query associated with the context 70262306a36Sopenharmony_ci * 70362306a36Sopenharmony_ci * @ctx_res: context the query belongs to 70462306a36Sopenharmony_ci * 70562306a36Sopenharmony_ci * This function assumes binding_mutex is held. 70662306a36Sopenharmony_ci */ 70762306a36Sopenharmony_cistatic int vmw_rebind_all_dx_query(struct vmw_resource *ctx_res) 70862306a36Sopenharmony_ci{ 70962306a36Sopenharmony_ci struct vmw_private *dev_priv = ctx_res->dev_priv; 71062306a36Sopenharmony_ci struct vmw_bo *dx_query_mob; 71162306a36Sopenharmony_ci VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdDXBindAllQuery); 71262306a36Sopenharmony_ci 71362306a36Sopenharmony_ci dx_query_mob = vmw_context_get_dx_query_mob(ctx_res); 71462306a36Sopenharmony_ci 71562306a36Sopenharmony_ci if (!dx_query_mob || dx_query_mob->dx_query_ctx) 71662306a36Sopenharmony_ci return 0; 71762306a36Sopenharmony_ci 71862306a36Sopenharmony_ci cmd = VMW_CMD_CTX_RESERVE(dev_priv, sizeof(*cmd), ctx_res->id); 71962306a36Sopenharmony_ci if (cmd == NULL) 72062306a36Sopenharmony_ci return -ENOMEM; 72162306a36Sopenharmony_ci 72262306a36Sopenharmony_ci cmd->header.id = SVGA_3D_CMD_DX_BIND_ALL_QUERY; 72362306a36Sopenharmony_ci cmd->header.size = sizeof(cmd->body); 72462306a36Sopenharmony_ci cmd->body.cid = ctx_res->id; 72562306a36Sopenharmony_ci cmd->body.mobid = dx_query_mob->tbo.resource->start; 72662306a36Sopenharmony_ci vmw_cmd_commit(dev_priv, sizeof(*cmd)); 72762306a36Sopenharmony_ci 72862306a36Sopenharmony_ci vmw_context_bind_dx_query(ctx_res, dx_query_mob); 72962306a36Sopenharmony_ci 73062306a36Sopenharmony_ci return 0; 73162306a36Sopenharmony_ci} 73262306a36Sopenharmony_ci 73362306a36Sopenharmony_ci/** 73462306a36Sopenharmony_ci * vmw_rebind_contexts - Rebind all resources previously bound to referenced 73562306a36Sopenharmony_ci * contexts. 73662306a36Sopenharmony_ci * 73762306a36Sopenharmony_ci * @sw_context: Pointer to the software context. 73862306a36Sopenharmony_ci * 73962306a36Sopenharmony_ci * Rebind context binding points that have been scrubbed because of eviction. 74062306a36Sopenharmony_ci */ 74162306a36Sopenharmony_cistatic int vmw_rebind_contexts(struct vmw_sw_context *sw_context) 74262306a36Sopenharmony_ci{ 74362306a36Sopenharmony_ci struct vmw_ctx_validation_info *val; 74462306a36Sopenharmony_ci int ret; 74562306a36Sopenharmony_ci 74662306a36Sopenharmony_ci list_for_each_entry(val, &sw_context->ctx_list, head) { 74762306a36Sopenharmony_ci ret = vmw_binding_rebind_all(val->cur); 74862306a36Sopenharmony_ci if (unlikely(ret != 0)) { 74962306a36Sopenharmony_ci if (ret != -ERESTARTSYS) 75062306a36Sopenharmony_ci VMW_DEBUG_USER("Failed to rebind context.\n"); 75162306a36Sopenharmony_ci return ret; 75262306a36Sopenharmony_ci } 75362306a36Sopenharmony_ci 75462306a36Sopenharmony_ci ret = vmw_rebind_all_dx_query(val->ctx); 75562306a36Sopenharmony_ci if (ret != 0) { 75662306a36Sopenharmony_ci VMW_DEBUG_USER("Failed to rebind queries.\n"); 75762306a36Sopenharmony_ci return ret; 75862306a36Sopenharmony_ci } 75962306a36Sopenharmony_ci } 76062306a36Sopenharmony_ci 76162306a36Sopenharmony_ci return 0; 76262306a36Sopenharmony_ci} 76362306a36Sopenharmony_ci 76462306a36Sopenharmony_ci/** 76562306a36Sopenharmony_ci * vmw_view_bindings_add - Add an array of view bindings to a context binding 76662306a36Sopenharmony_ci * state tracker. 76762306a36Sopenharmony_ci * 76862306a36Sopenharmony_ci * @sw_context: The execbuf state used for this command. 76962306a36Sopenharmony_ci * @view_type: View type for the bindings. 77062306a36Sopenharmony_ci * @binding_type: Binding type for the bindings. 77162306a36Sopenharmony_ci * @shader_slot: The shader slot to user for the bindings. 77262306a36Sopenharmony_ci * @view_ids: Array of view ids to be bound. 77362306a36Sopenharmony_ci * @num_views: Number of view ids in @view_ids. 77462306a36Sopenharmony_ci * @first_slot: The binding slot to be used for the first view id in @view_ids. 77562306a36Sopenharmony_ci */ 77662306a36Sopenharmony_cistatic int vmw_view_bindings_add(struct vmw_sw_context *sw_context, 77762306a36Sopenharmony_ci enum vmw_view_type view_type, 77862306a36Sopenharmony_ci enum vmw_ctx_binding_type binding_type, 77962306a36Sopenharmony_ci uint32 shader_slot, 78062306a36Sopenharmony_ci uint32 view_ids[], u32 num_views, 78162306a36Sopenharmony_ci u32 first_slot) 78262306a36Sopenharmony_ci{ 78362306a36Sopenharmony_ci struct vmw_ctx_validation_info *ctx_node = VMW_GET_CTX_NODE(sw_context); 78462306a36Sopenharmony_ci u32 i; 78562306a36Sopenharmony_ci 78662306a36Sopenharmony_ci if (!ctx_node) 78762306a36Sopenharmony_ci return -EINVAL; 78862306a36Sopenharmony_ci 78962306a36Sopenharmony_ci for (i = 0; i < num_views; ++i) { 79062306a36Sopenharmony_ci struct vmw_ctx_bindinfo_view binding; 79162306a36Sopenharmony_ci struct vmw_resource *view = NULL; 79262306a36Sopenharmony_ci 79362306a36Sopenharmony_ci if (view_ids[i] != SVGA3D_INVALID_ID) { 79462306a36Sopenharmony_ci view = vmw_view_id_val_add(sw_context, view_type, 79562306a36Sopenharmony_ci view_ids[i]); 79662306a36Sopenharmony_ci if (IS_ERR(view)) { 79762306a36Sopenharmony_ci VMW_DEBUG_USER("View not found.\n"); 79862306a36Sopenharmony_ci return PTR_ERR(view); 79962306a36Sopenharmony_ci } 80062306a36Sopenharmony_ci } 80162306a36Sopenharmony_ci binding.bi.ctx = ctx_node->ctx; 80262306a36Sopenharmony_ci binding.bi.res = view; 80362306a36Sopenharmony_ci binding.bi.bt = binding_type; 80462306a36Sopenharmony_ci binding.shader_slot = shader_slot; 80562306a36Sopenharmony_ci binding.slot = first_slot + i; 80662306a36Sopenharmony_ci vmw_binding_add(ctx_node->staged, &binding.bi, 80762306a36Sopenharmony_ci shader_slot, binding.slot); 80862306a36Sopenharmony_ci } 80962306a36Sopenharmony_ci 81062306a36Sopenharmony_ci return 0; 81162306a36Sopenharmony_ci} 81262306a36Sopenharmony_ci 81362306a36Sopenharmony_ci/** 81462306a36Sopenharmony_ci * vmw_cmd_cid_check - Check a command header for valid context information. 81562306a36Sopenharmony_ci * 81662306a36Sopenharmony_ci * @dev_priv: Pointer to a device private structure. 81762306a36Sopenharmony_ci * @sw_context: Pointer to the software context. 81862306a36Sopenharmony_ci * @header: A command header with an embedded user-space context handle. 81962306a36Sopenharmony_ci * 82062306a36Sopenharmony_ci * Convenience function: Call vmw_cmd_res_check with the user-space context 82162306a36Sopenharmony_ci * handle embedded in @header. 82262306a36Sopenharmony_ci */ 82362306a36Sopenharmony_cistatic int vmw_cmd_cid_check(struct vmw_private *dev_priv, 82462306a36Sopenharmony_ci struct vmw_sw_context *sw_context, 82562306a36Sopenharmony_ci SVGA3dCmdHeader *header) 82662306a36Sopenharmony_ci{ 82762306a36Sopenharmony_ci VMW_DECLARE_CMD_VAR(*cmd, uint32_t) = 82862306a36Sopenharmony_ci container_of(header, typeof(*cmd), header); 82962306a36Sopenharmony_ci 83062306a36Sopenharmony_ci return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_context, 83162306a36Sopenharmony_ci VMW_RES_DIRTY_SET, user_context_converter, 83262306a36Sopenharmony_ci &cmd->body, NULL); 83362306a36Sopenharmony_ci} 83462306a36Sopenharmony_ci 83562306a36Sopenharmony_ci/** 83662306a36Sopenharmony_ci * vmw_execbuf_info_from_res - Get the private validation metadata for a 83762306a36Sopenharmony_ci * recently validated resource 83862306a36Sopenharmony_ci * 83962306a36Sopenharmony_ci * @sw_context: Pointer to the command submission context 84062306a36Sopenharmony_ci * @res: The resource 84162306a36Sopenharmony_ci * 84262306a36Sopenharmony_ci * The resource pointed to by @res needs to be present in the command submission 84362306a36Sopenharmony_ci * context's resource cache and hence the last resource of that type to be 84462306a36Sopenharmony_ci * processed by the validation code. 84562306a36Sopenharmony_ci * 84662306a36Sopenharmony_ci * Return: a pointer to the private metadata of the resource, or NULL if it 84762306a36Sopenharmony_ci * wasn't found 84862306a36Sopenharmony_ci */ 84962306a36Sopenharmony_cistatic struct vmw_ctx_validation_info * 85062306a36Sopenharmony_civmw_execbuf_info_from_res(struct vmw_sw_context *sw_context, 85162306a36Sopenharmony_ci struct vmw_resource *res) 85262306a36Sopenharmony_ci{ 85362306a36Sopenharmony_ci struct vmw_res_cache_entry *rcache = 85462306a36Sopenharmony_ci &sw_context->res_cache[vmw_res_type(res)]; 85562306a36Sopenharmony_ci 85662306a36Sopenharmony_ci if (rcache->valid && rcache->res == res) 85762306a36Sopenharmony_ci return rcache->private; 85862306a36Sopenharmony_ci 85962306a36Sopenharmony_ci WARN_ON_ONCE(true); 86062306a36Sopenharmony_ci return NULL; 86162306a36Sopenharmony_ci} 86262306a36Sopenharmony_ci 86362306a36Sopenharmony_cistatic int vmw_cmd_set_render_target_check(struct vmw_private *dev_priv, 86462306a36Sopenharmony_ci struct vmw_sw_context *sw_context, 86562306a36Sopenharmony_ci SVGA3dCmdHeader *header) 86662306a36Sopenharmony_ci{ 86762306a36Sopenharmony_ci VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdSetRenderTarget); 86862306a36Sopenharmony_ci struct vmw_resource *ctx; 86962306a36Sopenharmony_ci struct vmw_resource *res; 87062306a36Sopenharmony_ci int ret; 87162306a36Sopenharmony_ci 87262306a36Sopenharmony_ci cmd = container_of(header, typeof(*cmd), header); 87362306a36Sopenharmony_ci 87462306a36Sopenharmony_ci if (cmd->body.type >= SVGA3D_RT_MAX) { 87562306a36Sopenharmony_ci VMW_DEBUG_USER("Illegal render target type %u.\n", 87662306a36Sopenharmony_ci (unsigned int) cmd->body.type); 87762306a36Sopenharmony_ci return -EINVAL; 87862306a36Sopenharmony_ci } 87962306a36Sopenharmony_ci 88062306a36Sopenharmony_ci ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_context, 88162306a36Sopenharmony_ci VMW_RES_DIRTY_SET, user_context_converter, 88262306a36Sopenharmony_ci &cmd->body.cid, &ctx); 88362306a36Sopenharmony_ci if (unlikely(ret != 0)) 88462306a36Sopenharmony_ci return ret; 88562306a36Sopenharmony_ci 88662306a36Sopenharmony_ci ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface, 88762306a36Sopenharmony_ci VMW_RES_DIRTY_SET, user_surface_converter, 88862306a36Sopenharmony_ci &cmd->body.target.sid, &res); 88962306a36Sopenharmony_ci if (unlikely(ret)) 89062306a36Sopenharmony_ci return ret; 89162306a36Sopenharmony_ci 89262306a36Sopenharmony_ci if (dev_priv->has_mob) { 89362306a36Sopenharmony_ci struct vmw_ctx_bindinfo_view binding; 89462306a36Sopenharmony_ci struct vmw_ctx_validation_info *node; 89562306a36Sopenharmony_ci 89662306a36Sopenharmony_ci node = vmw_execbuf_info_from_res(sw_context, ctx); 89762306a36Sopenharmony_ci if (!node) 89862306a36Sopenharmony_ci return -EINVAL; 89962306a36Sopenharmony_ci 90062306a36Sopenharmony_ci binding.bi.ctx = ctx; 90162306a36Sopenharmony_ci binding.bi.res = res; 90262306a36Sopenharmony_ci binding.bi.bt = vmw_ctx_binding_rt; 90362306a36Sopenharmony_ci binding.slot = cmd->body.type; 90462306a36Sopenharmony_ci vmw_binding_add(node->staged, &binding.bi, 0, binding.slot); 90562306a36Sopenharmony_ci } 90662306a36Sopenharmony_ci 90762306a36Sopenharmony_ci return 0; 90862306a36Sopenharmony_ci} 90962306a36Sopenharmony_ci 91062306a36Sopenharmony_cistatic int vmw_cmd_surface_copy_check(struct vmw_private *dev_priv, 91162306a36Sopenharmony_ci struct vmw_sw_context *sw_context, 91262306a36Sopenharmony_ci SVGA3dCmdHeader *header) 91362306a36Sopenharmony_ci{ 91462306a36Sopenharmony_ci VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdSurfaceCopy); 91562306a36Sopenharmony_ci int ret; 91662306a36Sopenharmony_ci 91762306a36Sopenharmony_ci cmd = container_of(header, typeof(*cmd), header); 91862306a36Sopenharmony_ci 91962306a36Sopenharmony_ci ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface, 92062306a36Sopenharmony_ci VMW_RES_DIRTY_NONE, user_surface_converter, 92162306a36Sopenharmony_ci &cmd->body.src.sid, NULL); 92262306a36Sopenharmony_ci if (ret) 92362306a36Sopenharmony_ci return ret; 92462306a36Sopenharmony_ci 92562306a36Sopenharmony_ci return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface, 92662306a36Sopenharmony_ci VMW_RES_DIRTY_SET, user_surface_converter, 92762306a36Sopenharmony_ci &cmd->body.dest.sid, NULL); 92862306a36Sopenharmony_ci} 92962306a36Sopenharmony_ci 93062306a36Sopenharmony_cistatic int vmw_cmd_buffer_copy_check(struct vmw_private *dev_priv, 93162306a36Sopenharmony_ci struct vmw_sw_context *sw_context, 93262306a36Sopenharmony_ci SVGA3dCmdHeader *header) 93362306a36Sopenharmony_ci{ 93462306a36Sopenharmony_ci VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdDXBufferCopy); 93562306a36Sopenharmony_ci int ret; 93662306a36Sopenharmony_ci 93762306a36Sopenharmony_ci cmd = container_of(header, typeof(*cmd), header); 93862306a36Sopenharmony_ci ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface, 93962306a36Sopenharmony_ci VMW_RES_DIRTY_NONE, user_surface_converter, 94062306a36Sopenharmony_ci &cmd->body.src, NULL); 94162306a36Sopenharmony_ci if (ret != 0) 94262306a36Sopenharmony_ci return ret; 94362306a36Sopenharmony_ci 94462306a36Sopenharmony_ci return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface, 94562306a36Sopenharmony_ci VMW_RES_DIRTY_SET, user_surface_converter, 94662306a36Sopenharmony_ci &cmd->body.dest, NULL); 94762306a36Sopenharmony_ci} 94862306a36Sopenharmony_ci 94962306a36Sopenharmony_cistatic int vmw_cmd_pred_copy_check(struct vmw_private *dev_priv, 95062306a36Sopenharmony_ci struct vmw_sw_context *sw_context, 95162306a36Sopenharmony_ci SVGA3dCmdHeader *header) 95262306a36Sopenharmony_ci{ 95362306a36Sopenharmony_ci VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdDXPredCopyRegion); 95462306a36Sopenharmony_ci int ret; 95562306a36Sopenharmony_ci 95662306a36Sopenharmony_ci cmd = container_of(header, typeof(*cmd), header); 95762306a36Sopenharmony_ci ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface, 95862306a36Sopenharmony_ci VMW_RES_DIRTY_NONE, user_surface_converter, 95962306a36Sopenharmony_ci &cmd->body.srcSid, NULL); 96062306a36Sopenharmony_ci if (ret != 0) 96162306a36Sopenharmony_ci return ret; 96262306a36Sopenharmony_ci 96362306a36Sopenharmony_ci return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface, 96462306a36Sopenharmony_ci VMW_RES_DIRTY_SET, user_surface_converter, 96562306a36Sopenharmony_ci &cmd->body.dstSid, NULL); 96662306a36Sopenharmony_ci} 96762306a36Sopenharmony_ci 96862306a36Sopenharmony_cistatic int vmw_cmd_stretch_blt_check(struct vmw_private *dev_priv, 96962306a36Sopenharmony_ci struct vmw_sw_context *sw_context, 97062306a36Sopenharmony_ci SVGA3dCmdHeader *header) 97162306a36Sopenharmony_ci{ 97262306a36Sopenharmony_ci VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdSurfaceStretchBlt); 97362306a36Sopenharmony_ci int ret; 97462306a36Sopenharmony_ci 97562306a36Sopenharmony_ci cmd = container_of(header, typeof(*cmd), header); 97662306a36Sopenharmony_ci ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface, 97762306a36Sopenharmony_ci VMW_RES_DIRTY_NONE, user_surface_converter, 97862306a36Sopenharmony_ci &cmd->body.src.sid, NULL); 97962306a36Sopenharmony_ci if (unlikely(ret != 0)) 98062306a36Sopenharmony_ci return ret; 98162306a36Sopenharmony_ci 98262306a36Sopenharmony_ci return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface, 98362306a36Sopenharmony_ci VMW_RES_DIRTY_SET, user_surface_converter, 98462306a36Sopenharmony_ci &cmd->body.dest.sid, NULL); 98562306a36Sopenharmony_ci} 98662306a36Sopenharmony_ci 98762306a36Sopenharmony_cistatic int vmw_cmd_blt_surf_screen_check(struct vmw_private *dev_priv, 98862306a36Sopenharmony_ci struct vmw_sw_context *sw_context, 98962306a36Sopenharmony_ci SVGA3dCmdHeader *header) 99062306a36Sopenharmony_ci{ 99162306a36Sopenharmony_ci VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdBlitSurfaceToScreen) = 99262306a36Sopenharmony_ci container_of(header, typeof(*cmd), header); 99362306a36Sopenharmony_ci 99462306a36Sopenharmony_ci return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface, 99562306a36Sopenharmony_ci VMW_RES_DIRTY_NONE, user_surface_converter, 99662306a36Sopenharmony_ci &cmd->body.srcImage.sid, NULL); 99762306a36Sopenharmony_ci} 99862306a36Sopenharmony_ci 99962306a36Sopenharmony_cistatic int vmw_cmd_present_check(struct vmw_private *dev_priv, 100062306a36Sopenharmony_ci struct vmw_sw_context *sw_context, 100162306a36Sopenharmony_ci SVGA3dCmdHeader *header) 100262306a36Sopenharmony_ci{ 100362306a36Sopenharmony_ci VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdPresent) = 100462306a36Sopenharmony_ci container_of(header, typeof(*cmd), header); 100562306a36Sopenharmony_ci 100662306a36Sopenharmony_ci return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface, 100762306a36Sopenharmony_ci VMW_RES_DIRTY_NONE, user_surface_converter, 100862306a36Sopenharmony_ci &cmd->body.sid, NULL); 100962306a36Sopenharmony_ci} 101062306a36Sopenharmony_ci 101162306a36Sopenharmony_ci/** 101262306a36Sopenharmony_ci * vmw_query_bo_switch_prepare - Prepare to switch pinned buffer for queries. 101362306a36Sopenharmony_ci * 101462306a36Sopenharmony_ci * @dev_priv: The device private structure. 101562306a36Sopenharmony_ci * @new_query_bo: The new buffer holding query results. 101662306a36Sopenharmony_ci * @sw_context: The software context used for this command submission. 101762306a36Sopenharmony_ci * 101862306a36Sopenharmony_ci * This function checks whether @new_query_bo is suitable for holding query 101962306a36Sopenharmony_ci * results, and if another buffer currently is pinned for query results. If so, 102062306a36Sopenharmony_ci * the function prepares the state of @sw_context for switching pinned buffers 102162306a36Sopenharmony_ci * after successful submission of the current command batch. 102262306a36Sopenharmony_ci */ 102362306a36Sopenharmony_cistatic int vmw_query_bo_switch_prepare(struct vmw_private *dev_priv, 102462306a36Sopenharmony_ci struct vmw_bo *new_query_bo, 102562306a36Sopenharmony_ci struct vmw_sw_context *sw_context) 102662306a36Sopenharmony_ci{ 102762306a36Sopenharmony_ci struct vmw_res_cache_entry *ctx_entry = 102862306a36Sopenharmony_ci &sw_context->res_cache[vmw_res_context]; 102962306a36Sopenharmony_ci int ret; 103062306a36Sopenharmony_ci 103162306a36Sopenharmony_ci BUG_ON(!ctx_entry->valid); 103262306a36Sopenharmony_ci sw_context->last_query_ctx = ctx_entry->res; 103362306a36Sopenharmony_ci 103462306a36Sopenharmony_ci if (unlikely(new_query_bo != sw_context->cur_query_bo)) { 103562306a36Sopenharmony_ci 103662306a36Sopenharmony_ci if (unlikely(PFN_UP(new_query_bo->tbo.resource->size) > 4)) { 103762306a36Sopenharmony_ci VMW_DEBUG_USER("Query buffer too large.\n"); 103862306a36Sopenharmony_ci return -EINVAL; 103962306a36Sopenharmony_ci } 104062306a36Sopenharmony_ci 104162306a36Sopenharmony_ci if (unlikely(sw_context->cur_query_bo != NULL)) { 104262306a36Sopenharmony_ci sw_context->needs_post_query_barrier = true; 104362306a36Sopenharmony_ci vmw_bo_placement_set_default_accelerated(sw_context->cur_query_bo); 104462306a36Sopenharmony_ci ret = vmw_validation_add_bo(sw_context->ctx, 104562306a36Sopenharmony_ci sw_context->cur_query_bo); 104662306a36Sopenharmony_ci if (unlikely(ret != 0)) 104762306a36Sopenharmony_ci return ret; 104862306a36Sopenharmony_ci } 104962306a36Sopenharmony_ci sw_context->cur_query_bo = new_query_bo; 105062306a36Sopenharmony_ci 105162306a36Sopenharmony_ci vmw_bo_placement_set_default_accelerated(dev_priv->dummy_query_bo); 105262306a36Sopenharmony_ci ret = vmw_validation_add_bo(sw_context->ctx, 105362306a36Sopenharmony_ci dev_priv->dummy_query_bo); 105462306a36Sopenharmony_ci if (unlikely(ret != 0)) 105562306a36Sopenharmony_ci return ret; 105662306a36Sopenharmony_ci } 105762306a36Sopenharmony_ci 105862306a36Sopenharmony_ci return 0; 105962306a36Sopenharmony_ci} 106062306a36Sopenharmony_ci 106162306a36Sopenharmony_ci/** 106262306a36Sopenharmony_ci * vmw_query_bo_switch_commit - Finalize switching pinned query buffer 106362306a36Sopenharmony_ci * 106462306a36Sopenharmony_ci * @dev_priv: The device private structure. 106562306a36Sopenharmony_ci * @sw_context: The software context used for this command submission batch. 106662306a36Sopenharmony_ci * 106762306a36Sopenharmony_ci * This function will check if we're switching query buffers, and will then, 106862306a36Sopenharmony_ci * issue a dummy occlusion query wait used as a query barrier. When the fence 106962306a36Sopenharmony_ci * object following that query wait has signaled, we are sure that all preceding 107062306a36Sopenharmony_ci * queries have finished, and the old query buffer can be unpinned. However, 107162306a36Sopenharmony_ci * since both the new query buffer and the old one are fenced with that fence, 107262306a36Sopenharmony_ci * we can do an asynchronus unpin now, and be sure that the old query buffer 107362306a36Sopenharmony_ci * won't be moved until the fence has signaled. 107462306a36Sopenharmony_ci * 107562306a36Sopenharmony_ci * As mentioned above, both the new - and old query buffers need to be fenced 107662306a36Sopenharmony_ci * using a sequence emitted *after* calling this function. 107762306a36Sopenharmony_ci */ 107862306a36Sopenharmony_cistatic void vmw_query_bo_switch_commit(struct vmw_private *dev_priv, 107962306a36Sopenharmony_ci struct vmw_sw_context *sw_context) 108062306a36Sopenharmony_ci{ 108162306a36Sopenharmony_ci /* 108262306a36Sopenharmony_ci * The validate list should still hold references to all 108362306a36Sopenharmony_ci * contexts here. 108462306a36Sopenharmony_ci */ 108562306a36Sopenharmony_ci if (sw_context->needs_post_query_barrier) { 108662306a36Sopenharmony_ci struct vmw_res_cache_entry *ctx_entry = 108762306a36Sopenharmony_ci &sw_context->res_cache[vmw_res_context]; 108862306a36Sopenharmony_ci struct vmw_resource *ctx; 108962306a36Sopenharmony_ci int ret; 109062306a36Sopenharmony_ci 109162306a36Sopenharmony_ci BUG_ON(!ctx_entry->valid); 109262306a36Sopenharmony_ci ctx = ctx_entry->res; 109362306a36Sopenharmony_ci 109462306a36Sopenharmony_ci ret = vmw_cmd_emit_dummy_query(dev_priv, ctx->id); 109562306a36Sopenharmony_ci 109662306a36Sopenharmony_ci if (unlikely(ret != 0)) 109762306a36Sopenharmony_ci VMW_DEBUG_USER("Out of fifo space for dummy query.\n"); 109862306a36Sopenharmony_ci } 109962306a36Sopenharmony_ci 110062306a36Sopenharmony_ci if (dev_priv->pinned_bo != sw_context->cur_query_bo) { 110162306a36Sopenharmony_ci if (dev_priv->pinned_bo) { 110262306a36Sopenharmony_ci vmw_bo_pin_reserved(dev_priv->pinned_bo, false); 110362306a36Sopenharmony_ci vmw_bo_unreference(&dev_priv->pinned_bo); 110462306a36Sopenharmony_ci } 110562306a36Sopenharmony_ci 110662306a36Sopenharmony_ci if (!sw_context->needs_post_query_barrier) { 110762306a36Sopenharmony_ci vmw_bo_pin_reserved(sw_context->cur_query_bo, true); 110862306a36Sopenharmony_ci 110962306a36Sopenharmony_ci /* 111062306a36Sopenharmony_ci * We pin also the dummy_query_bo buffer so that we 111162306a36Sopenharmony_ci * don't need to validate it when emitting dummy queries 111262306a36Sopenharmony_ci * in context destroy paths. 111362306a36Sopenharmony_ci */ 111462306a36Sopenharmony_ci if (!dev_priv->dummy_query_bo_pinned) { 111562306a36Sopenharmony_ci vmw_bo_pin_reserved(dev_priv->dummy_query_bo, 111662306a36Sopenharmony_ci true); 111762306a36Sopenharmony_ci dev_priv->dummy_query_bo_pinned = true; 111862306a36Sopenharmony_ci } 111962306a36Sopenharmony_ci 112062306a36Sopenharmony_ci BUG_ON(sw_context->last_query_ctx == NULL); 112162306a36Sopenharmony_ci dev_priv->query_cid = sw_context->last_query_ctx->id; 112262306a36Sopenharmony_ci dev_priv->query_cid_valid = true; 112362306a36Sopenharmony_ci dev_priv->pinned_bo = 112462306a36Sopenharmony_ci vmw_bo_reference(sw_context->cur_query_bo); 112562306a36Sopenharmony_ci } 112662306a36Sopenharmony_ci } 112762306a36Sopenharmony_ci} 112862306a36Sopenharmony_ci 112962306a36Sopenharmony_ci/** 113062306a36Sopenharmony_ci * vmw_translate_mob_ptr - Prepare to translate a user-space buffer handle 113162306a36Sopenharmony_ci * to a MOB id. 113262306a36Sopenharmony_ci * 113362306a36Sopenharmony_ci * @dev_priv: Pointer to a device private structure. 113462306a36Sopenharmony_ci * @sw_context: The software context used for this command batch validation. 113562306a36Sopenharmony_ci * @id: Pointer to the user-space handle to be translated. 113662306a36Sopenharmony_ci * @vmw_bo_p: Points to a location that, on successful return will carry a 113762306a36Sopenharmony_ci * non-reference-counted pointer to the buffer object identified by the 113862306a36Sopenharmony_ci * user-space handle in @id. 113962306a36Sopenharmony_ci * 114062306a36Sopenharmony_ci * This function saves information needed to translate a user-space buffer 114162306a36Sopenharmony_ci * handle to a MOB id. The translation does not take place immediately, but 114262306a36Sopenharmony_ci * during a call to vmw_apply_relocations(). 114362306a36Sopenharmony_ci * 114462306a36Sopenharmony_ci * This function builds a relocation list and a list of buffers to validate. The 114562306a36Sopenharmony_ci * former needs to be freed using either vmw_apply_relocations() or 114662306a36Sopenharmony_ci * vmw_free_relocations(). The latter needs to be freed using 114762306a36Sopenharmony_ci * vmw_clear_validations. 114862306a36Sopenharmony_ci */ 114962306a36Sopenharmony_cistatic int vmw_translate_mob_ptr(struct vmw_private *dev_priv, 115062306a36Sopenharmony_ci struct vmw_sw_context *sw_context, 115162306a36Sopenharmony_ci SVGAMobId *id, 115262306a36Sopenharmony_ci struct vmw_bo **vmw_bo_p) 115362306a36Sopenharmony_ci{ 115462306a36Sopenharmony_ci struct vmw_bo *vmw_bo, *tmp_bo; 115562306a36Sopenharmony_ci uint32_t handle = *id; 115662306a36Sopenharmony_ci struct vmw_relocation *reloc; 115762306a36Sopenharmony_ci int ret; 115862306a36Sopenharmony_ci 115962306a36Sopenharmony_ci vmw_validation_preload_bo(sw_context->ctx); 116062306a36Sopenharmony_ci ret = vmw_user_bo_lookup(sw_context->filp, handle, &vmw_bo); 116162306a36Sopenharmony_ci if (ret != 0) { 116262306a36Sopenharmony_ci drm_dbg(&dev_priv->drm, "Could not find or use MOB buffer.\n"); 116362306a36Sopenharmony_ci return PTR_ERR(vmw_bo); 116462306a36Sopenharmony_ci } 116562306a36Sopenharmony_ci vmw_bo_placement_set(vmw_bo, VMW_BO_DOMAIN_MOB, VMW_BO_DOMAIN_MOB); 116662306a36Sopenharmony_ci ret = vmw_validation_add_bo(sw_context->ctx, vmw_bo); 116762306a36Sopenharmony_ci tmp_bo = vmw_bo; 116862306a36Sopenharmony_ci vmw_user_bo_unref(&tmp_bo); 116962306a36Sopenharmony_ci if (unlikely(ret != 0)) 117062306a36Sopenharmony_ci return ret; 117162306a36Sopenharmony_ci 117262306a36Sopenharmony_ci reloc = vmw_validation_mem_alloc(sw_context->ctx, sizeof(*reloc)); 117362306a36Sopenharmony_ci if (!reloc) 117462306a36Sopenharmony_ci return -ENOMEM; 117562306a36Sopenharmony_ci 117662306a36Sopenharmony_ci reloc->mob_loc = id; 117762306a36Sopenharmony_ci reloc->vbo = vmw_bo; 117862306a36Sopenharmony_ci 117962306a36Sopenharmony_ci *vmw_bo_p = vmw_bo; 118062306a36Sopenharmony_ci list_add_tail(&reloc->head, &sw_context->bo_relocations); 118162306a36Sopenharmony_ci 118262306a36Sopenharmony_ci return 0; 118362306a36Sopenharmony_ci} 118462306a36Sopenharmony_ci 118562306a36Sopenharmony_ci/** 118662306a36Sopenharmony_ci * vmw_translate_guest_ptr - Prepare to translate a user-space buffer handle 118762306a36Sopenharmony_ci * to a valid SVGAGuestPtr 118862306a36Sopenharmony_ci * 118962306a36Sopenharmony_ci * @dev_priv: Pointer to a device private structure. 119062306a36Sopenharmony_ci * @sw_context: The software context used for this command batch validation. 119162306a36Sopenharmony_ci * @ptr: Pointer to the user-space handle to be translated. 119262306a36Sopenharmony_ci * @vmw_bo_p: Points to a location that, on successful return will carry a 119362306a36Sopenharmony_ci * non-reference-counted pointer to the DMA buffer identified by the user-space 119462306a36Sopenharmony_ci * handle in @id. 119562306a36Sopenharmony_ci * 119662306a36Sopenharmony_ci * This function saves information needed to translate a user-space buffer 119762306a36Sopenharmony_ci * handle to a valid SVGAGuestPtr. The translation does not take place 119862306a36Sopenharmony_ci * immediately, but during a call to vmw_apply_relocations(). 119962306a36Sopenharmony_ci * 120062306a36Sopenharmony_ci * This function builds a relocation list and a list of buffers to validate. 120162306a36Sopenharmony_ci * The former needs to be freed using either vmw_apply_relocations() or 120262306a36Sopenharmony_ci * vmw_free_relocations(). The latter needs to be freed using 120362306a36Sopenharmony_ci * vmw_clear_validations. 120462306a36Sopenharmony_ci */ 120562306a36Sopenharmony_cistatic int vmw_translate_guest_ptr(struct vmw_private *dev_priv, 120662306a36Sopenharmony_ci struct vmw_sw_context *sw_context, 120762306a36Sopenharmony_ci SVGAGuestPtr *ptr, 120862306a36Sopenharmony_ci struct vmw_bo **vmw_bo_p) 120962306a36Sopenharmony_ci{ 121062306a36Sopenharmony_ci struct vmw_bo *vmw_bo, *tmp_bo; 121162306a36Sopenharmony_ci uint32_t handle = ptr->gmrId; 121262306a36Sopenharmony_ci struct vmw_relocation *reloc; 121362306a36Sopenharmony_ci int ret; 121462306a36Sopenharmony_ci 121562306a36Sopenharmony_ci vmw_validation_preload_bo(sw_context->ctx); 121662306a36Sopenharmony_ci ret = vmw_user_bo_lookup(sw_context->filp, handle, &vmw_bo); 121762306a36Sopenharmony_ci if (ret != 0) { 121862306a36Sopenharmony_ci drm_dbg(&dev_priv->drm, "Could not find or use GMR region.\n"); 121962306a36Sopenharmony_ci return PTR_ERR(vmw_bo); 122062306a36Sopenharmony_ci } 122162306a36Sopenharmony_ci vmw_bo_placement_set(vmw_bo, VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM, 122262306a36Sopenharmony_ci VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM); 122362306a36Sopenharmony_ci ret = vmw_validation_add_bo(sw_context->ctx, vmw_bo); 122462306a36Sopenharmony_ci tmp_bo = vmw_bo; 122562306a36Sopenharmony_ci vmw_user_bo_unref(&tmp_bo); 122662306a36Sopenharmony_ci if (unlikely(ret != 0)) 122762306a36Sopenharmony_ci return ret; 122862306a36Sopenharmony_ci 122962306a36Sopenharmony_ci reloc = vmw_validation_mem_alloc(sw_context->ctx, sizeof(*reloc)); 123062306a36Sopenharmony_ci if (!reloc) 123162306a36Sopenharmony_ci return -ENOMEM; 123262306a36Sopenharmony_ci 123362306a36Sopenharmony_ci reloc->location = ptr; 123462306a36Sopenharmony_ci reloc->vbo = vmw_bo; 123562306a36Sopenharmony_ci *vmw_bo_p = vmw_bo; 123662306a36Sopenharmony_ci list_add_tail(&reloc->head, &sw_context->bo_relocations); 123762306a36Sopenharmony_ci 123862306a36Sopenharmony_ci return 0; 123962306a36Sopenharmony_ci} 124062306a36Sopenharmony_ci 124162306a36Sopenharmony_ci/** 124262306a36Sopenharmony_ci * vmw_cmd_dx_define_query - validate SVGA_3D_CMD_DX_DEFINE_QUERY command. 124362306a36Sopenharmony_ci * 124462306a36Sopenharmony_ci * @dev_priv: Pointer to a device private struct. 124562306a36Sopenharmony_ci * @sw_context: The software context used for this command submission. 124662306a36Sopenharmony_ci * @header: Pointer to the command header in the command stream. 124762306a36Sopenharmony_ci * 124862306a36Sopenharmony_ci * This function adds the new query into the query COTABLE 124962306a36Sopenharmony_ci */ 125062306a36Sopenharmony_cistatic int vmw_cmd_dx_define_query(struct vmw_private *dev_priv, 125162306a36Sopenharmony_ci struct vmw_sw_context *sw_context, 125262306a36Sopenharmony_ci SVGA3dCmdHeader *header) 125362306a36Sopenharmony_ci{ 125462306a36Sopenharmony_ci VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdDXDefineQuery); 125562306a36Sopenharmony_ci struct vmw_ctx_validation_info *ctx_node = VMW_GET_CTX_NODE(sw_context); 125662306a36Sopenharmony_ci struct vmw_resource *cotable_res; 125762306a36Sopenharmony_ci int ret; 125862306a36Sopenharmony_ci 125962306a36Sopenharmony_ci if (!ctx_node) 126062306a36Sopenharmony_ci return -EINVAL; 126162306a36Sopenharmony_ci 126262306a36Sopenharmony_ci cmd = container_of(header, typeof(*cmd), header); 126362306a36Sopenharmony_ci 126462306a36Sopenharmony_ci if (cmd->body.type < SVGA3D_QUERYTYPE_MIN || 126562306a36Sopenharmony_ci cmd->body.type >= SVGA3D_QUERYTYPE_MAX) 126662306a36Sopenharmony_ci return -EINVAL; 126762306a36Sopenharmony_ci 126862306a36Sopenharmony_ci cotable_res = vmw_context_cotable(ctx_node->ctx, SVGA_COTABLE_DXQUERY); 126962306a36Sopenharmony_ci if (IS_ERR_OR_NULL(cotable_res)) 127062306a36Sopenharmony_ci return cotable_res ? PTR_ERR(cotable_res) : -EINVAL; 127162306a36Sopenharmony_ci ret = vmw_cotable_notify(cotable_res, cmd->body.queryId); 127262306a36Sopenharmony_ci 127362306a36Sopenharmony_ci return ret; 127462306a36Sopenharmony_ci} 127562306a36Sopenharmony_ci 127662306a36Sopenharmony_ci/** 127762306a36Sopenharmony_ci * vmw_cmd_dx_bind_query - validate SVGA_3D_CMD_DX_BIND_QUERY command. 127862306a36Sopenharmony_ci * 127962306a36Sopenharmony_ci * @dev_priv: Pointer to a device private struct. 128062306a36Sopenharmony_ci * @sw_context: The software context used for this command submission. 128162306a36Sopenharmony_ci * @header: Pointer to the command header in the command stream. 128262306a36Sopenharmony_ci * 128362306a36Sopenharmony_ci * The query bind operation will eventually associate the query ID with its 128462306a36Sopenharmony_ci * backing MOB. In this function, we take the user mode MOB ID and use 128562306a36Sopenharmony_ci * vmw_translate_mob_ptr() to translate it to its kernel mode equivalent. 128662306a36Sopenharmony_ci */ 128762306a36Sopenharmony_cistatic int vmw_cmd_dx_bind_query(struct vmw_private *dev_priv, 128862306a36Sopenharmony_ci struct vmw_sw_context *sw_context, 128962306a36Sopenharmony_ci SVGA3dCmdHeader *header) 129062306a36Sopenharmony_ci{ 129162306a36Sopenharmony_ci VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdDXBindQuery); 129262306a36Sopenharmony_ci struct vmw_bo *vmw_bo; 129362306a36Sopenharmony_ci int ret; 129462306a36Sopenharmony_ci 129562306a36Sopenharmony_ci cmd = container_of(header, typeof(*cmd), header); 129662306a36Sopenharmony_ci 129762306a36Sopenharmony_ci /* 129862306a36Sopenharmony_ci * Look up the buffer pointed to by q.mobid, put it on the relocation 129962306a36Sopenharmony_ci * list so its kernel mode MOB ID can be filled in later 130062306a36Sopenharmony_ci */ 130162306a36Sopenharmony_ci ret = vmw_translate_mob_ptr(dev_priv, sw_context, &cmd->body.mobid, 130262306a36Sopenharmony_ci &vmw_bo); 130362306a36Sopenharmony_ci 130462306a36Sopenharmony_ci if (ret != 0) 130562306a36Sopenharmony_ci return ret; 130662306a36Sopenharmony_ci 130762306a36Sopenharmony_ci sw_context->dx_query_mob = vmw_bo; 130862306a36Sopenharmony_ci sw_context->dx_query_ctx = sw_context->dx_ctx_node->ctx; 130962306a36Sopenharmony_ci return 0; 131062306a36Sopenharmony_ci} 131162306a36Sopenharmony_ci 131262306a36Sopenharmony_ci/** 131362306a36Sopenharmony_ci * vmw_cmd_begin_gb_query - validate SVGA_3D_CMD_BEGIN_GB_QUERY command. 131462306a36Sopenharmony_ci * 131562306a36Sopenharmony_ci * @dev_priv: Pointer to a device private struct. 131662306a36Sopenharmony_ci * @sw_context: The software context used for this command submission. 131762306a36Sopenharmony_ci * @header: Pointer to the command header in the command stream. 131862306a36Sopenharmony_ci */ 131962306a36Sopenharmony_cistatic int vmw_cmd_begin_gb_query(struct vmw_private *dev_priv, 132062306a36Sopenharmony_ci struct vmw_sw_context *sw_context, 132162306a36Sopenharmony_ci SVGA3dCmdHeader *header) 132262306a36Sopenharmony_ci{ 132362306a36Sopenharmony_ci VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdBeginGBQuery) = 132462306a36Sopenharmony_ci container_of(header, typeof(*cmd), header); 132562306a36Sopenharmony_ci 132662306a36Sopenharmony_ci return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_context, 132762306a36Sopenharmony_ci VMW_RES_DIRTY_SET, user_context_converter, 132862306a36Sopenharmony_ci &cmd->body.cid, NULL); 132962306a36Sopenharmony_ci} 133062306a36Sopenharmony_ci 133162306a36Sopenharmony_ci/** 133262306a36Sopenharmony_ci * vmw_cmd_begin_query - validate SVGA_3D_CMD_BEGIN_QUERY command. 133362306a36Sopenharmony_ci * 133462306a36Sopenharmony_ci * @dev_priv: Pointer to a device private struct. 133562306a36Sopenharmony_ci * @sw_context: The software context used for this command submission. 133662306a36Sopenharmony_ci * @header: Pointer to the command header in the command stream. 133762306a36Sopenharmony_ci */ 133862306a36Sopenharmony_cistatic int vmw_cmd_begin_query(struct vmw_private *dev_priv, 133962306a36Sopenharmony_ci struct vmw_sw_context *sw_context, 134062306a36Sopenharmony_ci SVGA3dCmdHeader *header) 134162306a36Sopenharmony_ci{ 134262306a36Sopenharmony_ci VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdBeginQuery) = 134362306a36Sopenharmony_ci container_of(header, typeof(*cmd), header); 134462306a36Sopenharmony_ci 134562306a36Sopenharmony_ci if (unlikely(dev_priv->has_mob)) { 134662306a36Sopenharmony_ci VMW_DECLARE_CMD_VAR(gb_cmd, SVGA3dCmdBeginGBQuery); 134762306a36Sopenharmony_ci 134862306a36Sopenharmony_ci BUG_ON(sizeof(gb_cmd) != sizeof(*cmd)); 134962306a36Sopenharmony_ci 135062306a36Sopenharmony_ci gb_cmd.header.id = SVGA_3D_CMD_BEGIN_GB_QUERY; 135162306a36Sopenharmony_ci gb_cmd.header.size = cmd->header.size; 135262306a36Sopenharmony_ci gb_cmd.body.cid = cmd->body.cid; 135362306a36Sopenharmony_ci gb_cmd.body.type = cmd->body.type; 135462306a36Sopenharmony_ci 135562306a36Sopenharmony_ci memcpy(cmd, &gb_cmd, sizeof(*cmd)); 135662306a36Sopenharmony_ci return vmw_cmd_begin_gb_query(dev_priv, sw_context, header); 135762306a36Sopenharmony_ci } 135862306a36Sopenharmony_ci 135962306a36Sopenharmony_ci return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_context, 136062306a36Sopenharmony_ci VMW_RES_DIRTY_SET, user_context_converter, 136162306a36Sopenharmony_ci &cmd->body.cid, NULL); 136262306a36Sopenharmony_ci} 136362306a36Sopenharmony_ci 136462306a36Sopenharmony_ci/** 136562306a36Sopenharmony_ci * vmw_cmd_end_gb_query - validate SVGA_3D_CMD_END_GB_QUERY command. 136662306a36Sopenharmony_ci * 136762306a36Sopenharmony_ci * @dev_priv: Pointer to a device private struct. 136862306a36Sopenharmony_ci * @sw_context: The software context used for this command submission. 136962306a36Sopenharmony_ci * @header: Pointer to the command header in the command stream. 137062306a36Sopenharmony_ci */ 137162306a36Sopenharmony_cistatic int vmw_cmd_end_gb_query(struct vmw_private *dev_priv, 137262306a36Sopenharmony_ci struct vmw_sw_context *sw_context, 137362306a36Sopenharmony_ci SVGA3dCmdHeader *header) 137462306a36Sopenharmony_ci{ 137562306a36Sopenharmony_ci struct vmw_bo *vmw_bo; 137662306a36Sopenharmony_ci VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdEndGBQuery); 137762306a36Sopenharmony_ci int ret; 137862306a36Sopenharmony_ci 137962306a36Sopenharmony_ci cmd = container_of(header, typeof(*cmd), header); 138062306a36Sopenharmony_ci ret = vmw_cmd_cid_check(dev_priv, sw_context, header); 138162306a36Sopenharmony_ci if (unlikely(ret != 0)) 138262306a36Sopenharmony_ci return ret; 138362306a36Sopenharmony_ci 138462306a36Sopenharmony_ci ret = vmw_translate_mob_ptr(dev_priv, sw_context, &cmd->body.mobid, 138562306a36Sopenharmony_ci &vmw_bo); 138662306a36Sopenharmony_ci if (unlikely(ret != 0)) 138762306a36Sopenharmony_ci return ret; 138862306a36Sopenharmony_ci 138962306a36Sopenharmony_ci ret = vmw_query_bo_switch_prepare(dev_priv, vmw_bo, sw_context); 139062306a36Sopenharmony_ci 139162306a36Sopenharmony_ci return ret; 139262306a36Sopenharmony_ci} 139362306a36Sopenharmony_ci 139462306a36Sopenharmony_ci/** 139562306a36Sopenharmony_ci * vmw_cmd_end_query - validate SVGA_3D_CMD_END_QUERY command. 139662306a36Sopenharmony_ci * 139762306a36Sopenharmony_ci * @dev_priv: Pointer to a device private struct. 139862306a36Sopenharmony_ci * @sw_context: The software context used for this command submission. 139962306a36Sopenharmony_ci * @header: Pointer to the command header in the command stream. 140062306a36Sopenharmony_ci */ 140162306a36Sopenharmony_cistatic int vmw_cmd_end_query(struct vmw_private *dev_priv, 140262306a36Sopenharmony_ci struct vmw_sw_context *sw_context, 140362306a36Sopenharmony_ci SVGA3dCmdHeader *header) 140462306a36Sopenharmony_ci{ 140562306a36Sopenharmony_ci struct vmw_bo *vmw_bo; 140662306a36Sopenharmony_ci VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdEndQuery); 140762306a36Sopenharmony_ci int ret; 140862306a36Sopenharmony_ci 140962306a36Sopenharmony_ci cmd = container_of(header, typeof(*cmd), header); 141062306a36Sopenharmony_ci if (dev_priv->has_mob) { 141162306a36Sopenharmony_ci VMW_DECLARE_CMD_VAR(gb_cmd, SVGA3dCmdEndGBQuery); 141262306a36Sopenharmony_ci 141362306a36Sopenharmony_ci BUG_ON(sizeof(gb_cmd) != sizeof(*cmd)); 141462306a36Sopenharmony_ci 141562306a36Sopenharmony_ci gb_cmd.header.id = SVGA_3D_CMD_END_GB_QUERY; 141662306a36Sopenharmony_ci gb_cmd.header.size = cmd->header.size; 141762306a36Sopenharmony_ci gb_cmd.body.cid = cmd->body.cid; 141862306a36Sopenharmony_ci gb_cmd.body.type = cmd->body.type; 141962306a36Sopenharmony_ci gb_cmd.body.mobid = cmd->body.guestResult.gmrId; 142062306a36Sopenharmony_ci gb_cmd.body.offset = cmd->body.guestResult.offset; 142162306a36Sopenharmony_ci 142262306a36Sopenharmony_ci memcpy(cmd, &gb_cmd, sizeof(*cmd)); 142362306a36Sopenharmony_ci return vmw_cmd_end_gb_query(dev_priv, sw_context, header); 142462306a36Sopenharmony_ci } 142562306a36Sopenharmony_ci 142662306a36Sopenharmony_ci ret = vmw_cmd_cid_check(dev_priv, sw_context, header); 142762306a36Sopenharmony_ci if (unlikely(ret != 0)) 142862306a36Sopenharmony_ci return ret; 142962306a36Sopenharmony_ci 143062306a36Sopenharmony_ci ret = vmw_translate_guest_ptr(dev_priv, sw_context, 143162306a36Sopenharmony_ci &cmd->body.guestResult, &vmw_bo); 143262306a36Sopenharmony_ci if (unlikely(ret != 0)) 143362306a36Sopenharmony_ci return ret; 143462306a36Sopenharmony_ci 143562306a36Sopenharmony_ci ret = vmw_query_bo_switch_prepare(dev_priv, vmw_bo, sw_context); 143662306a36Sopenharmony_ci 143762306a36Sopenharmony_ci return ret; 143862306a36Sopenharmony_ci} 143962306a36Sopenharmony_ci 144062306a36Sopenharmony_ci/** 144162306a36Sopenharmony_ci * vmw_cmd_wait_gb_query - validate SVGA_3D_CMD_WAIT_GB_QUERY command. 144262306a36Sopenharmony_ci * 144362306a36Sopenharmony_ci * @dev_priv: Pointer to a device private struct. 144462306a36Sopenharmony_ci * @sw_context: The software context used for this command submission. 144562306a36Sopenharmony_ci * @header: Pointer to the command header in the command stream. 144662306a36Sopenharmony_ci */ 144762306a36Sopenharmony_cistatic int vmw_cmd_wait_gb_query(struct vmw_private *dev_priv, 144862306a36Sopenharmony_ci struct vmw_sw_context *sw_context, 144962306a36Sopenharmony_ci SVGA3dCmdHeader *header) 145062306a36Sopenharmony_ci{ 145162306a36Sopenharmony_ci struct vmw_bo *vmw_bo; 145262306a36Sopenharmony_ci VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdWaitForGBQuery); 145362306a36Sopenharmony_ci int ret; 145462306a36Sopenharmony_ci 145562306a36Sopenharmony_ci cmd = container_of(header, typeof(*cmd), header); 145662306a36Sopenharmony_ci ret = vmw_cmd_cid_check(dev_priv, sw_context, header); 145762306a36Sopenharmony_ci if (unlikely(ret != 0)) 145862306a36Sopenharmony_ci return ret; 145962306a36Sopenharmony_ci 146062306a36Sopenharmony_ci ret = vmw_translate_mob_ptr(dev_priv, sw_context, &cmd->body.mobid, 146162306a36Sopenharmony_ci &vmw_bo); 146262306a36Sopenharmony_ci if (unlikely(ret != 0)) 146362306a36Sopenharmony_ci return ret; 146462306a36Sopenharmony_ci 146562306a36Sopenharmony_ci return 0; 146662306a36Sopenharmony_ci} 146762306a36Sopenharmony_ci 146862306a36Sopenharmony_ci/** 146962306a36Sopenharmony_ci * vmw_cmd_wait_query - validate SVGA_3D_CMD_WAIT_QUERY command. 147062306a36Sopenharmony_ci * 147162306a36Sopenharmony_ci * @dev_priv: Pointer to a device private struct. 147262306a36Sopenharmony_ci * @sw_context: The software context used for this command submission. 147362306a36Sopenharmony_ci * @header: Pointer to the command header in the command stream. 147462306a36Sopenharmony_ci */ 147562306a36Sopenharmony_cistatic int vmw_cmd_wait_query(struct vmw_private *dev_priv, 147662306a36Sopenharmony_ci struct vmw_sw_context *sw_context, 147762306a36Sopenharmony_ci SVGA3dCmdHeader *header) 147862306a36Sopenharmony_ci{ 147962306a36Sopenharmony_ci struct vmw_bo *vmw_bo; 148062306a36Sopenharmony_ci VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdWaitForQuery); 148162306a36Sopenharmony_ci int ret; 148262306a36Sopenharmony_ci 148362306a36Sopenharmony_ci cmd = container_of(header, typeof(*cmd), header); 148462306a36Sopenharmony_ci if (dev_priv->has_mob) { 148562306a36Sopenharmony_ci VMW_DECLARE_CMD_VAR(gb_cmd, SVGA3dCmdWaitForGBQuery); 148662306a36Sopenharmony_ci 148762306a36Sopenharmony_ci BUG_ON(sizeof(gb_cmd) != sizeof(*cmd)); 148862306a36Sopenharmony_ci 148962306a36Sopenharmony_ci gb_cmd.header.id = SVGA_3D_CMD_WAIT_FOR_GB_QUERY; 149062306a36Sopenharmony_ci gb_cmd.header.size = cmd->header.size; 149162306a36Sopenharmony_ci gb_cmd.body.cid = cmd->body.cid; 149262306a36Sopenharmony_ci gb_cmd.body.type = cmd->body.type; 149362306a36Sopenharmony_ci gb_cmd.body.mobid = cmd->body.guestResult.gmrId; 149462306a36Sopenharmony_ci gb_cmd.body.offset = cmd->body.guestResult.offset; 149562306a36Sopenharmony_ci 149662306a36Sopenharmony_ci memcpy(cmd, &gb_cmd, sizeof(*cmd)); 149762306a36Sopenharmony_ci return vmw_cmd_wait_gb_query(dev_priv, sw_context, header); 149862306a36Sopenharmony_ci } 149962306a36Sopenharmony_ci 150062306a36Sopenharmony_ci ret = vmw_cmd_cid_check(dev_priv, sw_context, header); 150162306a36Sopenharmony_ci if (unlikely(ret != 0)) 150262306a36Sopenharmony_ci return ret; 150362306a36Sopenharmony_ci 150462306a36Sopenharmony_ci ret = vmw_translate_guest_ptr(dev_priv, sw_context, 150562306a36Sopenharmony_ci &cmd->body.guestResult, &vmw_bo); 150662306a36Sopenharmony_ci if (unlikely(ret != 0)) 150762306a36Sopenharmony_ci return ret; 150862306a36Sopenharmony_ci 150962306a36Sopenharmony_ci return 0; 151062306a36Sopenharmony_ci} 151162306a36Sopenharmony_ci 151262306a36Sopenharmony_cistatic int vmw_cmd_dma(struct vmw_private *dev_priv, 151362306a36Sopenharmony_ci struct vmw_sw_context *sw_context, 151462306a36Sopenharmony_ci SVGA3dCmdHeader *header) 151562306a36Sopenharmony_ci{ 151662306a36Sopenharmony_ci struct vmw_bo *vmw_bo = NULL; 151762306a36Sopenharmony_ci struct vmw_surface *srf = NULL; 151862306a36Sopenharmony_ci VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdSurfaceDMA); 151962306a36Sopenharmony_ci int ret; 152062306a36Sopenharmony_ci SVGA3dCmdSurfaceDMASuffix *suffix; 152162306a36Sopenharmony_ci uint32_t bo_size; 152262306a36Sopenharmony_ci bool dirty; 152362306a36Sopenharmony_ci 152462306a36Sopenharmony_ci cmd = container_of(header, typeof(*cmd), header); 152562306a36Sopenharmony_ci suffix = (SVGA3dCmdSurfaceDMASuffix *)((unsigned long) &cmd->body + 152662306a36Sopenharmony_ci header->size - sizeof(*suffix)); 152762306a36Sopenharmony_ci 152862306a36Sopenharmony_ci /* Make sure device and verifier stays in sync. */ 152962306a36Sopenharmony_ci if (unlikely(suffix->suffixSize != sizeof(*suffix))) { 153062306a36Sopenharmony_ci VMW_DEBUG_USER("Invalid DMA suffix size.\n"); 153162306a36Sopenharmony_ci return -EINVAL; 153262306a36Sopenharmony_ci } 153362306a36Sopenharmony_ci 153462306a36Sopenharmony_ci ret = vmw_translate_guest_ptr(dev_priv, sw_context, 153562306a36Sopenharmony_ci &cmd->body.guest.ptr, &vmw_bo); 153662306a36Sopenharmony_ci if (unlikely(ret != 0)) 153762306a36Sopenharmony_ci return ret; 153862306a36Sopenharmony_ci 153962306a36Sopenharmony_ci /* Make sure DMA doesn't cross BO boundaries. */ 154062306a36Sopenharmony_ci bo_size = vmw_bo->tbo.base.size; 154162306a36Sopenharmony_ci if (unlikely(cmd->body.guest.ptr.offset > bo_size)) { 154262306a36Sopenharmony_ci VMW_DEBUG_USER("Invalid DMA offset.\n"); 154362306a36Sopenharmony_ci return -EINVAL; 154462306a36Sopenharmony_ci } 154562306a36Sopenharmony_ci 154662306a36Sopenharmony_ci bo_size -= cmd->body.guest.ptr.offset; 154762306a36Sopenharmony_ci if (unlikely(suffix->maximumOffset > bo_size)) 154862306a36Sopenharmony_ci suffix->maximumOffset = bo_size; 154962306a36Sopenharmony_ci 155062306a36Sopenharmony_ci dirty = (cmd->body.transfer == SVGA3D_WRITE_HOST_VRAM) ? 155162306a36Sopenharmony_ci VMW_RES_DIRTY_SET : 0; 155262306a36Sopenharmony_ci ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface, 155362306a36Sopenharmony_ci dirty, user_surface_converter, 155462306a36Sopenharmony_ci &cmd->body.host.sid, NULL); 155562306a36Sopenharmony_ci if (unlikely(ret != 0)) { 155662306a36Sopenharmony_ci if (unlikely(ret != -ERESTARTSYS)) 155762306a36Sopenharmony_ci VMW_DEBUG_USER("could not find surface for DMA.\n"); 155862306a36Sopenharmony_ci return ret; 155962306a36Sopenharmony_ci } 156062306a36Sopenharmony_ci 156162306a36Sopenharmony_ci srf = vmw_res_to_srf(sw_context->res_cache[vmw_res_surface].res); 156262306a36Sopenharmony_ci 156362306a36Sopenharmony_ci vmw_kms_cursor_snoop(srf, sw_context->fp->tfile, &vmw_bo->tbo, header); 156462306a36Sopenharmony_ci 156562306a36Sopenharmony_ci return 0; 156662306a36Sopenharmony_ci} 156762306a36Sopenharmony_ci 156862306a36Sopenharmony_cistatic int vmw_cmd_draw(struct vmw_private *dev_priv, 156962306a36Sopenharmony_ci struct vmw_sw_context *sw_context, 157062306a36Sopenharmony_ci SVGA3dCmdHeader *header) 157162306a36Sopenharmony_ci{ 157262306a36Sopenharmony_ci VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdDrawPrimitives); 157362306a36Sopenharmony_ci SVGA3dVertexDecl *decl = (SVGA3dVertexDecl *)( 157462306a36Sopenharmony_ci (unsigned long)header + sizeof(*cmd)); 157562306a36Sopenharmony_ci SVGA3dPrimitiveRange *range; 157662306a36Sopenharmony_ci uint32_t i; 157762306a36Sopenharmony_ci uint32_t maxnum; 157862306a36Sopenharmony_ci int ret; 157962306a36Sopenharmony_ci 158062306a36Sopenharmony_ci ret = vmw_cmd_cid_check(dev_priv, sw_context, header); 158162306a36Sopenharmony_ci if (unlikely(ret != 0)) 158262306a36Sopenharmony_ci return ret; 158362306a36Sopenharmony_ci 158462306a36Sopenharmony_ci cmd = container_of(header, typeof(*cmd), header); 158562306a36Sopenharmony_ci maxnum = (header->size - sizeof(cmd->body)) / sizeof(*decl); 158662306a36Sopenharmony_ci 158762306a36Sopenharmony_ci if (unlikely(cmd->body.numVertexDecls > maxnum)) { 158862306a36Sopenharmony_ci VMW_DEBUG_USER("Illegal number of vertex declarations.\n"); 158962306a36Sopenharmony_ci return -EINVAL; 159062306a36Sopenharmony_ci } 159162306a36Sopenharmony_ci 159262306a36Sopenharmony_ci for (i = 0; i < cmd->body.numVertexDecls; ++i, ++decl) { 159362306a36Sopenharmony_ci ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface, 159462306a36Sopenharmony_ci VMW_RES_DIRTY_NONE, 159562306a36Sopenharmony_ci user_surface_converter, 159662306a36Sopenharmony_ci &decl->array.surfaceId, NULL); 159762306a36Sopenharmony_ci if (unlikely(ret != 0)) 159862306a36Sopenharmony_ci return ret; 159962306a36Sopenharmony_ci } 160062306a36Sopenharmony_ci 160162306a36Sopenharmony_ci maxnum = (header->size - sizeof(cmd->body) - 160262306a36Sopenharmony_ci cmd->body.numVertexDecls * sizeof(*decl)) / sizeof(*range); 160362306a36Sopenharmony_ci if (unlikely(cmd->body.numRanges > maxnum)) { 160462306a36Sopenharmony_ci VMW_DEBUG_USER("Illegal number of index ranges.\n"); 160562306a36Sopenharmony_ci return -EINVAL; 160662306a36Sopenharmony_ci } 160762306a36Sopenharmony_ci 160862306a36Sopenharmony_ci range = (SVGA3dPrimitiveRange *) decl; 160962306a36Sopenharmony_ci for (i = 0; i < cmd->body.numRanges; ++i, ++range) { 161062306a36Sopenharmony_ci ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface, 161162306a36Sopenharmony_ci VMW_RES_DIRTY_NONE, 161262306a36Sopenharmony_ci user_surface_converter, 161362306a36Sopenharmony_ci &range->indexArray.surfaceId, NULL); 161462306a36Sopenharmony_ci if (unlikely(ret != 0)) 161562306a36Sopenharmony_ci return ret; 161662306a36Sopenharmony_ci } 161762306a36Sopenharmony_ci return 0; 161862306a36Sopenharmony_ci} 161962306a36Sopenharmony_ci 162062306a36Sopenharmony_cistatic int vmw_cmd_tex_state(struct vmw_private *dev_priv, 162162306a36Sopenharmony_ci struct vmw_sw_context *sw_context, 162262306a36Sopenharmony_ci SVGA3dCmdHeader *header) 162362306a36Sopenharmony_ci{ 162462306a36Sopenharmony_ci VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdSetTextureState); 162562306a36Sopenharmony_ci SVGA3dTextureState *last_state = (SVGA3dTextureState *) 162662306a36Sopenharmony_ci ((unsigned long) header + header->size + sizeof(*header)); 162762306a36Sopenharmony_ci SVGA3dTextureState *cur_state = (SVGA3dTextureState *) 162862306a36Sopenharmony_ci ((unsigned long) header + sizeof(*cmd)); 162962306a36Sopenharmony_ci struct vmw_resource *ctx; 163062306a36Sopenharmony_ci struct vmw_resource *res; 163162306a36Sopenharmony_ci int ret; 163262306a36Sopenharmony_ci 163362306a36Sopenharmony_ci cmd = container_of(header, typeof(*cmd), header); 163462306a36Sopenharmony_ci 163562306a36Sopenharmony_ci ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_context, 163662306a36Sopenharmony_ci VMW_RES_DIRTY_SET, user_context_converter, 163762306a36Sopenharmony_ci &cmd->body.cid, &ctx); 163862306a36Sopenharmony_ci if (unlikely(ret != 0)) 163962306a36Sopenharmony_ci return ret; 164062306a36Sopenharmony_ci 164162306a36Sopenharmony_ci for (; cur_state < last_state; ++cur_state) { 164262306a36Sopenharmony_ci if (likely(cur_state->name != SVGA3D_TS_BIND_TEXTURE)) 164362306a36Sopenharmony_ci continue; 164462306a36Sopenharmony_ci 164562306a36Sopenharmony_ci if (cur_state->stage >= SVGA3D_NUM_TEXTURE_UNITS) { 164662306a36Sopenharmony_ci VMW_DEBUG_USER("Illegal texture/sampler unit %u.\n", 164762306a36Sopenharmony_ci (unsigned int) cur_state->stage); 164862306a36Sopenharmony_ci return -EINVAL; 164962306a36Sopenharmony_ci } 165062306a36Sopenharmony_ci 165162306a36Sopenharmony_ci ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface, 165262306a36Sopenharmony_ci VMW_RES_DIRTY_NONE, 165362306a36Sopenharmony_ci user_surface_converter, 165462306a36Sopenharmony_ci &cur_state->value, &res); 165562306a36Sopenharmony_ci if (unlikely(ret != 0)) 165662306a36Sopenharmony_ci return ret; 165762306a36Sopenharmony_ci 165862306a36Sopenharmony_ci if (dev_priv->has_mob) { 165962306a36Sopenharmony_ci struct vmw_ctx_bindinfo_tex binding; 166062306a36Sopenharmony_ci struct vmw_ctx_validation_info *node; 166162306a36Sopenharmony_ci 166262306a36Sopenharmony_ci node = vmw_execbuf_info_from_res(sw_context, ctx); 166362306a36Sopenharmony_ci if (!node) 166462306a36Sopenharmony_ci return -EINVAL; 166562306a36Sopenharmony_ci 166662306a36Sopenharmony_ci binding.bi.ctx = ctx; 166762306a36Sopenharmony_ci binding.bi.res = res; 166862306a36Sopenharmony_ci binding.bi.bt = vmw_ctx_binding_tex; 166962306a36Sopenharmony_ci binding.texture_stage = cur_state->stage; 167062306a36Sopenharmony_ci vmw_binding_add(node->staged, &binding.bi, 0, 167162306a36Sopenharmony_ci binding.texture_stage); 167262306a36Sopenharmony_ci } 167362306a36Sopenharmony_ci } 167462306a36Sopenharmony_ci 167562306a36Sopenharmony_ci return 0; 167662306a36Sopenharmony_ci} 167762306a36Sopenharmony_ci 167862306a36Sopenharmony_cistatic int vmw_cmd_check_define_gmrfb(struct vmw_private *dev_priv, 167962306a36Sopenharmony_ci struct vmw_sw_context *sw_context, 168062306a36Sopenharmony_ci void *buf) 168162306a36Sopenharmony_ci{ 168262306a36Sopenharmony_ci struct vmw_bo *vmw_bo; 168362306a36Sopenharmony_ci 168462306a36Sopenharmony_ci struct { 168562306a36Sopenharmony_ci uint32_t header; 168662306a36Sopenharmony_ci SVGAFifoCmdDefineGMRFB body; 168762306a36Sopenharmony_ci } *cmd = buf; 168862306a36Sopenharmony_ci 168962306a36Sopenharmony_ci return vmw_translate_guest_ptr(dev_priv, sw_context, &cmd->body.ptr, 169062306a36Sopenharmony_ci &vmw_bo); 169162306a36Sopenharmony_ci} 169262306a36Sopenharmony_ci 169362306a36Sopenharmony_ci/** 169462306a36Sopenharmony_ci * vmw_cmd_res_switch_backup - Utility function to handle backup buffer 169562306a36Sopenharmony_ci * switching 169662306a36Sopenharmony_ci * 169762306a36Sopenharmony_ci * @dev_priv: Pointer to a device private struct. 169862306a36Sopenharmony_ci * @sw_context: The software context being used for this batch. 169962306a36Sopenharmony_ci * @res: Pointer to the resource. 170062306a36Sopenharmony_ci * @buf_id: Pointer to the user-space backup buffer handle in the command 170162306a36Sopenharmony_ci * stream. 170262306a36Sopenharmony_ci * @backup_offset: Offset of backup into MOB. 170362306a36Sopenharmony_ci * 170462306a36Sopenharmony_ci * This function prepares for registering a switch of backup buffers in the 170562306a36Sopenharmony_ci * resource metadata just prior to unreserving. It's basically a wrapper around 170662306a36Sopenharmony_ci * vmw_cmd_res_switch_backup with a different interface. 170762306a36Sopenharmony_ci */ 170862306a36Sopenharmony_cistatic int vmw_cmd_res_switch_backup(struct vmw_private *dev_priv, 170962306a36Sopenharmony_ci struct vmw_sw_context *sw_context, 171062306a36Sopenharmony_ci struct vmw_resource *res, uint32_t *buf_id, 171162306a36Sopenharmony_ci unsigned long backup_offset) 171262306a36Sopenharmony_ci{ 171362306a36Sopenharmony_ci struct vmw_bo *vbo; 171462306a36Sopenharmony_ci void *info; 171562306a36Sopenharmony_ci int ret; 171662306a36Sopenharmony_ci 171762306a36Sopenharmony_ci info = vmw_execbuf_info_from_res(sw_context, res); 171862306a36Sopenharmony_ci if (!info) 171962306a36Sopenharmony_ci return -EINVAL; 172062306a36Sopenharmony_ci 172162306a36Sopenharmony_ci ret = vmw_translate_mob_ptr(dev_priv, sw_context, buf_id, &vbo); 172262306a36Sopenharmony_ci if (ret) 172362306a36Sopenharmony_ci return ret; 172462306a36Sopenharmony_ci 172562306a36Sopenharmony_ci vmw_validation_res_switch_backup(sw_context->ctx, info, vbo, 172662306a36Sopenharmony_ci backup_offset); 172762306a36Sopenharmony_ci return 0; 172862306a36Sopenharmony_ci} 172962306a36Sopenharmony_ci 173062306a36Sopenharmony_ci/** 173162306a36Sopenharmony_ci * vmw_cmd_switch_backup - Utility function to handle backup buffer switching 173262306a36Sopenharmony_ci * 173362306a36Sopenharmony_ci * @dev_priv: Pointer to a device private struct. 173462306a36Sopenharmony_ci * @sw_context: The software context being used for this batch. 173562306a36Sopenharmony_ci * @res_type: The resource type. 173662306a36Sopenharmony_ci * @converter: Information about user-space binding for this resource type. 173762306a36Sopenharmony_ci * @res_id: Pointer to the user-space resource handle in the command stream. 173862306a36Sopenharmony_ci * @buf_id: Pointer to the user-space backup buffer handle in the command 173962306a36Sopenharmony_ci * stream. 174062306a36Sopenharmony_ci * @backup_offset: Offset of backup into MOB. 174162306a36Sopenharmony_ci * 174262306a36Sopenharmony_ci * This function prepares for registering a switch of backup buffers in the 174362306a36Sopenharmony_ci * resource metadata just prior to unreserving. It's basically a wrapper around 174462306a36Sopenharmony_ci * vmw_cmd_res_switch_backup with a different interface. 174562306a36Sopenharmony_ci */ 174662306a36Sopenharmony_cistatic int vmw_cmd_switch_backup(struct vmw_private *dev_priv, 174762306a36Sopenharmony_ci struct vmw_sw_context *sw_context, 174862306a36Sopenharmony_ci enum vmw_res_type res_type, 174962306a36Sopenharmony_ci const struct vmw_user_resource_conv 175062306a36Sopenharmony_ci *converter, uint32_t *res_id, uint32_t *buf_id, 175162306a36Sopenharmony_ci unsigned long backup_offset) 175262306a36Sopenharmony_ci{ 175362306a36Sopenharmony_ci struct vmw_resource *res; 175462306a36Sopenharmony_ci int ret; 175562306a36Sopenharmony_ci 175662306a36Sopenharmony_ci ret = vmw_cmd_res_check(dev_priv, sw_context, res_type, 175762306a36Sopenharmony_ci VMW_RES_DIRTY_NONE, converter, res_id, &res); 175862306a36Sopenharmony_ci if (ret) 175962306a36Sopenharmony_ci return ret; 176062306a36Sopenharmony_ci 176162306a36Sopenharmony_ci return vmw_cmd_res_switch_backup(dev_priv, sw_context, res, buf_id, 176262306a36Sopenharmony_ci backup_offset); 176362306a36Sopenharmony_ci} 176462306a36Sopenharmony_ci 176562306a36Sopenharmony_ci/** 176662306a36Sopenharmony_ci * vmw_cmd_bind_gb_surface - Validate SVGA_3D_CMD_BIND_GB_SURFACE command 176762306a36Sopenharmony_ci * 176862306a36Sopenharmony_ci * @dev_priv: Pointer to a device private struct. 176962306a36Sopenharmony_ci * @sw_context: The software context being used for this batch. 177062306a36Sopenharmony_ci * @header: Pointer to the command header in the command stream. 177162306a36Sopenharmony_ci */ 177262306a36Sopenharmony_cistatic int vmw_cmd_bind_gb_surface(struct vmw_private *dev_priv, 177362306a36Sopenharmony_ci struct vmw_sw_context *sw_context, 177462306a36Sopenharmony_ci SVGA3dCmdHeader *header) 177562306a36Sopenharmony_ci{ 177662306a36Sopenharmony_ci VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdBindGBSurface) = 177762306a36Sopenharmony_ci container_of(header, typeof(*cmd), header); 177862306a36Sopenharmony_ci 177962306a36Sopenharmony_ci return vmw_cmd_switch_backup(dev_priv, sw_context, vmw_res_surface, 178062306a36Sopenharmony_ci user_surface_converter, &cmd->body.sid, 178162306a36Sopenharmony_ci &cmd->body.mobid, 0); 178262306a36Sopenharmony_ci} 178362306a36Sopenharmony_ci 178462306a36Sopenharmony_ci/** 178562306a36Sopenharmony_ci * vmw_cmd_update_gb_image - Validate SVGA_3D_CMD_UPDATE_GB_IMAGE command 178662306a36Sopenharmony_ci * 178762306a36Sopenharmony_ci * @dev_priv: Pointer to a device private struct. 178862306a36Sopenharmony_ci * @sw_context: The software context being used for this batch. 178962306a36Sopenharmony_ci * @header: Pointer to the command header in the command stream. 179062306a36Sopenharmony_ci */ 179162306a36Sopenharmony_cistatic int vmw_cmd_update_gb_image(struct vmw_private *dev_priv, 179262306a36Sopenharmony_ci struct vmw_sw_context *sw_context, 179362306a36Sopenharmony_ci SVGA3dCmdHeader *header) 179462306a36Sopenharmony_ci{ 179562306a36Sopenharmony_ci VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdUpdateGBImage) = 179662306a36Sopenharmony_ci container_of(header, typeof(*cmd), header); 179762306a36Sopenharmony_ci 179862306a36Sopenharmony_ci return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface, 179962306a36Sopenharmony_ci VMW_RES_DIRTY_NONE, user_surface_converter, 180062306a36Sopenharmony_ci &cmd->body.image.sid, NULL); 180162306a36Sopenharmony_ci} 180262306a36Sopenharmony_ci 180362306a36Sopenharmony_ci/** 180462306a36Sopenharmony_ci * vmw_cmd_update_gb_surface - Validate SVGA_3D_CMD_UPDATE_GB_SURFACE command 180562306a36Sopenharmony_ci * 180662306a36Sopenharmony_ci * @dev_priv: Pointer to a device private struct. 180762306a36Sopenharmony_ci * @sw_context: The software context being used for this batch. 180862306a36Sopenharmony_ci * @header: Pointer to the command header in the command stream. 180962306a36Sopenharmony_ci */ 181062306a36Sopenharmony_cistatic int vmw_cmd_update_gb_surface(struct vmw_private *dev_priv, 181162306a36Sopenharmony_ci struct vmw_sw_context *sw_context, 181262306a36Sopenharmony_ci SVGA3dCmdHeader *header) 181362306a36Sopenharmony_ci{ 181462306a36Sopenharmony_ci VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdUpdateGBSurface) = 181562306a36Sopenharmony_ci container_of(header, typeof(*cmd), header); 181662306a36Sopenharmony_ci 181762306a36Sopenharmony_ci return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface, 181862306a36Sopenharmony_ci VMW_RES_DIRTY_CLEAR, user_surface_converter, 181962306a36Sopenharmony_ci &cmd->body.sid, NULL); 182062306a36Sopenharmony_ci} 182162306a36Sopenharmony_ci 182262306a36Sopenharmony_ci/** 182362306a36Sopenharmony_ci * vmw_cmd_readback_gb_image - Validate SVGA_3D_CMD_READBACK_GB_IMAGE command 182462306a36Sopenharmony_ci * 182562306a36Sopenharmony_ci * @dev_priv: Pointer to a device private struct. 182662306a36Sopenharmony_ci * @sw_context: The software context being used for this batch. 182762306a36Sopenharmony_ci * @header: Pointer to the command header in the command stream. 182862306a36Sopenharmony_ci */ 182962306a36Sopenharmony_cistatic int vmw_cmd_readback_gb_image(struct vmw_private *dev_priv, 183062306a36Sopenharmony_ci struct vmw_sw_context *sw_context, 183162306a36Sopenharmony_ci SVGA3dCmdHeader *header) 183262306a36Sopenharmony_ci{ 183362306a36Sopenharmony_ci VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdReadbackGBImage) = 183462306a36Sopenharmony_ci container_of(header, typeof(*cmd), header); 183562306a36Sopenharmony_ci 183662306a36Sopenharmony_ci return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface, 183762306a36Sopenharmony_ci VMW_RES_DIRTY_NONE, user_surface_converter, 183862306a36Sopenharmony_ci &cmd->body.image.sid, NULL); 183962306a36Sopenharmony_ci} 184062306a36Sopenharmony_ci 184162306a36Sopenharmony_ci/** 184262306a36Sopenharmony_ci * vmw_cmd_readback_gb_surface - Validate SVGA_3D_CMD_READBACK_GB_SURFACE 184362306a36Sopenharmony_ci * command 184462306a36Sopenharmony_ci * 184562306a36Sopenharmony_ci * @dev_priv: Pointer to a device private struct. 184662306a36Sopenharmony_ci * @sw_context: The software context being used for this batch. 184762306a36Sopenharmony_ci * @header: Pointer to the command header in the command stream. 184862306a36Sopenharmony_ci */ 184962306a36Sopenharmony_cistatic int vmw_cmd_readback_gb_surface(struct vmw_private *dev_priv, 185062306a36Sopenharmony_ci struct vmw_sw_context *sw_context, 185162306a36Sopenharmony_ci SVGA3dCmdHeader *header) 185262306a36Sopenharmony_ci{ 185362306a36Sopenharmony_ci VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdReadbackGBSurface) = 185462306a36Sopenharmony_ci container_of(header, typeof(*cmd), header); 185562306a36Sopenharmony_ci 185662306a36Sopenharmony_ci return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface, 185762306a36Sopenharmony_ci VMW_RES_DIRTY_CLEAR, user_surface_converter, 185862306a36Sopenharmony_ci &cmd->body.sid, NULL); 185962306a36Sopenharmony_ci} 186062306a36Sopenharmony_ci 186162306a36Sopenharmony_ci/** 186262306a36Sopenharmony_ci * vmw_cmd_invalidate_gb_image - Validate SVGA_3D_CMD_INVALIDATE_GB_IMAGE 186362306a36Sopenharmony_ci * command 186462306a36Sopenharmony_ci * 186562306a36Sopenharmony_ci * @dev_priv: Pointer to a device private struct. 186662306a36Sopenharmony_ci * @sw_context: The software context being used for this batch. 186762306a36Sopenharmony_ci * @header: Pointer to the command header in the command stream. 186862306a36Sopenharmony_ci */ 186962306a36Sopenharmony_cistatic int vmw_cmd_invalidate_gb_image(struct vmw_private *dev_priv, 187062306a36Sopenharmony_ci struct vmw_sw_context *sw_context, 187162306a36Sopenharmony_ci SVGA3dCmdHeader *header) 187262306a36Sopenharmony_ci{ 187362306a36Sopenharmony_ci VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdInvalidateGBImage) = 187462306a36Sopenharmony_ci container_of(header, typeof(*cmd), header); 187562306a36Sopenharmony_ci 187662306a36Sopenharmony_ci return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface, 187762306a36Sopenharmony_ci VMW_RES_DIRTY_NONE, user_surface_converter, 187862306a36Sopenharmony_ci &cmd->body.image.sid, NULL); 187962306a36Sopenharmony_ci} 188062306a36Sopenharmony_ci 188162306a36Sopenharmony_ci/** 188262306a36Sopenharmony_ci * vmw_cmd_invalidate_gb_surface - Validate SVGA_3D_CMD_INVALIDATE_GB_SURFACE 188362306a36Sopenharmony_ci * command 188462306a36Sopenharmony_ci * 188562306a36Sopenharmony_ci * @dev_priv: Pointer to a device private struct. 188662306a36Sopenharmony_ci * @sw_context: The software context being used for this batch. 188762306a36Sopenharmony_ci * @header: Pointer to the command header in the command stream. 188862306a36Sopenharmony_ci */ 188962306a36Sopenharmony_cistatic int vmw_cmd_invalidate_gb_surface(struct vmw_private *dev_priv, 189062306a36Sopenharmony_ci struct vmw_sw_context *sw_context, 189162306a36Sopenharmony_ci SVGA3dCmdHeader *header) 189262306a36Sopenharmony_ci{ 189362306a36Sopenharmony_ci VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdInvalidateGBSurface) = 189462306a36Sopenharmony_ci container_of(header, typeof(*cmd), header); 189562306a36Sopenharmony_ci 189662306a36Sopenharmony_ci return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface, 189762306a36Sopenharmony_ci VMW_RES_DIRTY_CLEAR, user_surface_converter, 189862306a36Sopenharmony_ci &cmd->body.sid, NULL); 189962306a36Sopenharmony_ci} 190062306a36Sopenharmony_ci 190162306a36Sopenharmony_ci/** 190262306a36Sopenharmony_ci * vmw_cmd_shader_define - Validate SVGA_3D_CMD_SHADER_DEFINE command 190362306a36Sopenharmony_ci * 190462306a36Sopenharmony_ci * @dev_priv: Pointer to a device private struct. 190562306a36Sopenharmony_ci * @sw_context: The software context being used for this batch. 190662306a36Sopenharmony_ci * @header: Pointer to the command header in the command stream. 190762306a36Sopenharmony_ci */ 190862306a36Sopenharmony_cistatic int vmw_cmd_shader_define(struct vmw_private *dev_priv, 190962306a36Sopenharmony_ci struct vmw_sw_context *sw_context, 191062306a36Sopenharmony_ci SVGA3dCmdHeader *header) 191162306a36Sopenharmony_ci{ 191262306a36Sopenharmony_ci VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdDefineShader); 191362306a36Sopenharmony_ci int ret; 191462306a36Sopenharmony_ci size_t size; 191562306a36Sopenharmony_ci struct vmw_resource *ctx; 191662306a36Sopenharmony_ci 191762306a36Sopenharmony_ci cmd = container_of(header, typeof(*cmd), header); 191862306a36Sopenharmony_ci 191962306a36Sopenharmony_ci ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_context, 192062306a36Sopenharmony_ci VMW_RES_DIRTY_SET, user_context_converter, 192162306a36Sopenharmony_ci &cmd->body.cid, &ctx); 192262306a36Sopenharmony_ci if (unlikely(ret != 0)) 192362306a36Sopenharmony_ci return ret; 192462306a36Sopenharmony_ci 192562306a36Sopenharmony_ci if (unlikely(!dev_priv->has_mob)) 192662306a36Sopenharmony_ci return 0; 192762306a36Sopenharmony_ci 192862306a36Sopenharmony_ci size = cmd->header.size - sizeof(cmd->body); 192962306a36Sopenharmony_ci ret = vmw_compat_shader_add(dev_priv, vmw_context_res_man(ctx), 193062306a36Sopenharmony_ci cmd->body.shid, cmd + 1, cmd->body.type, 193162306a36Sopenharmony_ci size, &sw_context->staged_cmd_res); 193262306a36Sopenharmony_ci if (unlikely(ret != 0)) 193362306a36Sopenharmony_ci return ret; 193462306a36Sopenharmony_ci 193562306a36Sopenharmony_ci return vmw_resource_relocation_add(sw_context, NULL, 193662306a36Sopenharmony_ci vmw_ptr_diff(sw_context->buf_start, 193762306a36Sopenharmony_ci &cmd->header.id), 193862306a36Sopenharmony_ci vmw_res_rel_nop); 193962306a36Sopenharmony_ci} 194062306a36Sopenharmony_ci 194162306a36Sopenharmony_ci/** 194262306a36Sopenharmony_ci * vmw_cmd_shader_destroy - Validate SVGA_3D_CMD_SHADER_DESTROY command 194362306a36Sopenharmony_ci * 194462306a36Sopenharmony_ci * @dev_priv: Pointer to a device private struct. 194562306a36Sopenharmony_ci * @sw_context: The software context being used for this batch. 194662306a36Sopenharmony_ci * @header: Pointer to the command header in the command stream. 194762306a36Sopenharmony_ci */ 194862306a36Sopenharmony_cistatic int vmw_cmd_shader_destroy(struct vmw_private *dev_priv, 194962306a36Sopenharmony_ci struct vmw_sw_context *sw_context, 195062306a36Sopenharmony_ci SVGA3dCmdHeader *header) 195162306a36Sopenharmony_ci{ 195262306a36Sopenharmony_ci VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdDestroyShader); 195362306a36Sopenharmony_ci int ret; 195462306a36Sopenharmony_ci struct vmw_resource *ctx; 195562306a36Sopenharmony_ci 195662306a36Sopenharmony_ci cmd = container_of(header, typeof(*cmd), header); 195762306a36Sopenharmony_ci 195862306a36Sopenharmony_ci ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_context, 195962306a36Sopenharmony_ci VMW_RES_DIRTY_SET, user_context_converter, 196062306a36Sopenharmony_ci &cmd->body.cid, &ctx); 196162306a36Sopenharmony_ci if (unlikely(ret != 0)) 196262306a36Sopenharmony_ci return ret; 196362306a36Sopenharmony_ci 196462306a36Sopenharmony_ci if (unlikely(!dev_priv->has_mob)) 196562306a36Sopenharmony_ci return 0; 196662306a36Sopenharmony_ci 196762306a36Sopenharmony_ci ret = vmw_shader_remove(vmw_context_res_man(ctx), cmd->body.shid, 196862306a36Sopenharmony_ci cmd->body.type, &sw_context->staged_cmd_res); 196962306a36Sopenharmony_ci if (unlikely(ret != 0)) 197062306a36Sopenharmony_ci return ret; 197162306a36Sopenharmony_ci 197262306a36Sopenharmony_ci return vmw_resource_relocation_add(sw_context, NULL, 197362306a36Sopenharmony_ci vmw_ptr_diff(sw_context->buf_start, 197462306a36Sopenharmony_ci &cmd->header.id), 197562306a36Sopenharmony_ci vmw_res_rel_nop); 197662306a36Sopenharmony_ci} 197762306a36Sopenharmony_ci 197862306a36Sopenharmony_ci/** 197962306a36Sopenharmony_ci * vmw_cmd_set_shader - Validate SVGA_3D_CMD_SET_SHADER command 198062306a36Sopenharmony_ci * 198162306a36Sopenharmony_ci * @dev_priv: Pointer to a device private struct. 198262306a36Sopenharmony_ci * @sw_context: The software context being used for this batch. 198362306a36Sopenharmony_ci * @header: Pointer to the command header in the command stream. 198462306a36Sopenharmony_ci */ 198562306a36Sopenharmony_cistatic int vmw_cmd_set_shader(struct vmw_private *dev_priv, 198662306a36Sopenharmony_ci struct vmw_sw_context *sw_context, 198762306a36Sopenharmony_ci SVGA3dCmdHeader *header) 198862306a36Sopenharmony_ci{ 198962306a36Sopenharmony_ci VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdSetShader); 199062306a36Sopenharmony_ci struct vmw_ctx_bindinfo_shader binding; 199162306a36Sopenharmony_ci struct vmw_resource *ctx, *res = NULL; 199262306a36Sopenharmony_ci struct vmw_ctx_validation_info *ctx_info; 199362306a36Sopenharmony_ci int ret; 199462306a36Sopenharmony_ci 199562306a36Sopenharmony_ci cmd = container_of(header, typeof(*cmd), header); 199662306a36Sopenharmony_ci 199762306a36Sopenharmony_ci if (!vmw_shadertype_is_valid(VMW_SM_LEGACY, cmd->body.type)) { 199862306a36Sopenharmony_ci VMW_DEBUG_USER("Illegal shader type %u.\n", 199962306a36Sopenharmony_ci (unsigned int) cmd->body.type); 200062306a36Sopenharmony_ci return -EINVAL; 200162306a36Sopenharmony_ci } 200262306a36Sopenharmony_ci 200362306a36Sopenharmony_ci ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_context, 200462306a36Sopenharmony_ci VMW_RES_DIRTY_SET, user_context_converter, 200562306a36Sopenharmony_ci &cmd->body.cid, &ctx); 200662306a36Sopenharmony_ci if (unlikely(ret != 0)) 200762306a36Sopenharmony_ci return ret; 200862306a36Sopenharmony_ci 200962306a36Sopenharmony_ci if (!dev_priv->has_mob) 201062306a36Sopenharmony_ci return 0; 201162306a36Sopenharmony_ci 201262306a36Sopenharmony_ci if (cmd->body.shid != SVGA3D_INVALID_ID) { 201362306a36Sopenharmony_ci /* 201462306a36Sopenharmony_ci * This is the compat shader path - Per device guest-backed 201562306a36Sopenharmony_ci * shaders, but user-space thinks it's per context host- 201662306a36Sopenharmony_ci * backed shaders. 201762306a36Sopenharmony_ci */ 201862306a36Sopenharmony_ci res = vmw_shader_lookup(vmw_context_res_man(ctx), 201962306a36Sopenharmony_ci cmd->body.shid, cmd->body.type); 202062306a36Sopenharmony_ci if (!IS_ERR(res)) { 202162306a36Sopenharmony_ci ret = vmw_execbuf_res_val_add(sw_context, res, 202262306a36Sopenharmony_ci VMW_RES_DIRTY_NONE, 202362306a36Sopenharmony_ci vmw_val_add_flag_noctx); 202462306a36Sopenharmony_ci if (unlikely(ret != 0)) 202562306a36Sopenharmony_ci return ret; 202662306a36Sopenharmony_ci 202762306a36Sopenharmony_ci ret = vmw_resource_relocation_add 202862306a36Sopenharmony_ci (sw_context, res, 202962306a36Sopenharmony_ci vmw_ptr_diff(sw_context->buf_start, 203062306a36Sopenharmony_ci &cmd->body.shid), 203162306a36Sopenharmony_ci vmw_res_rel_normal); 203262306a36Sopenharmony_ci if (unlikely(ret != 0)) 203362306a36Sopenharmony_ci return ret; 203462306a36Sopenharmony_ci } 203562306a36Sopenharmony_ci } 203662306a36Sopenharmony_ci 203762306a36Sopenharmony_ci if (IS_ERR_OR_NULL(res)) { 203862306a36Sopenharmony_ci ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_shader, 203962306a36Sopenharmony_ci VMW_RES_DIRTY_NONE, 204062306a36Sopenharmony_ci user_shader_converter, &cmd->body.shid, 204162306a36Sopenharmony_ci &res); 204262306a36Sopenharmony_ci if (unlikely(ret != 0)) 204362306a36Sopenharmony_ci return ret; 204462306a36Sopenharmony_ci } 204562306a36Sopenharmony_ci 204662306a36Sopenharmony_ci ctx_info = vmw_execbuf_info_from_res(sw_context, ctx); 204762306a36Sopenharmony_ci if (!ctx_info) 204862306a36Sopenharmony_ci return -EINVAL; 204962306a36Sopenharmony_ci 205062306a36Sopenharmony_ci binding.bi.ctx = ctx; 205162306a36Sopenharmony_ci binding.bi.res = res; 205262306a36Sopenharmony_ci binding.bi.bt = vmw_ctx_binding_shader; 205362306a36Sopenharmony_ci binding.shader_slot = cmd->body.type - SVGA3D_SHADERTYPE_MIN; 205462306a36Sopenharmony_ci vmw_binding_add(ctx_info->staged, &binding.bi, binding.shader_slot, 0); 205562306a36Sopenharmony_ci 205662306a36Sopenharmony_ci return 0; 205762306a36Sopenharmony_ci} 205862306a36Sopenharmony_ci 205962306a36Sopenharmony_ci/** 206062306a36Sopenharmony_ci * vmw_cmd_set_shader_const - Validate SVGA_3D_CMD_SET_SHADER_CONST command 206162306a36Sopenharmony_ci * 206262306a36Sopenharmony_ci * @dev_priv: Pointer to a device private struct. 206362306a36Sopenharmony_ci * @sw_context: The software context being used for this batch. 206462306a36Sopenharmony_ci * @header: Pointer to the command header in the command stream. 206562306a36Sopenharmony_ci */ 206662306a36Sopenharmony_cistatic int vmw_cmd_set_shader_const(struct vmw_private *dev_priv, 206762306a36Sopenharmony_ci struct vmw_sw_context *sw_context, 206862306a36Sopenharmony_ci SVGA3dCmdHeader *header) 206962306a36Sopenharmony_ci{ 207062306a36Sopenharmony_ci VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdSetShaderConst); 207162306a36Sopenharmony_ci int ret; 207262306a36Sopenharmony_ci 207362306a36Sopenharmony_ci cmd = container_of(header, typeof(*cmd), header); 207462306a36Sopenharmony_ci 207562306a36Sopenharmony_ci ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_context, 207662306a36Sopenharmony_ci VMW_RES_DIRTY_SET, user_context_converter, 207762306a36Sopenharmony_ci &cmd->body.cid, NULL); 207862306a36Sopenharmony_ci if (unlikely(ret != 0)) 207962306a36Sopenharmony_ci return ret; 208062306a36Sopenharmony_ci 208162306a36Sopenharmony_ci if (dev_priv->has_mob) 208262306a36Sopenharmony_ci header->id = SVGA_3D_CMD_SET_GB_SHADERCONSTS_INLINE; 208362306a36Sopenharmony_ci 208462306a36Sopenharmony_ci return 0; 208562306a36Sopenharmony_ci} 208662306a36Sopenharmony_ci 208762306a36Sopenharmony_ci/** 208862306a36Sopenharmony_ci * vmw_cmd_bind_gb_shader - Validate SVGA_3D_CMD_BIND_GB_SHADER command 208962306a36Sopenharmony_ci * 209062306a36Sopenharmony_ci * @dev_priv: Pointer to a device private struct. 209162306a36Sopenharmony_ci * @sw_context: The software context being used for this batch. 209262306a36Sopenharmony_ci * @header: Pointer to the command header in the command stream. 209362306a36Sopenharmony_ci */ 209462306a36Sopenharmony_cistatic int vmw_cmd_bind_gb_shader(struct vmw_private *dev_priv, 209562306a36Sopenharmony_ci struct vmw_sw_context *sw_context, 209662306a36Sopenharmony_ci SVGA3dCmdHeader *header) 209762306a36Sopenharmony_ci{ 209862306a36Sopenharmony_ci VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdBindGBShader) = 209962306a36Sopenharmony_ci container_of(header, typeof(*cmd), header); 210062306a36Sopenharmony_ci 210162306a36Sopenharmony_ci return vmw_cmd_switch_backup(dev_priv, sw_context, vmw_res_shader, 210262306a36Sopenharmony_ci user_shader_converter, &cmd->body.shid, 210362306a36Sopenharmony_ci &cmd->body.mobid, cmd->body.offsetInBytes); 210462306a36Sopenharmony_ci} 210562306a36Sopenharmony_ci 210662306a36Sopenharmony_ci/** 210762306a36Sopenharmony_ci * vmw_cmd_dx_set_single_constant_buffer - Validate 210862306a36Sopenharmony_ci * SVGA_3D_CMD_DX_SET_SINGLE_CONSTANT_BUFFER command. 210962306a36Sopenharmony_ci * 211062306a36Sopenharmony_ci * @dev_priv: Pointer to a device private struct. 211162306a36Sopenharmony_ci * @sw_context: The software context being used for this batch. 211262306a36Sopenharmony_ci * @header: Pointer to the command header in the command stream. 211362306a36Sopenharmony_ci */ 211462306a36Sopenharmony_cistatic int 211562306a36Sopenharmony_civmw_cmd_dx_set_single_constant_buffer(struct vmw_private *dev_priv, 211662306a36Sopenharmony_ci struct vmw_sw_context *sw_context, 211762306a36Sopenharmony_ci SVGA3dCmdHeader *header) 211862306a36Sopenharmony_ci{ 211962306a36Sopenharmony_ci VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdDXSetSingleConstantBuffer); 212062306a36Sopenharmony_ci 212162306a36Sopenharmony_ci struct vmw_resource *res = NULL; 212262306a36Sopenharmony_ci struct vmw_ctx_validation_info *ctx_node = VMW_GET_CTX_NODE(sw_context); 212362306a36Sopenharmony_ci struct vmw_ctx_bindinfo_cb binding; 212462306a36Sopenharmony_ci int ret; 212562306a36Sopenharmony_ci 212662306a36Sopenharmony_ci if (!ctx_node) 212762306a36Sopenharmony_ci return -EINVAL; 212862306a36Sopenharmony_ci 212962306a36Sopenharmony_ci cmd = container_of(header, typeof(*cmd), header); 213062306a36Sopenharmony_ci ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface, 213162306a36Sopenharmony_ci VMW_RES_DIRTY_NONE, user_surface_converter, 213262306a36Sopenharmony_ci &cmd->body.sid, &res); 213362306a36Sopenharmony_ci if (unlikely(ret != 0)) 213462306a36Sopenharmony_ci return ret; 213562306a36Sopenharmony_ci 213662306a36Sopenharmony_ci if (!vmw_shadertype_is_valid(dev_priv->sm_type, cmd->body.type) || 213762306a36Sopenharmony_ci cmd->body.slot >= SVGA3D_DX_MAX_CONSTBUFFERS) { 213862306a36Sopenharmony_ci VMW_DEBUG_USER("Illegal const buffer shader %u slot %u.\n", 213962306a36Sopenharmony_ci (unsigned int) cmd->body.type, 214062306a36Sopenharmony_ci (unsigned int) cmd->body.slot); 214162306a36Sopenharmony_ci return -EINVAL; 214262306a36Sopenharmony_ci } 214362306a36Sopenharmony_ci 214462306a36Sopenharmony_ci binding.bi.ctx = ctx_node->ctx; 214562306a36Sopenharmony_ci binding.bi.res = res; 214662306a36Sopenharmony_ci binding.bi.bt = vmw_ctx_binding_cb; 214762306a36Sopenharmony_ci binding.shader_slot = cmd->body.type - SVGA3D_SHADERTYPE_MIN; 214862306a36Sopenharmony_ci binding.offset = cmd->body.offsetInBytes; 214962306a36Sopenharmony_ci binding.size = cmd->body.sizeInBytes; 215062306a36Sopenharmony_ci binding.slot = cmd->body.slot; 215162306a36Sopenharmony_ci 215262306a36Sopenharmony_ci vmw_binding_add(ctx_node->staged, &binding.bi, binding.shader_slot, 215362306a36Sopenharmony_ci binding.slot); 215462306a36Sopenharmony_ci 215562306a36Sopenharmony_ci return 0; 215662306a36Sopenharmony_ci} 215762306a36Sopenharmony_ci 215862306a36Sopenharmony_ci/** 215962306a36Sopenharmony_ci * vmw_cmd_dx_set_constant_buffer_offset - Validate 216062306a36Sopenharmony_ci * SVGA_3D_CMD_DX_SET_VS/PS/GS/HS/DS/CS_CONSTANT_BUFFER_OFFSET command. 216162306a36Sopenharmony_ci * 216262306a36Sopenharmony_ci * @dev_priv: Pointer to a device private struct. 216362306a36Sopenharmony_ci * @sw_context: The software context being used for this batch. 216462306a36Sopenharmony_ci * @header: Pointer to the command header in the command stream. 216562306a36Sopenharmony_ci */ 216662306a36Sopenharmony_cistatic int 216762306a36Sopenharmony_civmw_cmd_dx_set_constant_buffer_offset(struct vmw_private *dev_priv, 216862306a36Sopenharmony_ci struct vmw_sw_context *sw_context, 216962306a36Sopenharmony_ci SVGA3dCmdHeader *header) 217062306a36Sopenharmony_ci{ 217162306a36Sopenharmony_ci VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdDXSetConstantBufferOffset); 217262306a36Sopenharmony_ci 217362306a36Sopenharmony_ci struct vmw_ctx_validation_info *ctx_node = VMW_GET_CTX_NODE(sw_context); 217462306a36Sopenharmony_ci u32 shader_slot; 217562306a36Sopenharmony_ci 217662306a36Sopenharmony_ci if (!has_sm5_context(dev_priv)) 217762306a36Sopenharmony_ci return -EINVAL; 217862306a36Sopenharmony_ci 217962306a36Sopenharmony_ci if (!ctx_node) 218062306a36Sopenharmony_ci return -EINVAL; 218162306a36Sopenharmony_ci 218262306a36Sopenharmony_ci cmd = container_of(header, typeof(*cmd), header); 218362306a36Sopenharmony_ci if (cmd->body.slot >= SVGA3D_DX_MAX_CONSTBUFFERS) { 218462306a36Sopenharmony_ci VMW_DEBUG_USER("Illegal const buffer slot %u.\n", 218562306a36Sopenharmony_ci (unsigned int) cmd->body.slot); 218662306a36Sopenharmony_ci return -EINVAL; 218762306a36Sopenharmony_ci } 218862306a36Sopenharmony_ci 218962306a36Sopenharmony_ci shader_slot = cmd->header.id - SVGA_3D_CMD_DX_SET_VS_CONSTANT_BUFFER_OFFSET; 219062306a36Sopenharmony_ci vmw_binding_cb_offset_update(ctx_node->staged, shader_slot, 219162306a36Sopenharmony_ci cmd->body.slot, cmd->body.offsetInBytes); 219262306a36Sopenharmony_ci 219362306a36Sopenharmony_ci return 0; 219462306a36Sopenharmony_ci} 219562306a36Sopenharmony_ci 219662306a36Sopenharmony_ci/** 219762306a36Sopenharmony_ci * vmw_cmd_dx_set_shader_res - Validate SVGA_3D_CMD_DX_SET_SHADER_RESOURCES 219862306a36Sopenharmony_ci * command 219962306a36Sopenharmony_ci * 220062306a36Sopenharmony_ci * @dev_priv: Pointer to a device private struct. 220162306a36Sopenharmony_ci * @sw_context: The software context being used for this batch. 220262306a36Sopenharmony_ci * @header: Pointer to the command header in the command stream. 220362306a36Sopenharmony_ci */ 220462306a36Sopenharmony_cistatic int vmw_cmd_dx_set_shader_res(struct vmw_private *dev_priv, 220562306a36Sopenharmony_ci struct vmw_sw_context *sw_context, 220662306a36Sopenharmony_ci SVGA3dCmdHeader *header) 220762306a36Sopenharmony_ci{ 220862306a36Sopenharmony_ci VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdDXSetShaderResources) = 220962306a36Sopenharmony_ci container_of(header, typeof(*cmd), header); 221062306a36Sopenharmony_ci 221162306a36Sopenharmony_ci u32 num_sr_view = (cmd->header.size - sizeof(cmd->body)) / 221262306a36Sopenharmony_ci sizeof(SVGA3dShaderResourceViewId); 221362306a36Sopenharmony_ci 221462306a36Sopenharmony_ci if ((u64) cmd->body.startView + (u64) num_sr_view > 221562306a36Sopenharmony_ci (u64) SVGA3D_DX_MAX_SRVIEWS || 221662306a36Sopenharmony_ci !vmw_shadertype_is_valid(dev_priv->sm_type, cmd->body.type)) { 221762306a36Sopenharmony_ci VMW_DEBUG_USER("Invalid shader binding.\n"); 221862306a36Sopenharmony_ci return -EINVAL; 221962306a36Sopenharmony_ci } 222062306a36Sopenharmony_ci 222162306a36Sopenharmony_ci return vmw_view_bindings_add(sw_context, vmw_view_sr, 222262306a36Sopenharmony_ci vmw_ctx_binding_sr, 222362306a36Sopenharmony_ci cmd->body.type - SVGA3D_SHADERTYPE_MIN, 222462306a36Sopenharmony_ci (void *) &cmd[1], num_sr_view, 222562306a36Sopenharmony_ci cmd->body.startView); 222662306a36Sopenharmony_ci} 222762306a36Sopenharmony_ci 222862306a36Sopenharmony_ci/** 222962306a36Sopenharmony_ci * vmw_cmd_dx_set_shader - Validate SVGA_3D_CMD_DX_SET_SHADER command 223062306a36Sopenharmony_ci * 223162306a36Sopenharmony_ci * @dev_priv: Pointer to a device private struct. 223262306a36Sopenharmony_ci * @sw_context: The software context being used for this batch. 223362306a36Sopenharmony_ci * @header: Pointer to the command header in the command stream. 223462306a36Sopenharmony_ci */ 223562306a36Sopenharmony_cistatic int vmw_cmd_dx_set_shader(struct vmw_private *dev_priv, 223662306a36Sopenharmony_ci struct vmw_sw_context *sw_context, 223762306a36Sopenharmony_ci SVGA3dCmdHeader *header) 223862306a36Sopenharmony_ci{ 223962306a36Sopenharmony_ci VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdDXSetShader); 224062306a36Sopenharmony_ci struct vmw_resource *res = NULL; 224162306a36Sopenharmony_ci struct vmw_ctx_validation_info *ctx_node = VMW_GET_CTX_NODE(sw_context); 224262306a36Sopenharmony_ci struct vmw_ctx_bindinfo_shader binding; 224362306a36Sopenharmony_ci int ret = 0; 224462306a36Sopenharmony_ci 224562306a36Sopenharmony_ci if (!ctx_node) 224662306a36Sopenharmony_ci return -EINVAL; 224762306a36Sopenharmony_ci 224862306a36Sopenharmony_ci cmd = container_of(header, typeof(*cmd), header); 224962306a36Sopenharmony_ci 225062306a36Sopenharmony_ci if (!vmw_shadertype_is_valid(dev_priv->sm_type, cmd->body.type)) { 225162306a36Sopenharmony_ci VMW_DEBUG_USER("Illegal shader type %u.\n", 225262306a36Sopenharmony_ci (unsigned int) cmd->body.type); 225362306a36Sopenharmony_ci return -EINVAL; 225462306a36Sopenharmony_ci } 225562306a36Sopenharmony_ci 225662306a36Sopenharmony_ci if (cmd->body.shaderId != SVGA3D_INVALID_ID) { 225762306a36Sopenharmony_ci res = vmw_shader_lookup(sw_context->man, cmd->body.shaderId, 0); 225862306a36Sopenharmony_ci if (IS_ERR(res)) { 225962306a36Sopenharmony_ci VMW_DEBUG_USER("Could not find shader for binding.\n"); 226062306a36Sopenharmony_ci return PTR_ERR(res); 226162306a36Sopenharmony_ci } 226262306a36Sopenharmony_ci 226362306a36Sopenharmony_ci ret = vmw_execbuf_res_val_add(sw_context, res, 226462306a36Sopenharmony_ci VMW_RES_DIRTY_NONE, 226562306a36Sopenharmony_ci vmw_val_add_flag_noctx); 226662306a36Sopenharmony_ci if (ret) 226762306a36Sopenharmony_ci return ret; 226862306a36Sopenharmony_ci } 226962306a36Sopenharmony_ci 227062306a36Sopenharmony_ci binding.bi.ctx = ctx_node->ctx; 227162306a36Sopenharmony_ci binding.bi.res = res; 227262306a36Sopenharmony_ci binding.bi.bt = vmw_ctx_binding_dx_shader; 227362306a36Sopenharmony_ci binding.shader_slot = cmd->body.type - SVGA3D_SHADERTYPE_MIN; 227462306a36Sopenharmony_ci 227562306a36Sopenharmony_ci vmw_binding_add(ctx_node->staged, &binding.bi, binding.shader_slot, 0); 227662306a36Sopenharmony_ci 227762306a36Sopenharmony_ci return 0; 227862306a36Sopenharmony_ci} 227962306a36Sopenharmony_ci 228062306a36Sopenharmony_ci/** 228162306a36Sopenharmony_ci * vmw_cmd_dx_set_vertex_buffers - Validates SVGA_3D_CMD_DX_SET_VERTEX_BUFFERS 228262306a36Sopenharmony_ci * command 228362306a36Sopenharmony_ci * 228462306a36Sopenharmony_ci * @dev_priv: Pointer to a device private struct. 228562306a36Sopenharmony_ci * @sw_context: The software context being used for this batch. 228662306a36Sopenharmony_ci * @header: Pointer to the command header in the command stream. 228762306a36Sopenharmony_ci */ 228862306a36Sopenharmony_cistatic int vmw_cmd_dx_set_vertex_buffers(struct vmw_private *dev_priv, 228962306a36Sopenharmony_ci struct vmw_sw_context *sw_context, 229062306a36Sopenharmony_ci SVGA3dCmdHeader *header) 229162306a36Sopenharmony_ci{ 229262306a36Sopenharmony_ci struct vmw_ctx_validation_info *ctx_node = VMW_GET_CTX_NODE(sw_context); 229362306a36Sopenharmony_ci struct vmw_ctx_bindinfo_vb binding; 229462306a36Sopenharmony_ci struct vmw_resource *res; 229562306a36Sopenharmony_ci struct { 229662306a36Sopenharmony_ci SVGA3dCmdHeader header; 229762306a36Sopenharmony_ci SVGA3dCmdDXSetVertexBuffers body; 229862306a36Sopenharmony_ci SVGA3dVertexBuffer buf[]; 229962306a36Sopenharmony_ci } *cmd; 230062306a36Sopenharmony_ci int i, ret, num; 230162306a36Sopenharmony_ci 230262306a36Sopenharmony_ci if (!ctx_node) 230362306a36Sopenharmony_ci return -EINVAL; 230462306a36Sopenharmony_ci 230562306a36Sopenharmony_ci cmd = container_of(header, typeof(*cmd), header); 230662306a36Sopenharmony_ci num = (cmd->header.size - sizeof(cmd->body)) / 230762306a36Sopenharmony_ci sizeof(SVGA3dVertexBuffer); 230862306a36Sopenharmony_ci if ((u64)num + (u64)cmd->body.startBuffer > 230962306a36Sopenharmony_ci (u64)SVGA3D_DX_MAX_VERTEXBUFFERS) { 231062306a36Sopenharmony_ci VMW_DEBUG_USER("Invalid number of vertex buffers.\n"); 231162306a36Sopenharmony_ci return -EINVAL; 231262306a36Sopenharmony_ci } 231362306a36Sopenharmony_ci 231462306a36Sopenharmony_ci for (i = 0; i < num; i++) { 231562306a36Sopenharmony_ci ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface, 231662306a36Sopenharmony_ci VMW_RES_DIRTY_NONE, 231762306a36Sopenharmony_ci user_surface_converter, 231862306a36Sopenharmony_ci &cmd->buf[i].sid, &res); 231962306a36Sopenharmony_ci if (unlikely(ret != 0)) 232062306a36Sopenharmony_ci return ret; 232162306a36Sopenharmony_ci 232262306a36Sopenharmony_ci binding.bi.ctx = ctx_node->ctx; 232362306a36Sopenharmony_ci binding.bi.bt = vmw_ctx_binding_vb; 232462306a36Sopenharmony_ci binding.bi.res = res; 232562306a36Sopenharmony_ci binding.offset = cmd->buf[i].offset; 232662306a36Sopenharmony_ci binding.stride = cmd->buf[i].stride; 232762306a36Sopenharmony_ci binding.slot = i + cmd->body.startBuffer; 232862306a36Sopenharmony_ci 232962306a36Sopenharmony_ci vmw_binding_add(ctx_node->staged, &binding.bi, 0, binding.slot); 233062306a36Sopenharmony_ci } 233162306a36Sopenharmony_ci 233262306a36Sopenharmony_ci return 0; 233362306a36Sopenharmony_ci} 233462306a36Sopenharmony_ci 233562306a36Sopenharmony_ci/** 233662306a36Sopenharmony_ci * vmw_cmd_dx_set_index_buffer - Validate 233762306a36Sopenharmony_ci * SVGA_3D_CMD_DX_IA_SET_INDEX_BUFFER command. 233862306a36Sopenharmony_ci * 233962306a36Sopenharmony_ci * @dev_priv: Pointer to a device private struct. 234062306a36Sopenharmony_ci * @sw_context: The software context being used for this batch. 234162306a36Sopenharmony_ci * @header: Pointer to the command header in the command stream. 234262306a36Sopenharmony_ci */ 234362306a36Sopenharmony_cistatic int vmw_cmd_dx_set_index_buffer(struct vmw_private *dev_priv, 234462306a36Sopenharmony_ci struct vmw_sw_context *sw_context, 234562306a36Sopenharmony_ci SVGA3dCmdHeader *header) 234662306a36Sopenharmony_ci{ 234762306a36Sopenharmony_ci struct vmw_ctx_validation_info *ctx_node = VMW_GET_CTX_NODE(sw_context); 234862306a36Sopenharmony_ci struct vmw_ctx_bindinfo_ib binding; 234962306a36Sopenharmony_ci struct vmw_resource *res; 235062306a36Sopenharmony_ci VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdDXSetIndexBuffer); 235162306a36Sopenharmony_ci int ret; 235262306a36Sopenharmony_ci 235362306a36Sopenharmony_ci if (!ctx_node) 235462306a36Sopenharmony_ci return -EINVAL; 235562306a36Sopenharmony_ci 235662306a36Sopenharmony_ci cmd = container_of(header, typeof(*cmd), header); 235762306a36Sopenharmony_ci ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface, 235862306a36Sopenharmony_ci VMW_RES_DIRTY_NONE, user_surface_converter, 235962306a36Sopenharmony_ci &cmd->body.sid, &res); 236062306a36Sopenharmony_ci if (unlikely(ret != 0)) 236162306a36Sopenharmony_ci return ret; 236262306a36Sopenharmony_ci 236362306a36Sopenharmony_ci binding.bi.ctx = ctx_node->ctx; 236462306a36Sopenharmony_ci binding.bi.res = res; 236562306a36Sopenharmony_ci binding.bi.bt = vmw_ctx_binding_ib; 236662306a36Sopenharmony_ci binding.offset = cmd->body.offset; 236762306a36Sopenharmony_ci binding.format = cmd->body.format; 236862306a36Sopenharmony_ci 236962306a36Sopenharmony_ci vmw_binding_add(ctx_node->staged, &binding.bi, 0, 0); 237062306a36Sopenharmony_ci 237162306a36Sopenharmony_ci return 0; 237262306a36Sopenharmony_ci} 237362306a36Sopenharmony_ci 237462306a36Sopenharmony_ci/** 237562306a36Sopenharmony_ci * vmw_cmd_dx_set_rendertargets - Validate SVGA_3D_CMD_DX_SET_RENDERTARGETS 237662306a36Sopenharmony_ci * command 237762306a36Sopenharmony_ci * 237862306a36Sopenharmony_ci * @dev_priv: Pointer to a device private struct. 237962306a36Sopenharmony_ci * @sw_context: The software context being used for this batch. 238062306a36Sopenharmony_ci * @header: Pointer to the command header in the command stream. 238162306a36Sopenharmony_ci */ 238262306a36Sopenharmony_cistatic int vmw_cmd_dx_set_rendertargets(struct vmw_private *dev_priv, 238362306a36Sopenharmony_ci struct vmw_sw_context *sw_context, 238462306a36Sopenharmony_ci SVGA3dCmdHeader *header) 238562306a36Sopenharmony_ci{ 238662306a36Sopenharmony_ci VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdDXSetRenderTargets) = 238762306a36Sopenharmony_ci container_of(header, typeof(*cmd), header); 238862306a36Sopenharmony_ci u32 num_rt_view = (cmd->header.size - sizeof(cmd->body)) / 238962306a36Sopenharmony_ci sizeof(SVGA3dRenderTargetViewId); 239062306a36Sopenharmony_ci int ret; 239162306a36Sopenharmony_ci 239262306a36Sopenharmony_ci if (num_rt_view > SVGA3D_DX_MAX_RENDER_TARGETS) { 239362306a36Sopenharmony_ci VMW_DEBUG_USER("Invalid DX Rendertarget binding.\n"); 239462306a36Sopenharmony_ci return -EINVAL; 239562306a36Sopenharmony_ci } 239662306a36Sopenharmony_ci 239762306a36Sopenharmony_ci ret = vmw_view_bindings_add(sw_context, vmw_view_ds, vmw_ctx_binding_ds, 239862306a36Sopenharmony_ci 0, &cmd->body.depthStencilViewId, 1, 0); 239962306a36Sopenharmony_ci if (ret) 240062306a36Sopenharmony_ci return ret; 240162306a36Sopenharmony_ci 240262306a36Sopenharmony_ci return vmw_view_bindings_add(sw_context, vmw_view_rt, 240362306a36Sopenharmony_ci vmw_ctx_binding_dx_rt, 0, (void *)&cmd[1], 240462306a36Sopenharmony_ci num_rt_view, 0); 240562306a36Sopenharmony_ci} 240662306a36Sopenharmony_ci 240762306a36Sopenharmony_ci/** 240862306a36Sopenharmony_ci * vmw_cmd_dx_clear_rendertarget_view - Validate 240962306a36Sopenharmony_ci * SVGA_3D_CMD_DX_CLEAR_RENDERTARGET_VIEW command 241062306a36Sopenharmony_ci * 241162306a36Sopenharmony_ci * @dev_priv: Pointer to a device private struct. 241262306a36Sopenharmony_ci * @sw_context: The software context being used for this batch. 241362306a36Sopenharmony_ci * @header: Pointer to the command header in the command stream. 241462306a36Sopenharmony_ci */ 241562306a36Sopenharmony_cistatic int vmw_cmd_dx_clear_rendertarget_view(struct vmw_private *dev_priv, 241662306a36Sopenharmony_ci struct vmw_sw_context *sw_context, 241762306a36Sopenharmony_ci SVGA3dCmdHeader *header) 241862306a36Sopenharmony_ci{ 241962306a36Sopenharmony_ci VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdDXClearRenderTargetView) = 242062306a36Sopenharmony_ci container_of(header, typeof(*cmd), header); 242162306a36Sopenharmony_ci struct vmw_resource *ret; 242262306a36Sopenharmony_ci 242362306a36Sopenharmony_ci ret = vmw_view_id_val_add(sw_context, vmw_view_rt, 242462306a36Sopenharmony_ci cmd->body.renderTargetViewId); 242562306a36Sopenharmony_ci 242662306a36Sopenharmony_ci return PTR_ERR_OR_ZERO(ret); 242762306a36Sopenharmony_ci} 242862306a36Sopenharmony_ci 242962306a36Sopenharmony_ci/** 243062306a36Sopenharmony_ci * vmw_cmd_dx_clear_depthstencil_view - Validate 243162306a36Sopenharmony_ci * SVGA_3D_CMD_DX_CLEAR_DEPTHSTENCIL_VIEW command 243262306a36Sopenharmony_ci * 243362306a36Sopenharmony_ci * @dev_priv: Pointer to a device private struct. 243462306a36Sopenharmony_ci * @sw_context: The software context being used for this batch. 243562306a36Sopenharmony_ci * @header: Pointer to the command header in the command stream. 243662306a36Sopenharmony_ci */ 243762306a36Sopenharmony_cistatic int vmw_cmd_dx_clear_depthstencil_view(struct vmw_private *dev_priv, 243862306a36Sopenharmony_ci struct vmw_sw_context *sw_context, 243962306a36Sopenharmony_ci SVGA3dCmdHeader *header) 244062306a36Sopenharmony_ci{ 244162306a36Sopenharmony_ci VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdDXClearDepthStencilView) = 244262306a36Sopenharmony_ci container_of(header, typeof(*cmd), header); 244362306a36Sopenharmony_ci struct vmw_resource *ret; 244462306a36Sopenharmony_ci 244562306a36Sopenharmony_ci ret = vmw_view_id_val_add(sw_context, vmw_view_ds, 244662306a36Sopenharmony_ci cmd->body.depthStencilViewId); 244762306a36Sopenharmony_ci 244862306a36Sopenharmony_ci return PTR_ERR_OR_ZERO(ret); 244962306a36Sopenharmony_ci} 245062306a36Sopenharmony_ci 245162306a36Sopenharmony_cistatic int vmw_cmd_dx_view_define(struct vmw_private *dev_priv, 245262306a36Sopenharmony_ci struct vmw_sw_context *sw_context, 245362306a36Sopenharmony_ci SVGA3dCmdHeader *header) 245462306a36Sopenharmony_ci{ 245562306a36Sopenharmony_ci struct vmw_ctx_validation_info *ctx_node = VMW_GET_CTX_NODE(sw_context); 245662306a36Sopenharmony_ci struct vmw_resource *srf; 245762306a36Sopenharmony_ci struct vmw_resource *res; 245862306a36Sopenharmony_ci enum vmw_view_type view_type; 245962306a36Sopenharmony_ci int ret; 246062306a36Sopenharmony_ci /* 246162306a36Sopenharmony_ci * This is based on the fact that all affected define commands have the 246262306a36Sopenharmony_ci * same initial command body layout. 246362306a36Sopenharmony_ci */ 246462306a36Sopenharmony_ci struct { 246562306a36Sopenharmony_ci SVGA3dCmdHeader header; 246662306a36Sopenharmony_ci uint32 defined_id; 246762306a36Sopenharmony_ci uint32 sid; 246862306a36Sopenharmony_ci } *cmd; 246962306a36Sopenharmony_ci 247062306a36Sopenharmony_ci if (!ctx_node) 247162306a36Sopenharmony_ci return -EINVAL; 247262306a36Sopenharmony_ci 247362306a36Sopenharmony_ci view_type = vmw_view_cmd_to_type(header->id); 247462306a36Sopenharmony_ci if (view_type == vmw_view_max) 247562306a36Sopenharmony_ci return -EINVAL; 247662306a36Sopenharmony_ci 247762306a36Sopenharmony_ci cmd = container_of(header, typeof(*cmd), header); 247862306a36Sopenharmony_ci if (unlikely(cmd->sid == SVGA3D_INVALID_ID)) { 247962306a36Sopenharmony_ci VMW_DEBUG_USER("Invalid surface id.\n"); 248062306a36Sopenharmony_ci return -EINVAL; 248162306a36Sopenharmony_ci } 248262306a36Sopenharmony_ci ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface, 248362306a36Sopenharmony_ci VMW_RES_DIRTY_NONE, user_surface_converter, 248462306a36Sopenharmony_ci &cmd->sid, &srf); 248562306a36Sopenharmony_ci if (unlikely(ret != 0)) 248662306a36Sopenharmony_ci return ret; 248762306a36Sopenharmony_ci 248862306a36Sopenharmony_ci res = vmw_context_cotable(ctx_node->ctx, vmw_view_cotables[view_type]); 248962306a36Sopenharmony_ci if (IS_ERR_OR_NULL(res)) 249062306a36Sopenharmony_ci return res ? PTR_ERR(res) : -EINVAL; 249162306a36Sopenharmony_ci ret = vmw_cotable_notify(res, cmd->defined_id); 249262306a36Sopenharmony_ci if (unlikely(ret != 0)) 249362306a36Sopenharmony_ci return ret; 249462306a36Sopenharmony_ci 249562306a36Sopenharmony_ci return vmw_view_add(sw_context->man, ctx_node->ctx, srf, view_type, 249662306a36Sopenharmony_ci cmd->defined_id, header, 249762306a36Sopenharmony_ci header->size + sizeof(*header), 249862306a36Sopenharmony_ci &sw_context->staged_cmd_res); 249962306a36Sopenharmony_ci} 250062306a36Sopenharmony_ci 250162306a36Sopenharmony_ci/** 250262306a36Sopenharmony_ci * vmw_cmd_dx_set_so_targets - Validate SVGA_3D_CMD_DX_SET_SOTARGETS command. 250362306a36Sopenharmony_ci * 250462306a36Sopenharmony_ci * @dev_priv: Pointer to a device private struct. 250562306a36Sopenharmony_ci * @sw_context: The software context being used for this batch. 250662306a36Sopenharmony_ci * @header: Pointer to the command header in the command stream. 250762306a36Sopenharmony_ci */ 250862306a36Sopenharmony_cistatic int vmw_cmd_dx_set_so_targets(struct vmw_private *dev_priv, 250962306a36Sopenharmony_ci struct vmw_sw_context *sw_context, 251062306a36Sopenharmony_ci SVGA3dCmdHeader *header) 251162306a36Sopenharmony_ci{ 251262306a36Sopenharmony_ci struct vmw_ctx_validation_info *ctx_node = VMW_GET_CTX_NODE(sw_context); 251362306a36Sopenharmony_ci struct vmw_ctx_bindinfo_so_target binding; 251462306a36Sopenharmony_ci struct vmw_resource *res; 251562306a36Sopenharmony_ci struct { 251662306a36Sopenharmony_ci SVGA3dCmdHeader header; 251762306a36Sopenharmony_ci SVGA3dCmdDXSetSOTargets body; 251862306a36Sopenharmony_ci SVGA3dSoTarget targets[]; 251962306a36Sopenharmony_ci } *cmd; 252062306a36Sopenharmony_ci int i, ret, num; 252162306a36Sopenharmony_ci 252262306a36Sopenharmony_ci if (!ctx_node) 252362306a36Sopenharmony_ci return -EINVAL; 252462306a36Sopenharmony_ci 252562306a36Sopenharmony_ci cmd = container_of(header, typeof(*cmd), header); 252662306a36Sopenharmony_ci num = (cmd->header.size - sizeof(cmd->body)) / sizeof(SVGA3dSoTarget); 252762306a36Sopenharmony_ci 252862306a36Sopenharmony_ci if (num > SVGA3D_DX_MAX_SOTARGETS) { 252962306a36Sopenharmony_ci VMW_DEBUG_USER("Invalid DX SO binding.\n"); 253062306a36Sopenharmony_ci return -EINVAL; 253162306a36Sopenharmony_ci } 253262306a36Sopenharmony_ci 253362306a36Sopenharmony_ci for (i = 0; i < num; i++) { 253462306a36Sopenharmony_ci ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface, 253562306a36Sopenharmony_ci VMW_RES_DIRTY_SET, 253662306a36Sopenharmony_ci user_surface_converter, 253762306a36Sopenharmony_ci &cmd->targets[i].sid, &res); 253862306a36Sopenharmony_ci if (unlikely(ret != 0)) 253962306a36Sopenharmony_ci return ret; 254062306a36Sopenharmony_ci 254162306a36Sopenharmony_ci binding.bi.ctx = ctx_node->ctx; 254262306a36Sopenharmony_ci binding.bi.res = res; 254362306a36Sopenharmony_ci binding.bi.bt = vmw_ctx_binding_so_target; 254462306a36Sopenharmony_ci binding.offset = cmd->targets[i].offset; 254562306a36Sopenharmony_ci binding.size = cmd->targets[i].sizeInBytes; 254662306a36Sopenharmony_ci binding.slot = i; 254762306a36Sopenharmony_ci 254862306a36Sopenharmony_ci vmw_binding_add(ctx_node->staged, &binding.bi, 0, binding.slot); 254962306a36Sopenharmony_ci } 255062306a36Sopenharmony_ci 255162306a36Sopenharmony_ci return 0; 255262306a36Sopenharmony_ci} 255362306a36Sopenharmony_ci 255462306a36Sopenharmony_cistatic int vmw_cmd_dx_so_define(struct vmw_private *dev_priv, 255562306a36Sopenharmony_ci struct vmw_sw_context *sw_context, 255662306a36Sopenharmony_ci SVGA3dCmdHeader *header) 255762306a36Sopenharmony_ci{ 255862306a36Sopenharmony_ci struct vmw_ctx_validation_info *ctx_node = VMW_GET_CTX_NODE(sw_context); 255962306a36Sopenharmony_ci struct vmw_resource *res; 256062306a36Sopenharmony_ci /* 256162306a36Sopenharmony_ci * This is based on the fact that all affected define commands have 256262306a36Sopenharmony_ci * the same initial command body layout. 256362306a36Sopenharmony_ci */ 256462306a36Sopenharmony_ci struct { 256562306a36Sopenharmony_ci SVGA3dCmdHeader header; 256662306a36Sopenharmony_ci uint32 defined_id; 256762306a36Sopenharmony_ci } *cmd; 256862306a36Sopenharmony_ci enum vmw_so_type so_type; 256962306a36Sopenharmony_ci int ret; 257062306a36Sopenharmony_ci 257162306a36Sopenharmony_ci if (!ctx_node) 257262306a36Sopenharmony_ci return -EINVAL; 257362306a36Sopenharmony_ci 257462306a36Sopenharmony_ci so_type = vmw_so_cmd_to_type(header->id); 257562306a36Sopenharmony_ci res = vmw_context_cotable(ctx_node->ctx, vmw_so_cotables[so_type]); 257662306a36Sopenharmony_ci if (IS_ERR_OR_NULL(res)) 257762306a36Sopenharmony_ci return res ? PTR_ERR(res) : -EINVAL; 257862306a36Sopenharmony_ci cmd = container_of(header, typeof(*cmd), header); 257962306a36Sopenharmony_ci ret = vmw_cotable_notify(res, cmd->defined_id); 258062306a36Sopenharmony_ci 258162306a36Sopenharmony_ci return ret; 258262306a36Sopenharmony_ci} 258362306a36Sopenharmony_ci 258462306a36Sopenharmony_ci/** 258562306a36Sopenharmony_ci * vmw_cmd_dx_check_subresource - Validate SVGA_3D_CMD_DX_[X]_SUBRESOURCE 258662306a36Sopenharmony_ci * command 258762306a36Sopenharmony_ci * 258862306a36Sopenharmony_ci * @dev_priv: Pointer to a device private struct. 258962306a36Sopenharmony_ci * @sw_context: The software context being used for this batch. 259062306a36Sopenharmony_ci * @header: Pointer to the command header in the command stream. 259162306a36Sopenharmony_ci */ 259262306a36Sopenharmony_cistatic int vmw_cmd_dx_check_subresource(struct vmw_private *dev_priv, 259362306a36Sopenharmony_ci struct vmw_sw_context *sw_context, 259462306a36Sopenharmony_ci SVGA3dCmdHeader *header) 259562306a36Sopenharmony_ci{ 259662306a36Sopenharmony_ci struct { 259762306a36Sopenharmony_ci SVGA3dCmdHeader header; 259862306a36Sopenharmony_ci union { 259962306a36Sopenharmony_ci SVGA3dCmdDXReadbackSubResource r_body; 260062306a36Sopenharmony_ci SVGA3dCmdDXInvalidateSubResource i_body; 260162306a36Sopenharmony_ci SVGA3dCmdDXUpdateSubResource u_body; 260262306a36Sopenharmony_ci SVGA3dSurfaceId sid; 260362306a36Sopenharmony_ci }; 260462306a36Sopenharmony_ci } *cmd; 260562306a36Sopenharmony_ci 260662306a36Sopenharmony_ci BUILD_BUG_ON(offsetof(typeof(*cmd), r_body.sid) != 260762306a36Sopenharmony_ci offsetof(typeof(*cmd), sid)); 260862306a36Sopenharmony_ci BUILD_BUG_ON(offsetof(typeof(*cmd), i_body.sid) != 260962306a36Sopenharmony_ci offsetof(typeof(*cmd), sid)); 261062306a36Sopenharmony_ci BUILD_BUG_ON(offsetof(typeof(*cmd), u_body.sid) != 261162306a36Sopenharmony_ci offsetof(typeof(*cmd), sid)); 261262306a36Sopenharmony_ci 261362306a36Sopenharmony_ci cmd = container_of(header, typeof(*cmd), header); 261462306a36Sopenharmony_ci return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface, 261562306a36Sopenharmony_ci VMW_RES_DIRTY_NONE, user_surface_converter, 261662306a36Sopenharmony_ci &cmd->sid, NULL); 261762306a36Sopenharmony_ci} 261862306a36Sopenharmony_ci 261962306a36Sopenharmony_cistatic int vmw_cmd_dx_cid_check(struct vmw_private *dev_priv, 262062306a36Sopenharmony_ci struct vmw_sw_context *sw_context, 262162306a36Sopenharmony_ci SVGA3dCmdHeader *header) 262262306a36Sopenharmony_ci{ 262362306a36Sopenharmony_ci struct vmw_ctx_validation_info *ctx_node = VMW_GET_CTX_NODE(sw_context); 262462306a36Sopenharmony_ci 262562306a36Sopenharmony_ci if (!ctx_node) 262662306a36Sopenharmony_ci return -EINVAL; 262762306a36Sopenharmony_ci 262862306a36Sopenharmony_ci return 0; 262962306a36Sopenharmony_ci} 263062306a36Sopenharmony_ci 263162306a36Sopenharmony_ci/** 263262306a36Sopenharmony_ci * vmw_cmd_dx_view_remove - validate a view remove command and schedule the view 263362306a36Sopenharmony_ci * resource for removal. 263462306a36Sopenharmony_ci * 263562306a36Sopenharmony_ci * @dev_priv: Pointer to a device private struct. 263662306a36Sopenharmony_ci * @sw_context: The software context being used for this batch. 263762306a36Sopenharmony_ci * @header: Pointer to the command header in the command stream. 263862306a36Sopenharmony_ci * 263962306a36Sopenharmony_ci * Check that the view exists, and if it was not created using this command 264062306a36Sopenharmony_ci * batch, conditionally make this command a NOP. 264162306a36Sopenharmony_ci */ 264262306a36Sopenharmony_cistatic int vmw_cmd_dx_view_remove(struct vmw_private *dev_priv, 264362306a36Sopenharmony_ci struct vmw_sw_context *sw_context, 264462306a36Sopenharmony_ci SVGA3dCmdHeader *header) 264562306a36Sopenharmony_ci{ 264662306a36Sopenharmony_ci struct vmw_ctx_validation_info *ctx_node = VMW_GET_CTX_NODE(sw_context); 264762306a36Sopenharmony_ci struct { 264862306a36Sopenharmony_ci SVGA3dCmdHeader header; 264962306a36Sopenharmony_ci union vmw_view_destroy body; 265062306a36Sopenharmony_ci } *cmd = container_of(header, typeof(*cmd), header); 265162306a36Sopenharmony_ci enum vmw_view_type view_type = vmw_view_cmd_to_type(header->id); 265262306a36Sopenharmony_ci struct vmw_resource *view; 265362306a36Sopenharmony_ci int ret; 265462306a36Sopenharmony_ci 265562306a36Sopenharmony_ci if (!ctx_node) 265662306a36Sopenharmony_ci return -EINVAL; 265762306a36Sopenharmony_ci 265862306a36Sopenharmony_ci ret = vmw_view_remove(sw_context->man, cmd->body.view_id, view_type, 265962306a36Sopenharmony_ci &sw_context->staged_cmd_res, &view); 266062306a36Sopenharmony_ci if (ret || !view) 266162306a36Sopenharmony_ci return ret; 266262306a36Sopenharmony_ci 266362306a36Sopenharmony_ci /* 266462306a36Sopenharmony_ci * If the view wasn't created during this command batch, it might 266562306a36Sopenharmony_ci * have been removed due to a context swapout, so add a 266662306a36Sopenharmony_ci * relocation to conditionally make this command a NOP to avoid 266762306a36Sopenharmony_ci * device errors. 266862306a36Sopenharmony_ci */ 266962306a36Sopenharmony_ci return vmw_resource_relocation_add(sw_context, view, 267062306a36Sopenharmony_ci vmw_ptr_diff(sw_context->buf_start, 267162306a36Sopenharmony_ci &cmd->header.id), 267262306a36Sopenharmony_ci vmw_res_rel_cond_nop); 267362306a36Sopenharmony_ci} 267462306a36Sopenharmony_ci 267562306a36Sopenharmony_ci/** 267662306a36Sopenharmony_ci * vmw_cmd_dx_define_shader - Validate SVGA_3D_CMD_DX_DEFINE_SHADER command 267762306a36Sopenharmony_ci * 267862306a36Sopenharmony_ci * @dev_priv: Pointer to a device private struct. 267962306a36Sopenharmony_ci * @sw_context: The software context being used for this batch. 268062306a36Sopenharmony_ci * @header: Pointer to the command header in the command stream. 268162306a36Sopenharmony_ci */ 268262306a36Sopenharmony_cistatic int vmw_cmd_dx_define_shader(struct vmw_private *dev_priv, 268362306a36Sopenharmony_ci struct vmw_sw_context *sw_context, 268462306a36Sopenharmony_ci SVGA3dCmdHeader *header) 268562306a36Sopenharmony_ci{ 268662306a36Sopenharmony_ci struct vmw_ctx_validation_info *ctx_node = VMW_GET_CTX_NODE(sw_context); 268762306a36Sopenharmony_ci struct vmw_resource *res; 268862306a36Sopenharmony_ci VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdDXDefineShader) = 268962306a36Sopenharmony_ci container_of(header, typeof(*cmd), header); 269062306a36Sopenharmony_ci int ret; 269162306a36Sopenharmony_ci 269262306a36Sopenharmony_ci if (!ctx_node) 269362306a36Sopenharmony_ci return -EINVAL; 269462306a36Sopenharmony_ci 269562306a36Sopenharmony_ci res = vmw_context_cotable(ctx_node->ctx, SVGA_COTABLE_DXSHADER); 269662306a36Sopenharmony_ci if (IS_ERR_OR_NULL(res)) 269762306a36Sopenharmony_ci return res ? PTR_ERR(res) : -EINVAL; 269862306a36Sopenharmony_ci ret = vmw_cotable_notify(res, cmd->body.shaderId); 269962306a36Sopenharmony_ci if (ret) 270062306a36Sopenharmony_ci return ret; 270162306a36Sopenharmony_ci 270262306a36Sopenharmony_ci return vmw_dx_shader_add(sw_context->man, ctx_node->ctx, 270362306a36Sopenharmony_ci cmd->body.shaderId, cmd->body.type, 270462306a36Sopenharmony_ci &sw_context->staged_cmd_res); 270562306a36Sopenharmony_ci} 270662306a36Sopenharmony_ci 270762306a36Sopenharmony_ci/** 270862306a36Sopenharmony_ci * vmw_cmd_dx_destroy_shader - Validate SVGA_3D_CMD_DX_DESTROY_SHADER command 270962306a36Sopenharmony_ci * 271062306a36Sopenharmony_ci * @dev_priv: Pointer to a device private struct. 271162306a36Sopenharmony_ci * @sw_context: The software context being used for this batch. 271262306a36Sopenharmony_ci * @header: Pointer to the command header in the command stream. 271362306a36Sopenharmony_ci */ 271462306a36Sopenharmony_cistatic int vmw_cmd_dx_destroy_shader(struct vmw_private *dev_priv, 271562306a36Sopenharmony_ci struct vmw_sw_context *sw_context, 271662306a36Sopenharmony_ci SVGA3dCmdHeader *header) 271762306a36Sopenharmony_ci{ 271862306a36Sopenharmony_ci struct vmw_ctx_validation_info *ctx_node = VMW_GET_CTX_NODE(sw_context); 271962306a36Sopenharmony_ci VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdDXDestroyShader) = 272062306a36Sopenharmony_ci container_of(header, typeof(*cmd), header); 272162306a36Sopenharmony_ci int ret; 272262306a36Sopenharmony_ci 272362306a36Sopenharmony_ci if (!ctx_node) 272462306a36Sopenharmony_ci return -EINVAL; 272562306a36Sopenharmony_ci 272662306a36Sopenharmony_ci ret = vmw_shader_remove(sw_context->man, cmd->body.shaderId, 0, 272762306a36Sopenharmony_ci &sw_context->staged_cmd_res); 272862306a36Sopenharmony_ci 272962306a36Sopenharmony_ci return ret; 273062306a36Sopenharmony_ci} 273162306a36Sopenharmony_ci 273262306a36Sopenharmony_ci/** 273362306a36Sopenharmony_ci * vmw_cmd_dx_bind_shader - Validate SVGA_3D_CMD_DX_BIND_SHADER command 273462306a36Sopenharmony_ci * 273562306a36Sopenharmony_ci * @dev_priv: Pointer to a device private struct. 273662306a36Sopenharmony_ci * @sw_context: The software context being used for this batch. 273762306a36Sopenharmony_ci * @header: Pointer to the command header in the command stream. 273862306a36Sopenharmony_ci */ 273962306a36Sopenharmony_cistatic int vmw_cmd_dx_bind_shader(struct vmw_private *dev_priv, 274062306a36Sopenharmony_ci struct vmw_sw_context *sw_context, 274162306a36Sopenharmony_ci SVGA3dCmdHeader *header) 274262306a36Sopenharmony_ci{ 274362306a36Sopenharmony_ci struct vmw_resource *ctx; 274462306a36Sopenharmony_ci struct vmw_resource *res; 274562306a36Sopenharmony_ci VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdDXBindShader) = 274662306a36Sopenharmony_ci container_of(header, typeof(*cmd), header); 274762306a36Sopenharmony_ci int ret; 274862306a36Sopenharmony_ci 274962306a36Sopenharmony_ci if (cmd->body.cid != SVGA3D_INVALID_ID) { 275062306a36Sopenharmony_ci ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_context, 275162306a36Sopenharmony_ci VMW_RES_DIRTY_SET, 275262306a36Sopenharmony_ci user_context_converter, &cmd->body.cid, 275362306a36Sopenharmony_ci &ctx); 275462306a36Sopenharmony_ci if (ret) 275562306a36Sopenharmony_ci return ret; 275662306a36Sopenharmony_ci } else { 275762306a36Sopenharmony_ci struct vmw_ctx_validation_info *ctx_node = 275862306a36Sopenharmony_ci VMW_GET_CTX_NODE(sw_context); 275962306a36Sopenharmony_ci 276062306a36Sopenharmony_ci if (!ctx_node) 276162306a36Sopenharmony_ci return -EINVAL; 276262306a36Sopenharmony_ci 276362306a36Sopenharmony_ci ctx = ctx_node->ctx; 276462306a36Sopenharmony_ci } 276562306a36Sopenharmony_ci 276662306a36Sopenharmony_ci res = vmw_shader_lookup(vmw_context_res_man(ctx), cmd->body.shid, 0); 276762306a36Sopenharmony_ci if (IS_ERR(res)) { 276862306a36Sopenharmony_ci VMW_DEBUG_USER("Could not find shader to bind.\n"); 276962306a36Sopenharmony_ci return PTR_ERR(res); 277062306a36Sopenharmony_ci } 277162306a36Sopenharmony_ci 277262306a36Sopenharmony_ci ret = vmw_execbuf_res_val_add(sw_context, res, VMW_RES_DIRTY_NONE, 277362306a36Sopenharmony_ci vmw_val_add_flag_noctx); 277462306a36Sopenharmony_ci if (ret) { 277562306a36Sopenharmony_ci VMW_DEBUG_USER("Error creating resource validation node.\n"); 277662306a36Sopenharmony_ci return ret; 277762306a36Sopenharmony_ci } 277862306a36Sopenharmony_ci 277962306a36Sopenharmony_ci return vmw_cmd_res_switch_backup(dev_priv, sw_context, res, 278062306a36Sopenharmony_ci &cmd->body.mobid, 278162306a36Sopenharmony_ci cmd->body.offsetInBytes); 278262306a36Sopenharmony_ci} 278362306a36Sopenharmony_ci 278462306a36Sopenharmony_ci/** 278562306a36Sopenharmony_ci * vmw_cmd_dx_genmips - Validate SVGA_3D_CMD_DX_GENMIPS command 278662306a36Sopenharmony_ci * 278762306a36Sopenharmony_ci * @dev_priv: Pointer to a device private struct. 278862306a36Sopenharmony_ci * @sw_context: The software context being used for this batch. 278962306a36Sopenharmony_ci * @header: Pointer to the command header in the command stream. 279062306a36Sopenharmony_ci */ 279162306a36Sopenharmony_cistatic int vmw_cmd_dx_genmips(struct vmw_private *dev_priv, 279262306a36Sopenharmony_ci struct vmw_sw_context *sw_context, 279362306a36Sopenharmony_ci SVGA3dCmdHeader *header) 279462306a36Sopenharmony_ci{ 279562306a36Sopenharmony_ci VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdDXGenMips) = 279662306a36Sopenharmony_ci container_of(header, typeof(*cmd), header); 279762306a36Sopenharmony_ci struct vmw_resource *view; 279862306a36Sopenharmony_ci struct vmw_res_cache_entry *rcache; 279962306a36Sopenharmony_ci 280062306a36Sopenharmony_ci view = vmw_view_id_val_add(sw_context, vmw_view_sr, 280162306a36Sopenharmony_ci cmd->body.shaderResourceViewId); 280262306a36Sopenharmony_ci if (IS_ERR(view)) 280362306a36Sopenharmony_ci return PTR_ERR(view); 280462306a36Sopenharmony_ci 280562306a36Sopenharmony_ci /* 280662306a36Sopenharmony_ci * Normally the shader-resource view is not gpu-dirtying, but for 280762306a36Sopenharmony_ci * this particular command it is... 280862306a36Sopenharmony_ci * So mark the last looked-up surface, which is the surface 280962306a36Sopenharmony_ci * the view points to, gpu-dirty. 281062306a36Sopenharmony_ci */ 281162306a36Sopenharmony_ci rcache = &sw_context->res_cache[vmw_res_surface]; 281262306a36Sopenharmony_ci vmw_validation_res_set_dirty(sw_context->ctx, rcache->private, 281362306a36Sopenharmony_ci VMW_RES_DIRTY_SET); 281462306a36Sopenharmony_ci return 0; 281562306a36Sopenharmony_ci} 281662306a36Sopenharmony_ci 281762306a36Sopenharmony_ci/** 281862306a36Sopenharmony_ci * vmw_cmd_dx_transfer_from_buffer - Validate 281962306a36Sopenharmony_ci * SVGA_3D_CMD_DX_TRANSFER_FROM_BUFFER command 282062306a36Sopenharmony_ci * 282162306a36Sopenharmony_ci * @dev_priv: Pointer to a device private struct. 282262306a36Sopenharmony_ci * @sw_context: The software context being used for this batch. 282362306a36Sopenharmony_ci * @header: Pointer to the command header in the command stream. 282462306a36Sopenharmony_ci */ 282562306a36Sopenharmony_cistatic int vmw_cmd_dx_transfer_from_buffer(struct vmw_private *dev_priv, 282662306a36Sopenharmony_ci struct vmw_sw_context *sw_context, 282762306a36Sopenharmony_ci SVGA3dCmdHeader *header) 282862306a36Sopenharmony_ci{ 282962306a36Sopenharmony_ci VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdDXTransferFromBuffer) = 283062306a36Sopenharmony_ci container_of(header, typeof(*cmd), header); 283162306a36Sopenharmony_ci int ret; 283262306a36Sopenharmony_ci 283362306a36Sopenharmony_ci ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface, 283462306a36Sopenharmony_ci VMW_RES_DIRTY_NONE, user_surface_converter, 283562306a36Sopenharmony_ci &cmd->body.srcSid, NULL); 283662306a36Sopenharmony_ci if (ret != 0) 283762306a36Sopenharmony_ci return ret; 283862306a36Sopenharmony_ci 283962306a36Sopenharmony_ci return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface, 284062306a36Sopenharmony_ci VMW_RES_DIRTY_SET, user_surface_converter, 284162306a36Sopenharmony_ci &cmd->body.destSid, NULL); 284262306a36Sopenharmony_ci} 284362306a36Sopenharmony_ci 284462306a36Sopenharmony_ci/** 284562306a36Sopenharmony_ci * vmw_cmd_intra_surface_copy - Validate SVGA_3D_CMD_INTRA_SURFACE_COPY command 284662306a36Sopenharmony_ci * 284762306a36Sopenharmony_ci * @dev_priv: Pointer to a device private struct. 284862306a36Sopenharmony_ci * @sw_context: The software context being used for this batch. 284962306a36Sopenharmony_ci * @header: Pointer to the command header in the command stream. 285062306a36Sopenharmony_ci */ 285162306a36Sopenharmony_cistatic int vmw_cmd_intra_surface_copy(struct vmw_private *dev_priv, 285262306a36Sopenharmony_ci struct vmw_sw_context *sw_context, 285362306a36Sopenharmony_ci SVGA3dCmdHeader *header) 285462306a36Sopenharmony_ci{ 285562306a36Sopenharmony_ci VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdIntraSurfaceCopy) = 285662306a36Sopenharmony_ci container_of(header, typeof(*cmd), header); 285762306a36Sopenharmony_ci 285862306a36Sopenharmony_ci if (!(dev_priv->capabilities2 & SVGA_CAP2_INTRA_SURFACE_COPY)) 285962306a36Sopenharmony_ci return -EINVAL; 286062306a36Sopenharmony_ci 286162306a36Sopenharmony_ci return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface, 286262306a36Sopenharmony_ci VMW_RES_DIRTY_SET, user_surface_converter, 286362306a36Sopenharmony_ci &cmd->body.surface.sid, NULL); 286462306a36Sopenharmony_ci} 286562306a36Sopenharmony_ci 286662306a36Sopenharmony_cistatic int vmw_cmd_sm5(struct vmw_private *dev_priv, 286762306a36Sopenharmony_ci struct vmw_sw_context *sw_context, 286862306a36Sopenharmony_ci SVGA3dCmdHeader *header) 286962306a36Sopenharmony_ci{ 287062306a36Sopenharmony_ci if (!has_sm5_context(dev_priv)) 287162306a36Sopenharmony_ci return -EINVAL; 287262306a36Sopenharmony_ci 287362306a36Sopenharmony_ci return 0; 287462306a36Sopenharmony_ci} 287562306a36Sopenharmony_ci 287662306a36Sopenharmony_cistatic int vmw_cmd_sm5_view_define(struct vmw_private *dev_priv, 287762306a36Sopenharmony_ci struct vmw_sw_context *sw_context, 287862306a36Sopenharmony_ci SVGA3dCmdHeader *header) 287962306a36Sopenharmony_ci{ 288062306a36Sopenharmony_ci if (!has_sm5_context(dev_priv)) 288162306a36Sopenharmony_ci return -EINVAL; 288262306a36Sopenharmony_ci 288362306a36Sopenharmony_ci return vmw_cmd_dx_view_define(dev_priv, sw_context, header); 288462306a36Sopenharmony_ci} 288562306a36Sopenharmony_ci 288662306a36Sopenharmony_cistatic int vmw_cmd_sm5_view_remove(struct vmw_private *dev_priv, 288762306a36Sopenharmony_ci struct vmw_sw_context *sw_context, 288862306a36Sopenharmony_ci SVGA3dCmdHeader *header) 288962306a36Sopenharmony_ci{ 289062306a36Sopenharmony_ci if (!has_sm5_context(dev_priv)) 289162306a36Sopenharmony_ci return -EINVAL; 289262306a36Sopenharmony_ci 289362306a36Sopenharmony_ci return vmw_cmd_dx_view_remove(dev_priv, sw_context, header); 289462306a36Sopenharmony_ci} 289562306a36Sopenharmony_ci 289662306a36Sopenharmony_cistatic int vmw_cmd_clear_uav_uint(struct vmw_private *dev_priv, 289762306a36Sopenharmony_ci struct vmw_sw_context *sw_context, 289862306a36Sopenharmony_ci SVGA3dCmdHeader *header) 289962306a36Sopenharmony_ci{ 290062306a36Sopenharmony_ci struct { 290162306a36Sopenharmony_ci SVGA3dCmdHeader header; 290262306a36Sopenharmony_ci SVGA3dCmdDXClearUAViewUint body; 290362306a36Sopenharmony_ci } *cmd = container_of(header, typeof(*cmd), header); 290462306a36Sopenharmony_ci struct vmw_resource *ret; 290562306a36Sopenharmony_ci 290662306a36Sopenharmony_ci if (!has_sm5_context(dev_priv)) 290762306a36Sopenharmony_ci return -EINVAL; 290862306a36Sopenharmony_ci 290962306a36Sopenharmony_ci ret = vmw_view_id_val_add(sw_context, vmw_view_ua, 291062306a36Sopenharmony_ci cmd->body.uaViewId); 291162306a36Sopenharmony_ci 291262306a36Sopenharmony_ci return PTR_ERR_OR_ZERO(ret); 291362306a36Sopenharmony_ci} 291462306a36Sopenharmony_ci 291562306a36Sopenharmony_cistatic int vmw_cmd_clear_uav_float(struct vmw_private *dev_priv, 291662306a36Sopenharmony_ci struct vmw_sw_context *sw_context, 291762306a36Sopenharmony_ci SVGA3dCmdHeader *header) 291862306a36Sopenharmony_ci{ 291962306a36Sopenharmony_ci struct { 292062306a36Sopenharmony_ci SVGA3dCmdHeader header; 292162306a36Sopenharmony_ci SVGA3dCmdDXClearUAViewFloat body; 292262306a36Sopenharmony_ci } *cmd = container_of(header, typeof(*cmd), header); 292362306a36Sopenharmony_ci struct vmw_resource *ret; 292462306a36Sopenharmony_ci 292562306a36Sopenharmony_ci if (!has_sm5_context(dev_priv)) 292662306a36Sopenharmony_ci return -EINVAL; 292762306a36Sopenharmony_ci 292862306a36Sopenharmony_ci ret = vmw_view_id_val_add(sw_context, vmw_view_ua, 292962306a36Sopenharmony_ci cmd->body.uaViewId); 293062306a36Sopenharmony_ci 293162306a36Sopenharmony_ci return PTR_ERR_OR_ZERO(ret); 293262306a36Sopenharmony_ci} 293362306a36Sopenharmony_ci 293462306a36Sopenharmony_cistatic int vmw_cmd_set_uav(struct vmw_private *dev_priv, 293562306a36Sopenharmony_ci struct vmw_sw_context *sw_context, 293662306a36Sopenharmony_ci SVGA3dCmdHeader *header) 293762306a36Sopenharmony_ci{ 293862306a36Sopenharmony_ci struct { 293962306a36Sopenharmony_ci SVGA3dCmdHeader header; 294062306a36Sopenharmony_ci SVGA3dCmdDXSetUAViews body; 294162306a36Sopenharmony_ci } *cmd = container_of(header, typeof(*cmd), header); 294262306a36Sopenharmony_ci u32 num_uav = (cmd->header.size - sizeof(cmd->body)) / 294362306a36Sopenharmony_ci sizeof(SVGA3dUAViewId); 294462306a36Sopenharmony_ci int ret; 294562306a36Sopenharmony_ci 294662306a36Sopenharmony_ci if (!has_sm5_context(dev_priv)) 294762306a36Sopenharmony_ci return -EINVAL; 294862306a36Sopenharmony_ci 294962306a36Sopenharmony_ci if (num_uav > vmw_max_num_uavs(dev_priv)) { 295062306a36Sopenharmony_ci VMW_DEBUG_USER("Invalid UAV binding.\n"); 295162306a36Sopenharmony_ci return -EINVAL; 295262306a36Sopenharmony_ci } 295362306a36Sopenharmony_ci 295462306a36Sopenharmony_ci ret = vmw_view_bindings_add(sw_context, vmw_view_ua, 295562306a36Sopenharmony_ci vmw_ctx_binding_uav, 0, (void *)&cmd[1], 295662306a36Sopenharmony_ci num_uav, 0); 295762306a36Sopenharmony_ci if (ret) 295862306a36Sopenharmony_ci return ret; 295962306a36Sopenharmony_ci 296062306a36Sopenharmony_ci vmw_binding_add_uav_index(sw_context->dx_ctx_node->staged, 0, 296162306a36Sopenharmony_ci cmd->body.uavSpliceIndex); 296262306a36Sopenharmony_ci 296362306a36Sopenharmony_ci return ret; 296462306a36Sopenharmony_ci} 296562306a36Sopenharmony_ci 296662306a36Sopenharmony_cistatic int vmw_cmd_set_cs_uav(struct vmw_private *dev_priv, 296762306a36Sopenharmony_ci struct vmw_sw_context *sw_context, 296862306a36Sopenharmony_ci SVGA3dCmdHeader *header) 296962306a36Sopenharmony_ci{ 297062306a36Sopenharmony_ci struct { 297162306a36Sopenharmony_ci SVGA3dCmdHeader header; 297262306a36Sopenharmony_ci SVGA3dCmdDXSetCSUAViews body; 297362306a36Sopenharmony_ci } *cmd = container_of(header, typeof(*cmd), header); 297462306a36Sopenharmony_ci u32 num_uav = (cmd->header.size - sizeof(cmd->body)) / 297562306a36Sopenharmony_ci sizeof(SVGA3dUAViewId); 297662306a36Sopenharmony_ci int ret; 297762306a36Sopenharmony_ci 297862306a36Sopenharmony_ci if (!has_sm5_context(dev_priv)) 297962306a36Sopenharmony_ci return -EINVAL; 298062306a36Sopenharmony_ci 298162306a36Sopenharmony_ci if (num_uav > vmw_max_num_uavs(dev_priv)) { 298262306a36Sopenharmony_ci VMW_DEBUG_USER("Invalid UAV binding.\n"); 298362306a36Sopenharmony_ci return -EINVAL; 298462306a36Sopenharmony_ci } 298562306a36Sopenharmony_ci 298662306a36Sopenharmony_ci ret = vmw_view_bindings_add(sw_context, vmw_view_ua, 298762306a36Sopenharmony_ci vmw_ctx_binding_cs_uav, 0, (void *)&cmd[1], 298862306a36Sopenharmony_ci num_uav, 0); 298962306a36Sopenharmony_ci if (ret) 299062306a36Sopenharmony_ci return ret; 299162306a36Sopenharmony_ci 299262306a36Sopenharmony_ci vmw_binding_add_uav_index(sw_context->dx_ctx_node->staged, 1, 299362306a36Sopenharmony_ci cmd->body.startIndex); 299462306a36Sopenharmony_ci 299562306a36Sopenharmony_ci return ret; 299662306a36Sopenharmony_ci} 299762306a36Sopenharmony_ci 299862306a36Sopenharmony_cistatic int vmw_cmd_dx_define_streamoutput(struct vmw_private *dev_priv, 299962306a36Sopenharmony_ci struct vmw_sw_context *sw_context, 300062306a36Sopenharmony_ci SVGA3dCmdHeader *header) 300162306a36Sopenharmony_ci{ 300262306a36Sopenharmony_ci struct vmw_ctx_validation_info *ctx_node = sw_context->dx_ctx_node; 300362306a36Sopenharmony_ci struct vmw_resource *res; 300462306a36Sopenharmony_ci struct { 300562306a36Sopenharmony_ci SVGA3dCmdHeader header; 300662306a36Sopenharmony_ci SVGA3dCmdDXDefineStreamOutputWithMob body; 300762306a36Sopenharmony_ci } *cmd = container_of(header, typeof(*cmd), header); 300862306a36Sopenharmony_ci int ret; 300962306a36Sopenharmony_ci 301062306a36Sopenharmony_ci if (!has_sm5_context(dev_priv)) 301162306a36Sopenharmony_ci return -EINVAL; 301262306a36Sopenharmony_ci 301362306a36Sopenharmony_ci if (!ctx_node) { 301462306a36Sopenharmony_ci DRM_ERROR("DX Context not set.\n"); 301562306a36Sopenharmony_ci return -EINVAL; 301662306a36Sopenharmony_ci } 301762306a36Sopenharmony_ci 301862306a36Sopenharmony_ci res = vmw_context_cotable(ctx_node->ctx, SVGA_COTABLE_STREAMOUTPUT); 301962306a36Sopenharmony_ci if (IS_ERR_OR_NULL(res)) 302062306a36Sopenharmony_ci return res ? PTR_ERR(res) : -EINVAL; 302162306a36Sopenharmony_ci ret = vmw_cotable_notify(res, cmd->body.soid); 302262306a36Sopenharmony_ci if (ret) 302362306a36Sopenharmony_ci return ret; 302462306a36Sopenharmony_ci 302562306a36Sopenharmony_ci return vmw_dx_streamoutput_add(sw_context->man, ctx_node->ctx, 302662306a36Sopenharmony_ci cmd->body.soid, 302762306a36Sopenharmony_ci &sw_context->staged_cmd_res); 302862306a36Sopenharmony_ci} 302962306a36Sopenharmony_ci 303062306a36Sopenharmony_cistatic int vmw_cmd_dx_destroy_streamoutput(struct vmw_private *dev_priv, 303162306a36Sopenharmony_ci struct vmw_sw_context *sw_context, 303262306a36Sopenharmony_ci SVGA3dCmdHeader *header) 303362306a36Sopenharmony_ci{ 303462306a36Sopenharmony_ci struct vmw_ctx_validation_info *ctx_node = sw_context->dx_ctx_node; 303562306a36Sopenharmony_ci struct vmw_resource *res; 303662306a36Sopenharmony_ci struct { 303762306a36Sopenharmony_ci SVGA3dCmdHeader header; 303862306a36Sopenharmony_ci SVGA3dCmdDXDestroyStreamOutput body; 303962306a36Sopenharmony_ci } *cmd = container_of(header, typeof(*cmd), header); 304062306a36Sopenharmony_ci 304162306a36Sopenharmony_ci if (!ctx_node) { 304262306a36Sopenharmony_ci DRM_ERROR("DX Context not set.\n"); 304362306a36Sopenharmony_ci return -EINVAL; 304462306a36Sopenharmony_ci } 304562306a36Sopenharmony_ci 304662306a36Sopenharmony_ci /* 304762306a36Sopenharmony_ci * When device does not support SM5 then streamoutput with mob command is 304862306a36Sopenharmony_ci * not available to user-space. Simply return in this case. 304962306a36Sopenharmony_ci */ 305062306a36Sopenharmony_ci if (!has_sm5_context(dev_priv)) 305162306a36Sopenharmony_ci return 0; 305262306a36Sopenharmony_ci 305362306a36Sopenharmony_ci /* 305462306a36Sopenharmony_ci * With SM5 capable device if lookup fails then user-space probably used 305562306a36Sopenharmony_ci * old streamoutput define command. Return without an error. 305662306a36Sopenharmony_ci */ 305762306a36Sopenharmony_ci res = vmw_dx_streamoutput_lookup(vmw_context_res_man(ctx_node->ctx), 305862306a36Sopenharmony_ci cmd->body.soid); 305962306a36Sopenharmony_ci if (IS_ERR(res)) 306062306a36Sopenharmony_ci return 0; 306162306a36Sopenharmony_ci 306262306a36Sopenharmony_ci return vmw_dx_streamoutput_remove(sw_context->man, cmd->body.soid, 306362306a36Sopenharmony_ci &sw_context->staged_cmd_res); 306462306a36Sopenharmony_ci} 306562306a36Sopenharmony_ci 306662306a36Sopenharmony_cistatic int vmw_cmd_dx_bind_streamoutput(struct vmw_private *dev_priv, 306762306a36Sopenharmony_ci struct vmw_sw_context *sw_context, 306862306a36Sopenharmony_ci SVGA3dCmdHeader *header) 306962306a36Sopenharmony_ci{ 307062306a36Sopenharmony_ci struct vmw_ctx_validation_info *ctx_node = sw_context->dx_ctx_node; 307162306a36Sopenharmony_ci struct vmw_resource *res; 307262306a36Sopenharmony_ci struct { 307362306a36Sopenharmony_ci SVGA3dCmdHeader header; 307462306a36Sopenharmony_ci SVGA3dCmdDXBindStreamOutput body; 307562306a36Sopenharmony_ci } *cmd = container_of(header, typeof(*cmd), header); 307662306a36Sopenharmony_ci int ret; 307762306a36Sopenharmony_ci 307862306a36Sopenharmony_ci if (!has_sm5_context(dev_priv)) 307962306a36Sopenharmony_ci return -EINVAL; 308062306a36Sopenharmony_ci 308162306a36Sopenharmony_ci if (!ctx_node) { 308262306a36Sopenharmony_ci DRM_ERROR("DX Context not set.\n"); 308362306a36Sopenharmony_ci return -EINVAL; 308462306a36Sopenharmony_ci } 308562306a36Sopenharmony_ci 308662306a36Sopenharmony_ci res = vmw_dx_streamoutput_lookup(vmw_context_res_man(ctx_node->ctx), 308762306a36Sopenharmony_ci cmd->body.soid); 308862306a36Sopenharmony_ci if (IS_ERR(res)) { 308962306a36Sopenharmony_ci DRM_ERROR("Could not find streamoutput to bind.\n"); 309062306a36Sopenharmony_ci return PTR_ERR(res); 309162306a36Sopenharmony_ci } 309262306a36Sopenharmony_ci 309362306a36Sopenharmony_ci vmw_dx_streamoutput_set_size(res, cmd->body.sizeInBytes); 309462306a36Sopenharmony_ci 309562306a36Sopenharmony_ci ret = vmw_execbuf_res_val_add(sw_context, res, VMW_RES_DIRTY_NONE, 309662306a36Sopenharmony_ci vmw_val_add_flag_noctx); 309762306a36Sopenharmony_ci if (ret) { 309862306a36Sopenharmony_ci DRM_ERROR("Error creating resource validation node.\n"); 309962306a36Sopenharmony_ci return ret; 310062306a36Sopenharmony_ci } 310162306a36Sopenharmony_ci 310262306a36Sopenharmony_ci return vmw_cmd_res_switch_backup(dev_priv, sw_context, res, 310362306a36Sopenharmony_ci &cmd->body.mobid, 310462306a36Sopenharmony_ci cmd->body.offsetInBytes); 310562306a36Sopenharmony_ci} 310662306a36Sopenharmony_ci 310762306a36Sopenharmony_cistatic int vmw_cmd_dx_set_streamoutput(struct vmw_private *dev_priv, 310862306a36Sopenharmony_ci struct vmw_sw_context *sw_context, 310962306a36Sopenharmony_ci SVGA3dCmdHeader *header) 311062306a36Sopenharmony_ci{ 311162306a36Sopenharmony_ci struct vmw_ctx_validation_info *ctx_node = sw_context->dx_ctx_node; 311262306a36Sopenharmony_ci struct vmw_resource *res; 311362306a36Sopenharmony_ci struct vmw_ctx_bindinfo_so binding; 311462306a36Sopenharmony_ci struct { 311562306a36Sopenharmony_ci SVGA3dCmdHeader header; 311662306a36Sopenharmony_ci SVGA3dCmdDXSetStreamOutput body; 311762306a36Sopenharmony_ci } *cmd = container_of(header, typeof(*cmd), header); 311862306a36Sopenharmony_ci int ret; 311962306a36Sopenharmony_ci 312062306a36Sopenharmony_ci if (!ctx_node) { 312162306a36Sopenharmony_ci DRM_ERROR("DX Context not set.\n"); 312262306a36Sopenharmony_ci return -EINVAL; 312362306a36Sopenharmony_ci } 312462306a36Sopenharmony_ci 312562306a36Sopenharmony_ci if (cmd->body.soid == SVGA3D_INVALID_ID) 312662306a36Sopenharmony_ci return 0; 312762306a36Sopenharmony_ci 312862306a36Sopenharmony_ci /* 312962306a36Sopenharmony_ci * When device does not support SM5 then streamoutput with mob command is 313062306a36Sopenharmony_ci * not available to user-space. Simply return in this case. 313162306a36Sopenharmony_ci */ 313262306a36Sopenharmony_ci if (!has_sm5_context(dev_priv)) 313362306a36Sopenharmony_ci return 0; 313462306a36Sopenharmony_ci 313562306a36Sopenharmony_ci /* 313662306a36Sopenharmony_ci * With SM5 capable device if lookup fails then user-space probably used 313762306a36Sopenharmony_ci * old streamoutput define command. Return without an error. 313862306a36Sopenharmony_ci */ 313962306a36Sopenharmony_ci res = vmw_dx_streamoutput_lookup(vmw_context_res_man(ctx_node->ctx), 314062306a36Sopenharmony_ci cmd->body.soid); 314162306a36Sopenharmony_ci if (IS_ERR(res)) { 314262306a36Sopenharmony_ci return 0; 314362306a36Sopenharmony_ci } 314462306a36Sopenharmony_ci 314562306a36Sopenharmony_ci ret = vmw_execbuf_res_val_add(sw_context, res, VMW_RES_DIRTY_NONE, 314662306a36Sopenharmony_ci vmw_val_add_flag_noctx); 314762306a36Sopenharmony_ci if (ret) { 314862306a36Sopenharmony_ci DRM_ERROR("Error creating resource validation node.\n"); 314962306a36Sopenharmony_ci return ret; 315062306a36Sopenharmony_ci } 315162306a36Sopenharmony_ci 315262306a36Sopenharmony_ci binding.bi.ctx = ctx_node->ctx; 315362306a36Sopenharmony_ci binding.bi.res = res; 315462306a36Sopenharmony_ci binding.bi.bt = vmw_ctx_binding_so; 315562306a36Sopenharmony_ci binding.slot = 0; /* Only one SO set to context at a time. */ 315662306a36Sopenharmony_ci 315762306a36Sopenharmony_ci vmw_binding_add(sw_context->dx_ctx_node->staged, &binding.bi, 0, 315862306a36Sopenharmony_ci binding.slot); 315962306a36Sopenharmony_ci 316062306a36Sopenharmony_ci return ret; 316162306a36Sopenharmony_ci} 316262306a36Sopenharmony_ci 316362306a36Sopenharmony_cistatic int vmw_cmd_indexed_instanced_indirect(struct vmw_private *dev_priv, 316462306a36Sopenharmony_ci struct vmw_sw_context *sw_context, 316562306a36Sopenharmony_ci SVGA3dCmdHeader *header) 316662306a36Sopenharmony_ci{ 316762306a36Sopenharmony_ci struct vmw_draw_indexed_instanced_indirect_cmd { 316862306a36Sopenharmony_ci SVGA3dCmdHeader header; 316962306a36Sopenharmony_ci SVGA3dCmdDXDrawIndexedInstancedIndirect body; 317062306a36Sopenharmony_ci } *cmd = container_of(header, typeof(*cmd), header); 317162306a36Sopenharmony_ci 317262306a36Sopenharmony_ci if (!has_sm5_context(dev_priv)) 317362306a36Sopenharmony_ci return -EINVAL; 317462306a36Sopenharmony_ci 317562306a36Sopenharmony_ci return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface, 317662306a36Sopenharmony_ci VMW_RES_DIRTY_NONE, user_surface_converter, 317762306a36Sopenharmony_ci &cmd->body.argsBufferSid, NULL); 317862306a36Sopenharmony_ci} 317962306a36Sopenharmony_ci 318062306a36Sopenharmony_cistatic int vmw_cmd_instanced_indirect(struct vmw_private *dev_priv, 318162306a36Sopenharmony_ci struct vmw_sw_context *sw_context, 318262306a36Sopenharmony_ci SVGA3dCmdHeader *header) 318362306a36Sopenharmony_ci{ 318462306a36Sopenharmony_ci struct vmw_draw_instanced_indirect_cmd { 318562306a36Sopenharmony_ci SVGA3dCmdHeader header; 318662306a36Sopenharmony_ci SVGA3dCmdDXDrawInstancedIndirect body; 318762306a36Sopenharmony_ci } *cmd = container_of(header, typeof(*cmd), header); 318862306a36Sopenharmony_ci 318962306a36Sopenharmony_ci if (!has_sm5_context(dev_priv)) 319062306a36Sopenharmony_ci return -EINVAL; 319162306a36Sopenharmony_ci 319262306a36Sopenharmony_ci return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface, 319362306a36Sopenharmony_ci VMW_RES_DIRTY_NONE, user_surface_converter, 319462306a36Sopenharmony_ci &cmd->body.argsBufferSid, NULL); 319562306a36Sopenharmony_ci} 319662306a36Sopenharmony_ci 319762306a36Sopenharmony_cistatic int vmw_cmd_dispatch_indirect(struct vmw_private *dev_priv, 319862306a36Sopenharmony_ci struct vmw_sw_context *sw_context, 319962306a36Sopenharmony_ci SVGA3dCmdHeader *header) 320062306a36Sopenharmony_ci{ 320162306a36Sopenharmony_ci struct vmw_dispatch_indirect_cmd { 320262306a36Sopenharmony_ci SVGA3dCmdHeader header; 320362306a36Sopenharmony_ci SVGA3dCmdDXDispatchIndirect body; 320462306a36Sopenharmony_ci } *cmd = container_of(header, typeof(*cmd), header); 320562306a36Sopenharmony_ci 320662306a36Sopenharmony_ci if (!has_sm5_context(dev_priv)) 320762306a36Sopenharmony_ci return -EINVAL; 320862306a36Sopenharmony_ci 320962306a36Sopenharmony_ci return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface, 321062306a36Sopenharmony_ci VMW_RES_DIRTY_NONE, user_surface_converter, 321162306a36Sopenharmony_ci &cmd->body.argsBufferSid, NULL); 321262306a36Sopenharmony_ci} 321362306a36Sopenharmony_ci 321462306a36Sopenharmony_cistatic int vmw_cmd_check_not_3d(struct vmw_private *dev_priv, 321562306a36Sopenharmony_ci struct vmw_sw_context *sw_context, 321662306a36Sopenharmony_ci void *buf, uint32_t *size) 321762306a36Sopenharmony_ci{ 321862306a36Sopenharmony_ci uint32_t size_remaining = *size; 321962306a36Sopenharmony_ci uint32_t cmd_id; 322062306a36Sopenharmony_ci 322162306a36Sopenharmony_ci cmd_id = ((uint32_t *)buf)[0]; 322262306a36Sopenharmony_ci switch (cmd_id) { 322362306a36Sopenharmony_ci case SVGA_CMD_UPDATE: 322462306a36Sopenharmony_ci *size = sizeof(uint32_t) + sizeof(SVGAFifoCmdUpdate); 322562306a36Sopenharmony_ci break; 322662306a36Sopenharmony_ci case SVGA_CMD_DEFINE_GMRFB: 322762306a36Sopenharmony_ci *size = sizeof(uint32_t) + sizeof(SVGAFifoCmdDefineGMRFB); 322862306a36Sopenharmony_ci break; 322962306a36Sopenharmony_ci case SVGA_CMD_BLIT_GMRFB_TO_SCREEN: 323062306a36Sopenharmony_ci *size = sizeof(uint32_t) + sizeof(SVGAFifoCmdBlitGMRFBToScreen); 323162306a36Sopenharmony_ci break; 323262306a36Sopenharmony_ci case SVGA_CMD_BLIT_SCREEN_TO_GMRFB: 323362306a36Sopenharmony_ci *size = sizeof(uint32_t) + sizeof(SVGAFifoCmdBlitGMRFBToScreen); 323462306a36Sopenharmony_ci break; 323562306a36Sopenharmony_ci default: 323662306a36Sopenharmony_ci VMW_DEBUG_USER("Unsupported SVGA command: %u.\n", cmd_id); 323762306a36Sopenharmony_ci return -EINVAL; 323862306a36Sopenharmony_ci } 323962306a36Sopenharmony_ci 324062306a36Sopenharmony_ci if (*size > size_remaining) { 324162306a36Sopenharmony_ci VMW_DEBUG_USER("Invalid SVGA command (size mismatch): %u.\n", 324262306a36Sopenharmony_ci cmd_id); 324362306a36Sopenharmony_ci return -EINVAL; 324462306a36Sopenharmony_ci } 324562306a36Sopenharmony_ci 324662306a36Sopenharmony_ci if (unlikely(!sw_context->kernel)) { 324762306a36Sopenharmony_ci VMW_DEBUG_USER("Kernel only SVGA command: %u.\n", cmd_id); 324862306a36Sopenharmony_ci return -EPERM; 324962306a36Sopenharmony_ci } 325062306a36Sopenharmony_ci 325162306a36Sopenharmony_ci if (cmd_id == SVGA_CMD_DEFINE_GMRFB) 325262306a36Sopenharmony_ci return vmw_cmd_check_define_gmrfb(dev_priv, sw_context, buf); 325362306a36Sopenharmony_ci 325462306a36Sopenharmony_ci return 0; 325562306a36Sopenharmony_ci} 325662306a36Sopenharmony_ci 325762306a36Sopenharmony_cistatic const struct vmw_cmd_entry vmw_cmd_entries[SVGA_3D_CMD_MAX] = { 325862306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_SURFACE_DEFINE, &vmw_cmd_invalid, 325962306a36Sopenharmony_ci false, false, false), 326062306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_SURFACE_DESTROY, &vmw_cmd_invalid, 326162306a36Sopenharmony_ci false, false, false), 326262306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_SURFACE_COPY, &vmw_cmd_surface_copy_check, 326362306a36Sopenharmony_ci true, false, false), 326462306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_SURFACE_STRETCHBLT, &vmw_cmd_stretch_blt_check, 326562306a36Sopenharmony_ci true, false, false), 326662306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_SURFACE_DMA, &vmw_cmd_dma, 326762306a36Sopenharmony_ci true, false, false), 326862306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_CONTEXT_DEFINE, &vmw_cmd_invalid, 326962306a36Sopenharmony_ci false, false, false), 327062306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_CONTEXT_DESTROY, &vmw_cmd_invalid, 327162306a36Sopenharmony_ci false, false, false), 327262306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_SETTRANSFORM, &vmw_cmd_cid_check, 327362306a36Sopenharmony_ci true, false, false), 327462306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_SETZRANGE, &vmw_cmd_cid_check, 327562306a36Sopenharmony_ci true, false, false), 327662306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_SETRENDERSTATE, &vmw_cmd_cid_check, 327762306a36Sopenharmony_ci true, false, false), 327862306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_SETRENDERTARGET, 327962306a36Sopenharmony_ci &vmw_cmd_set_render_target_check, true, false, false), 328062306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_SETTEXTURESTATE, &vmw_cmd_tex_state, 328162306a36Sopenharmony_ci true, false, false), 328262306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_SETMATERIAL, &vmw_cmd_cid_check, 328362306a36Sopenharmony_ci true, false, false), 328462306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_SETLIGHTDATA, &vmw_cmd_cid_check, 328562306a36Sopenharmony_ci true, false, false), 328662306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_SETLIGHTENABLED, &vmw_cmd_cid_check, 328762306a36Sopenharmony_ci true, false, false), 328862306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_SETVIEWPORT, &vmw_cmd_cid_check, 328962306a36Sopenharmony_ci true, false, false), 329062306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_SETCLIPPLANE, &vmw_cmd_cid_check, 329162306a36Sopenharmony_ci true, false, false), 329262306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_CLEAR, &vmw_cmd_cid_check, 329362306a36Sopenharmony_ci true, false, false), 329462306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_PRESENT, &vmw_cmd_present_check, 329562306a36Sopenharmony_ci false, false, false), 329662306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_SHADER_DEFINE, &vmw_cmd_shader_define, 329762306a36Sopenharmony_ci true, false, false), 329862306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_SHADER_DESTROY, &vmw_cmd_shader_destroy, 329962306a36Sopenharmony_ci true, false, false), 330062306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_SET_SHADER, &vmw_cmd_set_shader, 330162306a36Sopenharmony_ci true, false, false), 330262306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_SET_SHADER_CONST, &vmw_cmd_set_shader_const, 330362306a36Sopenharmony_ci true, false, false), 330462306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DRAW_PRIMITIVES, &vmw_cmd_draw, 330562306a36Sopenharmony_ci true, false, false), 330662306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_SETSCISSORRECT, &vmw_cmd_cid_check, 330762306a36Sopenharmony_ci true, false, false), 330862306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_BEGIN_QUERY, &vmw_cmd_begin_query, 330962306a36Sopenharmony_ci true, false, false), 331062306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_END_QUERY, &vmw_cmd_end_query, 331162306a36Sopenharmony_ci true, false, false), 331262306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_WAIT_FOR_QUERY, &vmw_cmd_wait_query, 331362306a36Sopenharmony_ci true, false, false), 331462306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_PRESENT_READBACK, &vmw_cmd_ok, 331562306a36Sopenharmony_ci true, false, false), 331662306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_BLIT_SURFACE_TO_SCREEN, 331762306a36Sopenharmony_ci &vmw_cmd_blt_surf_screen_check, false, false, false), 331862306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_SURFACE_DEFINE_V2, &vmw_cmd_invalid, 331962306a36Sopenharmony_ci false, false, false), 332062306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_GENERATE_MIPMAPS, &vmw_cmd_invalid, 332162306a36Sopenharmony_ci false, false, false), 332262306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_ACTIVATE_SURFACE, &vmw_cmd_invalid, 332362306a36Sopenharmony_ci false, false, false), 332462306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DEACTIVATE_SURFACE, &vmw_cmd_invalid, 332562306a36Sopenharmony_ci false, false, false), 332662306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_SCREEN_DMA, &vmw_cmd_invalid, 332762306a36Sopenharmony_ci false, false, false), 332862306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DEAD1, &vmw_cmd_invalid, 332962306a36Sopenharmony_ci false, false, false), 333062306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DEAD2, &vmw_cmd_invalid, 333162306a36Sopenharmony_ci false, false, false), 333262306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DEAD12, &vmw_cmd_invalid, false, false, false), 333362306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DEAD13, &vmw_cmd_invalid, false, false, false), 333462306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DEAD14, &vmw_cmd_invalid, false, false, false), 333562306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DEAD15, &vmw_cmd_invalid, false, false, false), 333662306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DEAD16, &vmw_cmd_invalid, false, false, false), 333762306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DEAD17, &vmw_cmd_invalid, false, false, false), 333862306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_SET_OTABLE_BASE, &vmw_cmd_invalid, 333962306a36Sopenharmony_ci false, false, true), 334062306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_READBACK_OTABLE, &vmw_cmd_invalid, 334162306a36Sopenharmony_ci false, false, true), 334262306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DEFINE_GB_MOB, &vmw_cmd_invalid, 334362306a36Sopenharmony_ci false, false, true), 334462306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DESTROY_GB_MOB, &vmw_cmd_invalid, 334562306a36Sopenharmony_ci false, false, true), 334662306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_REDEFINE_GB_MOB64, &vmw_cmd_invalid, 334762306a36Sopenharmony_ci false, false, true), 334862306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_UPDATE_GB_MOB_MAPPING, &vmw_cmd_invalid, 334962306a36Sopenharmony_ci false, false, true), 335062306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DEFINE_GB_SURFACE, &vmw_cmd_invalid, 335162306a36Sopenharmony_ci false, false, true), 335262306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DESTROY_GB_SURFACE, &vmw_cmd_invalid, 335362306a36Sopenharmony_ci false, false, true), 335462306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_BIND_GB_SURFACE, &vmw_cmd_bind_gb_surface, 335562306a36Sopenharmony_ci true, false, true), 335662306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_COND_BIND_GB_SURFACE, &vmw_cmd_invalid, 335762306a36Sopenharmony_ci false, false, true), 335862306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_UPDATE_GB_IMAGE, &vmw_cmd_update_gb_image, 335962306a36Sopenharmony_ci true, false, true), 336062306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_UPDATE_GB_SURFACE, 336162306a36Sopenharmony_ci &vmw_cmd_update_gb_surface, true, false, true), 336262306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_READBACK_GB_IMAGE, 336362306a36Sopenharmony_ci &vmw_cmd_readback_gb_image, true, false, true), 336462306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_READBACK_GB_SURFACE, 336562306a36Sopenharmony_ci &vmw_cmd_readback_gb_surface, true, false, true), 336662306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_INVALIDATE_GB_IMAGE, 336762306a36Sopenharmony_ci &vmw_cmd_invalidate_gb_image, true, false, true), 336862306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_INVALIDATE_GB_SURFACE, 336962306a36Sopenharmony_ci &vmw_cmd_invalidate_gb_surface, true, false, true), 337062306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DEFINE_GB_CONTEXT, &vmw_cmd_invalid, 337162306a36Sopenharmony_ci false, false, true), 337262306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DESTROY_GB_CONTEXT, &vmw_cmd_invalid, 337362306a36Sopenharmony_ci false, false, true), 337462306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_BIND_GB_CONTEXT, &vmw_cmd_invalid, 337562306a36Sopenharmony_ci false, false, true), 337662306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_READBACK_GB_CONTEXT, &vmw_cmd_invalid, 337762306a36Sopenharmony_ci false, false, true), 337862306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_INVALIDATE_GB_CONTEXT, &vmw_cmd_invalid, 337962306a36Sopenharmony_ci false, false, true), 338062306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DEFINE_GB_SHADER, &vmw_cmd_invalid, 338162306a36Sopenharmony_ci false, false, true), 338262306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_BIND_GB_SHADER, &vmw_cmd_bind_gb_shader, 338362306a36Sopenharmony_ci true, false, true), 338462306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DESTROY_GB_SHADER, &vmw_cmd_invalid, 338562306a36Sopenharmony_ci false, false, true), 338662306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_SET_OTABLE_BASE64, &vmw_cmd_invalid, 338762306a36Sopenharmony_ci false, false, false), 338862306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_BEGIN_GB_QUERY, &vmw_cmd_begin_gb_query, 338962306a36Sopenharmony_ci true, false, true), 339062306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_END_GB_QUERY, &vmw_cmd_end_gb_query, 339162306a36Sopenharmony_ci true, false, true), 339262306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_WAIT_FOR_GB_QUERY, &vmw_cmd_wait_gb_query, 339362306a36Sopenharmony_ci true, false, true), 339462306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_NOP, &vmw_cmd_ok, 339562306a36Sopenharmony_ci true, false, true), 339662306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_NOP_ERROR, &vmw_cmd_ok, 339762306a36Sopenharmony_ci true, false, true), 339862306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_ENABLE_GART, &vmw_cmd_invalid, 339962306a36Sopenharmony_ci false, false, true), 340062306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DISABLE_GART, &vmw_cmd_invalid, 340162306a36Sopenharmony_ci false, false, true), 340262306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_MAP_MOB_INTO_GART, &vmw_cmd_invalid, 340362306a36Sopenharmony_ci false, false, true), 340462306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_UNMAP_GART_RANGE, &vmw_cmd_invalid, 340562306a36Sopenharmony_ci false, false, true), 340662306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DEFINE_GB_SCREENTARGET, &vmw_cmd_invalid, 340762306a36Sopenharmony_ci false, false, true), 340862306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DESTROY_GB_SCREENTARGET, &vmw_cmd_invalid, 340962306a36Sopenharmony_ci false, false, true), 341062306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_BIND_GB_SCREENTARGET, &vmw_cmd_invalid, 341162306a36Sopenharmony_ci false, false, true), 341262306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_UPDATE_GB_SCREENTARGET, &vmw_cmd_invalid, 341362306a36Sopenharmony_ci false, false, true), 341462306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_READBACK_GB_IMAGE_PARTIAL, &vmw_cmd_invalid, 341562306a36Sopenharmony_ci false, false, true), 341662306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_INVALIDATE_GB_IMAGE_PARTIAL, &vmw_cmd_invalid, 341762306a36Sopenharmony_ci false, false, true), 341862306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_SET_GB_SHADERCONSTS_INLINE, &vmw_cmd_cid_check, 341962306a36Sopenharmony_ci true, false, true), 342062306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_GB_SCREEN_DMA, &vmw_cmd_invalid, 342162306a36Sopenharmony_ci false, false, true), 342262306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_BIND_GB_SURFACE_WITH_PITCH, &vmw_cmd_invalid, 342362306a36Sopenharmony_ci false, false, true), 342462306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_GB_MOB_FENCE, &vmw_cmd_invalid, 342562306a36Sopenharmony_ci false, false, true), 342662306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DEFINE_GB_SURFACE_V2, &vmw_cmd_invalid, 342762306a36Sopenharmony_ci false, false, true), 342862306a36Sopenharmony_ci 342962306a36Sopenharmony_ci /* SM commands */ 343062306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_DEFINE_CONTEXT, &vmw_cmd_invalid, 343162306a36Sopenharmony_ci false, false, true), 343262306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_DESTROY_CONTEXT, &vmw_cmd_invalid, 343362306a36Sopenharmony_ci false, false, true), 343462306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_BIND_CONTEXT, &vmw_cmd_invalid, 343562306a36Sopenharmony_ci false, false, true), 343662306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_READBACK_CONTEXT, &vmw_cmd_invalid, 343762306a36Sopenharmony_ci false, false, true), 343862306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_INVALIDATE_CONTEXT, &vmw_cmd_invalid, 343962306a36Sopenharmony_ci false, false, true), 344062306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_SET_SINGLE_CONSTANT_BUFFER, 344162306a36Sopenharmony_ci &vmw_cmd_dx_set_single_constant_buffer, true, false, true), 344262306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_SET_SHADER_RESOURCES, 344362306a36Sopenharmony_ci &vmw_cmd_dx_set_shader_res, true, false, true), 344462306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_SET_SHADER, &vmw_cmd_dx_set_shader, 344562306a36Sopenharmony_ci true, false, true), 344662306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_SET_SAMPLERS, &vmw_cmd_dx_cid_check, 344762306a36Sopenharmony_ci true, false, true), 344862306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_DRAW, &vmw_cmd_dx_cid_check, 344962306a36Sopenharmony_ci true, false, true), 345062306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_DRAW_INDEXED, &vmw_cmd_dx_cid_check, 345162306a36Sopenharmony_ci true, false, true), 345262306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_DRAW_INSTANCED, &vmw_cmd_dx_cid_check, 345362306a36Sopenharmony_ci true, false, true), 345462306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_DRAW_INDEXED_INSTANCED, 345562306a36Sopenharmony_ci &vmw_cmd_dx_cid_check, true, false, true), 345662306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_DRAW_AUTO, &vmw_cmd_dx_cid_check, 345762306a36Sopenharmony_ci true, false, true), 345862306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_SET_VERTEX_BUFFERS, 345962306a36Sopenharmony_ci &vmw_cmd_dx_set_vertex_buffers, true, false, true), 346062306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_SET_INDEX_BUFFER, 346162306a36Sopenharmony_ci &vmw_cmd_dx_set_index_buffer, true, false, true), 346262306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_SET_RENDERTARGETS, 346362306a36Sopenharmony_ci &vmw_cmd_dx_set_rendertargets, true, false, true), 346462306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_SET_BLEND_STATE, &vmw_cmd_dx_cid_check, 346562306a36Sopenharmony_ci true, false, true), 346662306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_SET_DEPTHSTENCIL_STATE, 346762306a36Sopenharmony_ci &vmw_cmd_dx_cid_check, true, false, true), 346862306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_SET_RASTERIZER_STATE, 346962306a36Sopenharmony_ci &vmw_cmd_dx_cid_check, true, false, true), 347062306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_DEFINE_QUERY, &vmw_cmd_dx_define_query, 347162306a36Sopenharmony_ci true, false, true), 347262306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_DESTROY_QUERY, &vmw_cmd_dx_cid_check, 347362306a36Sopenharmony_ci true, false, true), 347462306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_BIND_QUERY, &vmw_cmd_dx_bind_query, 347562306a36Sopenharmony_ci true, false, true), 347662306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_SET_QUERY_OFFSET, 347762306a36Sopenharmony_ci &vmw_cmd_dx_cid_check, true, false, true), 347862306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_BEGIN_QUERY, &vmw_cmd_dx_cid_check, 347962306a36Sopenharmony_ci true, false, true), 348062306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_END_QUERY, &vmw_cmd_dx_cid_check, 348162306a36Sopenharmony_ci true, false, true), 348262306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_READBACK_QUERY, &vmw_cmd_invalid, 348362306a36Sopenharmony_ci true, false, true), 348462306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_SET_PREDICATION, &vmw_cmd_dx_cid_check, 348562306a36Sopenharmony_ci true, false, true), 348662306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_SET_VIEWPORTS, &vmw_cmd_dx_cid_check, 348762306a36Sopenharmony_ci true, false, true), 348862306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_SET_SCISSORRECTS, &vmw_cmd_dx_cid_check, 348962306a36Sopenharmony_ci true, false, true), 349062306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_CLEAR_RENDERTARGET_VIEW, 349162306a36Sopenharmony_ci &vmw_cmd_dx_clear_rendertarget_view, true, false, true), 349262306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_CLEAR_DEPTHSTENCIL_VIEW, 349362306a36Sopenharmony_ci &vmw_cmd_dx_clear_depthstencil_view, true, false, true), 349462306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_PRED_COPY, &vmw_cmd_invalid, 349562306a36Sopenharmony_ci true, false, true), 349662306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_GENMIPS, &vmw_cmd_dx_genmips, 349762306a36Sopenharmony_ci true, false, true), 349862306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_UPDATE_SUBRESOURCE, 349962306a36Sopenharmony_ci &vmw_cmd_dx_check_subresource, true, false, true), 350062306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_READBACK_SUBRESOURCE, 350162306a36Sopenharmony_ci &vmw_cmd_dx_check_subresource, true, false, true), 350262306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_INVALIDATE_SUBRESOURCE, 350362306a36Sopenharmony_ci &vmw_cmd_dx_check_subresource, true, false, true), 350462306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_DEFINE_SHADERRESOURCE_VIEW, 350562306a36Sopenharmony_ci &vmw_cmd_dx_view_define, true, false, true), 350662306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_DESTROY_SHADERRESOURCE_VIEW, 350762306a36Sopenharmony_ci &vmw_cmd_dx_view_remove, true, false, true), 350862306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_DEFINE_RENDERTARGET_VIEW, 350962306a36Sopenharmony_ci &vmw_cmd_dx_view_define, true, false, true), 351062306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_DESTROY_RENDERTARGET_VIEW, 351162306a36Sopenharmony_ci &vmw_cmd_dx_view_remove, true, false, true), 351262306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_DEFINE_DEPTHSTENCIL_VIEW, 351362306a36Sopenharmony_ci &vmw_cmd_dx_view_define, true, false, true), 351462306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_DESTROY_DEPTHSTENCIL_VIEW, 351562306a36Sopenharmony_ci &vmw_cmd_dx_view_remove, true, false, true), 351662306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_DEFINE_ELEMENTLAYOUT, 351762306a36Sopenharmony_ci &vmw_cmd_dx_so_define, true, false, true), 351862306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_DESTROY_ELEMENTLAYOUT, 351962306a36Sopenharmony_ci &vmw_cmd_dx_cid_check, true, false, true), 352062306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_DEFINE_BLEND_STATE, 352162306a36Sopenharmony_ci &vmw_cmd_dx_so_define, true, false, true), 352262306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_DESTROY_BLEND_STATE, 352362306a36Sopenharmony_ci &vmw_cmd_dx_cid_check, true, false, true), 352462306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_DEFINE_DEPTHSTENCIL_STATE, 352562306a36Sopenharmony_ci &vmw_cmd_dx_so_define, true, false, true), 352662306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_DESTROY_DEPTHSTENCIL_STATE, 352762306a36Sopenharmony_ci &vmw_cmd_dx_cid_check, true, false, true), 352862306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_DEFINE_RASTERIZER_STATE, 352962306a36Sopenharmony_ci &vmw_cmd_dx_so_define, true, false, true), 353062306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_DESTROY_RASTERIZER_STATE, 353162306a36Sopenharmony_ci &vmw_cmd_dx_cid_check, true, false, true), 353262306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_DEFINE_SAMPLER_STATE, 353362306a36Sopenharmony_ci &vmw_cmd_dx_so_define, true, false, true), 353462306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_DESTROY_SAMPLER_STATE, 353562306a36Sopenharmony_ci &vmw_cmd_dx_cid_check, true, false, true), 353662306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_DEFINE_SHADER, 353762306a36Sopenharmony_ci &vmw_cmd_dx_define_shader, true, false, true), 353862306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_DESTROY_SHADER, 353962306a36Sopenharmony_ci &vmw_cmd_dx_destroy_shader, true, false, true), 354062306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_BIND_SHADER, 354162306a36Sopenharmony_ci &vmw_cmd_dx_bind_shader, true, false, true), 354262306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_DEFINE_STREAMOUTPUT, 354362306a36Sopenharmony_ci &vmw_cmd_dx_so_define, true, false, true), 354462306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_DESTROY_STREAMOUTPUT, 354562306a36Sopenharmony_ci &vmw_cmd_dx_destroy_streamoutput, true, false, true), 354662306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_SET_STREAMOUTPUT, 354762306a36Sopenharmony_ci &vmw_cmd_dx_set_streamoutput, true, false, true), 354862306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_SET_SOTARGETS, 354962306a36Sopenharmony_ci &vmw_cmd_dx_set_so_targets, true, false, true), 355062306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_SET_INPUT_LAYOUT, 355162306a36Sopenharmony_ci &vmw_cmd_dx_cid_check, true, false, true), 355262306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_SET_TOPOLOGY, 355362306a36Sopenharmony_ci &vmw_cmd_dx_cid_check, true, false, true), 355462306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_BUFFER_COPY, 355562306a36Sopenharmony_ci &vmw_cmd_buffer_copy_check, true, false, true), 355662306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_PRED_COPY_REGION, 355762306a36Sopenharmony_ci &vmw_cmd_pred_copy_check, true, false, true), 355862306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_TRANSFER_FROM_BUFFER, 355962306a36Sopenharmony_ci &vmw_cmd_dx_transfer_from_buffer, 356062306a36Sopenharmony_ci true, false, true), 356162306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_SET_VS_CONSTANT_BUFFER_OFFSET, 356262306a36Sopenharmony_ci &vmw_cmd_dx_set_constant_buffer_offset, 356362306a36Sopenharmony_ci true, false, true), 356462306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_SET_PS_CONSTANT_BUFFER_OFFSET, 356562306a36Sopenharmony_ci &vmw_cmd_dx_set_constant_buffer_offset, 356662306a36Sopenharmony_ci true, false, true), 356762306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_SET_GS_CONSTANT_BUFFER_OFFSET, 356862306a36Sopenharmony_ci &vmw_cmd_dx_set_constant_buffer_offset, 356962306a36Sopenharmony_ci true, false, true), 357062306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_SET_HS_CONSTANT_BUFFER_OFFSET, 357162306a36Sopenharmony_ci &vmw_cmd_dx_set_constant_buffer_offset, 357262306a36Sopenharmony_ci true, false, true), 357362306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_SET_DS_CONSTANT_BUFFER_OFFSET, 357462306a36Sopenharmony_ci &vmw_cmd_dx_set_constant_buffer_offset, 357562306a36Sopenharmony_ci true, false, true), 357662306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_SET_CS_CONSTANT_BUFFER_OFFSET, 357762306a36Sopenharmony_ci &vmw_cmd_dx_set_constant_buffer_offset, 357862306a36Sopenharmony_ci true, false, true), 357962306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_INTRA_SURFACE_COPY, &vmw_cmd_intra_surface_copy, 358062306a36Sopenharmony_ci true, false, true), 358162306a36Sopenharmony_ci 358262306a36Sopenharmony_ci /* 358362306a36Sopenharmony_ci * SM5 commands 358462306a36Sopenharmony_ci */ 358562306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_DEFINE_UA_VIEW, &vmw_cmd_sm5_view_define, 358662306a36Sopenharmony_ci true, false, true), 358762306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_DESTROY_UA_VIEW, &vmw_cmd_sm5_view_remove, 358862306a36Sopenharmony_ci true, false, true), 358962306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_CLEAR_UA_VIEW_UINT, &vmw_cmd_clear_uav_uint, 359062306a36Sopenharmony_ci true, false, true), 359162306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_CLEAR_UA_VIEW_FLOAT, 359262306a36Sopenharmony_ci &vmw_cmd_clear_uav_float, true, false, true), 359362306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_COPY_STRUCTURE_COUNT, &vmw_cmd_invalid, true, 359462306a36Sopenharmony_ci false, true), 359562306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_SET_UA_VIEWS, &vmw_cmd_set_uav, true, false, 359662306a36Sopenharmony_ci true), 359762306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_DRAW_INDEXED_INSTANCED_INDIRECT, 359862306a36Sopenharmony_ci &vmw_cmd_indexed_instanced_indirect, true, false, true), 359962306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_DRAW_INSTANCED_INDIRECT, 360062306a36Sopenharmony_ci &vmw_cmd_instanced_indirect, true, false, true), 360162306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_DISPATCH, &vmw_cmd_sm5, true, false, true), 360262306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_DISPATCH_INDIRECT, 360362306a36Sopenharmony_ci &vmw_cmd_dispatch_indirect, true, false, true), 360462306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_SET_CS_UA_VIEWS, &vmw_cmd_set_cs_uav, true, 360562306a36Sopenharmony_ci false, true), 360662306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_DEFINE_DEPTHSTENCIL_VIEW_V2, 360762306a36Sopenharmony_ci &vmw_cmd_sm5_view_define, true, false, true), 360862306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_DEFINE_STREAMOUTPUT_WITH_MOB, 360962306a36Sopenharmony_ci &vmw_cmd_dx_define_streamoutput, true, false, true), 361062306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_BIND_STREAMOUTPUT, 361162306a36Sopenharmony_ci &vmw_cmd_dx_bind_streamoutput, true, false, true), 361262306a36Sopenharmony_ci VMW_CMD_DEF(SVGA_3D_CMD_DX_DEFINE_RASTERIZER_STATE_V2, 361362306a36Sopenharmony_ci &vmw_cmd_dx_so_define, true, false, true), 361462306a36Sopenharmony_ci}; 361562306a36Sopenharmony_ci 361662306a36Sopenharmony_cibool vmw_cmd_describe(const void *buf, u32 *size, char const **cmd) 361762306a36Sopenharmony_ci{ 361862306a36Sopenharmony_ci u32 cmd_id = ((u32 *) buf)[0]; 361962306a36Sopenharmony_ci 362062306a36Sopenharmony_ci if (cmd_id >= SVGA_CMD_MAX) { 362162306a36Sopenharmony_ci SVGA3dCmdHeader *header = (SVGA3dCmdHeader *) buf; 362262306a36Sopenharmony_ci const struct vmw_cmd_entry *entry; 362362306a36Sopenharmony_ci 362462306a36Sopenharmony_ci *size = header->size + sizeof(SVGA3dCmdHeader); 362562306a36Sopenharmony_ci cmd_id = header->id; 362662306a36Sopenharmony_ci if (cmd_id >= SVGA_3D_CMD_MAX) 362762306a36Sopenharmony_ci return false; 362862306a36Sopenharmony_ci 362962306a36Sopenharmony_ci cmd_id -= SVGA_3D_CMD_BASE; 363062306a36Sopenharmony_ci entry = &vmw_cmd_entries[cmd_id]; 363162306a36Sopenharmony_ci *cmd = entry->cmd_name; 363262306a36Sopenharmony_ci return true; 363362306a36Sopenharmony_ci } 363462306a36Sopenharmony_ci 363562306a36Sopenharmony_ci switch (cmd_id) { 363662306a36Sopenharmony_ci case SVGA_CMD_UPDATE: 363762306a36Sopenharmony_ci *cmd = "SVGA_CMD_UPDATE"; 363862306a36Sopenharmony_ci *size = sizeof(u32) + sizeof(SVGAFifoCmdUpdate); 363962306a36Sopenharmony_ci break; 364062306a36Sopenharmony_ci case SVGA_CMD_DEFINE_GMRFB: 364162306a36Sopenharmony_ci *cmd = "SVGA_CMD_DEFINE_GMRFB"; 364262306a36Sopenharmony_ci *size = sizeof(u32) + sizeof(SVGAFifoCmdDefineGMRFB); 364362306a36Sopenharmony_ci break; 364462306a36Sopenharmony_ci case SVGA_CMD_BLIT_GMRFB_TO_SCREEN: 364562306a36Sopenharmony_ci *cmd = "SVGA_CMD_BLIT_GMRFB_TO_SCREEN"; 364662306a36Sopenharmony_ci *size = sizeof(u32) + sizeof(SVGAFifoCmdBlitGMRFBToScreen); 364762306a36Sopenharmony_ci break; 364862306a36Sopenharmony_ci case SVGA_CMD_BLIT_SCREEN_TO_GMRFB: 364962306a36Sopenharmony_ci *cmd = "SVGA_CMD_BLIT_SCREEN_TO_GMRFB"; 365062306a36Sopenharmony_ci *size = sizeof(u32) + sizeof(SVGAFifoCmdBlitGMRFBToScreen); 365162306a36Sopenharmony_ci break; 365262306a36Sopenharmony_ci default: 365362306a36Sopenharmony_ci *cmd = "UNKNOWN"; 365462306a36Sopenharmony_ci *size = 0; 365562306a36Sopenharmony_ci return false; 365662306a36Sopenharmony_ci } 365762306a36Sopenharmony_ci 365862306a36Sopenharmony_ci return true; 365962306a36Sopenharmony_ci} 366062306a36Sopenharmony_ci 366162306a36Sopenharmony_cistatic int vmw_cmd_check(struct vmw_private *dev_priv, 366262306a36Sopenharmony_ci struct vmw_sw_context *sw_context, void *buf, 366362306a36Sopenharmony_ci uint32_t *size) 366462306a36Sopenharmony_ci{ 366562306a36Sopenharmony_ci uint32_t cmd_id; 366662306a36Sopenharmony_ci uint32_t size_remaining = *size; 366762306a36Sopenharmony_ci SVGA3dCmdHeader *header = (SVGA3dCmdHeader *) buf; 366862306a36Sopenharmony_ci int ret; 366962306a36Sopenharmony_ci const struct vmw_cmd_entry *entry; 367062306a36Sopenharmony_ci bool gb = dev_priv->capabilities & SVGA_CAP_GBOBJECTS; 367162306a36Sopenharmony_ci 367262306a36Sopenharmony_ci cmd_id = ((uint32_t *)buf)[0]; 367362306a36Sopenharmony_ci /* Handle any none 3D commands */ 367462306a36Sopenharmony_ci if (unlikely(cmd_id < SVGA_CMD_MAX)) 367562306a36Sopenharmony_ci return vmw_cmd_check_not_3d(dev_priv, sw_context, buf, size); 367662306a36Sopenharmony_ci 367762306a36Sopenharmony_ci 367862306a36Sopenharmony_ci cmd_id = header->id; 367962306a36Sopenharmony_ci *size = header->size + sizeof(SVGA3dCmdHeader); 368062306a36Sopenharmony_ci 368162306a36Sopenharmony_ci cmd_id -= SVGA_3D_CMD_BASE; 368262306a36Sopenharmony_ci if (unlikely(*size > size_remaining)) 368362306a36Sopenharmony_ci goto out_invalid; 368462306a36Sopenharmony_ci 368562306a36Sopenharmony_ci if (unlikely(cmd_id >= SVGA_3D_CMD_MAX - SVGA_3D_CMD_BASE)) 368662306a36Sopenharmony_ci goto out_invalid; 368762306a36Sopenharmony_ci 368862306a36Sopenharmony_ci entry = &vmw_cmd_entries[cmd_id]; 368962306a36Sopenharmony_ci if (unlikely(!entry->func)) 369062306a36Sopenharmony_ci goto out_invalid; 369162306a36Sopenharmony_ci 369262306a36Sopenharmony_ci if (unlikely(!entry->user_allow && !sw_context->kernel)) 369362306a36Sopenharmony_ci goto out_privileged; 369462306a36Sopenharmony_ci 369562306a36Sopenharmony_ci if (unlikely(entry->gb_disable && gb)) 369662306a36Sopenharmony_ci goto out_old; 369762306a36Sopenharmony_ci 369862306a36Sopenharmony_ci if (unlikely(entry->gb_enable && !gb)) 369962306a36Sopenharmony_ci goto out_new; 370062306a36Sopenharmony_ci 370162306a36Sopenharmony_ci ret = entry->func(dev_priv, sw_context, header); 370262306a36Sopenharmony_ci if (unlikely(ret != 0)) { 370362306a36Sopenharmony_ci VMW_DEBUG_USER("SVGA3D command: %d failed with error %d\n", 370462306a36Sopenharmony_ci cmd_id + SVGA_3D_CMD_BASE, ret); 370562306a36Sopenharmony_ci return ret; 370662306a36Sopenharmony_ci } 370762306a36Sopenharmony_ci 370862306a36Sopenharmony_ci return 0; 370962306a36Sopenharmony_ciout_invalid: 371062306a36Sopenharmony_ci VMW_DEBUG_USER("Invalid SVGA3D command: %d\n", 371162306a36Sopenharmony_ci cmd_id + SVGA_3D_CMD_BASE); 371262306a36Sopenharmony_ci return -EINVAL; 371362306a36Sopenharmony_ciout_privileged: 371462306a36Sopenharmony_ci VMW_DEBUG_USER("Privileged SVGA3D command: %d\n", 371562306a36Sopenharmony_ci cmd_id + SVGA_3D_CMD_BASE); 371662306a36Sopenharmony_ci return -EPERM; 371762306a36Sopenharmony_ciout_old: 371862306a36Sopenharmony_ci VMW_DEBUG_USER("Deprecated (disallowed) SVGA3D command: %d\n", 371962306a36Sopenharmony_ci cmd_id + SVGA_3D_CMD_BASE); 372062306a36Sopenharmony_ci return -EINVAL; 372162306a36Sopenharmony_ciout_new: 372262306a36Sopenharmony_ci VMW_DEBUG_USER("SVGA3D command: %d not supported by virtual device.\n", 372362306a36Sopenharmony_ci cmd_id + SVGA_3D_CMD_BASE); 372462306a36Sopenharmony_ci return -EINVAL; 372562306a36Sopenharmony_ci} 372662306a36Sopenharmony_ci 372762306a36Sopenharmony_cistatic int vmw_cmd_check_all(struct vmw_private *dev_priv, 372862306a36Sopenharmony_ci struct vmw_sw_context *sw_context, void *buf, 372962306a36Sopenharmony_ci uint32_t size) 373062306a36Sopenharmony_ci{ 373162306a36Sopenharmony_ci int32_t cur_size = size; 373262306a36Sopenharmony_ci int ret; 373362306a36Sopenharmony_ci 373462306a36Sopenharmony_ci sw_context->buf_start = buf; 373562306a36Sopenharmony_ci 373662306a36Sopenharmony_ci while (cur_size > 0) { 373762306a36Sopenharmony_ci size = cur_size; 373862306a36Sopenharmony_ci ret = vmw_cmd_check(dev_priv, sw_context, buf, &size); 373962306a36Sopenharmony_ci if (unlikely(ret != 0)) 374062306a36Sopenharmony_ci return ret; 374162306a36Sopenharmony_ci buf = (void *)((unsigned long) buf + size); 374262306a36Sopenharmony_ci cur_size -= size; 374362306a36Sopenharmony_ci } 374462306a36Sopenharmony_ci 374562306a36Sopenharmony_ci if (unlikely(cur_size != 0)) { 374662306a36Sopenharmony_ci VMW_DEBUG_USER("Command verifier out of sync.\n"); 374762306a36Sopenharmony_ci return -EINVAL; 374862306a36Sopenharmony_ci } 374962306a36Sopenharmony_ci 375062306a36Sopenharmony_ci return 0; 375162306a36Sopenharmony_ci} 375262306a36Sopenharmony_ci 375362306a36Sopenharmony_cistatic void vmw_free_relocations(struct vmw_sw_context *sw_context) 375462306a36Sopenharmony_ci{ 375562306a36Sopenharmony_ci /* Memory is validation context memory, so no need to free it */ 375662306a36Sopenharmony_ci INIT_LIST_HEAD(&sw_context->bo_relocations); 375762306a36Sopenharmony_ci} 375862306a36Sopenharmony_ci 375962306a36Sopenharmony_cistatic void vmw_apply_relocations(struct vmw_sw_context *sw_context) 376062306a36Sopenharmony_ci{ 376162306a36Sopenharmony_ci struct vmw_relocation *reloc; 376262306a36Sopenharmony_ci struct ttm_buffer_object *bo; 376362306a36Sopenharmony_ci 376462306a36Sopenharmony_ci list_for_each_entry(reloc, &sw_context->bo_relocations, head) { 376562306a36Sopenharmony_ci bo = &reloc->vbo->tbo; 376662306a36Sopenharmony_ci switch (bo->resource->mem_type) { 376762306a36Sopenharmony_ci case TTM_PL_VRAM: 376862306a36Sopenharmony_ci reloc->location->offset += bo->resource->start << PAGE_SHIFT; 376962306a36Sopenharmony_ci reloc->location->gmrId = SVGA_GMR_FRAMEBUFFER; 377062306a36Sopenharmony_ci break; 377162306a36Sopenharmony_ci case VMW_PL_GMR: 377262306a36Sopenharmony_ci reloc->location->gmrId = bo->resource->start; 377362306a36Sopenharmony_ci break; 377462306a36Sopenharmony_ci case VMW_PL_MOB: 377562306a36Sopenharmony_ci *reloc->mob_loc = bo->resource->start; 377662306a36Sopenharmony_ci break; 377762306a36Sopenharmony_ci default: 377862306a36Sopenharmony_ci BUG(); 377962306a36Sopenharmony_ci } 378062306a36Sopenharmony_ci } 378162306a36Sopenharmony_ci vmw_free_relocations(sw_context); 378262306a36Sopenharmony_ci} 378362306a36Sopenharmony_ci 378462306a36Sopenharmony_cistatic int vmw_resize_cmd_bounce(struct vmw_sw_context *sw_context, 378562306a36Sopenharmony_ci uint32_t size) 378662306a36Sopenharmony_ci{ 378762306a36Sopenharmony_ci if (likely(sw_context->cmd_bounce_size >= size)) 378862306a36Sopenharmony_ci return 0; 378962306a36Sopenharmony_ci 379062306a36Sopenharmony_ci if (sw_context->cmd_bounce_size == 0) 379162306a36Sopenharmony_ci sw_context->cmd_bounce_size = VMWGFX_CMD_BOUNCE_INIT_SIZE; 379262306a36Sopenharmony_ci 379362306a36Sopenharmony_ci while (sw_context->cmd_bounce_size < size) { 379462306a36Sopenharmony_ci sw_context->cmd_bounce_size = 379562306a36Sopenharmony_ci PAGE_ALIGN(sw_context->cmd_bounce_size + 379662306a36Sopenharmony_ci (sw_context->cmd_bounce_size >> 1)); 379762306a36Sopenharmony_ci } 379862306a36Sopenharmony_ci 379962306a36Sopenharmony_ci vfree(sw_context->cmd_bounce); 380062306a36Sopenharmony_ci sw_context->cmd_bounce = vmalloc(sw_context->cmd_bounce_size); 380162306a36Sopenharmony_ci 380262306a36Sopenharmony_ci if (sw_context->cmd_bounce == NULL) { 380362306a36Sopenharmony_ci VMW_DEBUG_USER("Failed to allocate command bounce buffer.\n"); 380462306a36Sopenharmony_ci sw_context->cmd_bounce_size = 0; 380562306a36Sopenharmony_ci return -ENOMEM; 380662306a36Sopenharmony_ci } 380762306a36Sopenharmony_ci 380862306a36Sopenharmony_ci return 0; 380962306a36Sopenharmony_ci} 381062306a36Sopenharmony_ci 381162306a36Sopenharmony_ci/* 381262306a36Sopenharmony_ci * vmw_execbuf_fence_commands - create and submit a command stream fence 381362306a36Sopenharmony_ci * 381462306a36Sopenharmony_ci * Creates a fence object and submits a command stream marker. 381562306a36Sopenharmony_ci * If this fails for some reason, We sync the fifo and return NULL. 381662306a36Sopenharmony_ci * It is then safe to fence buffers with a NULL pointer. 381762306a36Sopenharmony_ci * 381862306a36Sopenharmony_ci * If @p_handle is not NULL @file_priv must also not be NULL. Creates a 381962306a36Sopenharmony_ci * userspace handle if @p_handle is not NULL, otherwise not. 382062306a36Sopenharmony_ci */ 382162306a36Sopenharmony_ci 382262306a36Sopenharmony_ciint vmw_execbuf_fence_commands(struct drm_file *file_priv, 382362306a36Sopenharmony_ci struct vmw_private *dev_priv, 382462306a36Sopenharmony_ci struct vmw_fence_obj **p_fence, 382562306a36Sopenharmony_ci uint32_t *p_handle) 382662306a36Sopenharmony_ci{ 382762306a36Sopenharmony_ci uint32_t sequence; 382862306a36Sopenharmony_ci int ret; 382962306a36Sopenharmony_ci bool synced = false; 383062306a36Sopenharmony_ci 383162306a36Sopenharmony_ci /* p_handle implies file_priv. */ 383262306a36Sopenharmony_ci BUG_ON(p_handle != NULL && file_priv == NULL); 383362306a36Sopenharmony_ci 383462306a36Sopenharmony_ci ret = vmw_cmd_send_fence(dev_priv, &sequence); 383562306a36Sopenharmony_ci if (unlikely(ret != 0)) { 383662306a36Sopenharmony_ci VMW_DEBUG_USER("Fence submission error. Syncing.\n"); 383762306a36Sopenharmony_ci synced = true; 383862306a36Sopenharmony_ci } 383962306a36Sopenharmony_ci 384062306a36Sopenharmony_ci if (p_handle != NULL) 384162306a36Sopenharmony_ci ret = vmw_user_fence_create(file_priv, dev_priv->fman, 384262306a36Sopenharmony_ci sequence, p_fence, p_handle); 384362306a36Sopenharmony_ci else 384462306a36Sopenharmony_ci ret = vmw_fence_create(dev_priv->fman, sequence, p_fence); 384562306a36Sopenharmony_ci 384662306a36Sopenharmony_ci if (unlikely(ret != 0 && !synced)) { 384762306a36Sopenharmony_ci (void) vmw_fallback_wait(dev_priv, false, false, sequence, 384862306a36Sopenharmony_ci false, VMW_FENCE_WAIT_TIMEOUT); 384962306a36Sopenharmony_ci *p_fence = NULL; 385062306a36Sopenharmony_ci } 385162306a36Sopenharmony_ci 385262306a36Sopenharmony_ci return ret; 385362306a36Sopenharmony_ci} 385462306a36Sopenharmony_ci 385562306a36Sopenharmony_ci/** 385662306a36Sopenharmony_ci * vmw_execbuf_copy_fence_user - copy fence object information to user-space. 385762306a36Sopenharmony_ci * 385862306a36Sopenharmony_ci * @dev_priv: Pointer to a vmw_private struct. 385962306a36Sopenharmony_ci * @vmw_fp: Pointer to the struct vmw_fpriv representing the calling file. 386062306a36Sopenharmony_ci * @ret: Return value from fence object creation. 386162306a36Sopenharmony_ci * @user_fence_rep: User space address of a struct drm_vmw_fence_rep to which 386262306a36Sopenharmony_ci * the information should be copied. 386362306a36Sopenharmony_ci * @fence: Pointer to the fenc object. 386462306a36Sopenharmony_ci * @fence_handle: User-space fence handle. 386562306a36Sopenharmony_ci * @out_fence_fd: exported file descriptor for the fence. -1 if not used 386662306a36Sopenharmony_ci * 386762306a36Sopenharmony_ci * This function copies fence information to user-space. If copying fails, the 386862306a36Sopenharmony_ci * user-space struct drm_vmw_fence_rep::error member is hopefully left 386962306a36Sopenharmony_ci * untouched, and if it's preloaded with an -EFAULT by user-space, the error 387062306a36Sopenharmony_ci * will hopefully be detected. 387162306a36Sopenharmony_ci * 387262306a36Sopenharmony_ci * Also if copying fails, user-space will be unable to signal the fence object 387362306a36Sopenharmony_ci * so we wait for it immediately, and then unreference the user-space reference. 387462306a36Sopenharmony_ci */ 387562306a36Sopenharmony_ciint 387662306a36Sopenharmony_civmw_execbuf_copy_fence_user(struct vmw_private *dev_priv, 387762306a36Sopenharmony_ci struct vmw_fpriv *vmw_fp, int ret, 387862306a36Sopenharmony_ci struct drm_vmw_fence_rep __user *user_fence_rep, 387962306a36Sopenharmony_ci struct vmw_fence_obj *fence, uint32_t fence_handle, 388062306a36Sopenharmony_ci int32_t out_fence_fd) 388162306a36Sopenharmony_ci{ 388262306a36Sopenharmony_ci struct drm_vmw_fence_rep fence_rep; 388362306a36Sopenharmony_ci 388462306a36Sopenharmony_ci if (user_fence_rep == NULL) 388562306a36Sopenharmony_ci return 0; 388662306a36Sopenharmony_ci 388762306a36Sopenharmony_ci memset(&fence_rep, 0, sizeof(fence_rep)); 388862306a36Sopenharmony_ci 388962306a36Sopenharmony_ci fence_rep.error = ret; 389062306a36Sopenharmony_ci fence_rep.fd = out_fence_fd; 389162306a36Sopenharmony_ci if (ret == 0) { 389262306a36Sopenharmony_ci BUG_ON(fence == NULL); 389362306a36Sopenharmony_ci 389462306a36Sopenharmony_ci fence_rep.handle = fence_handle; 389562306a36Sopenharmony_ci fence_rep.seqno = fence->base.seqno; 389662306a36Sopenharmony_ci vmw_update_seqno(dev_priv); 389762306a36Sopenharmony_ci fence_rep.passed_seqno = dev_priv->last_read_seqno; 389862306a36Sopenharmony_ci } 389962306a36Sopenharmony_ci 390062306a36Sopenharmony_ci /* 390162306a36Sopenharmony_ci * copy_to_user errors will be detected by user space not seeing 390262306a36Sopenharmony_ci * fence_rep::error filled in. Typically user-space would have pre-set 390362306a36Sopenharmony_ci * that member to -EFAULT. 390462306a36Sopenharmony_ci */ 390562306a36Sopenharmony_ci ret = copy_to_user(user_fence_rep, &fence_rep, 390662306a36Sopenharmony_ci sizeof(fence_rep)); 390762306a36Sopenharmony_ci 390862306a36Sopenharmony_ci /* 390962306a36Sopenharmony_ci * User-space lost the fence object. We need to sync and unreference the 391062306a36Sopenharmony_ci * handle. 391162306a36Sopenharmony_ci */ 391262306a36Sopenharmony_ci if (unlikely(ret != 0) && (fence_rep.error == 0)) { 391362306a36Sopenharmony_ci ttm_ref_object_base_unref(vmw_fp->tfile, fence_handle); 391462306a36Sopenharmony_ci VMW_DEBUG_USER("Fence copy error. Syncing.\n"); 391562306a36Sopenharmony_ci (void) vmw_fence_obj_wait(fence, false, false, 391662306a36Sopenharmony_ci VMW_FENCE_WAIT_TIMEOUT); 391762306a36Sopenharmony_ci } 391862306a36Sopenharmony_ci 391962306a36Sopenharmony_ci return ret ? -EFAULT : 0; 392062306a36Sopenharmony_ci} 392162306a36Sopenharmony_ci 392262306a36Sopenharmony_ci/** 392362306a36Sopenharmony_ci * vmw_execbuf_submit_fifo - Patch a command batch and submit it using the fifo. 392462306a36Sopenharmony_ci * 392562306a36Sopenharmony_ci * @dev_priv: Pointer to a device private structure. 392662306a36Sopenharmony_ci * @kernel_commands: Pointer to the unpatched command batch. 392762306a36Sopenharmony_ci * @command_size: Size of the unpatched command batch. 392862306a36Sopenharmony_ci * @sw_context: Structure holding the relocation lists. 392962306a36Sopenharmony_ci * 393062306a36Sopenharmony_ci * Side effects: If this function returns 0, then the command batch pointed to 393162306a36Sopenharmony_ci * by @kernel_commands will have been modified. 393262306a36Sopenharmony_ci */ 393362306a36Sopenharmony_cistatic int vmw_execbuf_submit_fifo(struct vmw_private *dev_priv, 393462306a36Sopenharmony_ci void *kernel_commands, u32 command_size, 393562306a36Sopenharmony_ci struct vmw_sw_context *sw_context) 393662306a36Sopenharmony_ci{ 393762306a36Sopenharmony_ci void *cmd; 393862306a36Sopenharmony_ci 393962306a36Sopenharmony_ci if (sw_context->dx_ctx_node) 394062306a36Sopenharmony_ci cmd = VMW_CMD_CTX_RESERVE(dev_priv, command_size, 394162306a36Sopenharmony_ci sw_context->dx_ctx_node->ctx->id); 394262306a36Sopenharmony_ci else 394362306a36Sopenharmony_ci cmd = VMW_CMD_RESERVE(dev_priv, command_size); 394462306a36Sopenharmony_ci 394562306a36Sopenharmony_ci if (!cmd) 394662306a36Sopenharmony_ci return -ENOMEM; 394762306a36Sopenharmony_ci 394862306a36Sopenharmony_ci vmw_apply_relocations(sw_context); 394962306a36Sopenharmony_ci memcpy(cmd, kernel_commands, command_size); 395062306a36Sopenharmony_ci vmw_resource_relocations_apply(cmd, &sw_context->res_relocations); 395162306a36Sopenharmony_ci vmw_resource_relocations_free(&sw_context->res_relocations); 395262306a36Sopenharmony_ci vmw_cmd_commit(dev_priv, command_size); 395362306a36Sopenharmony_ci 395462306a36Sopenharmony_ci return 0; 395562306a36Sopenharmony_ci} 395662306a36Sopenharmony_ci 395762306a36Sopenharmony_ci/** 395862306a36Sopenharmony_ci * vmw_execbuf_submit_cmdbuf - Patch a command batch and submit it using the 395962306a36Sopenharmony_ci * command buffer manager. 396062306a36Sopenharmony_ci * 396162306a36Sopenharmony_ci * @dev_priv: Pointer to a device private structure. 396262306a36Sopenharmony_ci * @header: Opaque handle to the command buffer allocation. 396362306a36Sopenharmony_ci * @command_size: Size of the unpatched command batch. 396462306a36Sopenharmony_ci * @sw_context: Structure holding the relocation lists. 396562306a36Sopenharmony_ci * 396662306a36Sopenharmony_ci * Side effects: If this function returns 0, then the command buffer represented 396762306a36Sopenharmony_ci * by @header will have been modified. 396862306a36Sopenharmony_ci */ 396962306a36Sopenharmony_cistatic int vmw_execbuf_submit_cmdbuf(struct vmw_private *dev_priv, 397062306a36Sopenharmony_ci struct vmw_cmdbuf_header *header, 397162306a36Sopenharmony_ci u32 command_size, 397262306a36Sopenharmony_ci struct vmw_sw_context *sw_context) 397362306a36Sopenharmony_ci{ 397462306a36Sopenharmony_ci u32 id = ((sw_context->dx_ctx_node) ? sw_context->dx_ctx_node->ctx->id : 397562306a36Sopenharmony_ci SVGA3D_INVALID_ID); 397662306a36Sopenharmony_ci void *cmd = vmw_cmdbuf_reserve(dev_priv->cman, command_size, id, false, 397762306a36Sopenharmony_ci header); 397862306a36Sopenharmony_ci 397962306a36Sopenharmony_ci vmw_apply_relocations(sw_context); 398062306a36Sopenharmony_ci vmw_resource_relocations_apply(cmd, &sw_context->res_relocations); 398162306a36Sopenharmony_ci vmw_resource_relocations_free(&sw_context->res_relocations); 398262306a36Sopenharmony_ci vmw_cmdbuf_commit(dev_priv->cman, command_size, header, false); 398362306a36Sopenharmony_ci 398462306a36Sopenharmony_ci return 0; 398562306a36Sopenharmony_ci} 398662306a36Sopenharmony_ci 398762306a36Sopenharmony_ci/** 398862306a36Sopenharmony_ci * vmw_execbuf_cmdbuf - Prepare, if possible, a user-space command batch for 398962306a36Sopenharmony_ci * submission using a command buffer. 399062306a36Sopenharmony_ci * 399162306a36Sopenharmony_ci * @dev_priv: Pointer to a device private structure. 399262306a36Sopenharmony_ci * @user_commands: User-space pointer to the commands to be submitted. 399362306a36Sopenharmony_ci * @command_size: Size of the unpatched command batch. 399462306a36Sopenharmony_ci * @header: Out parameter returning the opaque pointer to the command buffer. 399562306a36Sopenharmony_ci * 399662306a36Sopenharmony_ci * This function checks whether we can use the command buffer manager for 399762306a36Sopenharmony_ci * submission and if so, creates a command buffer of suitable size and copies 399862306a36Sopenharmony_ci * the user data into that buffer. 399962306a36Sopenharmony_ci * 400062306a36Sopenharmony_ci * On successful return, the function returns a pointer to the data in the 400162306a36Sopenharmony_ci * command buffer and *@header is set to non-NULL. 400262306a36Sopenharmony_ci * 400362306a36Sopenharmony_ci * @kernel_commands: If command buffers could not be used, the function will 400462306a36Sopenharmony_ci * return the value of @kernel_commands on function call. That value may be 400562306a36Sopenharmony_ci * NULL. In that case, the value of *@header will be set to NULL. 400662306a36Sopenharmony_ci * 400762306a36Sopenharmony_ci * If an error is encountered, the function will return a pointer error value. 400862306a36Sopenharmony_ci * If the function is interrupted by a signal while sleeping, it will return 400962306a36Sopenharmony_ci * -ERESTARTSYS casted to a pointer error value. 401062306a36Sopenharmony_ci */ 401162306a36Sopenharmony_cistatic void *vmw_execbuf_cmdbuf(struct vmw_private *dev_priv, 401262306a36Sopenharmony_ci void __user *user_commands, 401362306a36Sopenharmony_ci void *kernel_commands, u32 command_size, 401462306a36Sopenharmony_ci struct vmw_cmdbuf_header **header) 401562306a36Sopenharmony_ci{ 401662306a36Sopenharmony_ci size_t cmdbuf_size; 401762306a36Sopenharmony_ci int ret; 401862306a36Sopenharmony_ci 401962306a36Sopenharmony_ci *header = NULL; 402062306a36Sopenharmony_ci if (command_size > SVGA_CB_MAX_SIZE) { 402162306a36Sopenharmony_ci VMW_DEBUG_USER("Command buffer is too large.\n"); 402262306a36Sopenharmony_ci return ERR_PTR(-EINVAL); 402362306a36Sopenharmony_ci } 402462306a36Sopenharmony_ci 402562306a36Sopenharmony_ci if (!dev_priv->cman || kernel_commands) 402662306a36Sopenharmony_ci return kernel_commands; 402762306a36Sopenharmony_ci 402862306a36Sopenharmony_ci /* If possible, add a little space for fencing. */ 402962306a36Sopenharmony_ci cmdbuf_size = command_size + 512; 403062306a36Sopenharmony_ci cmdbuf_size = min_t(size_t, cmdbuf_size, SVGA_CB_MAX_SIZE); 403162306a36Sopenharmony_ci kernel_commands = vmw_cmdbuf_alloc(dev_priv->cman, cmdbuf_size, true, 403262306a36Sopenharmony_ci header); 403362306a36Sopenharmony_ci if (IS_ERR(kernel_commands)) 403462306a36Sopenharmony_ci return kernel_commands; 403562306a36Sopenharmony_ci 403662306a36Sopenharmony_ci ret = copy_from_user(kernel_commands, user_commands, command_size); 403762306a36Sopenharmony_ci if (ret) { 403862306a36Sopenharmony_ci VMW_DEBUG_USER("Failed copying commands.\n"); 403962306a36Sopenharmony_ci vmw_cmdbuf_header_free(*header); 404062306a36Sopenharmony_ci *header = NULL; 404162306a36Sopenharmony_ci return ERR_PTR(-EFAULT); 404262306a36Sopenharmony_ci } 404362306a36Sopenharmony_ci 404462306a36Sopenharmony_ci return kernel_commands; 404562306a36Sopenharmony_ci} 404662306a36Sopenharmony_ci 404762306a36Sopenharmony_cistatic int vmw_execbuf_tie_context(struct vmw_private *dev_priv, 404862306a36Sopenharmony_ci struct vmw_sw_context *sw_context, 404962306a36Sopenharmony_ci uint32_t handle) 405062306a36Sopenharmony_ci{ 405162306a36Sopenharmony_ci struct vmw_resource *res; 405262306a36Sopenharmony_ci int ret; 405362306a36Sopenharmony_ci unsigned int size; 405462306a36Sopenharmony_ci 405562306a36Sopenharmony_ci if (handle == SVGA3D_INVALID_ID) 405662306a36Sopenharmony_ci return 0; 405762306a36Sopenharmony_ci 405862306a36Sopenharmony_ci size = vmw_execbuf_res_size(dev_priv, vmw_res_dx_context); 405962306a36Sopenharmony_ci ret = vmw_validation_preload_res(sw_context->ctx, size); 406062306a36Sopenharmony_ci if (ret) 406162306a36Sopenharmony_ci return ret; 406262306a36Sopenharmony_ci 406362306a36Sopenharmony_ci ret = vmw_user_resource_lookup_handle 406462306a36Sopenharmony_ci (dev_priv, sw_context->fp->tfile, handle, 406562306a36Sopenharmony_ci user_context_converter, &res); 406662306a36Sopenharmony_ci if (ret != 0) { 406762306a36Sopenharmony_ci VMW_DEBUG_USER("Could not find or user DX context 0x%08x.\n", 406862306a36Sopenharmony_ci (unsigned int) handle); 406962306a36Sopenharmony_ci return ret; 407062306a36Sopenharmony_ci } 407162306a36Sopenharmony_ci 407262306a36Sopenharmony_ci ret = vmw_execbuf_res_val_add(sw_context, res, VMW_RES_DIRTY_SET, 407362306a36Sopenharmony_ci vmw_val_add_flag_none); 407462306a36Sopenharmony_ci if (unlikely(ret != 0)) { 407562306a36Sopenharmony_ci vmw_resource_unreference(&res); 407662306a36Sopenharmony_ci return ret; 407762306a36Sopenharmony_ci } 407862306a36Sopenharmony_ci 407962306a36Sopenharmony_ci sw_context->dx_ctx_node = vmw_execbuf_info_from_res(sw_context, res); 408062306a36Sopenharmony_ci sw_context->man = vmw_context_res_man(res); 408162306a36Sopenharmony_ci 408262306a36Sopenharmony_ci vmw_resource_unreference(&res); 408362306a36Sopenharmony_ci return 0; 408462306a36Sopenharmony_ci} 408562306a36Sopenharmony_ci 408662306a36Sopenharmony_ciint vmw_execbuf_process(struct drm_file *file_priv, 408762306a36Sopenharmony_ci struct vmw_private *dev_priv, 408862306a36Sopenharmony_ci void __user *user_commands, void *kernel_commands, 408962306a36Sopenharmony_ci uint32_t command_size, uint64_t throttle_us, 409062306a36Sopenharmony_ci uint32_t dx_context_handle, 409162306a36Sopenharmony_ci struct drm_vmw_fence_rep __user *user_fence_rep, 409262306a36Sopenharmony_ci struct vmw_fence_obj **out_fence, uint32_t flags) 409362306a36Sopenharmony_ci{ 409462306a36Sopenharmony_ci struct vmw_sw_context *sw_context = &dev_priv->ctx; 409562306a36Sopenharmony_ci struct vmw_fence_obj *fence = NULL; 409662306a36Sopenharmony_ci struct vmw_cmdbuf_header *header; 409762306a36Sopenharmony_ci uint32_t handle = 0; 409862306a36Sopenharmony_ci int ret; 409962306a36Sopenharmony_ci int32_t out_fence_fd = -1; 410062306a36Sopenharmony_ci struct sync_file *sync_file = NULL; 410162306a36Sopenharmony_ci DECLARE_VAL_CONTEXT(val_ctx, sw_context, 1); 410262306a36Sopenharmony_ci 410362306a36Sopenharmony_ci if (flags & DRM_VMW_EXECBUF_FLAG_EXPORT_FENCE_FD) { 410462306a36Sopenharmony_ci out_fence_fd = get_unused_fd_flags(O_CLOEXEC); 410562306a36Sopenharmony_ci if (out_fence_fd < 0) { 410662306a36Sopenharmony_ci VMW_DEBUG_USER("Failed to get a fence fd.\n"); 410762306a36Sopenharmony_ci return out_fence_fd; 410862306a36Sopenharmony_ci } 410962306a36Sopenharmony_ci } 411062306a36Sopenharmony_ci 411162306a36Sopenharmony_ci if (throttle_us) { 411262306a36Sopenharmony_ci VMW_DEBUG_USER("Throttling is no longer supported.\n"); 411362306a36Sopenharmony_ci } 411462306a36Sopenharmony_ci 411562306a36Sopenharmony_ci kernel_commands = vmw_execbuf_cmdbuf(dev_priv, user_commands, 411662306a36Sopenharmony_ci kernel_commands, command_size, 411762306a36Sopenharmony_ci &header); 411862306a36Sopenharmony_ci if (IS_ERR(kernel_commands)) { 411962306a36Sopenharmony_ci ret = PTR_ERR(kernel_commands); 412062306a36Sopenharmony_ci goto out_free_fence_fd; 412162306a36Sopenharmony_ci } 412262306a36Sopenharmony_ci 412362306a36Sopenharmony_ci ret = mutex_lock_interruptible(&dev_priv->cmdbuf_mutex); 412462306a36Sopenharmony_ci if (ret) { 412562306a36Sopenharmony_ci ret = -ERESTARTSYS; 412662306a36Sopenharmony_ci goto out_free_header; 412762306a36Sopenharmony_ci } 412862306a36Sopenharmony_ci 412962306a36Sopenharmony_ci sw_context->kernel = false; 413062306a36Sopenharmony_ci if (kernel_commands == NULL) { 413162306a36Sopenharmony_ci ret = vmw_resize_cmd_bounce(sw_context, command_size); 413262306a36Sopenharmony_ci if (unlikely(ret != 0)) 413362306a36Sopenharmony_ci goto out_unlock; 413462306a36Sopenharmony_ci 413562306a36Sopenharmony_ci ret = copy_from_user(sw_context->cmd_bounce, user_commands, 413662306a36Sopenharmony_ci command_size); 413762306a36Sopenharmony_ci if (unlikely(ret != 0)) { 413862306a36Sopenharmony_ci ret = -EFAULT; 413962306a36Sopenharmony_ci VMW_DEBUG_USER("Failed copying commands.\n"); 414062306a36Sopenharmony_ci goto out_unlock; 414162306a36Sopenharmony_ci } 414262306a36Sopenharmony_ci 414362306a36Sopenharmony_ci kernel_commands = sw_context->cmd_bounce; 414462306a36Sopenharmony_ci } else if (!header) { 414562306a36Sopenharmony_ci sw_context->kernel = true; 414662306a36Sopenharmony_ci } 414762306a36Sopenharmony_ci 414862306a36Sopenharmony_ci sw_context->filp = file_priv; 414962306a36Sopenharmony_ci sw_context->fp = vmw_fpriv(file_priv); 415062306a36Sopenharmony_ci INIT_LIST_HEAD(&sw_context->ctx_list); 415162306a36Sopenharmony_ci sw_context->cur_query_bo = dev_priv->pinned_bo; 415262306a36Sopenharmony_ci sw_context->last_query_ctx = NULL; 415362306a36Sopenharmony_ci sw_context->needs_post_query_barrier = false; 415462306a36Sopenharmony_ci sw_context->dx_ctx_node = NULL; 415562306a36Sopenharmony_ci sw_context->dx_query_mob = NULL; 415662306a36Sopenharmony_ci sw_context->dx_query_ctx = NULL; 415762306a36Sopenharmony_ci memset(sw_context->res_cache, 0, sizeof(sw_context->res_cache)); 415862306a36Sopenharmony_ci INIT_LIST_HEAD(&sw_context->res_relocations); 415962306a36Sopenharmony_ci INIT_LIST_HEAD(&sw_context->bo_relocations); 416062306a36Sopenharmony_ci 416162306a36Sopenharmony_ci if (sw_context->staged_bindings) 416262306a36Sopenharmony_ci vmw_binding_state_reset(sw_context->staged_bindings); 416362306a36Sopenharmony_ci 416462306a36Sopenharmony_ci INIT_LIST_HEAD(&sw_context->staged_cmd_res); 416562306a36Sopenharmony_ci sw_context->ctx = &val_ctx; 416662306a36Sopenharmony_ci ret = vmw_execbuf_tie_context(dev_priv, sw_context, dx_context_handle); 416762306a36Sopenharmony_ci if (unlikely(ret != 0)) 416862306a36Sopenharmony_ci goto out_err_nores; 416962306a36Sopenharmony_ci 417062306a36Sopenharmony_ci ret = vmw_cmd_check_all(dev_priv, sw_context, kernel_commands, 417162306a36Sopenharmony_ci command_size); 417262306a36Sopenharmony_ci if (unlikely(ret != 0)) 417362306a36Sopenharmony_ci goto out_err_nores; 417462306a36Sopenharmony_ci 417562306a36Sopenharmony_ci ret = vmw_resources_reserve(sw_context); 417662306a36Sopenharmony_ci if (unlikely(ret != 0)) 417762306a36Sopenharmony_ci goto out_err_nores; 417862306a36Sopenharmony_ci 417962306a36Sopenharmony_ci ret = vmw_validation_bo_reserve(&val_ctx, true); 418062306a36Sopenharmony_ci if (unlikely(ret != 0)) 418162306a36Sopenharmony_ci goto out_err_nores; 418262306a36Sopenharmony_ci 418362306a36Sopenharmony_ci ret = vmw_validation_bo_validate(&val_ctx, true); 418462306a36Sopenharmony_ci if (unlikely(ret != 0)) 418562306a36Sopenharmony_ci goto out_err; 418662306a36Sopenharmony_ci 418762306a36Sopenharmony_ci ret = vmw_validation_res_validate(&val_ctx, true); 418862306a36Sopenharmony_ci if (unlikely(ret != 0)) 418962306a36Sopenharmony_ci goto out_err; 419062306a36Sopenharmony_ci 419162306a36Sopenharmony_ci vmw_validation_drop_ht(&val_ctx); 419262306a36Sopenharmony_ci 419362306a36Sopenharmony_ci ret = mutex_lock_interruptible(&dev_priv->binding_mutex); 419462306a36Sopenharmony_ci if (unlikely(ret != 0)) { 419562306a36Sopenharmony_ci ret = -ERESTARTSYS; 419662306a36Sopenharmony_ci goto out_err; 419762306a36Sopenharmony_ci } 419862306a36Sopenharmony_ci 419962306a36Sopenharmony_ci if (dev_priv->has_mob) { 420062306a36Sopenharmony_ci ret = vmw_rebind_contexts(sw_context); 420162306a36Sopenharmony_ci if (unlikely(ret != 0)) 420262306a36Sopenharmony_ci goto out_unlock_binding; 420362306a36Sopenharmony_ci } 420462306a36Sopenharmony_ci 420562306a36Sopenharmony_ci if (!header) { 420662306a36Sopenharmony_ci ret = vmw_execbuf_submit_fifo(dev_priv, kernel_commands, 420762306a36Sopenharmony_ci command_size, sw_context); 420862306a36Sopenharmony_ci } else { 420962306a36Sopenharmony_ci ret = vmw_execbuf_submit_cmdbuf(dev_priv, header, command_size, 421062306a36Sopenharmony_ci sw_context); 421162306a36Sopenharmony_ci header = NULL; 421262306a36Sopenharmony_ci } 421362306a36Sopenharmony_ci mutex_unlock(&dev_priv->binding_mutex); 421462306a36Sopenharmony_ci if (ret) 421562306a36Sopenharmony_ci goto out_err; 421662306a36Sopenharmony_ci 421762306a36Sopenharmony_ci vmw_query_bo_switch_commit(dev_priv, sw_context); 421862306a36Sopenharmony_ci ret = vmw_execbuf_fence_commands(file_priv, dev_priv, &fence, 421962306a36Sopenharmony_ci (user_fence_rep) ? &handle : NULL); 422062306a36Sopenharmony_ci /* 422162306a36Sopenharmony_ci * This error is harmless, because if fence submission fails, 422262306a36Sopenharmony_ci * vmw_fifo_send_fence will sync. The error will be propagated to 422362306a36Sopenharmony_ci * user-space in @fence_rep 422462306a36Sopenharmony_ci */ 422562306a36Sopenharmony_ci if (ret != 0) 422662306a36Sopenharmony_ci VMW_DEBUG_USER("Fence submission error. Syncing.\n"); 422762306a36Sopenharmony_ci 422862306a36Sopenharmony_ci vmw_execbuf_bindings_commit(sw_context, false); 422962306a36Sopenharmony_ci vmw_bind_dx_query_mob(sw_context); 423062306a36Sopenharmony_ci vmw_validation_res_unreserve(&val_ctx, false); 423162306a36Sopenharmony_ci 423262306a36Sopenharmony_ci vmw_validation_bo_fence(sw_context->ctx, fence); 423362306a36Sopenharmony_ci 423462306a36Sopenharmony_ci if (unlikely(dev_priv->pinned_bo != NULL && !dev_priv->query_cid_valid)) 423562306a36Sopenharmony_ci __vmw_execbuf_release_pinned_bo(dev_priv, fence); 423662306a36Sopenharmony_ci 423762306a36Sopenharmony_ci /* 423862306a36Sopenharmony_ci * If anything fails here, give up trying to export the fence and do a 423962306a36Sopenharmony_ci * sync since the user mode will not be able to sync the fence itself. 424062306a36Sopenharmony_ci * This ensures we are still functionally correct. 424162306a36Sopenharmony_ci */ 424262306a36Sopenharmony_ci if (flags & DRM_VMW_EXECBUF_FLAG_EXPORT_FENCE_FD) { 424362306a36Sopenharmony_ci 424462306a36Sopenharmony_ci sync_file = sync_file_create(&fence->base); 424562306a36Sopenharmony_ci if (!sync_file) { 424662306a36Sopenharmony_ci VMW_DEBUG_USER("Sync file create failed for fence\n"); 424762306a36Sopenharmony_ci put_unused_fd(out_fence_fd); 424862306a36Sopenharmony_ci out_fence_fd = -1; 424962306a36Sopenharmony_ci 425062306a36Sopenharmony_ci (void) vmw_fence_obj_wait(fence, false, false, 425162306a36Sopenharmony_ci VMW_FENCE_WAIT_TIMEOUT); 425262306a36Sopenharmony_ci } 425362306a36Sopenharmony_ci } 425462306a36Sopenharmony_ci 425562306a36Sopenharmony_ci ret = vmw_execbuf_copy_fence_user(dev_priv, vmw_fpriv(file_priv), ret, 425662306a36Sopenharmony_ci user_fence_rep, fence, handle, out_fence_fd); 425762306a36Sopenharmony_ci 425862306a36Sopenharmony_ci if (sync_file) { 425962306a36Sopenharmony_ci if (ret) { 426062306a36Sopenharmony_ci /* usercopy of fence failed, put the file object */ 426162306a36Sopenharmony_ci fput(sync_file->file); 426262306a36Sopenharmony_ci put_unused_fd(out_fence_fd); 426362306a36Sopenharmony_ci } else { 426462306a36Sopenharmony_ci /* Link the fence with the FD created earlier */ 426562306a36Sopenharmony_ci fd_install(out_fence_fd, sync_file->file); 426662306a36Sopenharmony_ci } 426762306a36Sopenharmony_ci } 426862306a36Sopenharmony_ci 426962306a36Sopenharmony_ci /* Don't unreference when handing fence out */ 427062306a36Sopenharmony_ci if (unlikely(out_fence != NULL)) { 427162306a36Sopenharmony_ci *out_fence = fence; 427262306a36Sopenharmony_ci fence = NULL; 427362306a36Sopenharmony_ci } else if (likely(fence != NULL)) { 427462306a36Sopenharmony_ci vmw_fence_obj_unreference(&fence); 427562306a36Sopenharmony_ci } 427662306a36Sopenharmony_ci 427762306a36Sopenharmony_ci vmw_cmdbuf_res_commit(&sw_context->staged_cmd_res); 427862306a36Sopenharmony_ci mutex_unlock(&dev_priv->cmdbuf_mutex); 427962306a36Sopenharmony_ci 428062306a36Sopenharmony_ci /* 428162306a36Sopenharmony_ci * Unreference resources outside of the cmdbuf_mutex to avoid deadlocks 428262306a36Sopenharmony_ci * in resource destruction paths. 428362306a36Sopenharmony_ci */ 428462306a36Sopenharmony_ci vmw_validation_unref_lists(&val_ctx); 428562306a36Sopenharmony_ci 428662306a36Sopenharmony_ci return ret; 428762306a36Sopenharmony_ci 428862306a36Sopenharmony_ciout_unlock_binding: 428962306a36Sopenharmony_ci mutex_unlock(&dev_priv->binding_mutex); 429062306a36Sopenharmony_ciout_err: 429162306a36Sopenharmony_ci vmw_validation_bo_backoff(&val_ctx); 429262306a36Sopenharmony_ciout_err_nores: 429362306a36Sopenharmony_ci vmw_execbuf_bindings_commit(sw_context, true); 429462306a36Sopenharmony_ci vmw_validation_res_unreserve(&val_ctx, true); 429562306a36Sopenharmony_ci vmw_resource_relocations_free(&sw_context->res_relocations); 429662306a36Sopenharmony_ci vmw_free_relocations(sw_context); 429762306a36Sopenharmony_ci if (unlikely(dev_priv->pinned_bo != NULL && !dev_priv->query_cid_valid)) 429862306a36Sopenharmony_ci __vmw_execbuf_release_pinned_bo(dev_priv, NULL); 429962306a36Sopenharmony_ciout_unlock: 430062306a36Sopenharmony_ci vmw_cmdbuf_res_revert(&sw_context->staged_cmd_res); 430162306a36Sopenharmony_ci vmw_validation_drop_ht(&val_ctx); 430262306a36Sopenharmony_ci WARN_ON(!list_empty(&sw_context->ctx_list)); 430362306a36Sopenharmony_ci mutex_unlock(&dev_priv->cmdbuf_mutex); 430462306a36Sopenharmony_ci 430562306a36Sopenharmony_ci /* 430662306a36Sopenharmony_ci * Unreference resources outside of the cmdbuf_mutex to avoid deadlocks 430762306a36Sopenharmony_ci * in resource destruction paths. 430862306a36Sopenharmony_ci */ 430962306a36Sopenharmony_ci vmw_validation_unref_lists(&val_ctx); 431062306a36Sopenharmony_ciout_free_header: 431162306a36Sopenharmony_ci if (header) 431262306a36Sopenharmony_ci vmw_cmdbuf_header_free(header); 431362306a36Sopenharmony_ciout_free_fence_fd: 431462306a36Sopenharmony_ci if (out_fence_fd >= 0) 431562306a36Sopenharmony_ci put_unused_fd(out_fence_fd); 431662306a36Sopenharmony_ci 431762306a36Sopenharmony_ci return ret; 431862306a36Sopenharmony_ci} 431962306a36Sopenharmony_ci 432062306a36Sopenharmony_ci/** 432162306a36Sopenharmony_ci * vmw_execbuf_unpin_panic - Idle the fifo and unpin the query buffer. 432262306a36Sopenharmony_ci * 432362306a36Sopenharmony_ci * @dev_priv: The device private structure. 432462306a36Sopenharmony_ci * 432562306a36Sopenharmony_ci * This function is called to idle the fifo and unpin the query buffer if the 432662306a36Sopenharmony_ci * normal way to do this hits an error, which should typically be extremely 432762306a36Sopenharmony_ci * rare. 432862306a36Sopenharmony_ci */ 432962306a36Sopenharmony_cistatic void vmw_execbuf_unpin_panic(struct vmw_private *dev_priv) 433062306a36Sopenharmony_ci{ 433162306a36Sopenharmony_ci VMW_DEBUG_USER("Can't unpin query buffer. Trying to recover.\n"); 433262306a36Sopenharmony_ci 433362306a36Sopenharmony_ci (void) vmw_fallback_wait(dev_priv, false, true, 0, false, 10*HZ); 433462306a36Sopenharmony_ci vmw_bo_pin_reserved(dev_priv->pinned_bo, false); 433562306a36Sopenharmony_ci if (dev_priv->dummy_query_bo_pinned) { 433662306a36Sopenharmony_ci vmw_bo_pin_reserved(dev_priv->dummy_query_bo, false); 433762306a36Sopenharmony_ci dev_priv->dummy_query_bo_pinned = false; 433862306a36Sopenharmony_ci } 433962306a36Sopenharmony_ci} 434062306a36Sopenharmony_ci 434162306a36Sopenharmony_ci 434262306a36Sopenharmony_ci/** 434362306a36Sopenharmony_ci * __vmw_execbuf_release_pinned_bo - Flush queries and unpin the pinned query 434462306a36Sopenharmony_ci * bo. 434562306a36Sopenharmony_ci * 434662306a36Sopenharmony_ci * @dev_priv: The device private structure. 434762306a36Sopenharmony_ci * @fence: If non-NULL should point to a struct vmw_fence_obj issued _after_ a 434862306a36Sopenharmony_ci * query barrier that flushes all queries touching the current buffer pointed to 434962306a36Sopenharmony_ci * by @dev_priv->pinned_bo 435062306a36Sopenharmony_ci * 435162306a36Sopenharmony_ci * This function should be used to unpin the pinned query bo, or as a query 435262306a36Sopenharmony_ci * barrier when we need to make sure that all queries have finished before the 435362306a36Sopenharmony_ci * next fifo command. (For example on hardware context destructions where the 435462306a36Sopenharmony_ci * hardware may otherwise leak unfinished queries). 435562306a36Sopenharmony_ci * 435662306a36Sopenharmony_ci * This function does not return any failure codes, but make attempts to do safe 435762306a36Sopenharmony_ci * unpinning in case of errors. 435862306a36Sopenharmony_ci * 435962306a36Sopenharmony_ci * The function will synchronize on the previous query barrier, and will thus 436062306a36Sopenharmony_ci * not finish until that barrier has executed. 436162306a36Sopenharmony_ci * 436262306a36Sopenharmony_ci * the @dev_priv->cmdbuf_mutex needs to be held by the current thread before 436362306a36Sopenharmony_ci * calling this function. 436462306a36Sopenharmony_ci */ 436562306a36Sopenharmony_civoid __vmw_execbuf_release_pinned_bo(struct vmw_private *dev_priv, 436662306a36Sopenharmony_ci struct vmw_fence_obj *fence) 436762306a36Sopenharmony_ci{ 436862306a36Sopenharmony_ci int ret = 0; 436962306a36Sopenharmony_ci struct vmw_fence_obj *lfence = NULL; 437062306a36Sopenharmony_ci DECLARE_VAL_CONTEXT(val_ctx, NULL, 0); 437162306a36Sopenharmony_ci 437262306a36Sopenharmony_ci if (dev_priv->pinned_bo == NULL) 437362306a36Sopenharmony_ci goto out_unlock; 437462306a36Sopenharmony_ci 437562306a36Sopenharmony_ci vmw_bo_placement_set(dev_priv->pinned_bo, 437662306a36Sopenharmony_ci VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM, 437762306a36Sopenharmony_ci VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM); 437862306a36Sopenharmony_ci ret = vmw_validation_add_bo(&val_ctx, dev_priv->pinned_bo); 437962306a36Sopenharmony_ci if (ret) 438062306a36Sopenharmony_ci goto out_no_reserve; 438162306a36Sopenharmony_ci 438262306a36Sopenharmony_ci vmw_bo_placement_set(dev_priv->dummy_query_bo, 438362306a36Sopenharmony_ci VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM, 438462306a36Sopenharmony_ci VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM); 438562306a36Sopenharmony_ci ret = vmw_validation_add_bo(&val_ctx, dev_priv->dummy_query_bo); 438662306a36Sopenharmony_ci if (ret) 438762306a36Sopenharmony_ci goto out_no_reserve; 438862306a36Sopenharmony_ci 438962306a36Sopenharmony_ci ret = vmw_validation_bo_reserve(&val_ctx, false); 439062306a36Sopenharmony_ci if (ret) 439162306a36Sopenharmony_ci goto out_no_reserve; 439262306a36Sopenharmony_ci 439362306a36Sopenharmony_ci if (dev_priv->query_cid_valid) { 439462306a36Sopenharmony_ci BUG_ON(fence != NULL); 439562306a36Sopenharmony_ci ret = vmw_cmd_emit_dummy_query(dev_priv, dev_priv->query_cid); 439662306a36Sopenharmony_ci if (ret) 439762306a36Sopenharmony_ci goto out_no_emit; 439862306a36Sopenharmony_ci dev_priv->query_cid_valid = false; 439962306a36Sopenharmony_ci } 440062306a36Sopenharmony_ci 440162306a36Sopenharmony_ci vmw_bo_pin_reserved(dev_priv->pinned_bo, false); 440262306a36Sopenharmony_ci if (dev_priv->dummy_query_bo_pinned) { 440362306a36Sopenharmony_ci vmw_bo_pin_reserved(dev_priv->dummy_query_bo, false); 440462306a36Sopenharmony_ci dev_priv->dummy_query_bo_pinned = false; 440562306a36Sopenharmony_ci } 440662306a36Sopenharmony_ci if (fence == NULL) { 440762306a36Sopenharmony_ci (void) vmw_execbuf_fence_commands(NULL, dev_priv, &lfence, 440862306a36Sopenharmony_ci NULL); 440962306a36Sopenharmony_ci fence = lfence; 441062306a36Sopenharmony_ci } 441162306a36Sopenharmony_ci vmw_validation_bo_fence(&val_ctx, fence); 441262306a36Sopenharmony_ci if (lfence != NULL) 441362306a36Sopenharmony_ci vmw_fence_obj_unreference(&lfence); 441462306a36Sopenharmony_ci 441562306a36Sopenharmony_ci vmw_validation_unref_lists(&val_ctx); 441662306a36Sopenharmony_ci vmw_bo_unreference(&dev_priv->pinned_bo); 441762306a36Sopenharmony_ci 441862306a36Sopenharmony_ciout_unlock: 441962306a36Sopenharmony_ci return; 442062306a36Sopenharmony_ciout_no_emit: 442162306a36Sopenharmony_ci vmw_validation_bo_backoff(&val_ctx); 442262306a36Sopenharmony_ciout_no_reserve: 442362306a36Sopenharmony_ci vmw_validation_unref_lists(&val_ctx); 442462306a36Sopenharmony_ci vmw_execbuf_unpin_panic(dev_priv); 442562306a36Sopenharmony_ci vmw_bo_unreference(&dev_priv->pinned_bo); 442662306a36Sopenharmony_ci} 442762306a36Sopenharmony_ci 442862306a36Sopenharmony_ci/** 442962306a36Sopenharmony_ci * vmw_execbuf_release_pinned_bo - Flush queries and unpin the pinned query bo. 443062306a36Sopenharmony_ci * 443162306a36Sopenharmony_ci * @dev_priv: The device private structure. 443262306a36Sopenharmony_ci * 443362306a36Sopenharmony_ci * This function should be used to unpin the pinned query bo, or as a query 443462306a36Sopenharmony_ci * barrier when we need to make sure that all queries have finished before the 443562306a36Sopenharmony_ci * next fifo command. (For example on hardware context destructions where the 443662306a36Sopenharmony_ci * hardware may otherwise leak unfinished queries). 443762306a36Sopenharmony_ci * 443862306a36Sopenharmony_ci * This function does not return any failure codes, but make attempts to do safe 443962306a36Sopenharmony_ci * unpinning in case of errors. 444062306a36Sopenharmony_ci * 444162306a36Sopenharmony_ci * The function will synchronize on the previous query barrier, and will thus 444262306a36Sopenharmony_ci * not finish until that barrier has executed. 444362306a36Sopenharmony_ci */ 444462306a36Sopenharmony_civoid vmw_execbuf_release_pinned_bo(struct vmw_private *dev_priv) 444562306a36Sopenharmony_ci{ 444662306a36Sopenharmony_ci mutex_lock(&dev_priv->cmdbuf_mutex); 444762306a36Sopenharmony_ci if (dev_priv->query_cid_valid) 444862306a36Sopenharmony_ci __vmw_execbuf_release_pinned_bo(dev_priv, NULL); 444962306a36Sopenharmony_ci mutex_unlock(&dev_priv->cmdbuf_mutex); 445062306a36Sopenharmony_ci} 445162306a36Sopenharmony_ci 445262306a36Sopenharmony_ciint vmw_execbuf_ioctl(struct drm_device *dev, void *data, 445362306a36Sopenharmony_ci struct drm_file *file_priv) 445462306a36Sopenharmony_ci{ 445562306a36Sopenharmony_ci struct vmw_private *dev_priv = vmw_priv(dev); 445662306a36Sopenharmony_ci struct drm_vmw_execbuf_arg *arg = data; 445762306a36Sopenharmony_ci int ret; 445862306a36Sopenharmony_ci struct dma_fence *in_fence = NULL; 445962306a36Sopenharmony_ci 446062306a36Sopenharmony_ci MKS_STAT_TIME_DECL(MKSSTAT_KERN_EXECBUF); 446162306a36Sopenharmony_ci MKS_STAT_TIME_PUSH(MKSSTAT_KERN_EXECBUF); 446262306a36Sopenharmony_ci 446362306a36Sopenharmony_ci /* 446462306a36Sopenharmony_ci * Extend the ioctl argument while maintaining backwards compatibility: 446562306a36Sopenharmony_ci * We take different code paths depending on the value of arg->version. 446662306a36Sopenharmony_ci * 446762306a36Sopenharmony_ci * Note: The ioctl argument is extended and zeropadded by core DRM. 446862306a36Sopenharmony_ci */ 446962306a36Sopenharmony_ci if (unlikely(arg->version > DRM_VMW_EXECBUF_VERSION || 447062306a36Sopenharmony_ci arg->version == 0)) { 447162306a36Sopenharmony_ci VMW_DEBUG_USER("Incorrect execbuf version.\n"); 447262306a36Sopenharmony_ci ret = -EINVAL; 447362306a36Sopenharmony_ci goto mksstats_out; 447462306a36Sopenharmony_ci } 447562306a36Sopenharmony_ci 447662306a36Sopenharmony_ci switch (arg->version) { 447762306a36Sopenharmony_ci case 1: 447862306a36Sopenharmony_ci /* For v1 core DRM have extended + zeropadded the data */ 447962306a36Sopenharmony_ci arg->context_handle = (uint32_t) -1; 448062306a36Sopenharmony_ci break; 448162306a36Sopenharmony_ci case 2: 448262306a36Sopenharmony_ci default: 448362306a36Sopenharmony_ci /* For v2 and later core DRM would have correctly copied it */ 448462306a36Sopenharmony_ci break; 448562306a36Sopenharmony_ci } 448662306a36Sopenharmony_ci 448762306a36Sopenharmony_ci /* If imported a fence FD from elsewhere, then wait on it */ 448862306a36Sopenharmony_ci if (arg->flags & DRM_VMW_EXECBUF_FLAG_IMPORT_FENCE_FD) { 448962306a36Sopenharmony_ci in_fence = sync_file_get_fence(arg->imported_fence_fd); 449062306a36Sopenharmony_ci 449162306a36Sopenharmony_ci if (!in_fence) { 449262306a36Sopenharmony_ci VMW_DEBUG_USER("Cannot get imported fence\n"); 449362306a36Sopenharmony_ci ret = -EINVAL; 449462306a36Sopenharmony_ci goto mksstats_out; 449562306a36Sopenharmony_ci } 449662306a36Sopenharmony_ci 449762306a36Sopenharmony_ci ret = dma_fence_wait(in_fence, true); 449862306a36Sopenharmony_ci if (ret) 449962306a36Sopenharmony_ci goto out; 450062306a36Sopenharmony_ci } 450162306a36Sopenharmony_ci 450262306a36Sopenharmony_ci ret = vmw_execbuf_process(file_priv, dev_priv, 450362306a36Sopenharmony_ci (void __user *)(unsigned long)arg->commands, 450462306a36Sopenharmony_ci NULL, arg->command_size, arg->throttle_us, 450562306a36Sopenharmony_ci arg->context_handle, 450662306a36Sopenharmony_ci (void __user *)(unsigned long)arg->fence_rep, 450762306a36Sopenharmony_ci NULL, arg->flags); 450862306a36Sopenharmony_ci 450962306a36Sopenharmony_ci if (unlikely(ret != 0)) 451062306a36Sopenharmony_ci goto out; 451162306a36Sopenharmony_ci 451262306a36Sopenharmony_ci vmw_kms_cursor_post_execbuf(dev_priv); 451362306a36Sopenharmony_ci 451462306a36Sopenharmony_ciout: 451562306a36Sopenharmony_ci if (in_fence) 451662306a36Sopenharmony_ci dma_fence_put(in_fence); 451762306a36Sopenharmony_ci 451862306a36Sopenharmony_cimksstats_out: 451962306a36Sopenharmony_ci MKS_STAT_TIME_POP(MKSSTAT_KERN_EXECBUF); 452062306a36Sopenharmony_ci return ret; 452162306a36Sopenharmony_ci} 4522