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