18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 OR MIT
28c2ecf20Sopenharmony_ci/**************************************************************************
38c2ecf20Sopenharmony_ci * Copyright 2014-2015 VMware, Inc., Palo Alto, CA., USA
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
68c2ecf20Sopenharmony_ci * copy of this software and associated documentation files (the
78c2ecf20Sopenharmony_ci * "Software"), to deal in the Software without restriction, including
88c2ecf20Sopenharmony_ci * without limitation the rights to use, copy, modify, merge, publish,
98c2ecf20Sopenharmony_ci * distribute, sub license, and/or sell copies of the Software, and to
108c2ecf20Sopenharmony_ci * permit persons to whom the Software is furnished to do so, subject to
118c2ecf20Sopenharmony_ci * the following conditions:
128c2ecf20Sopenharmony_ci *
138c2ecf20Sopenharmony_ci * The above copyright notice and this permission notice (including the
148c2ecf20Sopenharmony_ci * next paragraph) shall be included in all copies or substantial portions
158c2ecf20Sopenharmony_ci * of the Software.
168c2ecf20Sopenharmony_ci *
178c2ecf20Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
188c2ecf20Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
198c2ecf20Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
208c2ecf20Sopenharmony_ci * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
218c2ecf20Sopenharmony_ci * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
228c2ecf20Sopenharmony_ci * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
238c2ecf20Sopenharmony_ci * USE OR OTHER DEALINGS IN THE SOFTWARE.
248c2ecf20Sopenharmony_ci *
258c2ecf20Sopenharmony_ci **************************************************************************/
268c2ecf20Sopenharmony_ci
278c2ecf20Sopenharmony_ci#include "vmwgfx_drv.h"
288c2ecf20Sopenharmony_ci#include "vmwgfx_resource_priv.h"
298c2ecf20Sopenharmony_ci#include "vmwgfx_so.h"
308c2ecf20Sopenharmony_ci#include "vmwgfx_binding.h"
318c2ecf20Sopenharmony_ci
328c2ecf20Sopenharmony_ci/*
338c2ecf20Sopenharmony_ci * The currently only reason we need to keep track of views is that if we
348c2ecf20Sopenharmony_ci * destroy a hardware surface, all views pointing to it must also be destroyed,
358c2ecf20Sopenharmony_ci * otherwise the device will error.
368c2ecf20Sopenharmony_ci * So in particuar if a surface is evicted, we must destroy all views pointing
378c2ecf20Sopenharmony_ci * to it, and all context bindings of that view. Similarly we must restore
388c2ecf20Sopenharmony_ci * the view bindings, views and surfaces pointed to by the views when a
398c2ecf20Sopenharmony_ci * context is referenced in the command stream.
408c2ecf20Sopenharmony_ci */
418c2ecf20Sopenharmony_ci
428c2ecf20Sopenharmony_ci/**
438c2ecf20Sopenharmony_ci * struct vmw_view - view metadata
448c2ecf20Sopenharmony_ci *
458c2ecf20Sopenharmony_ci * @res: The struct vmw_resource we derive from
468c2ecf20Sopenharmony_ci * @ctx: Non-refcounted pointer to the context this view belongs to.
478c2ecf20Sopenharmony_ci * @srf: Refcounted pointer to the surface pointed to by this view.
488c2ecf20Sopenharmony_ci * @cotable: Refcounted pointer to the cotable holding this view.
498c2ecf20Sopenharmony_ci * @srf_head: List head for the surface-to-view list.
508c2ecf20Sopenharmony_ci * @cotable_head: List head for the cotable-to_view list.
518c2ecf20Sopenharmony_ci * @view_type: View type.
528c2ecf20Sopenharmony_ci * @view_id: User-space per context view id. Currently used also as per
538c2ecf20Sopenharmony_ci * context device view id.
548c2ecf20Sopenharmony_ci * @cmd_size: Size of the SVGA3D define view command that we've copied from the
558c2ecf20Sopenharmony_ci * command stream.
568c2ecf20Sopenharmony_ci * @committed: Whether the view is actually created or pending creation at the
578c2ecf20Sopenharmony_ci * device level.
588c2ecf20Sopenharmony_ci * @cmd: The SVGA3D define view command copied from the command stream.
598c2ecf20Sopenharmony_ci */
608c2ecf20Sopenharmony_cistruct vmw_view {
618c2ecf20Sopenharmony_ci	struct rcu_head rcu;
628c2ecf20Sopenharmony_ci	struct vmw_resource res;
638c2ecf20Sopenharmony_ci	struct vmw_resource *ctx;      /* Immutable */
648c2ecf20Sopenharmony_ci	struct vmw_resource *srf;      /* Immutable */
658c2ecf20Sopenharmony_ci	struct vmw_resource *cotable;  /* Immutable */
668c2ecf20Sopenharmony_ci	struct list_head srf_head;     /* Protected by binding_mutex */
678c2ecf20Sopenharmony_ci	struct list_head cotable_head; /* Protected by binding_mutex */
688c2ecf20Sopenharmony_ci	unsigned view_type;            /* Immutable */
698c2ecf20Sopenharmony_ci	unsigned view_id;              /* Immutable */
708c2ecf20Sopenharmony_ci	u32 cmd_size;                  /* Immutable */
718c2ecf20Sopenharmony_ci	bool committed;                /* Protected by binding_mutex */
728c2ecf20Sopenharmony_ci	u32 cmd[1];                    /* Immutable */
738c2ecf20Sopenharmony_ci};
748c2ecf20Sopenharmony_ci
758c2ecf20Sopenharmony_cistatic int vmw_view_create(struct vmw_resource *res);
768c2ecf20Sopenharmony_cistatic int vmw_view_destroy(struct vmw_resource *res);
778c2ecf20Sopenharmony_cistatic void vmw_hw_view_destroy(struct vmw_resource *res);
788c2ecf20Sopenharmony_cistatic void vmw_view_commit_notify(struct vmw_resource *res,
798c2ecf20Sopenharmony_ci				   enum vmw_cmdbuf_res_state state);
808c2ecf20Sopenharmony_ci
818c2ecf20Sopenharmony_cistatic const struct vmw_res_func vmw_view_func = {
828c2ecf20Sopenharmony_ci	.res_type = vmw_res_view,
838c2ecf20Sopenharmony_ci	.needs_backup = false,
848c2ecf20Sopenharmony_ci	.may_evict = false,
858c2ecf20Sopenharmony_ci	.type_name = "DX view",
868c2ecf20Sopenharmony_ci	.backup_placement = NULL,
878c2ecf20Sopenharmony_ci	.create = vmw_view_create,
888c2ecf20Sopenharmony_ci	.commit_notify = vmw_view_commit_notify,
898c2ecf20Sopenharmony_ci};
908c2ecf20Sopenharmony_ci
918c2ecf20Sopenharmony_ci/**
928c2ecf20Sopenharmony_ci * struct vmw_view - view define command body stub
938c2ecf20Sopenharmony_ci *
948c2ecf20Sopenharmony_ci * @view_id: The device id of the view being defined
958c2ecf20Sopenharmony_ci * @sid: The surface id of the view being defined
968c2ecf20Sopenharmony_ci *
978c2ecf20Sopenharmony_ci * This generic struct is used by the code to change @view_id and @sid of a
988c2ecf20Sopenharmony_ci * saved view define command.
998c2ecf20Sopenharmony_ci */
1008c2ecf20Sopenharmony_cistruct vmw_view_define {
1018c2ecf20Sopenharmony_ci	uint32 view_id;
1028c2ecf20Sopenharmony_ci	uint32 sid;
1038c2ecf20Sopenharmony_ci};
1048c2ecf20Sopenharmony_ci
1058c2ecf20Sopenharmony_ci/**
1068c2ecf20Sopenharmony_ci * vmw_view - Convert a struct vmw_resource to a struct vmw_view
1078c2ecf20Sopenharmony_ci *
1088c2ecf20Sopenharmony_ci * @res: Pointer to the resource to convert.
1098c2ecf20Sopenharmony_ci *
1108c2ecf20Sopenharmony_ci * Returns a pointer to a struct vmw_view.
1118c2ecf20Sopenharmony_ci */
1128c2ecf20Sopenharmony_cistatic struct vmw_view *vmw_view(struct vmw_resource *res)
1138c2ecf20Sopenharmony_ci{
1148c2ecf20Sopenharmony_ci	return container_of(res, struct vmw_view, res);
1158c2ecf20Sopenharmony_ci}
1168c2ecf20Sopenharmony_ci
1178c2ecf20Sopenharmony_ci/**
1188c2ecf20Sopenharmony_ci * vmw_view_commit_notify - Notify that a view operation has been committed to
1198c2ecf20Sopenharmony_ci * hardware from a user-supplied command stream.
1208c2ecf20Sopenharmony_ci *
1218c2ecf20Sopenharmony_ci * @res: Pointer to the view resource.
1228c2ecf20Sopenharmony_ci * @state: Indicating whether a creation or removal has been committed.
1238c2ecf20Sopenharmony_ci *
1248c2ecf20Sopenharmony_ci */
1258c2ecf20Sopenharmony_cistatic void vmw_view_commit_notify(struct vmw_resource *res,
1268c2ecf20Sopenharmony_ci				   enum vmw_cmdbuf_res_state state)
1278c2ecf20Sopenharmony_ci{
1288c2ecf20Sopenharmony_ci	struct vmw_view *view = vmw_view(res);
1298c2ecf20Sopenharmony_ci	struct vmw_private *dev_priv = res->dev_priv;
1308c2ecf20Sopenharmony_ci
1318c2ecf20Sopenharmony_ci	mutex_lock(&dev_priv->binding_mutex);
1328c2ecf20Sopenharmony_ci	if (state == VMW_CMDBUF_RES_ADD) {
1338c2ecf20Sopenharmony_ci		struct vmw_surface *srf = vmw_res_to_srf(view->srf);
1348c2ecf20Sopenharmony_ci
1358c2ecf20Sopenharmony_ci		list_add_tail(&view->srf_head, &srf->view_list);
1368c2ecf20Sopenharmony_ci		vmw_cotable_add_resource(view->cotable, &view->cotable_head);
1378c2ecf20Sopenharmony_ci		view->committed = true;
1388c2ecf20Sopenharmony_ci		res->id = view->view_id;
1398c2ecf20Sopenharmony_ci
1408c2ecf20Sopenharmony_ci	} else {
1418c2ecf20Sopenharmony_ci		list_del_init(&view->cotable_head);
1428c2ecf20Sopenharmony_ci		list_del_init(&view->srf_head);
1438c2ecf20Sopenharmony_ci		view->committed = false;
1448c2ecf20Sopenharmony_ci		res->id = -1;
1458c2ecf20Sopenharmony_ci	}
1468c2ecf20Sopenharmony_ci	mutex_unlock(&dev_priv->binding_mutex);
1478c2ecf20Sopenharmony_ci}
1488c2ecf20Sopenharmony_ci
1498c2ecf20Sopenharmony_ci/**
1508c2ecf20Sopenharmony_ci * vmw_view_create - Create a hardware view.
1518c2ecf20Sopenharmony_ci *
1528c2ecf20Sopenharmony_ci * @res: Pointer to the view resource.
1538c2ecf20Sopenharmony_ci *
1548c2ecf20Sopenharmony_ci * Create a hardware view. Typically used if that view has previously been
1558c2ecf20Sopenharmony_ci * destroyed by an eviction operation.
1568c2ecf20Sopenharmony_ci */
1578c2ecf20Sopenharmony_cistatic int vmw_view_create(struct vmw_resource *res)
1588c2ecf20Sopenharmony_ci{
1598c2ecf20Sopenharmony_ci	struct vmw_view *view = vmw_view(res);
1608c2ecf20Sopenharmony_ci	struct vmw_surface *srf = vmw_res_to_srf(view->srf);
1618c2ecf20Sopenharmony_ci	struct vmw_private *dev_priv = res->dev_priv;
1628c2ecf20Sopenharmony_ci	struct {
1638c2ecf20Sopenharmony_ci		SVGA3dCmdHeader header;
1648c2ecf20Sopenharmony_ci		struct vmw_view_define body;
1658c2ecf20Sopenharmony_ci	} *cmd;
1668c2ecf20Sopenharmony_ci
1678c2ecf20Sopenharmony_ci	mutex_lock(&dev_priv->binding_mutex);
1688c2ecf20Sopenharmony_ci	if (!view->committed) {
1698c2ecf20Sopenharmony_ci		mutex_unlock(&dev_priv->binding_mutex);
1708c2ecf20Sopenharmony_ci		return 0;
1718c2ecf20Sopenharmony_ci	}
1728c2ecf20Sopenharmony_ci
1738c2ecf20Sopenharmony_ci	cmd = VMW_FIFO_RESERVE_DX(res->dev_priv, view->cmd_size, view->ctx->id);
1748c2ecf20Sopenharmony_ci	if (!cmd) {
1758c2ecf20Sopenharmony_ci		mutex_unlock(&dev_priv->binding_mutex);
1768c2ecf20Sopenharmony_ci		return -ENOMEM;
1778c2ecf20Sopenharmony_ci	}
1788c2ecf20Sopenharmony_ci
1798c2ecf20Sopenharmony_ci	memcpy(cmd, &view->cmd, view->cmd_size);
1808c2ecf20Sopenharmony_ci	WARN_ON(cmd->body.view_id != view->view_id);
1818c2ecf20Sopenharmony_ci	/* Sid may have changed due to surface eviction. */
1828c2ecf20Sopenharmony_ci	WARN_ON(view->srf->id == SVGA3D_INVALID_ID);
1838c2ecf20Sopenharmony_ci	cmd->body.sid = view->srf->id;
1848c2ecf20Sopenharmony_ci	vmw_fifo_commit(res->dev_priv, view->cmd_size);
1858c2ecf20Sopenharmony_ci	res->id = view->view_id;
1868c2ecf20Sopenharmony_ci	list_add_tail(&view->srf_head, &srf->view_list);
1878c2ecf20Sopenharmony_ci	vmw_cotable_add_resource(view->cotable, &view->cotable_head);
1888c2ecf20Sopenharmony_ci	mutex_unlock(&dev_priv->binding_mutex);
1898c2ecf20Sopenharmony_ci
1908c2ecf20Sopenharmony_ci	return 0;
1918c2ecf20Sopenharmony_ci}
1928c2ecf20Sopenharmony_ci
1938c2ecf20Sopenharmony_ci/**
1948c2ecf20Sopenharmony_ci * vmw_view_destroy - Destroy a hardware view.
1958c2ecf20Sopenharmony_ci *
1968c2ecf20Sopenharmony_ci * @res: Pointer to the view resource.
1978c2ecf20Sopenharmony_ci *
1988c2ecf20Sopenharmony_ci * Destroy a hardware view. Typically used on unexpected termination of the
1998c2ecf20Sopenharmony_ci * owning process or if the surface the view is pointing to is destroyed.
2008c2ecf20Sopenharmony_ci */
2018c2ecf20Sopenharmony_cistatic int vmw_view_destroy(struct vmw_resource *res)
2028c2ecf20Sopenharmony_ci{
2038c2ecf20Sopenharmony_ci	struct vmw_private *dev_priv = res->dev_priv;
2048c2ecf20Sopenharmony_ci	struct vmw_view *view = vmw_view(res);
2058c2ecf20Sopenharmony_ci	struct {
2068c2ecf20Sopenharmony_ci		SVGA3dCmdHeader header;
2078c2ecf20Sopenharmony_ci		union vmw_view_destroy body;
2088c2ecf20Sopenharmony_ci	} *cmd;
2098c2ecf20Sopenharmony_ci
2108c2ecf20Sopenharmony_ci	lockdep_assert_held_once(&dev_priv->binding_mutex);
2118c2ecf20Sopenharmony_ci	vmw_binding_res_list_scrub(&res->binding_head);
2128c2ecf20Sopenharmony_ci
2138c2ecf20Sopenharmony_ci	if (!view->committed || res->id == -1)
2148c2ecf20Sopenharmony_ci		return 0;
2158c2ecf20Sopenharmony_ci
2168c2ecf20Sopenharmony_ci	cmd = VMW_FIFO_RESERVE_DX(dev_priv, sizeof(*cmd), view->ctx->id);
2178c2ecf20Sopenharmony_ci	if (!cmd)
2188c2ecf20Sopenharmony_ci		return -ENOMEM;
2198c2ecf20Sopenharmony_ci
2208c2ecf20Sopenharmony_ci	cmd->header.id = vmw_view_destroy_cmds[view->view_type];
2218c2ecf20Sopenharmony_ci	cmd->header.size = sizeof(cmd->body);
2228c2ecf20Sopenharmony_ci	cmd->body.view_id = view->view_id;
2238c2ecf20Sopenharmony_ci	vmw_fifo_commit(dev_priv, sizeof(*cmd));
2248c2ecf20Sopenharmony_ci	res->id = -1;
2258c2ecf20Sopenharmony_ci	list_del_init(&view->cotable_head);
2268c2ecf20Sopenharmony_ci	list_del_init(&view->srf_head);
2278c2ecf20Sopenharmony_ci
2288c2ecf20Sopenharmony_ci	return 0;
2298c2ecf20Sopenharmony_ci}
2308c2ecf20Sopenharmony_ci
2318c2ecf20Sopenharmony_ci/**
2328c2ecf20Sopenharmony_ci * vmw_hw_view_destroy - Destroy a hardware view as part of resource cleanup.
2338c2ecf20Sopenharmony_ci *
2348c2ecf20Sopenharmony_ci * @res: Pointer to the view resource.
2358c2ecf20Sopenharmony_ci *
2368c2ecf20Sopenharmony_ci * Destroy a hardware view if it's still present.
2378c2ecf20Sopenharmony_ci */
2388c2ecf20Sopenharmony_cistatic void vmw_hw_view_destroy(struct vmw_resource *res)
2398c2ecf20Sopenharmony_ci{
2408c2ecf20Sopenharmony_ci	struct vmw_private *dev_priv = res->dev_priv;
2418c2ecf20Sopenharmony_ci
2428c2ecf20Sopenharmony_ci	mutex_lock(&dev_priv->binding_mutex);
2438c2ecf20Sopenharmony_ci	WARN_ON(vmw_view_destroy(res));
2448c2ecf20Sopenharmony_ci	res->id = -1;
2458c2ecf20Sopenharmony_ci	mutex_unlock(&dev_priv->binding_mutex);
2468c2ecf20Sopenharmony_ci}
2478c2ecf20Sopenharmony_ci
2488c2ecf20Sopenharmony_ci/**
2498c2ecf20Sopenharmony_ci * vmw_view_key - Compute a view key suitable for the cmdbuf resource manager
2508c2ecf20Sopenharmony_ci *
2518c2ecf20Sopenharmony_ci * @user_key: The user-space id used for the view.
2528c2ecf20Sopenharmony_ci * @view_type: The view type.
2538c2ecf20Sopenharmony_ci *
2548c2ecf20Sopenharmony_ci * Destroy a hardware view if it's still present.
2558c2ecf20Sopenharmony_ci */
2568c2ecf20Sopenharmony_cistatic u32 vmw_view_key(u32 user_key, enum vmw_view_type view_type)
2578c2ecf20Sopenharmony_ci{
2588c2ecf20Sopenharmony_ci	return user_key | (view_type << 20);
2598c2ecf20Sopenharmony_ci}
2608c2ecf20Sopenharmony_ci
2618c2ecf20Sopenharmony_ci/**
2628c2ecf20Sopenharmony_ci * vmw_view_id_ok - Basic view id and type range checks.
2638c2ecf20Sopenharmony_ci *
2648c2ecf20Sopenharmony_ci * @user_key: The user-space id used for the view.
2658c2ecf20Sopenharmony_ci * @view_type: The view type.
2668c2ecf20Sopenharmony_ci *
2678c2ecf20Sopenharmony_ci * Checks that the view id and type (typically provided by user-space) is
2688c2ecf20Sopenharmony_ci * valid.
2698c2ecf20Sopenharmony_ci */
2708c2ecf20Sopenharmony_cistatic bool vmw_view_id_ok(u32 user_key, enum vmw_view_type view_type)
2718c2ecf20Sopenharmony_ci{
2728c2ecf20Sopenharmony_ci	return (user_key < SVGA_COTABLE_MAX_IDS &&
2738c2ecf20Sopenharmony_ci		view_type < vmw_view_max);
2748c2ecf20Sopenharmony_ci}
2758c2ecf20Sopenharmony_ci
2768c2ecf20Sopenharmony_ci/**
2778c2ecf20Sopenharmony_ci * vmw_view_res_free - resource res_free callback for view resources
2788c2ecf20Sopenharmony_ci *
2798c2ecf20Sopenharmony_ci * @res: Pointer to a struct vmw_resource
2808c2ecf20Sopenharmony_ci *
2818c2ecf20Sopenharmony_ci * Frees memory and memory accounting held by a struct vmw_view.
2828c2ecf20Sopenharmony_ci */
2838c2ecf20Sopenharmony_cistatic void vmw_view_res_free(struct vmw_resource *res)
2848c2ecf20Sopenharmony_ci{
2858c2ecf20Sopenharmony_ci	struct vmw_view *view = vmw_view(res);
2868c2ecf20Sopenharmony_ci	size_t size = offsetof(struct vmw_view, cmd) + view->cmd_size;
2878c2ecf20Sopenharmony_ci	struct vmw_private *dev_priv = res->dev_priv;
2888c2ecf20Sopenharmony_ci
2898c2ecf20Sopenharmony_ci	vmw_resource_unreference(&view->cotable);
2908c2ecf20Sopenharmony_ci	vmw_resource_unreference(&view->srf);
2918c2ecf20Sopenharmony_ci	kfree_rcu(view, rcu);
2928c2ecf20Sopenharmony_ci	ttm_mem_global_free(vmw_mem_glob(dev_priv), size);
2938c2ecf20Sopenharmony_ci}
2948c2ecf20Sopenharmony_ci
2958c2ecf20Sopenharmony_ci/**
2968c2ecf20Sopenharmony_ci * vmw_view_add - Create a view resource and stage it for addition
2978c2ecf20Sopenharmony_ci * as a command buffer managed resource.
2988c2ecf20Sopenharmony_ci *
2998c2ecf20Sopenharmony_ci * @man: Pointer to the compat shader manager identifying the shader namespace.
3008c2ecf20Sopenharmony_ci * @ctx: Pointer to a struct vmw_resource identifying the active context.
3018c2ecf20Sopenharmony_ci * @srf: Pointer to a struct vmw_resource identifying the surface the view
3028c2ecf20Sopenharmony_ci * points to.
3038c2ecf20Sopenharmony_ci * @view_type: The view type deduced from the view create command.
3048c2ecf20Sopenharmony_ci * @user_key: The key that is used to identify the shader. The key is
3058c2ecf20Sopenharmony_ci * unique to the view type and to the context.
3068c2ecf20Sopenharmony_ci * @cmd: Pointer to the view create command in the command stream.
3078c2ecf20Sopenharmony_ci * @cmd_size: Size of the view create command in the command stream.
3088c2ecf20Sopenharmony_ci * @list: Caller's list of staged command buffer resource actions.
3098c2ecf20Sopenharmony_ci */
3108c2ecf20Sopenharmony_ciint vmw_view_add(struct vmw_cmdbuf_res_manager *man,
3118c2ecf20Sopenharmony_ci		 struct vmw_resource *ctx,
3128c2ecf20Sopenharmony_ci		 struct vmw_resource *srf,
3138c2ecf20Sopenharmony_ci		 enum vmw_view_type view_type,
3148c2ecf20Sopenharmony_ci		 u32 user_key,
3158c2ecf20Sopenharmony_ci		 const void *cmd,
3168c2ecf20Sopenharmony_ci		 size_t cmd_size,
3178c2ecf20Sopenharmony_ci		 struct list_head *list)
3188c2ecf20Sopenharmony_ci{
3198c2ecf20Sopenharmony_ci	static const size_t vmw_view_define_sizes[] = {
3208c2ecf20Sopenharmony_ci		[vmw_view_sr] = sizeof(SVGA3dCmdDXDefineShaderResourceView),
3218c2ecf20Sopenharmony_ci		[vmw_view_rt] = sizeof(SVGA3dCmdDXDefineRenderTargetView),
3228c2ecf20Sopenharmony_ci		[vmw_view_ds] = sizeof(SVGA3dCmdDXDefineDepthStencilView),
3238c2ecf20Sopenharmony_ci		[vmw_view_ua] = sizeof(SVGA3dCmdDXDefineUAView)
3248c2ecf20Sopenharmony_ci	};
3258c2ecf20Sopenharmony_ci
3268c2ecf20Sopenharmony_ci	struct vmw_private *dev_priv = ctx->dev_priv;
3278c2ecf20Sopenharmony_ci	struct vmw_resource *res;
3288c2ecf20Sopenharmony_ci	struct vmw_view *view;
3298c2ecf20Sopenharmony_ci	struct ttm_operation_ctx ttm_opt_ctx = {
3308c2ecf20Sopenharmony_ci		.interruptible = true,
3318c2ecf20Sopenharmony_ci		.no_wait_gpu = false
3328c2ecf20Sopenharmony_ci	};
3338c2ecf20Sopenharmony_ci	size_t size;
3348c2ecf20Sopenharmony_ci	int ret;
3358c2ecf20Sopenharmony_ci
3368c2ecf20Sopenharmony_ci	if (cmd_size != vmw_view_define_sizes[view_type] +
3378c2ecf20Sopenharmony_ci	    sizeof(SVGA3dCmdHeader)) {
3388c2ecf20Sopenharmony_ci		VMW_DEBUG_USER("Illegal view create command size.\n");
3398c2ecf20Sopenharmony_ci		return -EINVAL;
3408c2ecf20Sopenharmony_ci	}
3418c2ecf20Sopenharmony_ci
3428c2ecf20Sopenharmony_ci	if (!vmw_view_id_ok(user_key, view_type)) {
3438c2ecf20Sopenharmony_ci		VMW_DEBUG_USER("Illegal view add view id.\n");
3448c2ecf20Sopenharmony_ci		return -EINVAL;
3458c2ecf20Sopenharmony_ci	}
3468c2ecf20Sopenharmony_ci
3478c2ecf20Sopenharmony_ci	size = offsetof(struct vmw_view, cmd) + cmd_size;
3488c2ecf20Sopenharmony_ci
3498c2ecf20Sopenharmony_ci	ret = ttm_mem_global_alloc(vmw_mem_glob(dev_priv), size, &ttm_opt_ctx);
3508c2ecf20Sopenharmony_ci	if (ret) {
3518c2ecf20Sopenharmony_ci		if (ret != -ERESTARTSYS)
3528c2ecf20Sopenharmony_ci			DRM_ERROR("Out of graphics memory for view creation\n");
3538c2ecf20Sopenharmony_ci		return ret;
3548c2ecf20Sopenharmony_ci	}
3558c2ecf20Sopenharmony_ci
3568c2ecf20Sopenharmony_ci	view = kmalloc(size, GFP_KERNEL);
3578c2ecf20Sopenharmony_ci	if (!view) {
3588c2ecf20Sopenharmony_ci		ttm_mem_global_free(vmw_mem_glob(dev_priv), size);
3598c2ecf20Sopenharmony_ci		return -ENOMEM;
3608c2ecf20Sopenharmony_ci	}
3618c2ecf20Sopenharmony_ci
3628c2ecf20Sopenharmony_ci	res = &view->res;
3638c2ecf20Sopenharmony_ci	view->ctx = ctx;
3648c2ecf20Sopenharmony_ci	view->srf = vmw_resource_reference(srf);
3658c2ecf20Sopenharmony_ci	view->cotable = vmw_resource_reference
3668c2ecf20Sopenharmony_ci		(vmw_context_cotable(ctx, vmw_view_cotables[view_type]));
3678c2ecf20Sopenharmony_ci	view->view_type = view_type;
3688c2ecf20Sopenharmony_ci	view->view_id = user_key;
3698c2ecf20Sopenharmony_ci	view->cmd_size = cmd_size;
3708c2ecf20Sopenharmony_ci	view->committed = false;
3718c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&view->srf_head);
3728c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&view->cotable_head);
3738c2ecf20Sopenharmony_ci	memcpy(&view->cmd, cmd, cmd_size);
3748c2ecf20Sopenharmony_ci	ret = vmw_resource_init(dev_priv, res, true,
3758c2ecf20Sopenharmony_ci				vmw_view_res_free, &vmw_view_func);
3768c2ecf20Sopenharmony_ci	if (ret)
3778c2ecf20Sopenharmony_ci		goto out_resource_init;
3788c2ecf20Sopenharmony_ci
3798c2ecf20Sopenharmony_ci	ret = vmw_cmdbuf_res_add(man, vmw_cmdbuf_res_view,
3808c2ecf20Sopenharmony_ci				 vmw_view_key(user_key, view_type),
3818c2ecf20Sopenharmony_ci				 res, list);
3828c2ecf20Sopenharmony_ci	if (ret)
3838c2ecf20Sopenharmony_ci		goto out_resource_init;
3848c2ecf20Sopenharmony_ci
3858c2ecf20Sopenharmony_ci	res->id = view->view_id;
3868c2ecf20Sopenharmony_ci	res->hw_destroy = vmw_hw_view_destroy;
3878c2ecf20Sopenharmony_ci
3888c2ecf20Sopenharmony_ciout_resource_init:
3898c2ecf20Sopenharmony_ci	vmw_resource_unreference(&res);
3908c2ecf20Sopenharmony_ci
3918c2ecf20Sopenharmony_ci	return ret;
3928c2ecf20Sopenharmony_ci}
3938c2ecf20Sopenharmony_ci
3948c2ecf20Sopenharmony_ci/**
3958c2ecf20Sopenharmony_ci * vmw_view_remove - Stage a view for removal.
3968c2ecf20Sopenharmony_ci *
3978c2ecf20Sopenharmony_ci * @man: Pointer to the view manager identifying the shader namespace.
3988c2ecf20Sopenharmony_ci * @user_key: The key that is used to identify the view. The key is
3998c2ecf20Sopenharmony_ci * unique to the view type.
4008c2ecf20Sopenharmony_ci * @view_type: View type
4018c2ecf20Sopenharmony_ci * @list: Caller's list of staged command buffer resource actions.
4028c2ecf20Sopenharmony_ci * @res_p: If the resource is in an already committed state, points to the
4038c2ecf20Sopenharmony_ci * struct vmw_resource on successful return. The pointer will be
4048c2ecf20Sopenharmony_ci * non ref-counted.
4058c2ecf20Sopenharmony_ci */
4068c2ecf20Sopenharmony_ciint vmw_view_remove(struct vmw_cmdbuf_res_manager *man,
4078c2ecf20Sopenharmony_ci		    u32 user_key, enum vmw_view_type view_type,
4088c2ecf20Sopenharmony_ci		    struct list_head *list,
4098c2ecf20Sopenharmony_ci		    struct vmw_resource **res_p)
4108c2ecf20Sopenharmony_ci{
4118c2ecf20Sopenharmony_ci	if (!vmw_view_id_ok(user_key, view_type)) {
4128c2ecf20Sopenharmony_ci		VMW_DEBUG_USER("Illegal view remove view id.\n");
4138c2ecf20Sopenharmony_ci		return -EINVAL;
4148c2ecf20Sopenharmony_ci	}
4158c2ecf20Sopenharmony_ci
4168c2ecf20Sopenharmony_ci	return vmw_cmdbuf_res_remove(man, vmw_cmdbuf_res_view,
4178c2ecf20Sopenharmony_ci				     vmw_view_key(user_key, view_type),
4188c2ecf20Sopenharmony_ci				     list, res_p);
4198c2ecf20Sopenharmony_ci}
4208c2ecf20Sopenharmony_ci
4218c2ecf20Sopenharmony_ci/**
4228c2ecf20Sopenharmony_ci * vmw_view_cotable_list_destroy - Evict all views belonging to a cotable.
4238c2ecf20Sopenharmony_ci *
4248c2ecf20Sopenharmony_ci * @dev_priv: Pointer to a device private struct.
4258c2ecf20Sopenharmony_ci * @list: List of views belonging to a cotable.
4268c2ecf20Sopenharmony_ci * @readback: Unused. Needed for function interface only.
4278c2ecf20Sopenharmony_ci *
4288c2ecf20Sopenharmony_ci * This function evicts all views belonging to a cotable.
4298c2ecf20Sopenharmony_ci * It must be called with the binding_mutex held, and the caller must hold
4308c2ecf20Sopenharmony_ci * a reference to the view resource. This is typically called before the
4318c2ecf20Sopenharmony_ci * cotable is paged out.
4328c2ecf20Sopenharmony_ci */
4338c2ecf20Sopenharmony_civoid vmw_view_cotable_list_destroy(struct vmw_private *dev_priv,
4348c2ecf20Sopenharmony_ci				   struct list_head *list,
4358c2ecf20Sopenharmony_ci				   bool readback)
4368c2ecf20Sopenharmony_ci{
4378c2ecf20Sopenharmony_ci	struct vmw_view *entry, *next;
4388c2ecf20Sopenharmony_ci
4398c2ecf20Sopenharmony_ci	lockdep_assert_held_once(&dev_priv->binding_mutex);
4408c2ecf20Sopenharmony_ci
4418c2ecf20Sopenharmony_ci	list_for_each_entry_safe(entry, next, list, cotable_head)
4428c2ecf20Sopenharmony_ci		WARN_ON(vmw_view_destroy(&entry->res));
4438c2ecf20Sopenharmony_ci}
4448c2ecf20Sopenharmony_ci
4458c2ecf20Sopenharmony_ci/**
4468c2ecf20Sopenharmony_ci * vmw_view_surface_list_destroy - Evict all views pointing to a surface
4478c2ecf20Sopenharmony_ci *
4488c2ecf20Sopenharmony_ci * @dev_priv: Pointer to a device private struct.
4498c2ecf20Sopenharmony_ci * @list: List of views pointing to a surface.
4508c2ecf20Sopenharmony_ci *
4518c2ecf20Sopenharmony_ci * This function evicts all views pointing to a surface. This is typically
4528c2ecf20Sopenharmony_ci * called before the surface is evicted.
4538c2ecf20Sopenharmony_ci */
4548c2ecf20Sopenharmony_civoid vmw_view_surface_list_destroy(struct vmw_private *dev_priv,
4558c2ecf20Sopenharmony_ci				   struct list_head *list)
4568c2ecf20Sopenharmony_ci{
4578c2ecf20Sopenharmony_ci	struct vmw_view *entry, *next;
4588c2ecf20Sopenharmony_ci
4598c2ecf20Sopenharmony_ci	lockdep_assert_held_once(&dev_priv->binding_mutex);
4608c2ecf20Sopenharmony_ci
4618c2ecf20Sopenharmony_ci	list_for_each_entry_safe(entry, next, list, srf_head)
4628c2ecf20Sopenharmony_ci		WARN_ON(vmw_view_destroy(&entry->res));
4638c2ecf20Sopenharmony_ci}
4648c2ecf20Sopenharmony_ci
4658c2ecf20Sopenharmony_ci/**
4668c2ecf20Sopenharmony_ci * vmw_view_srf - Return a non-refcounted pointer to the surface a view is
4678c2ecf20Sopenharmony_ci * pointing to.
4688c2ecf20Sopenharmony_ci *
4698c2ecf20Sopenharmony_ci * @res: pointer to a view resource.
4708c2ecf20Sopenharmony_ci *
4718c2ecf20Sopenharmony_ci * Note that the view itself is holding a reference, so as long
4728c2ecf20Sopenharmony_ci * the view resource is alive, the surface resource will be.
4738c2ecf20Sopenharmony_ci */
4748c2ecf20Sopenharmony_cistruct vmw_resource *vmw_view_srf(struct vmw_resource *res)
4758c2ecf20Sopenharmony_ci{
4768c2ecf20Sopenharmony_ci	return vmw_view(res)->srf;
4778c2ecf20Sopenharmony_ci}
4788c2ecf20Sopenharmony_ci
4798c2ecf20Sopenharmony_ci/**
4808c2ecf20Sopenharmony_ci * vmw_view_lookup - Look up a view.
4818c2ecf20Sopenharmony_ci *
4828c2ecf20Sopenharmony_ci * @man: The context's cmdbuf ref manager.
4838c2ecf20Sopenharmony_ci * @view_type: The view type.
4848c2ecf20Sopenharmony_ci * @user_key: The view user id.
4858c2ecf20Sopenharmony_ci *
4868c2ecf20Sopenharmony_ci * returns a refcounted pointer to a view or an error pointer if not found.
4878c2ecf20Sopenharmony_ci */
4888c2ecf20Sopenharmony_cistruct vmw_resource *vmw_view_lookup(struct vmw_cmdbuf_res_manager *man,
4898c2ecf20Sopenharmony_ci				     enum vmw_view_type view_type,
4908c2ecf20Sopenharmony_ci				     u32 user_key)
4918c2ecf20Sopenharmony_ci{
4928c2ecf20Sopenharmony_ci	return vmw_cmdbuf_res_lookup(man, vmw_cmdbuf_res_view,
4938c2ecf20Sopenharmony_ci				     vmw_view_key(user_key, view_type));
4948c2ecf20Sopenharmony_ci}
4958c2ecf20Sopenharmony_ci
4968c2ecf20Sopenharmony_ci/**
4978c2ecf20Sopenharmony_ci * vmw_view_dirtying - Return whether a view type is dirtying its resource
4988c2ecf20Sopenharmony_ci * @res: Pointer to the view
4998c2ecf20Sopenharmony_ci *
5008c2ecf20Sopenharmony_ci * Each time a resource is put on the validation list as the result of a
5018c2ecf20Sopenharmony_ci * view pointing to it, we need to determine whether that resource will
5028c2ecf20Sopenharmony_ci * be dirtied (written to by the GPU) as a result of the corresponding
5038c2ecf20Sopenharmony_ci * GPU operation. Currently only rendertarget-, depth-stencil and unordered
5048c2ecf20Sopenharmony_ci * access views are capable of dirtying its resource.
5058c2ecf20Sopenharmony_ci *
5068c2ecf20Sopenharmony_ci * Return: Whether the view type of @res dirties the resource it points to.
5078c2ecf20Sopenharmony_ci */
5088c2ecf20Sopenharmony_ciu32 vmw_view_dirtying(struct vmw_resource *res)
5098c2ecf20Sopenharmony_ci{
5108c2ecf20Sopenharmony_ci	static u32 view_is_dirtying[vmw_view_max] = {
5118c2ecf20Sopenharmony_ci		[vmw_view_rt] = VMW_RES_DIRTY_SET,
5128c2ecf20Sopenharmony_ci		[vmw_view_ds] = VMW_RES_DIRTY_SET,
5138c2ecf20Sopenharmony_ci		[vmw_view_ua] = VMW_RES_DIRTY_SET,
5148c2ecf20Sopenharmony_ci	};
5158c2ecf20Sopenharmony_ci
5168c2ecf20Sopenharmony_ci	/* Update this function as we add more view types */
5178c2ecf20Sopenharmony_ci	BUILD_BUG_ON(vmw_view_max != 4);
5188c2ecf20Sopenharmony_ci	return view_is_dirtying[vmw_view(res)->view_type];
5198c2ecf20Sopenharmony_ci}
5208c2ecf20Sopenharmony_ci
5218c2ecf20Sopenharmony_ciconst u32 vmw_view_destroy_cmds[] = {
5228c2ecf20Sopenharmony_ci	[vmw_view_sr] = SVGA_3D_CMD_DX_DESTROY_SHADERRESOURCE_VIEW,
5238c2ecf20Sopenharmony_ci	[vmw_view_rt] = SVGA_3D_CMD_DX_DESTROY_RENDERTARGET_VIEW,
5248c2ecf20Sopenharmony_ci	[vmw_view_ds] = SVGA_3D_CMD_DX_DESTROY_DEPTHSTENCIL_VIEW,
5258c2ecf20Sopenharmony_ci	[vmw_view_ua] = SVGA_3D_CMD_DX_DESTROY_UA_VIEW,
5268c2ecf20Sopenharmony_ci};
5278c2ecf20Sopenharmony_ci
5288c2ecf20Sopenharmony_ciconst SVGACOTableType vmw_view_cotables[] = {
5298c2ecf20Sopenharmony_ci	[vmw_view_sr] = SVGA_COTABLE_SRVIEW,
5308c2ecf20Sopenharmony_ci	[vmw_view_rt] = SVGA_COTABLE_RTVIEW,
5318c2ecf20Sopenharmony_ci	[vmw_view_ds] = SVGA_COTABLE_DSVIEW,
5328c2ecf20Sopenharmony_ci	[vmw_view_ua] = SVGA_COTABLE_UAVIEW,
5338c2ecf20Sopenharmony_ci};
5348c2ecf20Sopenharmony_ci
5358c2ecf20Sopenharmony_ciconst SVGACOTableType vmw_so_cotables[] = {
5368c2ecf20Sopenharmony_ci	[vmw_so_el] = SVGA_COTABLE_ELEMENTLAYOUT,
5378c2ecf20Sopenharmony_ci	[vmw_so_bs] = SVGA_COTABLE_BLENDSTATE,
5388c2ecf20Sopenharmony_ci	[vmw_so_ds] = SVGA_COTABLE_DEPTHSTENCIL,
5398c2ecf20Sopenharmony_ci	[vmw_so_rs] = SVGA_COTABLE_RASTERIZERSTATE,
5408c2ecf20Sopenharmony_ci	[vmw_so_ss] = SVGA_COTABLE_SAMPLER,
5418c2ecf20Sopenharmony_ci	[vmw_so_so] = SVGA_COTABLE_STREAMOUTPUT
5428c2ecf20Sopenharmony_ci};
5438c2ecf20Sopenharmony_ci
5448c2ecf20Sopenharmony_ci
5458c2ecf20Sopenharmony_ci/* To remove unused function warning */
5468c2ecf20Sopenharmony_cistatic void vmw_so_build_asserts(void) __attribute__((used));
5478c2ecf20Sopenharmony_ci
5488c2ecf20Sopenharmony_ci
5498c2ecf20Sopenharmony_ci/*
5508c2ecf20Sopenharmony_ci * This function is unused at run-time, and only used to dump various build
5518c2ecf20Sopenharmony_ci * asserts important for code optimization assumptions.
5528c2ecf20Sopenharmony_ci */
5538c2ecf20Sopenharmony_cistatic void vmw_so_build_asserts(void)
5548c2ecf20Sopenharmony_ci{
5558c2ecf20Sopenharmony_ci	/* Assert that our vmw_view_cmd_to_type() function is correct. */
5568c2ecf20Sopenharmony_ci	BUILD_BUG_ON(SVGA_3D_CMD_DX_DESTROY_SHADERRESOURCE_VIEW !=
5578c2ecf20Sopenharmony_ci		     SVGA_3D_CMD_DX_DEFINE_SHADERRESOURCE_VIEW + 1);
5588c2ecf20Sopenharmony_ci	BUILD_BUG_ON(SVGA_3D_CMD_DX_DEFINE_RENDERTARGET_VIEW !=
5598c2ecf20Sopenharmony_ci		     SVGA_3D_CMD_DX_DEFINE_SHADERRESOURCE_VIEW + 2);
5608c2ecf20Sopenharmony_ci	BUILD_BUG_ON(SVGA_3D_CMD_DX_DESTROY_RENDERTARGET_VIEW !=
5618c2ecf20Sopenharmony_ci		     SVGA_3D_CMD_DX_DEFINE_SHADERRESOURCE_VIEW + 3);
5628c2ecf20Sopenharmony_ci	BUILD_BUG_ON(SVGA_3D_CMD_DX_DEFINE_DEPTHSTENCIL_VIEW !=
5638c2ecf20Sopenharmony_ci		     SVGA_3D_CMD_DX_DEFINE_SHADERRESOURCE_VIEW + 4);
5648c2ecf20Sopenharmony_ci	BUILD_BUG_ON(SVGA_3D_CMD_DX_DESTROY_DEPTHSTENCIL_VIEW !=
5658c2ecf20Sopenharmony_ci		     SVGA_3D_CMD_DX_DEFINE_SHADERRESOURCE_VIEW + 5);
5668c2ecf20Sopenharmony_ci
5678c2ecf20Sopenharmony_ci	/* Assert that our "one body fits all" assumption is valid */
5688c2ecf20Sopenharmony_ci	BUILD_BUG_ON(sizeof(union vmw_view_destroy) != sizeof(u32));
5698c2ecf20Sopenharmony_ci
5708c2ecf20Sopenharmony_ci	/* Assert that the view key space can hold all view ids. */
5718c2ecf20Sopenharmony_ci	BUILD_BUG_ON(SVGA_COTABLE_MAX_IDS >= ((1 << 20) - 1));
5728c2ecf20Sopenharmony_ci
5738c2ecf20Sopenharmony_ci	/*
5748c2ecf20Sopenharmony_ci	 * Assert that the offset of sid in all view define commands
5758c2ecf20Sopenharmony_ci	 * is what we assume it to be.
5768c2ecf20Sopenharmony_ci	 */
5778c2ecf20Sopenharmony_ci	BUILD_BUG_ON(offsetof(struct vmw_view_define, sid) !=
5788c2ecf20Sopenharmony_ci		     offsetof(SVGA3dCmdDXDefineShaderResourceView, sid));
5798c2ecf20Sopenharmony_ci	BUILD_BUG_ON(offsetof(struct vmw_view_define, sid) !=
5808c2ecf20Sopenharmony_ci		     offsetof(SVGA3dCmdDXDefineRenderTargetView, sid));
5818c2ecf20Sopenharmony_ci	BUILD_BUG_ON(offsetof(struct vmw_view_define, sid) !=
5828c2ecf20Sopenharmony_ci		     offsetof(SVGA3dCmdDXDefineDepthStencilView, sid));
5838c2ecf20Sopenharmony_ci}
584