1fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz/**************************************************************************
2fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz *
3fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * Copyright © 2009 VMware, Inc., Palo Alto, CA., USA
4fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * All Rights Reserved.
5fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz *
6fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * Permission is hereby granted, free of charge, to any person obtaining a
7fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * copy of this software and associated documentation files (the
8fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * "Software"), to deal in the Software without restriction, including
9fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * without limitation the rights to use, copy, modify, merge, publish,
10fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * distribute, sub license, and/or sell copies of the Software, and to
11fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * permit persons to whom the Software is furnished to do so, subject to
12fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * the following conditions:
13fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz *
14fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * The above copyright notice and this permission notice (including the
15fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * next paragraph) shall be included in all copies or substantial portions
16fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * of the Software.
17fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz *
18fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
21fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
22fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
23fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
24fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * USE OR OTHER DEALINGS IN THE SOFTWARE.
25fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz *
26fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz **************************************************************************/
27fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
28fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz#include "vmwgfx_drv.h"
29fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz#include "vmwgfx_reg.h"
30760285e7e7ab282c25b5e90816f7c47000557f4fDavid Howells#include <drm/ttm/ttm_bo_api.h>
31760285e7e7ab282c25b5e90816f7c47000557f4fDavid Howells#include <drm/ttm/ttm_placement.h>
32fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
33c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom#define VMW_RES_HT_ORDER 12
34c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom
35c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom/**
36c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * struct vmw_resource_relocation - Relocation info for resources
37c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom *
38c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * @head: List head for the software context's relocation list.
39c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * @res: Non-ref-counted pointer to the resource.
40c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * @offset: Offset of 4 byte entries into the command buffer where the
41c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * id that needs fixup is located.
42c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom */
43c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstromstruct vmw_resource_relocation {
44c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	struct list_head head;
45c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	const struct vmw_resource *res;
46c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	unsigned long offset;
47c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom};
48c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom
49c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom/**
50c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * struct vmw_resource_val_node - Validation info for resources
51c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom *
52c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * @head: List head for the software context's resource list.
53c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * @hash: Hash entry for quick resouce to val_node lookup.
54c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * @res: Ref-counted pointer to the resource.
55c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * @switch_backup: Boolean whether to switch backup buffer on unreserve.
56c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * @new_backup: Refcounted pointer to the new backup buffer.
57b5c3b1a6bfaf71895d656162f29e979c5c904888Thomas Hellstrom * @staged_bindings: If @res is a context, tracks bindings set up during
58b5c3b1a6bfaf71895d656162f29e979c5c904888Thomas Hellstrom * the command batch. Otherwise NULL.
59c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * @new_backup_offset: New backup buffer offset if @new_backup is non-NUll.
60c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * @first_usage: Set to true the first time the resource is referenced in
61c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * the command stream.
62c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * @no_buffer_needed: Resources do not need to allocate buffer backup on
63c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * reservation. The command stream will provide one.
64c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom */
65c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstromstruct vmw_resource_val_node {
66c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	struct list_head head;
67c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	struct drm_hash_item hash;
68c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	struct vmw_resource *res;
69c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	struct vmw_dma_buffer *new_backup;
70b5c3b1a6bfaf71895d656162f29e979c5c904888Thomas Hellstrom	struct vmw_ctx_binding_state *staged_bindings;
71c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	unsigned long new_backup_offset;
72c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	bool first_usage;
73c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	bool no_buffer_needed;
74c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom};
75c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom
76c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom/**
77c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom * struct vmw_cmd_entry - Describe a command for the verifier
78c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom *
79c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom * @user_allow: Whether allowed from the execbuf ioctl.
80c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom * @gb_disable: Whether disabled if guest-backed objects are available.
81c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom * @gb_enable: Whether enabled iff guest-backed objects are available.
82c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom */
83c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstromstruct vmw_cmd_entry {
84c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom	int (*func) (struct vmw_private *, struct vmw_sw_context *,
85c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom		     SVGA3dCmdHeader *);
86c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom	bool user_allow;
87c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom	bool gb_disable;
88c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom	bool gb_enable;
89c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom};
90c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom
91c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom#define VMW_CMD_DEF(_cmd, _func, _user_allow, _gb_disable, _gb_enable)	\
92c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom	[(_cmd) - SVGA_3D_CMD_BASE] = {(_func), (_user_allow),\
93c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom				       (_gb_disable), (_gb_enable)}
94c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom
95c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom/**
96c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * vmw_resource_unreserve - unreserve resources previously reserved for
97c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * command submission.
98c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom *
99c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * @list_head: list of resources to unreserve.
100c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * @backoff: Whether command submission failed.
101c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom */
102c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstromstatic void vmw_resource_list_unreserve(struct list_head *list,
103c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom					bool backoff)
104c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom{
105c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	struct vmw_resource_val_node *val;
106c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom
107c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	list_for_each_entry(val, list, head) {
108c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom		struct vmw_resource *res = val->res;
109c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom		struct vmw_dma_buffer *new_backup =
110c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom			backoff ? NULL : val->new_backup;
111c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom
112173fb7d4e26705a9e8b8e9d197a18ff39bfdad0aThomas Hellstrom		/*
113173fb7d4e26705a9e8b8e9d197a18ff39bfdad0aThomas Hellstrom		 * Transfer staged context bindings to the
114173fb7d4e26705a9e8b8e9d197a18ff39bfdad0aThomas Hellstrom		 * persistent context binding tracker.
115173fb7d4e26705a9e8b8e9d197a18ff39bfdad0aThomas Hellstrom		 */
116b5c3b1a6bfaf71895d656162f29e979c5c904888Thomas Hellstrom		if (unlikely(val->staged_bindings)) {
11776c7d18bcddc9794f898ebdee44a3160c636da9cThomas Hellstrom			if (!backoff) {
11876c7d18bcddc9794f898ebdee44a3160c636da9cThomas Hellstrom				vmw_context_binding_state_transfer
11976c7d18bcddc9794f898ebdee44a3160c636da9cThomas Hellstrom					(val->res, val->staged_bindings);
12076c7d18bcddc9794f898ebdee44a3160c636da9cThomas Hellstrom			}
121b5c3b1a6bfaf71895d656162f29e979c5c904888Thomas Hellstrom			kfree(val->staged_bindings);
122b5c3b1a6bfaf71895d656162f29e979c5c904888Thomas Hellstrom			val->staged_bindings = NULL;
123b5c3b1a6bfaf71895d656162f29e979c5c904888Thomas Hellstrom		}
124c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom		vmw_resource_unreserve(res, new_backup,
125c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom			val->new_backup_offset);
126c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom		vmw_dmabuf_unreference(&val->new_backup);
127c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	}
128c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom}
129c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom
130c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom
131c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom/**
132c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * vmw_resource_val_add - Add a resource to the software context's
133c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * resource list if it's not already on it.
134c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom *
135c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * @sw_context: Pointer to the software context.
136c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * @res: Pointer to the resource.
137c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * @p_node On successful return points to a valid pointer to a
138c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * struct vmw_resource_val_node, if non-NULL on entry.
139c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom */
140c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstromstatic int vmw_resource_val_add(struct vmw_sw_context *sw_context,
141c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom				struct vmw_resource *res,
142c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom				struct vmw_resource_val_node **p_node)
143c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom{
144c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	struct vmw_resource_val_node *node;
145c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	struct drm_hash_item *hash;
146c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	int ret;
147c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom
148c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	if (likely(drm_ht_find_item(&sw_context->res_ht, (unsigned long) res,
149c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom				    &hash) == 0)) {
150c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom		node = container_of(hash, struct vmw_resource_val_node, hash);
151c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom		node->first_usage = false;
152c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom		if (unlikely(p_node != NULL))
153c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom			*p_node = node;
154c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom		return 0;
155c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	}
156c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom
157c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	node = kzalloc(sizeof(*node), GFP_KERNEL);
158c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	if (unlikely(node == NULL)) {
159c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom		DRM_ERROR("Failed to allocate a resource validation "
160c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom			  "entry.\n");
161c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom		return -ENOMEM;
162c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	}
163c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom
164c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	node->hash.key = (unsigned long) res;
165c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	ret = drm_ht_insert_item(&sw_context->res_ht, &node->hash);
166c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	if (unlikely(ret != 0)) {
167c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom		DRM_ERROR("Failed to initialize a resource validation "
168c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom			  "entry.\n");
169c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom		kfree(node);
170c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom		return ret;
171c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	}
172c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	list_add_tail(&node->head, &sw_context->resource_list);
173c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	node->res = vmw_resource_reference(res);
174c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	node->first_usage = true;
175c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom
176c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	if (unlikely(p_node != NULL))
177c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom		*p_node = node;
178c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom
179c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	return 0;
180c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom}
181c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom
182c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom/**
18330f82d816d2dccfdc2063ac8cca994904c9b612cThomas Hellstrom * vmw_resource_context_res_add - Put resources previously bound to a context on
18430f82d816d2dccfdc2063ac8cca994904c9b612cThomas Hellstrom * the validation list
18530f82d816d2dccfdc2063ac8cca994904c9b612cThomas Hellstrom *
18630f82d816d2dccfdc2063ac8cca994904c9b612cThomas Hellstrom * @dev_priv: Pointer to a device private structure
18730f82d816d2dccfdc2063ac8cca994904c9b612cThomas Hellstrom * @sw_context: Pointer to a software context used for this command submission
18830f82d816d2dccfdc2063ac8cca994904c9b612cThomas Hellstrom * @ctx: Pointer to the context resource
18930f82d816d2dccfdc2063ac8cca994904c9b612cThomas Hellstrom *
19030f82d816d2dccfdc2063ac8cca994904c9b612cThomas Hellstrom * This function puts all resources that were previously bound to @ctx on
19130f82d816d2dccfdc2063ac8cca994904c9b612cThomas Hellstrom * the resource validation list. This is part of the context state reemission
19230f82d816d2dccfdc2063ac8cca994904c9b612cThomas Hellstrom */
19330f82d816d2dccfdc2063ac8cca994904c9b612cThomas Hellstromstatic int vmw_resource_context_res_add(struct vmw_private *dev_priv,
19430f82d816d2dccfdc2063ac8cca994904c9b612cThomas Hellstrom					struct vmw_sw_context *sw_context,
19530f82d816d2dccfdc2063ac8cca994904c9b612cThomas Hellstrom					struct vmw_resource *ctx)
19630f82d816d2dccfdc2063ac8cca994904c9b612cThomas Hellstrom{
19730f82d816d2dccfdc2063ac8cca994904c9b612cThomas Hellstrom	struct list_head *binding_list;
19830f82d816d2dccfdc2063ac8cca994904c9b612cThomas Hellstrom	struct vmw_ctx_binding *entry;
19930f82d816d2dccfdc2063ac8cca994904c9b612cThomas Hellstrom	int ret = 0;
20030f82d816d2dccfdc2063ac8cca994904c9b612cThomas Hellstrom	struct vmw_resource *res;
20130f82d816d2dccfdc2063ac8cca994904c9b612cThomas Hellstrom
20230f82d816d2dccfdc2063ac8cca994904c9b612cThomas Hellstrom	mutex_lock(&dev_priv->binding_mutex);
20330f82d816d2dccfdc2063ac8cca994904c9b612cThomas Hellstrom	binding_list = vmw_context_binding_list(ctx);
20430f82d816d2dccfdc2063ac8cca994904c9b612cThomas Hellstrom
20530f82d816d2dccfdc2063ac8cca994904c9b612cThomas Hellstrom	list_for_each_entry(entry, binding_list, ctx_list) {
20630f82d816d2dccfdc2063ac8cca994904c9b612cThomas Hellstrom		res = vmw_resource_reference_unless_doomed(entry->bi.res);
20730f82d816d2dccfdc2063ac8cca994904c9b612cThomas Hellstrom		if (unlikely(res == NULL))
20830f82d816d2dccfdc2063ac8cca994904c9b612cThomas Hellstrom			continue;
20930f82d816d2dccfdc2063ac8cca994904c9b612cThomas Hellstrom
21030f82d816d2dccfdc2063ac8cca994904c9b612cThomas Hellstrom		ret = vmw_resource_val_add(sw_context, entry->bi.res, NULL);
21130f82d816d2dccfdc2063ac8cca994904c9b612cThomas Hellstrom		vmw_resource_unreference(&res);
21230f82d816d2dccfdc2063ac8cca994904c9b612cThomas Hellstrom		if (unlikely(ret != 0))
21330f82d816d2dccfdc2063ac8cca994904c9b612cThomas Hellstrom			break;
21430f82d816d2dccfdc2063ac8cca994904c9b612cThomas Hellstrom	}
21530f82d816d2dccfdc2063ac8cca994904c9b612cThomas Hellstrom
21630f82d816d2dccfdc2063ac8cca994904c9b612cThomas Hellstrom	mutex_unlock(&dev_priv->binding_mutex);
21730f82d816d2dccfdc2063ac8cca994904c9b612cThomas Hellstrom	return ret;
21830f82d816d2dccfdc2063ac8cca994904c9b612cThomas Hellstrom}
21930f82d816d2dccfdc2063ac8cca994904c9b612cThomas Hellstrom
22030f82d816d2dccfdc2063ac8cca994904c9b612cThomas Hellstrom/**
221c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * vmw_resource_relocation_add - Add a relocation to the relocation list
222c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom *
223c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * @list: Pointer to head of relocation list.
224c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * @res: The resource.
225c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * @offset: Offset into the command buffer currently being parsed where the
226c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * id that needs fixup is located. Granularity is 4 bytes.
227c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom */
228c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstromstatic int vmw_resource_relocation_add(struct list_head *list,
229c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom				       const struct vmw_resource *res,
230c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom				       unsigned long offset)
231c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom{
232c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	struct vmw_resource_relocation *rel;
233c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom
234c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	rel = kmalloc(sizeof(*rel), GFP_KERNEL);
235c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	if (unlikely(rel == NULL)) {
236c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom		DRM_ERROR("Failed to allocate a resource relocation.\n");
237c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom		return -ENOMEM;
238c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	}
239c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom
240c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	rel->res = res;
241c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	rel->offset = offset;
242c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	list_add_tail(&rel->head, list);
243c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom
244c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	return 0;
245c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom}
246c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom
247c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom/**
248c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * vmw_resource_relocations_free - Free all relocations on a list
249c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom *
250c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * @list: Pointer to the head of the relocation list.
251c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom */
252c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstromstatic void vmw_resource_relocations_free(struct list_head *list)
253c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom{
254c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	struct vmw_resource_relocation *rel, *n;
255c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom
256c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	list_for_each_entry_safe(rel, n, list, head) {
257c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom		list_del(&rel->head);
258c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom		kfree(rel);
259c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	}
260c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom}
261c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom
262c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom/**
263c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * vmw_resource_relocations_apply - Apply all relocations on a list
264c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom *
265c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * @cb: Pointer to the start of the command buffer bein patch. This need
266c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * not be the same buffer as the one being parsed when the relocation
267c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * list was built, but the contents must be the same modulo the
268c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * resource ids.
269c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * @list: Pointer to the head of the relocation list.
270c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom */
271c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstromstatic void vmw_resource_relocations_apply(uint32_t *cb,
272c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom					   struct list_head *list)
273c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom{
274c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	struct vmw_resource_relocation *rel;
275c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom
276d5bde956630b86462ee22055f5816a04290aed57Thomas Hellstrom	list_for_each_entry(rel, list, head) {
277d5bde956630b86462ee22055f5816a04290aed57Thomas Hellstrom		if (likely(rel->res != NULL))
278d5bde956630b86462ee22055f5816a04290aed57Thomas Hellstrom			cb[rel->offset] = rel->res->id;
279d5bde956630b86462ee22055f5816a04290aed57Thomas Hellstrom		else
280d5bde956630b86462ee22055f5816a04290aed57Thomas Hellstrom			cb[rel->offset] = SVGA_3D_CMD_NOP;
281d5bde956630b86462ee22055f5816a04290aed57Thomas Hellstrom	}
282c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom}
283c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom
284fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzstatic int vmw_cmd_invalid(struct vmw_private *dev_priv,
285fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz			   struct vmw_sw_context *sw_context,
286fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz			   SVGA3dCmdHeader *header)
287fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{
288fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	return capable(CAP_SYS_ADMIN) ? : -EINVAL;
289fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz}
290fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
291fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzstatic int vmw_cmd_ok(struct vmw_private *dev_priv,
292fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		      struct vmw_sw_context *sw_context,
293fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		      SVGA3dCmdHeader *header)
294fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{
295fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	return 0;
296fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz}
297fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
298e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom/**
299e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom * vmw_bo_to_validate_list - add a bo to a validate list
300e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom *
301e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom * @sw_context: The software context used for this command submission batch.
302e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom * @bo: The buffer object to add.
30396c5f0df22aaf1f20075bc6ad3bdd7656e49cf4dThomas Hellstrom * @validate_as_mob: Validate this buffer as a MOB.
304e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom * @p_val_node: If non-NULL Will be updated with the validate node number
305e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom * on return.
306e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom *
307e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom * Returns -EINVAL if the limit of number of buffer objects per command
308e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom * submission is reached.
309e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom */
310e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstromstatic int vmw_bo_to_validate_list(struct vmw_sw_context *sw_context,
311e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom				   struct ttm_buffer_object *bo,
31296c5f0df22aaf1f20075bc6ad3bdd7656e49cf4dThomas Hellstrom				   bool validate_as_mob,
313e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom				   uint32_t *p_val_node)
314e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom{
315e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom	uint32_t val_node;
316c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	struct vmw_validate_buffer *vval_buf;
317e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom	struct ttm_validate_buffer *val_buf;
318c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	struct drm_hash_item *hash;
319c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	int ret;
320e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom
321c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	if (likely(drm_ht_find_item(&sw_context->res_ht, (unsigned long) bo,
322c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom				    &hash) == 0)) {
323c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom		vval_buf = container_of(hash, struct vmw_validate_buffer,
324c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom					hash);
32596c5f0df22aaf1f20075bc6ad3bdd7656e49cf4dThomas Hellstrom		if (unlikely(vval_buf->validate_as_mob != validate_as_mob)) {
32696c5f0df22aaf1f20075bc6ad3bdd7656e49cf4dThomas Hellstrom			DRM_ERROR("Inconsistent buffer usage.\n");
32796c5f0df22aaf1f20075bc6ad3bdd7656e49cf4dThomas Hellstrom			return -EINVAL;
32896c5f0df22aaf1f20075bc6ad3bdd7656e49cf4dThomas Hellstrom		}
329c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom		val_buf = &vval_buf->base;
330c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom		val_node = vval_buf - sw_context->val_bufs;
331c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	} else {
332c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom		val_node = sw_context->cur_val_buf;
333c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom		if (unlikely(val_node >= VMWGFX_MAX_VALIDATIONS)) {
334c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom			DRM_ERROR("Max number of DMA buffers per submission "
335c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom				  "exceeded.\n");
336c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom			return -EINVAL;
337c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom		}
338c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom		vval_buf = &sw_context->val_bufs[val_node];
339c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom		vval_buf->hash.key = (unsigned long) bo;
340c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom		ret = drm_ht_insert_item(&sw_context->res_ht, &vval_buf->hash);
341c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom		if (unlikely(ret != 0)) {
342c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom			DRM_ERROR("Failed to initialize a buffer validation "
343c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom				  "entry.\n");
344c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom			return ret;
345c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom		}
346c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom		++sw_context->cur_val_buf;
347c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom		val_buf = &vval_buf->base;
348e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom		val_buf->bo = ttm_bo_reference(bo);
349ae9c0af2c0ea92e57013ab2dd7271ba7d6b2a833Christian König		val_buf->shared = false;
350e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom		list_add_tail(&val_buf->head, &sw_context->validate_nodes);
35196c5f0df22aaf1f20075bc6ad3bdd7656e49cf4dThomas Hellstrom		vval_buf->validate_as_mob = validate_as_mob;
352e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom	}
353e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom
354e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom	if (p_val_node)
355e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom		*p_val_node = val_node;
356e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom
357e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom	return 0;
358e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom}
359e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom
360c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom/**
361c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * vmw_resources_reserve - Reserve all resources on the sw_context's
362c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * resource list.
363c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom *
364c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * @sw_context: Pointer to the software context.
365c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom *
366c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * Note that since vmware's command submission currently is protected by
367c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * the cmdbuf mutex, no fancy deadlock avoidance is required for resources,
368c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * since only a single thread at once will attempt this.
369c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom */
370c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstromstatic int vmw_resources_reserve(struct vmw_sw_context *sw_context)
371fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{
372c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	struct vmw_resource_val_node *val;
373fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	int ret;
374fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
375c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	list_for_each_entry(val, &sw_context->resource_list, head) {
376c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom		struct vmw_resource *res = val->res;
377fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
378c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom		ret = vmw_resource_reserve(res, val->no_buffer_needed);
379c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom		if (unlikely(ret != 0))
380c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom			return ret;
381c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom
382c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom		if (res->backup) {
383c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom			struct ttm_buffer_object *bo = &res->backup->base;
384c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom
385c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom			ret = vmw_bo_to_validate_list
38696c5f0df22aaf1f20075bc6ad3bdd7656e49cf4dThomas Hellstrom				(sw_context, bo,
38796c5f0df22aaf1f20075bc6ad3bdd7656e49cf4dThomas Hellstrom				 vmw_resource_needs_backup(res), NULL);
388c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom
389c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom			if (unlikely(ret != 0))
390c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom				return ret;
391c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom		}
392fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	}
393c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	return 0;
394c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom}
395fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
396c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom/**
397c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * vmw_resources_validate - Validate all resources on the sw_context's
398c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * resource list.
399c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom *
400c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * @sw_context: Pointer to the software context.
401c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom *
402c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * Before this function is called, all resource backup buffers must have
403c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * been validated.
404c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom */
405c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstromstatic int vmw_resources_validate(struct vmw_sw_context *sw_context)
406c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom{
407c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	struct vmw_resource_val_node *val;
408c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	int ret;
409c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom
410c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	list_for_each_entry(val, &sw_context->resource_list, head) {
411c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom		struct vmw_resource *res = val->res;
412f18c8840bef4195e6f35298b7746563f10d2d502Thomas Hellstrom
413c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom		ret = vmw_resource_validate(res);
414c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom		if (unlikely(ret != 0)) {
415c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom			if (ret != -ERESTARTSYS)
416c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom				DRM_ERROR("Failed to validate resource.\n");
417c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom			return ret;
418c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom		}
419c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	}
420f18c8840bef4195e6f35298b7746563f10d2d502Thomas Hellstrom	return 0;
421fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz}
422fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
42318e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom
42418e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom/**
42518e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom * vmw_cmd_res_reloc_add - Add a resource to a software context's
42618e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom * relocation- and validation lists.
42718e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom *
42818e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom * @dev_priv: Pointer to a struct vmw_private identifying the device.
42918e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom * @sw_context: Pointer to the software context.
43018e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom * @res_type: Resource type.
43118e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom * @id_loc: Pointer to where the id that needs translation is located.
43218e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom * @res: Valid pointer to a struct vmw_resource.
43318e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom * @p_val: If non null, a pointer to the struct vmw_resource_validate_node
43418e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom * used for this resource is returned here.
43518e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom */
43618e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstromstatic int vmw_cmd_res_reloc_add(struct vmw_private *dev_priv,
43718e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom				 struct vmw_sw_context *sw_context,
43818e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom				 enum vmw_res_type res_type,
43918e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom				 uint32_t *id_loc,
44018e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom				 struct vmw_resource *res,
44118e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom				 struct vmw_resource_val_node **p_val)
44218e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom{
44318e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom	int ret;
44418e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom	struct vmw_resource_val_node *node;
44518e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom
44618e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom	*p_val = NULL;
44718e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom	ret = vmw_resource_relocation_add(&sw_context->res_relocations,
44818e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom					  res,
44918e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom					  id_loc - sw_context->buf_start);
45018e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom	if (unlikely(ret != 0))
4519f9cb84f416f07f57d75789d77e7d47d6141f44eThomas Hellstrom		return ret;
45218e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom
45318e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom	ret = vmw_resource_val_add(sw_context, res, &node);
45418e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom	if (unlikely(ret != 0))
4559f9cb84f416f07f57d75789d77e7d47d6141f44eThomas Hellstrom		return ret;
45618e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom
45718e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom	if (res_type == vmw_res_context && dev_priv->has_mob &&
45818e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom	    node->first_usage) {
45918e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom
46018e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom		/*
46118e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom		 * Put contexts first on the list to be able to exit
46218e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom		 * list traversal for contexts early.
46318e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom		 */
46418e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom		list_del(&node->head);
46518e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom		list_add(&node->head, &sw_context->resource_list);
46618e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom
46718e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom		ret = vmw_resource_context_res_add(dev_priv, sw_context, res);
46818e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom		if (unlikely(ret != 0))
4699f9cb84f416f07f57d75789d77e7d47d6141f44eThomas Hellstrom			return ret;
47018e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom		node->staged_bindings =
47118e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom			kzalloc(sizeof(*node->staged_bindings), GFP_KERNEL);
47218e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom		if (node->staged_bindings == NULL) {
47318e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom			DRM_ERROR("Failed to allocate context binding "
47418e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom				  "information.\n");
4759f9cb84f416f07f57d75789d77e7d47d6141f44eThomas Hellstrom			return -ENOMEM;
47618e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom		}
47718e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom		INIT_LIST_HEAD(&node->staged_bindings->list);
47818e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom	}
47918e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom
48018e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom	if (p_val)
48118e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom		*p_val = node;
48218e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom
4839f9cb84f416f07f57d75789d77e7d47d6141f44eThomas Hellstrom	return 0;
48418e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom}
48518e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom
48618e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom
487c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom/**
48818e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom * vmw_cmd_res_check - Check that a resource is present and if so, put it
489c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * on the resource validate list unless it's already there.
490c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom *
491c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * @dev_priv: Pointer to a device private structure.
492c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * @sw_context: Pointer to the software context.
493c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * @res_type: Resource type.
494c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * @converter: User-space visisble type specific information.
495d5bde956630b86462ee22055f5816a04290aed57Thomas Hellstrom * @id_loc: Pointer to the location in the command buffer currently being
496c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * parsed from where the user-space resource id handle is located.
497d5bde956630b86462ee22055f5816a04290aed57Thomas Hellstrom * @p_val: Pointer to pointer to resource validalidation node. Populated
498d5bde956630b86462ee22055f5816a04290aed57Thomas Hellstrom * on exit.
499c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom */
500d5bde956630b86462ee22055f5816a04290aed57Thomas Hellstromstatic int
50118e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstromvmw_cmd_res_check(struct vmw_private *dev_priv,
50218e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom		  struct vmw_sw_context *sw_context,
50318e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom		  enum vmw_res_type res_type,
50418e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom		  const struct vmw_user_resource_conv *converter,
50518e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom		  uint32_t *id_loc,
50618e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom		  struct vmw_resource_val_node **p_val)
507fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{
508c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	struct vmw_res_cache_entry *rcache =
509c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom		&sw_context->res_cache[res_type];
510be38ab6ea7b0de0542a0ff78690d63bb22f66a4dThomas Hellstrom	struct vmw_resource *res;
511c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	struct vmw_resource_val_node *node;
512c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	int ret;
513be38ab6ea7b0de0542a0ff78690d63bb22f66a4dThomas Hellstrom
51418e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom	if (*id_loc == SVGA3D_INVALID_ID) {
515b5c3b1a6bfaf71895d656162f29e979c5c904888Thomas Hellstrom		if (p_val)
516b5c3b1a6bfaf71895d656162f29e979c5c904888Thomas Hellstrom			*p_val = NULL;
517b5c3b1a6bfaf71895d656162f29e979c5c904888Thomas Hellstrom		if (res_type == vmw_res_context) {
518b5c3b1a6bfaf71895d656162f29e979c5c904888Thomas Hellstrom			DRM_ERROR("Illegal context invalid id.\n");
519b5c3b1a6bfaf71895d656162f29e979c5c904888Thomas Hellstrom			return -EINVAL;
520b5c3b1a6bfaf71895d656162f29e979c5c904888Thomas Hellstrom		}
5217a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom		return 0;
522b5c3b1a6bfaf71895d656162f29e979c5c904888Thomas Hellstrom	}
5237a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom
524c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	/*
525c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	 * Fastpath in case of repeated commands referencing the same
526c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	 * resource
527c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	 */
5287a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom
52918e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom	if (likely(rcache->valid && *id_loc == rcache->handle)) {
530c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom		const struct vmw_resource *res = rcache->res;
531c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom
532c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom		rcache->node->first_usage = false;
533c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom		if (p_val)
534c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom			*p_val = rcache->node;
535c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom
536c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom		return vmw_resource_relocation_add
537c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom			(&sw_context->res_relocations, res,
538d5bde956630b86462ee22055f5816a04290aed57Thomas Hellstrom			 id_loc - sw_context->buf_start);
539be38ab6ea7b0de0542a0ff78690d63bb22f66a4dThomas Hellstrom	}
540be38ab6ea7b0de0542a0ff78690d63bb22f66a4dThomas Hellstrom
541c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	ret = vmw_user_resource_lookup_handle(dev_priv,
542d5bde956630b86462ee22055f5816a04290aed57Thomas Hellstrom					      sw_context->fp->tfile,
54318e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom					      *id_loc,
544c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom					      converter,
545c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom					      &res);
5465bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom	if (unlikely(ret != 0)) {
547c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom		DRM_ERROR("Could not find or use resource 0x%08x.\n",
54818e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom			  (unsigned) *id_loc);
549c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom		dump_stack();
5505bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom		return ret;
5515bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom	}
5525bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom
553c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	rcache->valid = true;
554c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	rcache->res = res;
55518e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom	rcache->handle = *id_loc;
556c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom
55718e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom	ret = vmw_cmd_res_reloc_add(dev_priv, sw_context, res_type, id_loc,
55818e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom				    res, &node);
559c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	if (unlikely(ret != 0))
560c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom		goto out_no_reloc;
561f18c8840bef4195e6f35298b7746563f10d2d502Thomas Hellstrom
562c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	rcache->node = node;
563c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	if (p_val)
564c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom		*p_val = node;
565c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	vmw_resource_unreference(&res);
566f18c8840bef4195e6f35298b7746563f10d2d502Thomas Hellstrom	return 0;
567c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom
568c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstromout_no_reloc:
569c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	BUG_ON(sw_context->error_resource != NULL);
570c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	sw_context->error_resource = res;
571c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom
572c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	return ret;
573fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz}
574fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
575c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom/**
57630f82d816d2dccfdc2063ac8cca994904c9b612cThomas Hellstrom * vmw_rebind_contexts - Rebind all resources previously bound to
57730f82d816d2dccfdc2063ac8cca994904c9b612cThomas Hellstrom * referenced contexts.
57830f82d816d2dccfdc2063ac8cca994904c9b612cThomas Hellstrom *
57930f82d816d2dccfdc2063ac8cca994904c9b612cThomas Hellstrom * @sw_context: Pointer to the software context.
58030f82d816d2dccfdc2063ac8cca994904c9b612cThomas Hellstrom *
58130f82d816d2dccfdc2063ac8cca994904c9b612cThomas Hellstrom * Rebind context binding points that have been scrubbed because of eviction.
58230f82d816d2dccfdc2063ac8cca994904c9b612cThomas Hellstrom */
58330f82d816d2dccfdc2063ac8cca994904c9b612cThomas Hellstromstatic int vmw_rebind_contexts(struct vmw_sw_context *sw_context)
58430f82d816d2dccfdc2063ac8cca994904c9b612cThomas Hellstrom{
58530f82d816d2dccfdc2063ac8cca994904c9b612cThomas Hellstrom	struct vmw_resource_val_node *val;
58630f82d816d2dccfdc2063ac8cca994904c9b612cThomas Hellstrom	int ret;
58730f82d816d2dccfdc2063ac8cca994904c9b612cThomas Hellstrom
58830f82d816d2dccfdc2063ac8cca994904c9b612cThomas Hellstrom	list_for_each_entry(val, &sw_context->resource_list, head) {
58918e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom		if (unlikely(!val->staged_bindings))
59018e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom			break;
59130f82d816d2dccfdc2063ac8cca994904c9b612cThomas Hellstrom
59230f82d816d2dccfdc2063ac8cca994904c9b612cThomas Hellstrom		ret = vmw_context_rebind_all(val->res);
59330f82d816d2dccfdc2063ac8cca994904c9b612cThomas Hellstrom		if (unlikely(ret != 0)) {
59430f82d816d2dccfdc2063ac8cca994904c9b612cThomas Hellstrom			if (ret != -ERESTARTSYS)
59530f82d816d2dccfdc2063ac8cca994904c9b612cThomas Hellstrom				DRM_ERROR("Failed to rebind context.\n");
59630f82d816d2dccfdc2063ac8cca994904c9b612cThomas Hellstrom			return ret;
59730f82d816d2dccfdc2063ac8cca994904c9b612cThomas Hellstrom		}
59830f82d816d2dccfdc2063ac8cca994904c9b612cThomas Hellstrom	}
59930f82d816d2dccfdc2063ac8cca994904c9b612cThomas Hellstrom
60030f82d816d2dccfdc2063ac8cca994904c9b612cThomas Hellstrom	return 0;
60130f82d816d2dccfdc2063ac8cca994904c9b612cThomas Hellstrom}
60230f82d816d2dccfdc2063ac8cca994904c9b612cThomas Hellstrom
60330f82d816d2dccfdc2063ac8cca994904c9b612cThomas Hellstrom/**
604c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * vmw_cmd_cid_check - Check a command header for valid context information.
605c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom *
606c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * @dev_priv: Pointer to a device private structure.
607c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * @sw_context: Pointer to the software context.
608c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * @header: A command header with an embedded user-space context handle.
609c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom *
610c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * Convenience function: Call vmw_cmd_res_check with the user-space context
611c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * handle embedded in @header.
612c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom */
613c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstromstatic int vmw_cmd_cid_check(struct vmw_private *dev_priv,
614c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom			     struct vmw_sw_context *sw_context,
615c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom			     SVGA3dCmdHeader *header)
616c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom{
617c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	struct vmw_cid_cmd {
618c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom		SVGA3dCmdHeader header;
6198e67bbbc51dbeaba480e83fe2162eb08083a0459Thomas Hellstrom		uint32_t cid;
620c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	} *cmd;
621c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom
622c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	cmd = container_of(header, struct vmw_cid_cmd, header);
623c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_context,
624c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom				 user_context_converter, &cmd->cid, NULL);
625c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom}
626fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
627fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzstatic int vmw_cmd_set_render_target_check(struct vmw_private *dev_priv,
628fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz					   struct vmw_sw_context *sw_context,
629fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz					   SVGA3dCmdHeader *header)
630fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{
631fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	struct vmw_sid_cmd {
632fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		SVGA3dCmdHeader header;
633fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		SVGA3dCmdSetRenderTarget body;
634fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	} *cmd;
635b5c3b1a6bfaf71895d656162f29e979c5c904888Thomas Hellstrom	struct vmw_resource_val_node *ctx_node;
636173fb7d4e26705a9e8b8e9d197a18ff39bfdad0aThomas Hellstrom	struct vmw_resource_val_node *res_node;
637fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	int ret;
638fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
639b5c3b1a6bfaf71895d656162f29e979c5c904888Thomas Hellstrom	cmd = container_of(header, struct vmw_sid_cmd, header);
640b5c3b1a6bfaf71895d656162f29e979c5c904888Thomas Hellstrom
641b5c3b1a6bfaf71895d656162f29e979c5c904888Thomas Hellstrom	ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_context,
642b5c3b1a6bfaf71895d656162f29e979c5c904888Thomas Hellstrom				user_context_converter, &cmd->body.cid,
643b5c3b1a6bfaf71895d656162f29e979c5c904888Thomas Hellstrom				&ctx_node);
644fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	if (unlikely(ret != 0))
645fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		return ret;
646fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
647c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface,
648c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom				user_surface_converter,
649173fb7d4e26705a9e8b8e9d197a18ff39bfdad0aThomas Hellstrom				&cmd->body.target.sid, &res_node);
650b5c3b1a6bfaf71895d656162f29e979c5c904888Thomas Hellstrom	if (unlikely(ret != 0))
651b5c3b1a6bfaf71895d656162f29e979c5c904888Thomas Hellstrom		return ret;
652b5c3b1a6bfaf71895d656162f29e979c5c904888Thomas Hellstrom
653b5c3b1a6bfaf71895d656162f29e979c5c904888Thomas Hellstrom	if (dev_priv->has_mob) {
654b5c3b1a6bfaf71895d656162f29e979c5c904888Thomas Hellstrom		struct vmw_ctx_bindinfo bi;
655b5c3b1a6bfaf71895d656162f29e979c5c904888Thomas Hellstrom
656b5c3b1a6bfaf71895d656162f29e979c5c904888Thomas Hellstrom		bi.ctx = ctx_node->res;
657173fb7d4e26705a9e8b8e9d197a18ff39bfdad0aThomas Hellstrom		bi.res = res_node ? res_node->res : NULL;
658b5c3b1a6bfaf71895d656162f29e979c5c904888Thomas Hellstrom		bi.bt = vmw_ctx_binding_rt;
659b5c3b1a6bfaf71895d656162f29e979c5c904888Thomas Hellstrom		bi.i1.rt_type = cmd->body.type;
660b5c3b1a6bfaf71895d656162f29e979c5c904888Thomas Hellstrom		return vmw_context_binding_add(ctx_node->staged_bindings, &bi);
661b5c3b1a6bfaf71895d656162f29e979c5c904888Thomas Hellstrom	}
662b5c3b1a6bfaf71895d656162f29e979c5c904888Thomas Hellstrom
663b5c3b1a6bfaf71895d656162f29e979c5c904888Thomas Hellstrom	return 0;
664fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz}
665fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
666fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzstatic int vmw_cmd_surface_copy_check(struct vmw_private *dev_priv,
667fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz				      struct vmw_sw_context *sw_context,
668fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz				      SVGA3dCmdHeader *header)
669fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{
670fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	struct vmw_sid_cmd {
671fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		SVGA3dCmdHeader header;
672fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		SVGA3dCmdSurfaceCopy body;
673fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	} *cmd;
674fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	int ret;
675fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
676fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	cmd = container_of(header, struct vmw_sid_cmd, header);
677c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface,
678c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom				user_surface_converter,
679c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom				&cmd->body.src.sid, NULL);
680fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	if (unlikely(ret != 0))
681fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		return ret;
682c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface,
683c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom				 user_surface_converter,
684c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom				 &cmd->body.dest.sid, NULL);
685fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz}
686fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
687fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzstatic int vmw_cmd_stretch_blt_check(struct vmw_private *dev_priv,
688fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz				     struct vmw_sw_context *sw_context,
689fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz				     SVGA3dCmdHeader *header)
690fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{
691fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	struct vmw_sid_cmd {
692fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		SVGA3dCmdHeader header;
693fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		SVGA3dCmdSurfaceStretchBlt body;
694fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	} *cmd;
695fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	int ret;
696fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
697fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	cmd = container_of(header, struct vmw_sid_cmd, header);
698c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface,
699c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom				user_surface_converter,
700c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom				&cmd->body.src.sid, NULL);
701fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	if (unlikely(ret != 0))
702fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		return ret;
703c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface,
704c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom				 user_surface_converter,
705c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom				 &cmd->body.dest.sid, NULL);
706fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz}
707fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
708fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzstatic int vmw_cmd_blt_surf_screen_check(struct vmw_private *dev_priv,
709fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz					 struct vmw_sw_context *sw_context,
710fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz					 SVGA3dCmdHeader *header)
711fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{
712fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	struct vmw_sid_cmd {
713fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		SVGA3dCmdHeader header;
714fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		SVGA3dCmdBlitSurfaceToScreen body;
715fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	} *cmd;
716fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
717fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	cmd = container_of(header, struct vmw_sid_cmd, header);
7180cff60c625131c64847debc2b4cee33ba33e8d8fJakob Bornecrantz
719c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface,
720c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom				 user_surface_converter,
721c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom				 &cmd->body.srcImage.sid, NULL);
722fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz}
723fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
724fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzstatic int vmw_cmd_present_check(struct vmw_private *dev_priv,
725fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz				 struct vmw_sw_context *sw_context,
726fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz				 SVGA3dCmdHeader *header)
727fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{
728fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	struct vmw_sid_cmd {
729fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		SVGA3dCmdHeader header;
730fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		SVGA3dCmdPresent body;
731fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	} *cmd;
732fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
7335bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom
734fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	cmd = container_of(header, struct vmw_sid_cmd, header);
7350cff60c625131c64847debc2b4cee33ba33e8d8fJakob Bornecrantz
736c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface,
737c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom				 user_surface_converter, &cmd->body.sid,
738c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom				 NULL);
739fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz}
740fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
741e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom/**
742e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom * vmw_query_bo_switch_prepare - Prepare to switch pinned buffer for queries.
743e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom *
744e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom * @dev_priv: The device private structure.
745e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom * @new_query_bo: The new buffer holding query results.
746e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom * @sw_context: The software context used for this command submission.
747e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom *
748e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom * This function checks whether @new_query_bo is suitable for holding
749e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom * query results, and if another buffer currently is pinned for query
750e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom * results. If so, the function prepares the state of @sw_context for
751e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom * switching pinned buffers after successful submission of the current
752c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * command batch.
753e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom */
754e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstromstatic int vmw_query_bo_switch_prepare(struct vmw_private *dev_priv,
755e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom				       struct ttm_buffer_object *new_query_bo,
756e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom				       struct vmw_sw_context *sw_context)
757e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom{
758c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	struct vmw_res_cache_entry *ctx_entry =
759c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom		&sw_context->res_cache[vmw_res_context];
760e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom	int ret;
761c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom
762c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	BUG_ON(!ctx_entry->valid);
763c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	sw_context->last_query_ctx = ctx_entry->res;
764e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom
765e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom	if (unlikely(new_query_bo != sw_context->cur_query_bo)) {
766e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom
767e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom		if (unlikely(new_query_bo->num_pages > 4)) {
768e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom			DRM_ERROR("Query buffer too large.\n");
769e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom			return -EINVAL;
770e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom		}
771e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom
772e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom		if (unlikely(sw_context->cur_query_bo != NULL)) {
773c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom			sw_context->needs_post_query_barrier = true;
774e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom			ret = vmw_bo_to_validate_list(sw_context,
775e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom						      sw_context->cur_query_bo,
77696c5f0df22aaf1f20075bc6ad3bdd7656e49cf4dThomas Hellstrom						      dev_priv->has_mob, NULL);
777e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom			if (unlikely(ret != 0))
778e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom				return ret;
779e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom		}
780e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom		sw_context->cur_query_bo = new_query_bo;
781e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom
782e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom		ret = vmw_bo_to_validate_list(sw_context,
783e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom					      dev_priv->dummy_query_bo,
78496c5f0df22aaf1f20075bc6ad3bdd7656e49cf4dThomas Hellstrom					      dev_priv->has_mob, NULL);
785e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom		if (unlikely(ret != 0))
786e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom			return ret;
787e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom
788e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom	}
789e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom
790e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom	return 0;
791e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom}
792e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom
793e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom
794e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom/**
795e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom * vmw_query_bo_switch_commit - Finalize switching pinned query buffer
796e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom *
797e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom * @dev_priv: The device private structure.
798e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom * @sw_context: The software context used for this command submission batch.
799e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom *
800e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom * This function will check if we're switching query buffers, and will then,
801e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom * issue a dummy occlusion query wait used as a query barrier. When the fence
802e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom * object following that query wait has signaled, we are sure that all
803c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * preceding queries have finished, and the old query buffer can be unpinned.
804e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom * However, since both the new query buffer and the old one are fenced with
805e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom * that fence, we can do an asynchronus unpin now, and be sure that the
806e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom * old query buffer won't be moved until the fence has signaled.
807e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom *
808e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom * As mentioned above, both the new - and old query buffers need to be fenced
809e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom * using a sequence emitted *after* calling this function.
810e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom */
811e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstromstatic void vmw_query_bo_switch_commit(struct vmw_private *dev_priv,
812e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom				     struct vmw_sw_context *sw_context)
813e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom{
814e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom	/*
815e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom	 * The validate list should still hold references to all
816e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom	 * contexts here.
817e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom	 */
818e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom
819c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	if (sw_context->needs_post_query_barrier) {
820c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom		struct vmw_res_cache_entry *ctx_entry =
821c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom			&sw_context->res_cache[vmw_res_context];
822c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom		struct vmw_resource *ctx;
823c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom		int ret;
824e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom
825c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom		BUG_ON(!ctx_entry->valid);
826c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom		ctx = ctx_entry->res;
827e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom
828e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom		ret = vmw_fifo_emit_dummy_query(dev_priv, ctx->id);
829e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom
830e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom		if (unlikely(ret != 0))
831e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom			DRM_ERROR("Out of fifo space for dummy query.\n");
832e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom	}
833e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom
834e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom	if (dev_priv->pinned_bo != sw_context->cur_query_bo) {
835e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom		if (dev_priv->pinned_bo) {
836e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom			vmw_bo_pin(dev_priv->pinned_bo, false);
837e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom			ttm_bo_unref(&dev_priv->pinned_bo);
838e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom		}
839e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom
840c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom		if (!sw_context->needs_post_query_barrier) {
841c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom			vmw_bo_pin(sw_context->cur_query_bo, true);
842e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom
843c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom			/*
844c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom			 * We pin also the dummy_query_bo buffer so that we
845c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom			 * don't need to validate it when emitting
846c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom			 * dummy queries in context destroy paths.
847c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom			 */
848e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom
849c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom			vmw_bo_pin(dev_priv->dummy_query_bo, true);
850c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom			dev_priv->dummy_query_bo_pinned = true;
851e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom
852c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom			BUG_ON(sw_context->last_query_ctx == NULL);
853c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom			dev_priv->query_cid = sw_context->last_query_ctx->id;
854c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom			dev_priv->query_cid_valid = true;
855c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom			dev_priv->pinned_bo =
856c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom				ttm_bo_reference(sw_context->cur_query_bo);
857c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom		}
858e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom	}
859e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom}
860e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom
861e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom/**
862ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom * vmw_translate_mob_pointer - Prepare to translate a user-space buffer
863ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom * handle to a MOB id.
864ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom *
865ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom * @dev_priv: Pointer to a device private structure.
866ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom * @sw_context: The software context used for this command batch validation.
867ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom * @id: Pointer to the user-space handle to be translated.
868ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom * @vmw_bo_p: Points to a location that, on successful return will carry
869ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom * a reference-counted pointer to the DMA buffer identified by the
870ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom * user-space handle in @id.
871ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom *
872ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom * This function saves information needed to translate a user-space buffer
873ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom * handle to a MOB id. The translation does not take place immediately, but
874ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom * during a call to vmw_apply_relocations(). This function builds a relocation
875ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom * list and a list of buffers to validate. The former needs to be freed using
876ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom * either vmw_apply_relocations() or vmw_free_relocations(). The latter
877ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom * needs to be freed using vmw_clear_validations.
878ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom */
879ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstromstatic int vmw_translate_mob_ptr(struct vmw_private *dev_priv,
880ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom				 struct vmw_sw_context *sw_context,
881ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom				 SVGAMobId *id,
882ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom				 struct vmw_dma_buffer **vmw_bo_p)
883ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom{
884ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom	struct vmw_dma_buffer *vmw_bo = NULL;
885ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom	struct ttm_buffer_object *bo;
886ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom	uint32_t handle = *id;
887ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom	struct vmw_relocation *reloc;
888ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom	int ret;
889ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom
890d5bde956630b86462ee22055f5816a04290aed57Thomas Hellstrom	ret = vmw_user_dmabuf_lookup(sw_context->fp->tfile, handle, &vmw_bo);
891ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom	if (unlikely(ret != 0)) {
892ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom		DRM_ERROR("Could not find or use MOB buffer.\n");
893ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom		return -EINVAL;
894ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom	}
895ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom	bo = &vmw_bo->base;
896ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom
897ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom	if (unlikely(sw_context->cur_reloc >= VMWGFX_MAX_RELOCATIONS)) {
898ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom		DRM_ERROR("Max number relocations per submission"
899ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom			  " exceeded\n");
900ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom		ret = -EINVAL;
901ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom		goto out_no_reloc;
902ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom	}
903ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom
904ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom	reloc = &sw_context->relocs[sw_context->cur_reloc++];
905ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom	reloc->mob_loc = id;
906ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom	reloc->location = NULL;
907ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom
908ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom	ret = vmw_bo_to_validate_list(sw_context, bo, true, &reloc->index);
909ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom	if (unlikely(ret != 0))
910ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom		goto out_no_reloc;
911ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom
912ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom	*vmw_bo_p = vmw_bo;
913ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom	return 0;
914ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom
915ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstromout_no_reloc:
916ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom	vmw_dmabuf_unreference(&vmw_bo);
917ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom	vmw_bo_p = NULL;
918ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom	return ret;
919ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom}
920ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom
921ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom/**
922c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * vmw_translate_guest_pointer - Prepare to translate a user-space buffer
923c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * handle to a valid SVGAGuestPtr
924e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom *
925c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * @dev_priv: Pointer to a device private structure.
926c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * @sw_context: The software context used for this command batch validation.
927c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * @ptr: Pointer to the user-space handle to be translated.
928c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * @vmw_bo_p: Points to a location that, on successful return will carry
929c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * a reference-counted pointer to the DMA buffer identified by the
930c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * user-space handle in @id.
931e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom *
932c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * This function saves information needed to translate a user-space buffer
933c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * handle to a valid SVGAGuestPtr. The translation does not take place
934c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * immediately, but during a call to vmw_apply_relocations().
935c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * This function builds a relocation list and a list of buffers to validate.
936c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * The former needs to be freed using either vmw_apply_relocations() or
937c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * vmw_free_relocations(). The latter needs to be freed using
938c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * vmw_clear_validations.
939e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom */
9404e4ddd47774313accc86b233d6ca2c6a9037a671Thomas Hellstromstatic int vmw_translate_guest_ptr(struct vmw_private *dev_priv,
9414e4ddd47774313accc86b233d6ca2c6a9037a671Thomas Hellstrom				   struct vmw_sw_context *sw_context,
9424e4ddd47774313accc86b233d6ca2c6a9037a671Thomas Hellstrom				   SVGAGuestPtr *ptr,
9434e4ddd47774313accc86b233d6ca2c6a9037a671Thomas Hellstrom				   struct vmw_dma_buffer **vmw_bo_p)
944fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{
945fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	struct vmw_dma_buffer *vmw_bo = NULL;
946fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	struct ttm_buffer_object *bo;
9474e4ddd47774313accc86b233d6ca2c6a9037a671Thomas Hellstrom	uint32_t handle = ptr->gmrId;
948fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	struct vmw_relocation *reloc;
9494e4ddd47774313accc86b233d6ca2c6a9037a671Thomas Hellstrom	int ret;
950fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
951d5bde956630b86462ee22055f5816a04290aed57Thomas Hellstrom	ret = vmw_user_dmabuf_lookup(sw_context->fp->tfile, handle, &vmw_bo);
952fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	if (unlikely(ret != 0)) {
953fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		DRM_ERROR("Could not find or use GMR region.\n");
954fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		return -EINVAL;
955fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	}
956fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	bo = &vmw_bo->base;
957fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
958fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	if (unlikely(sw_context->cur_reloc >= VMWGFX_MAX_RELOCATIONS)) {
9594e4ddd47774313accc86b233d6ca2c6a9037a671Thomas Hellstrom		DRM_ERROR("Max number relocations per submission"
960fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz			  " exceeded\n");
961fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		ret = -EINVAL;
962fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		goto out_no_reloc;
963fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	}
964fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
965fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	reloc = &sw_context->relocs[sw_context->cur_reloc++];
9664e4ddd47774313accc86b233d6ca2c6a9037a671Thomas Hellstrom	reloc->location = ptr;
967fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
96896c5f0df22aaf1f20075bc6ad3bdd7656e49cf4dThomas Hellstrom	ret = vmw_bo_to_validate_list(sw_context, bo, false, &reloc->index);
969e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom	if (unlikely(ret != 0))
970fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		goto out_no_reloc;
971fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
9724e4ddd47774313accc86b233d6ca2c6a9037a671Thomas Hellstrom	*vmw_bo_p = vmw_bo;
9734e4ddd47774313accc86b233d6ca2c6a9037a671Thomas Hellstrom	return 0;
9744e4ddd47774313accc86b233d6ca2c6a9037a671Thomas Hellstrom
9754e4ddd47774313accc86b233d6ca2c6a9037a671Thomas Hellstromout_no_reloc:
9764e4ddd47774313accc86b233d6ca2c6a9037a671Thomas Hellstrom	vmw_dmabuf_unreference(&vmw_bo);
9774e4ddd47774313accc86b233d6ca2c6a9037a671Thomas Hellstrom	vmw_bo_p = NULL;
9784e4ddd47774313accc86b233d6ca2c6a9037a671Thomas Hellstrom	return ret;
9794e4ddd47774313accc86b233d6ca2c6a9037a671Thomas Hellstrom}
9804e4ddd47774313accc86b233d6ca2c6a9037a671Thomas Hellstrom
981c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom/**
982ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom * vmw_cmd_begin_gb_query - validate a  SVGA_3D_CMD_BEGIN_GB_QUERY command.
983ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom *
984ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom * @dev_priv: Pointer to a device private struct.
985ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom * @sw_context: The software context used for this command submission.
986ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom * @header: Pointer to the command header in the command stream.
987ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom */
988ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstromstatic int vmw_cmd_begin_gb_query(struct vmw_private *dev_priv,
989ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom				  struct vmw_sw_context *sw_context,
990ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom				  SVGA3dCmdHeader *header)
991ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom{
992ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom	struct vmw_begin_gb_query_cmd {
993ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom		SVGA3dCmdHeader header;
994ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom		SVGA3dCmdBeginGBQuery q;
995ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom	} *cmd;
996ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom
997ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom	cmd = container_of(header, struct vmw_begin_gb_query_cmd,
998ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom			   header);
999ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom
1000ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom	return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_context,
1001ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom				 user_context_converter, &cmd->q.cid,
1002ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom				 NULL);
1003ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom}
1004ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom
1005ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom/**
1006c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * vmw_cmd_begin_query - validate a  SVGA_3D_CMD_BEGIN_QUERY command.
1007c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom *
1008c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * @dev_priv: Pointer to a device private struct.
1009c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * @sw_context: The software context used for this command submission.
1010c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * @header: Pointer to the command header in the command stream.
1011c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom */
1012c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstromstatic int vmw_cmd_begin_query(struct vmw_private *dev_priv,
1013c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom			       struct vmw_sw_context *sw_context,
1014c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom			       SVGA3dCmdHeader *header)
1015c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom{
1016c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	struct vmw_begin_query_cmd {
1017c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom		SVGA3dCmdHeader header;
1018c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom		SVGA3dCmdBeginQuery q;
1019c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	} *cmd;
1020c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom
1021c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	cmd = container_of(header, struct vmw_begin_query_cmd,
1022c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom			   header);
1023c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom
1024ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom	if (unlikely(dev_priv->has_mob)) {
1025ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom		struct {
1026ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom			SVGA3dCmdHeader header;
1027ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom			SVGA3dCmdBeginGBQuery q;
1028ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom		} gb_cmd;
1029ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom
1030ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom		BUG_ON(sizeof(gb_cmd) != sizeof(*cmd));
1031ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom
1032ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom		gb_cmd.header.id = SVGA_3D_CMD_BEGIN_GB_QUERY;
1033ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom		gb_cmd.header.size = cmd->header.size;
1034ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom		gb_cmd.q.cid = cmd->q.cid;
1035ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom		gb_cmd.q.type = cmd->q.type;
1036ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom
1037ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom		memcpy(cmd, &gb_cmd, sizeof(*cmd));
1038ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom		return vmw_cmd_begin_gb_query(dev_priv, sw_context, header);
1039ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom	}
1040ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom
1041c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_context,
1042c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom				 user_context_converter, &cmd->q.cid,
1043c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom				 NULL);
1044c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom}
1045c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom
1046c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom/**
1047ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom * vmw_cmd_end_gb_query - validate a  SVGA_3D_CMD_END_GB_QUERY command.
1048ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom *
1049ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom * @dev_priv: Pointer to a device private struct.
1050ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom * @sw_context: The software context used for this command submission.
1051ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom * @header: Pointer to the command header in the command stream.
1052ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom */
1053ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstromstatic int vmw_cmd_end_gb_query(struct vmw_private *dev_priv,
1054ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom				struct vmw_sw_context *sw_context,
1055ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom				SVGA3dCmdHeader *header)
1056ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom{
1057ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom	struct vmw_dma_buffer *vmw_bo;
1058ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom	struct vmw_query_cmd {
1059ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom		SVGA3dCmdHeader header;
1060ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom		SVGA3dCmdEndGBQuery q;
1061ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom	} *cmd;
1062ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom	int ret;
1063ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom
1064ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom	cmd = container_of(header, struct vmw_query_cmd, header);
1065ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom	ret = vmw_cmd_cid_check(dev_priv, sw_context, header);
1066ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom	if (unlikely(ret != 0))
1067ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom		return ret;
1068ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom
1069ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom	ret = vmw_translate_mob_ptr(dev_priv, sw_context,
1070ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom				    &cmd->q.mobid,
1071ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom				    &vmw_bo);
1072ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom	if (unlikely(ret != 0))
1073ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom		return ret;
1074ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom
1075ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom	ret = vmw_query_bo_switch_prepare(dev_priv, &vmw_bo->base, sw_context);
1076ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom
1077ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom	vmw_dmabuf_unreference(&vmw_bo);
1078ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom	return ret;
1079ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom}
1080ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom
1081ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom/**
1082c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * vmw_cmd_end_query - validate a  SVGA_3D_CMD_END_QUERY command.
1083c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom *
1084c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * @dev_priv: Pointer to a device private struct.
1085c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * @sw_context: The software context used for this command submission.
1086c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * @header: Pointer to the command header in the command stream.
1087c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom */
10884e4ddd47774313accc86b233d6ca2c6a9037a671Thomas Hellstromstatic int vmw_cmd_end_query(struct vmw_private *dev_priv,
10894e4ddd47774313accc86b233d6ca2c6a9037a671Thomas Hellstrom			     struct vmw_sw_context *sw_context,
10904e4ddd47774313accc86b233d6ca2c6a9037a671Thomas Hellstrom			     SVGA3dCmdHeader *header)
10914e4ddd47774313accc86b233d6ca2c6a9037a671Thomas Hellstrom{
10924e4ddd47774313accc86b233d6ca2c6a9037a671Thomas Hellstrom	struct vmw_dma_buffer *vmw_bo;
10934e4ddd47774313accc86b233d6ca2c6a9037a671Thomas Hellstrom	struct vmw_query_cmd {
10944e4ddd47774313accc86b233d6ca2c6a9037a671Thomas Hellstrom		SVGA3dCmdHeader header;
10954e4ddd47774313accc86b233d6ca2c6a9037a671Thomas Hellstrom		SVGA3dCmdEndQuery q;
10964e4ddd47774313accc86b233d6ca2c6a9037a671Thomas Hellstrom	} *cmd;
10974e4ddd47774313accc86b233d6ca2c6a9037a671Thomas Hellstrom	int ret;
10984e4ddd47774313accc86b233d6ca2c6a9037a671Thomas Hellstrom
10994e4ddd47774313accc86b233d6ca2c6a9037a671Thomas Hellstrom	cmd = container_of(header, struct vmw_query_cmd, header);
1100ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom	if (dev_priv->has_mob) {
1101ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom		struct {
1102ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom			SVGA3dCmdHeader header;
1103ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom			SVGA3dCmdEndGBQuery q;
1104ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom		} gb_cmd;
1105ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom
1106ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom		BUG_ON(sizeof(gb_cmd) != sizeof(*cmd));
1107ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom
1108ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom		gb_cmd.header.id = SVGA_3D_CMD_END_GB_QUERY;
1109ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom		gb_cmd.header.size = cmd->header.size;
1110ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom		gb_cmd.q.cid = cmd->q.cid;
1111ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom		gb_cmd.q.type = cmd->q.type;
1112ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom		gb_cmd.q.mobid = cmd->q.guestResult.gmrId;
1113ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom		gb_cmd.q.offset = cmd->q.guestResult.offset;
1114ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom
1115ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom		memcpy(cmd, &gb_cmd, sizeof(*cmd));
1116ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom		return vmw_cmd_end_gb_query(dev_priv, sw_context, header);
1117ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom	}
1118ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom
11194e4ddd47774313accc86b233d6ca2c6a9037a671Thomas Hellstrom	ret = vmw_cmd_cid_check(dev_priv, sw_context, header);
11204e4ddd47774313accc86b233d6ca2c6a9037a671Thomas Hellstrom	if (unlikely(ret != 0))
11214e4ddd47774313accc86b233d6ca2c6a9037a671Thomas Hellstrom		return ret;
11224e4ddd47774313accc86b233d6ca2c6a9037a671Thomas Hellstrom
11234e4ddd47774313accc86b233d6ca2c6a9037a671Thomas Hellstrom	ret = vmw_translate_guest_ptr(dev_priv, sw_context,
11244e4ddd47774313accc86b233d6ca2c6a9037a671Thomas Hellstrom				      &cmd->q.guestResult,
11254e4ddd47774313accc86b233d6ca2c6a9037a671Thomas Hellstrom				      &vmw_bo);
11264e4ddd47774313accc86b233d6ca2c6a9037a671Thomas Hellstrom	if (unlikely(ret != 0))
11274e4ddd47774313accc86b233d6ca2c6a9037a671Thomas Hellstrom		return ret;
11284e4ddd47774313accc86b233d6ca2c6a9037a671Thomas Hellstrom
1129c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	ret = vmw_query_bo_switch_prepare(dev_priv, &vmw_bo->base, sw_context);
1130e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom
11314e4ddd47774313accc86b233d6ca2c6a9037a671Thomas Hellstrom	vmw_dmabuf_unreference(&vmw_bo);
1132e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom	return ret;
11334e4ddd47774313accc86b233d6ca2c6a9037a671Thomas Hellstrom}
1134fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
1135ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom/**
1136ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom * vmw_cmd_wait_gb_query - validate a  SVGA_3D_CMD_WAIT_GB_QUERY command.
1137ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom *
1138ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom * @dev_priv: Pointer to a device private struct.
1139ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom * @sw_context: The software context used for this command submission.
1140ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom * @header: Pointer to the command header in the command stream.
1141ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom */
1142ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstromstatic int vmw_cmd_wait_gb_query(struct vmw_private *dev_priv,
1143ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom				 struct vmw_sw_context *sw_context,
1144ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom				 SVGA3dCmdHeader *header)
1145ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom{
1146ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom	struct vmw_dma_buffer *vmw_bo;
1147ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom	struct vmw_query_cmd {
1148ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom		SVGA3dCmdHeader header;
1149ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom		SVGA3dCmdWaitForGBQuery q;
1150ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom	} *cmd;
1151ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom	int ret;
1152ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom
1153ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom	cmd = container_of(header, struct vmw_query_cmd, header);
1154ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom	ret = vmw_cmd_cid_check(dev_priv, sw_context, header);
1155ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom	if (unlikely(ret != 0))
1156ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom		return ret;
1157ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom
1158ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom	ret = vmw_translate_mob_ptr(dev_priv, sw_context,
1159ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom				    &cmd->q.mobid,
1160ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom				    &vmw_bo);
1161ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom	if (unlikely(ret != 0))
1162ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom		return ret;
1163ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom
1164ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom	vmw_dmabuf_unreference(&vmw_bo);
1165ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom	return 0;
1166ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom}
1167ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom
1168ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom/**
1169c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * vmw_cmd_wait_query - validate a  SVGA_3D_CMD_WAIT_QUERY command.
1170c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom *
1171c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * @dev_priv: Pointer to a device private struct.
1172c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * @sw_context: The software context used for this command submission.
1173c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * @header: Pointer to the command header in the command stream.
1174c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom */
11754e4ddd47774313accc86b233d6ca2c6a9037a671Thomas Hellstromstatic int vmw_cmd_wait_query(struct vmw_private *dev_priv,
11764e4ddd47774313accc86b233d6ca2c6a9037a671Thomas Hellstrom			      struct vmw_sw_context *sw_context,
11774e4ddd47774313accc86b233d6ca2c6a9037a671Thomas Hellstrom			      SVGA3dCmdHeader *header)
11784e4ddd47774313accc86b233d6ca2c6a9037a671Thomas Hellstrom{
11794e4ddd47774313accc86b233d6ca2c6a9037a671Thomas Hellstrom	struct vmw_dma_buffer *vmw_bo;
11804e4ddd47774313accc86b233d6ca2c6a9037a671Thomas Hellstrom	struct vmw_query_cmd {
11814e4ddd47774313accc86b233d6ca2c6a9037a671Thomas Hellstrom		SVGA3dCmdHeader header;
11824e4ddd47774313accc86b233d6ca2c6a9037a671Thomas Hellstrom		SVGA3dCmdWaitForQuery q;
11834e4ddd47774313accc86b233d6ca2c6a9037a671Thomas Hellstrom	} *cmd;
11844e4ddd47774313accc86b233d6ca2c6a9037a671Thomas Hellstrom	int ret;
11854e4ddd47774313accc86b233d6ca2c6a9037a671Thomas Hellstrom
11864e4ddd47774313accc86b233d6ca2c6a9037a671Thomas Hellstrom	cmd = container_of(header, struct vmw_query_cmd, header);
1187ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom	if (dev_priv->has_mob) {
1188ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom		struct {
1189ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom			SVGA3dCmdHeader header;
1190ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom			SVGA3dCmdWaitForGBQuery q;
1191ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom		} gb_cmd;
1192ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom
1193ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom		BUG_ON(sizeof(gb_cmd) != sizeof(*cmd));
1194ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom
1195ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom		gb_cmd.header.id = SVGA_3D_CMD_WAIT_FOR_GB_QUERY;
1196ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom		gb_cmd.header.size = cmd->header.size;
1197ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom		gb_cmd.q.cid = cmd->q.cid;
1198ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom		gb_cmd.q.type = cmd->q.type;
1199ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom		gb_cmd.q.mobid = cmd->q.guestResult.gmrId;
1200ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom		gb_cmd.q.offset = cmd->q.guestResult.offset;
1201ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom
1202ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom		memcpy(cmd, &gb_cmd, sizeof(*cmd));
1203ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom		return vmw_cmd_wait_gb_query(dev_priv, sw_context, header);
1204ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom	}
1205ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom
12064e4ddd47774313accc86b233d6ca2c6a9037a671Thomas Hellstrom	ret = vmw_cmd_cid_check(dev_priv, sw_context, header);
12074e4ddd47774313accc86b233d6ca2c6a9037a671Thomas Hellstrom	if (unlikely(ret != 0))
12084e4ddd47774313accc86b233d6ca2c6a9037a671Thomas Hellstrom		return ret;
12094e4ddd47774313accc86b233d6ca2c6a9037a671Thomas Hellstrom
12104e4ddd47774313accc86b233d6ca2c6a9037a671Thomas Hellstrom	ret = vmw_translate_guest_ptr(dev_priv, sw_context,
12114e4ddd47774313accc86b233d6ca2c6a9037a671Thomas Hellstrom				      &cmd->q.guestResult,
12124e4ddd47774313accc86b233d6ca2c6a9037a671Thomas Hellstrom				      &vmw_bo);
12134e4ddd47774313accc86b233d6ca2c6a9037a671Thomas Hellstrom	if (unlikely(ret != 0))
12144e4ddd47774313accc86b233d6ca2c6a9037a671Thomas Hellstrom		return ret;
12154e4ddd47774313accc86b233d6ca2c6a9037a671Thomas Hellstrom
12164e4ddd47774313accc86b233d6ca2c6a9037a671Thomas Hellstrom	vmw_dmabuf_unreference(&vmw_bo);
12174e4ddd47774313accc86b233d6ca2c6a9037a671Thomas Hellstrom	return 0;
12184e4ddd47774313accc86b233d6ca2c6a9037a671Thomas Hellstrom}
12194e4ddd47774313accc86b233d6ca2c6a9037a671Thomas Hellstrom
12204e4ddd47774313accc86b233d6ca2c6a9037a671Thomas Hellstromstatic int vmw_cmd_dma(struct vmw_private *dev_priv,
12214e4ddd47774313accc86b233d6ca2c6a9037a671Thomas Hellstrom		       struct vmw_sw_context *sw_context,
12224e4ddd47774313accc86b233d6ca2c6a9037a671Thomas Hellstrom		       SVGA3dCmdHeader *header)
12234e4ddd47774313accc86b233d6ca2c6a9037a671Thomas Hellstrom{
12244e4ddd47774313accc86b233d6ca2c6a9037a671Thomas Hellstrom	struct vmw_dma_buffer *vmw_bo = NULL;
12254e4ddd47774313accc86b233d6ca2c6a9037a671Thomas Hellstrom	struct vmw_surface *srf = NULL;
12264e4ddd47774313accc86b233d6ca2c6a9037a671Thomas Hellstrom	struct vmw_dma_cmd {
12274e4ddd47774313accc86b233d6ca2c6a9037a671Thomas Hellstrom		SVGA3dCmdHeader header;
12284e4ddd47774313accc86b233d6ca2c6a9037a671Thomas Hellstrom		SVGA3dCmdSurfaceDMA dma;
12294e4ddd47774313accc86b233d6ca2c6a9037a671Thomas Hellstrom	} *cmd;
12304e4ddd47774313accc86b233d6ca2c6a9037a671Thomas Hellstrom	int ret;
1231cbd75e97a525e3819c02dc18bc2d67aa544c9e45Thomas Hellstrom	SVGA3dCmdSurfaceDMASuffix *suffix;
1232cbd75e97a525e3819c02dc18bc2d67aa544c9e45Thomas Hellstrom	uint32_t bo_size;
12334e4ddd47774313accc86b233d6ca2c6a9037a671Thomas Hellstrom
12344e4ddd47774313accc86b233d6ca2c6a9037a671Thomas Hellstrom	cmd = container_of(header, struct vmw_dma_cmd, header);
1235cbd75e97a525e3819c02dc18bc2d67aa544c9e45Thomas Hellstrom	suffix = (SVGA3dCmdSurfaceDMASuffix *)((unsigned long) &cmd->dma +
1236cbd75e97a525e3819c02dc18bc2d67aa544c9e45Thomas Hellstrom					       header->size - sizeof(*suffix));
1237cbd75e97a525e3819c02dc18bc2d67aa544c9e45Thomas Hellstrom
1238cbd75e97a525e3819c02dc18bc2d67aa544c9e45Thomas Hellstrom	/* Make sure device and verifier stays in sync. */
1239cbd75e97a525e3819c02dc18bc2d67aa544c9e45Thomas Hellstrom	if (unlikely(suffix->suffixSize != sizeof(*suffix))) {
1240cbd75e97a525e3819c02dc18bc2d67aa544c9e45Thomas Hellstrom		DRM_ERROR("Invalid DMA suffix size.\n");
1241cbd75e97a525e3819c02dc18bc2d67aa544c9e45Thomas Hellstrom		return -EINVAL;
1242cbd75e97a525e3819c02dc18bc2d67aa544c9e45Thomas Hellstrom	}
1243cbd75e97a525e3819c02dc18bc2d67aa544c9e45Thomas Hellstrom
12444e4ddd47774313accc86b233d6ca2c6a9037a671Thomas Hellstrom	ret = vmw_translate_guest_ptr(dev_priv, sw_context,
12454e4ddd47774313accc86b233d6ca2c6a9037a671Thomas Hellstrom				      &cmd->dma.guest.ptr,
12464e4ddd47774313accc86b233d6ca2c6a9037a671Thomas Hellstrom				      &vmw_bo);
12474e4ddd47774313accc86b233d6ca2c6a9037a671Thomas Hellstrom	if (unlikely(ret != 0))
12484e4ddd47774313accc86b233d6ca2c6a9037a671Thomas Hellstrom		return ret;
12494e4ddd47774313accc86b233d6ca2c6a9037a671Thomas Hellstrom
1250cbd75e97a525e3819c02dc18bc2d67aa544c9e45Thomas Hellstrom	/* Make sure DMA doesn't cross BO boundaries. */
1251cbd75e97a525e3819c02dc18bc2d67aa544c9e45Thomas Hellstrom	bo_size = vmw_bo->base.num_pages * PAGE_SIZE;
1252cbd75e97a525e3819c02dc18bc2d67aa544c9e45Thomas Hellstrom	if (unlikely(cmd->dma.guest.ptr.offset > bo_size)) {
1253cbd75e97a525e3819c02dc18bc2d67aa544c9e45Thomas Hellstrom		DRM_ERROR("Invalid DMA offset.\n");
1254cbd75e97a525e3819c02dc18bc2d67aa544c9e45Thomas Hellstrom		return -EINVAL;
1255cbd75e97a525e3819c02dc18bc2d67aa544c9e45Thomas Hellstrom	}
1256cbd75e97a525e3819c02dc18bc2d67aa544c9e45Thomas Hellstrom
1257cbd75e97a525e3819c02dc18bc2d67aa544c9e45Thomas Hellstrom	bo_size -= cmd->dma.guest.ptr.offset;
1258cbd75e97a525e3819c02dc18bc2d67aa544c9e45Thomas Hellstrom	if (unlikely(suffix->maximumOffset > bo_size))
1259cbd75e97a525e3819c02dc18bc2d67aa544c9e45Thomas Hellstrom		suffix->maximumOffset = bo_size;
1260cbd75e97a525e3819c02dc18bc2d67aa544c9e45Thomas Hellstrom
1261c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface,
1262c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom				user_surface_converter, &cmd->dma.host.sid,
1263c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom				NULL);
12645bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom	if (unlikely(ret != 0)) {
1265c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom		if (unlikely(ret != -ERESTARTSYS))
1266c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom			DRM_ERROR("could not find surface for DMA.\n");
1267c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom		goto out_no_surface;
12685bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom	}
12695bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom
1270c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	srf = vmw_res_to_srf(sw_context->res_cache[vmw_res_surface].res);
1271f18c8840bef4195e6f35298b7746563f10d2d502Thomas Hellstrom
1272d5bde956630b86462ee22055f5816a04290aed57Thomas Hellstrom	vmw_kms_cursor_snoop(srf, sw_context->fp->tfile, &vmw_bo->base,
1273d5bde956630b86462ee22055f5816a04290aed57Thomas Hellstrom			     header);
1274fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
1275c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstromout_no_surface:
1276fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	vmw_dmabuf_unreference(&vmw_bo);
1277fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	return ret;
1278fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz}
1279fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
12807a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstromstatic int vmw_cmd_draw(struct vmw_private *dev_priv,
12817a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom			struct vmw_sw_context *sw_context,
12827a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom			SVGA3dCmdHeader *header)
12837a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom{
12847a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom	struct vmw_draw_cmd {
12857a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom		SVGA3dCmdHeader header;
12867a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom		SVGA3dCmdDrawPrimitives body;
12877a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom	} *cmd;
12887a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom	SVGA3dVertexDecl *decl = (SVGA3dVertexDecl *)(
12897a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom		(unsigned long)header + sizeof(*cmd));
12907a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom	SVGA3dPrimitiveRange *range;
12917a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom	uint32_t i;
12927a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom	uint32_t maxnum;
12937a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom	int ret;
12947a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom
12957a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom	ret = vmw_cmd_cid_check(dev_priv, sw_context, header);
12967a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom	if (unlikely(ret != 0))
12977a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom		return ret;
12987a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom
12997a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom	cmd = container_of(header, struct vmw_draw_cmd, header);
13007a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom	maxnum = (header->size - sizeof(cmd->body)) / sizeof(*decl);
13017a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom
13027a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom	if (unlikely(cmd->body.numVertexDecls > maxnum)) {
13037a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom		DRM_ERROR("Illegal number of vertex declarations.\n");
13047a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom		return -EINVAL;
13057a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom	}
13067a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom
13077a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom	for (i = 0; i < cmd->body.numVertexDecls; ++i, ++decl) {
1308c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom		ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface,
1309c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom					user_surface_converter,
1310c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom					&decl->array.surfaceId, NULL);
13117a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom		if (unlikely(ret != 0))
13127a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom			return ret;
13137a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom	}
13147a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom
13157a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom	maxnum = (header->size - sizeof(cmd->body) -
13167a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom		  cmd->body.numVertexDecls * sizeof(*decl)) / sizeof(*range);
13177a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom	if (unlikely(cmd->body.numRanges > maxnum)) {
13187a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom		DRM_ERROR("Illegal number of index ranges.\n");
13197a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom		return -EINVAL;
13207a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom	}
13217a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom
13227a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom	range = (SVGA3dPrimitiveRange *) decl;
13237a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom	for (i = 0; i < cmd->body.numRanges; ++i, ++range) {
1324c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom		ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface,
1325c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom					user_surface_converter,
1326c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom					&range->indexArray.surfaceId, NULL);
13277a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom		if (unlikely(ret != 0))
13287a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom			return ret;
13297a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom	}
13307a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom	return 0;
13317a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom}
13327a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom
13337a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom
13347a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstromstatic int vmw_cmd_tex_state(struct vmw_private *dev_priv,
13357a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom			     struct vmw_sw_context *sw_context,
13367a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom			     SVGA3dCmdHeader *header)
13377a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom{
13387a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom	struct vmw_tex_state_cmd {
13397a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom		SVGA3dCmdHeader header;
13407a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom		SVGA3dCmdSetTextureState state;
1341b5c3b1a6bfaf71895d656162f29e979c5c904888Thomas Hellstrom	} *cmd;
13427a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom
13437a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom	SVGA3dTextureState *last_state = (SVGA3dTextureState *)
13447a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom	  ((unsigned long) header + header->size + sizeof(header));
13457a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom	SVGA3dTextureState *cur_state = (SVGA3dTextureState *)
13467a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom		((unsigned long) header + sizeof(struct vmw_tex_state_cmd));
1347b5c3b1a6bfaf71895d656162f29e979c5c904888Thomas Hellstrom	struct vmw_resource_val_node *ctx_node;
1348173fb7d4e26705a9e8b8e9d197a18ff39bfdad0aThomas Hellstrom	struct vmw_resource_val_node *res_node;
13497a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom	int ret;
13507a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom
1351b5c3b1a6bfaf71895d656162f29e979c5c904888Thomas Hellstrom	cmd = container_of(header, struct vmw_tex_state_cmd,
1352b5c3b1a6bfaf71895d656162f29e979c5c904888Thomas Hellstrom			   header);
1353b5c3b1a6bfaf71895d656162f29e979c5c904888Thomas Hellstrom
1354b5c3b1a6bfaf71895d656162f29e979c5c904888Thomas Hellstrom	ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_context,
1355b5c3b1a6bfaf71895d656162f29e979c5c904888Thomas Hellstrom				user_context_converter, &cmd->state.cid,
1356b5c3b1a6bfaf71895d656162f29e979c5c904888Thomas Hellstrom				&ctx_node);
13577a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom	if (unlikely(ret != 0))
13587a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom		return ret;
13597a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom
13607a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom	for (; cur_state < last_state; ++cur_state) {
13617a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom		if (likely(cur_state->name != SVGA3D_TS_BIND_TEXTURE))
13627a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom			continue;
13637a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom
1364c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom		ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface,
1365c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom					user_surface_converter,
1366173fb7d4e26705a9e8b8e9d197a18ff39bfdad0aThomas Hellstrom					&cur_state->value, &res_node);
13677a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom		if (unlikely(ret != 0))
13687a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom			return ret;
1369b5c3b1a6bfaf71895d656162f29e979c5c904888Thomas Hellstrom
1370b5c3b1a6bfaf71895d656162f29e979c5c904888Thomas Hellstrom		if (dev_priv->has_mob) {
1371b5c3b1a6bfaf71895d656162f29e979c5c904888Thomas Hellstrom			struct vmw_ctx_bindinfo bi;
1372b5c3b1a6bfaf71895d656162f29e979c5c904888Thomas Hellstrom
1373b5c3b1a6bfaf71895d656162f29e979c5c904888Thomas Hellstrom			bi.ctx = ctx_node->res;
1374173fb7d4e26705a9e8b8e9d197a18ff39bfdad0aThomas Hellstrom			bi.res = res_node ? res_node->res : NULL;
1375b5c3b1a6bfaf71895d656162f29e979c5c904888Thomas Hellstrom			bi.bt = vmw_ctx_binding_tex;
1376b5c3b1a6bfaf71895d656162f29e979c5c904888Thomas Hellstrom			bi.i1.texture_stage = cur_state->stage;
1377b5c3b1a6bfaf71895d656162f29e979c5c904888Thomas Hellstrom			vmw_context_binding_add(ctx_node->staged_bindings,
1378b5c3b1a6bfaf71895d656162f29e979c5c904888Thomas Hellstrom						&bi);
1379b5c3b1a6bfaf71895d656162f29e979c5c904888Thomas Hellstrom		}
13807a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom	}
13817a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom
13827a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom	return 0;
13837a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom}
13847a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom
13854084fb89e6b463686219a2369d1d35e6b78f785dJakob Bornecrantzstatic int vmw_cmd_check_define_gmrfb(struct vmw_private *dev_priv,
13864084fb89e6b463686219a2369d1d35e6b78f785dJakob Bornecrantz				      struct vmw_sw_context *sw_context,
13874084fb89e6b463686219a2369d1d35e6b78f785dJakob Bornecrantz				      void *buf)
13884084fb89e6b463686219a2369d1d35e6b78f785dJakob Bornecrantz{
13894084fb89e6b463686219a2369d1d35e6b78f785dJakob Bornecrantz	struct vmw_dma_buffer *vmw_bo;
13904084fb89e6b463686219a2369d1d35e6b78f785dJakob Bornecrantz	int ret;
13914084fb89e6b463686219a2369d1d35e6b78f785dJakob Bornecrantz
13924084fb89e6b463686219a2369d1d35e6b78f785dJakob Bornecrantz	struct {
13934084fb89e6b463686219a2369d1d35e6b78f785dJakob Bornecrantz		uint32_t header;
13944084fb89e6b463686219a2369d1d35e6b78f785dJakob Bornecrantz		SVGAFifoCmdDefineGMRFB body;
13954084fb89e6b463686219a2369d1d35e6b78f785dJakob Bornecrantz	} *cmd = buf;
13964084fb89e6b463686219a2369d1d35e6b78f785dJakob Bornecrantz
13974084fb89e6b463686219a2369d1d35e6b78f785dJakob Bornecrantz	ret = vmw_translate_guest_ptr(dev_priv, sw_context,
13984084fb89e6b463686219a2369d1d35e6b78f785dJakob Bornecrantz				      &cmd->body.ptr,
13994084fb89e6b463686219a2369d1d35e6b78f785dJakob Bornecrantz				      &vmw_bo);
14004084fb89e6b463686219a2369d1d35e6b78f785dJakob Bornecrantz	if (unlikely(ret != 0))
14014084fb89e6b463686219a2369d1d35e6b78f785dJakob Bornecrantz		return ret;
14024084fb89e6b463686219a2369d1d35e6b78f785dJakob Bornecrantz
14034084fb89e6b463686219a2369d1d35e6b78f785dJakob Bornecrantz	vmw_dmabuf_unreference(&vmw_bo);
14044084fb89e6b463686219a2369d1d35e6b78f785dJakob Bornecrantz
14054084fb89e6b463686219a2369d1d35e6b78f785dJakob Bornecrantz	return ret;
14064084fb89e6b463686219a2369d1d35e6b78f785dJakob Bornecrantz}
14074084fb89e6b463686219a2369d1d35e6b78f785dJakob Bornecrantz
1408c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom/**
1409a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom * vmw_cmd_switch_backup - Utility function to handle backup buffer switching
1410a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom *
1411a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom * @dev_priv: Pointer to a device private struct.
1412a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom * @sw_context: The software context being used for this batch.
1413a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom * @res_type: The resource type.
1414a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom * @converter: Information about user-space binding for this resource type.
1415a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom * @res_id: Pointer to the user-space resource handle in the command stream.
1416a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom * @buf_id: Pointer to the user-space backup buffer handle in the command
1417a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom * stream.
1418a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom * @backup_offset: Offset of backup into MOB.
1419a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom *
1420a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom * This function prepares for registering a switch of backup buffers
1421a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom * in the resource metadata just prior to unreserving.
1422a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom */
1423a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstromstatic int vmw_cmd_switch_backup(struct vmw_private *dev_priv,
1424a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom				 struct vmw_sw_context *sw_context,
1425a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom				 enum vmw_res_type res_type,
1426a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom				 const struct vmw_user_resource_conv
1427a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom				 *converter,
1428a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom				 uint32_t *res_id,
1429a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom				 uint32_t *buf_id,
1430a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom				 unsigned long backup_offset)
1431a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom{
1432a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom	int ret;
1433a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom	struct vmw_dma_buffer *dma_buf;
1434a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom	struct vmw_resource_val_node *val_node;
1435a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom
1436a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom	ret = vmw_cmd_res_check(dev_priv, sw_context, res_type,
1437a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom				converter, res_id, &val_node);
1438a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom	if (unlikely(ret != 0))
1439a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom		return ret;
1440a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom
1441a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom	ret = vmw_translate_mob_ptr(dev_priv, sw_context, buf_id, &dma_buf);
1442a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom	if (unlikely(ret != 0))
1443a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom		return ret;
1444a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom
1445a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom	if (val_node->first_usage)
1446a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom		val_node->no_buffer_needed = true;
1447a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom
1448a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom	vmw_dmabuf_unreference(&val_node->new_backup);
1449a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom	val_node->new_backup = dma_buf;
1450a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom	val_node->new_backup_offset = backup_offset;
1451a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom
1452a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom	return 0;
1453a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom}
1454a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom
1455a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom/**
1456a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom * vmw_cmd_bind_gb_surface - Validate an SVGA_3D_CMD_BIND_GB_SURFACE
1457a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom * command
1458a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom *
1459a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom * @dev_priv: Pointer to a device private struct.
1460a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom * @sw_context: The software context being used for this batch.
1461a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom * @header: Pointer to the command header in the command stream.
1462a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom */
1463a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstromstatic int vmw_cmd_bind_gb_surface(struct vmw_private *dev_priv,
1464a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom				   struct vmw_sw_context *sw_context,
1465a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom				   SVGA3dCmdHeader *header)
1466a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom{
1467a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom	struct vmw_bind_gb_surface_cmd {
1468a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom		SVGA3dCmdHeader header;
1469a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom		SVGA3dCmdBindGBSurface body;
1470a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom	} *cmd;
1471a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom
1472a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom	cmd = container_of(header, struct vmw_bind_gb_surface_cmd, header);
1473a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom
1474a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom	return vmw_cmd_switch_backup(dev_priv, sw_context, vmw_res_surface,
1475a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom				     user_surface_converter,
1476a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom				     &cmd->body.sid, &cmd->body.mobid,
1477a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom				     0);
1478a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom}
1479a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom
1480a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom/**
1481a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom * vmw_cmd_update_gb_image - Validate an SVGA_3D_CMD_UPDATE_GB_IMAGE
1482a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom * command
1483a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom *
1484a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom * @dev_priv: Pointer to a device private struct.
1485a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom * @sw_context: The software context being used for this batch.
1486a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom * @header: Pointer to the command header in the command stream.
1487a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom */
1488a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstromstatic int vmw_cmd_update_gb_image(struct vmw_private *dev_priv,
1489a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom				   struct vmw_sw_context *sw_context,
1490a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom				   SVGA3dCmdHeader *header)
1491a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom{
1492a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom	struct vmw_gb_surface_cmd {
1493a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom		SVGA3dCmdHeader header;
1494a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom		SVGA3dCmdUpdateGBImage body;
1495a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom	} *cmd;
1496a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom
1497a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom	cmd = container_of(header, struct vmw_gb_surface_cmd, header);
1498a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom
1499a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom	return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface,
1500a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom				 user_surface_converter,
1501a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom				 &cmd->body.image.sid, NULL);
1502a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom}
1503a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom
1504a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom/**
1505a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom * vmw_cmd_update_gb_surface - Validate an SVGA_3D_CMD_UPDATE_GB_SURFACE
1506a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom * command
1507a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom *
1508a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom * @dev_priv: Pointer to a device private struct.
1509a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom * @sw_context: The software context being used for this batch.
1510a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom * @header: Pointer to the command header in the command stream.
1511a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom */
1512a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstromstatic int vmw_cmd_update_gb_surface(struct vmw_private *dev_priv,
1513a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom				     struct vmw_sw_context *sw_context,
1514a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom				     SVGA3dCmdHeader *header)
1515a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom{
1516a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom	struct vmw_gb_surface_cmd {
1517a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom		SVGA3dCmdHeader header;
1518a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom		SVGA3dCmdUpdateGBSurface body;
1519a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom	} *cmd;
1520a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom
1521a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom	cmd = container_of(header, struct vmw_gb_surface_cmd, header);
1522a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom
1523a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom	return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface,
1524a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom				 user_surface_converter,
1525a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom				 &cmd->body.sid, NULL);
1526a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom}
1527a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom
1528a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom/**
1529a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom * vmw_cmd_readback_gb_image - Validate an SVGA_3D_CMD_READBACK_GB_IMAGE
1530a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom * command
1531a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom *
1532a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom * @dev_priv: Pointer to a device private struct.
1533a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom * @sw_context: The software context being used for this batch.
1534a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom * @header: Pointer to the command header in the command stream.
1535a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom */
1536a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstromstatic int vmw_cmd_readback_gb_image(struct vmw_private *dev_priv,
1537a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom				     struct vmw_sw_context *sw_context,
1538a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom				     SVGA3dCmdHeader *header)
1539a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom{
1540a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom	struct vmw_gb_surface_cmd {
1541a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom		SVGA3dCmdHeader header;
1542a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom		SVGA3dCmdReadbackGBImage body;
1543a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom	} *cmd;
1544a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom
1545a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom	cmd = container_of(header, struct vmw_gb_surface_cmd, header);
1546a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom
1547a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom	return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface,
1548a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom				 user_surface_converter,
1549a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom				 &cmd->body.image.sid, NULL);
1550a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom}
1551a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom
1552a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom/**
1553a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom * vmw_cmd_readback_gb_surface - Validate an SVGA_3D_CMD_READBACK_GB_SURFACE
1554a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom * command
1555a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom *
1556a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom * @dev_priv: Pointer to a device private struct.
1557a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom * @sw_context: The software context being used for this batch.
1558a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom * @header: Pointer to the command header in the command stream.
1559a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom */
1560a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstromstatic int vmw_cmd_readback_gb_surface(struct vmw_private *dev_priv,
1561a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom				       struct vmw_sw_context *sw_context,
1562a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom				       SVGA3dCmdHeader *header)
1563a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom{
1564a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom	struct vmw_gb_surface_cmd {
1565a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom		SVGA3dCmdHeader header;
1566a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom		SVGA3dCmdReadbackGBSurface body;
1567a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom	} *cmd;
1568a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom
1569a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom	cmd = container_of(header, struct vmw_gb_surface_cmd, header);
1570a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom
1571a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom	return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface,
1572a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom				 user_surface_converter,
1573a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom				 &cmd->body.sid, NULL);
1574a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom}
1575a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom
1576a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom/**
1577a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom * vmw_cmd_invalidate_gb_image - Validate an SVGA_3D_CMD_INVALIDATE_GB_IMAGE
1578a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom * command
1579a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom *
1580a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom * @dev_priv: Pointer to a device private struct.
1581a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom * @sw_context: The software context being used for this batch.
1582a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom * @header: Pointer to the command header in the command stream.
1583a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom */
1584a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstromstatic int vmw_cmd_invalidate_gb_image(struct vmw_private *dev_priv,
1585a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom				       struct vmw_sw_context *sw_context,
1586a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom				       SVGA3dCmdHeader *header)
1587a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom{
1588a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom	struct vmw_gb_surface_cmd {
1589a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom		SVGA3dCmdHeader header;
1590a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom		SVGA3dCmdInvalidateGBImage body;
1591a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom	} *cmd;
1592a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom
1593a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom	cmd = container_of(header, struct vmw_gb_surface_cmd, header);
1594a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom
1595a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom	return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface,
1596a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom				 user_surface_converter,
1597a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom				 &cmd->body.image.sid, NULL);
1598a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom}
1599a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom
1600a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom/**
1601a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom * vmw_cmd_invalidate_gb_surface - Validate an
1602a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom * SVGA_3D_CMD_INVALIDATE_GB_SURFACE command
1603a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom *
1604a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom * @dev_priv: Pointer to a device private struct.
1605a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom * @sw_context: The software context being used for this batch.
1606a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom * @header: Pointer to the command header in the command stream.
1607a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom */
1608a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstromstatic int vmw_cmd_invalidate_gb_surface(struct vmw_private *dev_priv,
1609a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom					 struct vmw_sw_context *sw_context,
1610a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom					 SVGA3dCmdHeader *header)
1611a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom{
1612a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom	struct vmw_gb_surface_cmd {
1613a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom		SVGA3dCmdHeader header;
1614a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom		SVGA3dCmdInvalidateGBSurface body;
1615a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom	} *cmd;
1616a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom
1617a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom	cmd = container_of(header, struct vmw_gb_surface_cmd, header);
1618a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom
1619a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom	return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface,
1620a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom				 user_surface_converter,
1621a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom				 &cmd->body.sid, NULL);
1622a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom}
1623a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom
1624d5bde956630b86462ee22055f5816a04290aed57Thomas Hellstrom
1625d5bde956630b86462ee22055f5816a04290aed57Thomas Hellstrom/**
1626d5bde956630b86462ee22055f5816a04290aed57Thomas Hellstrom * vmw_cmd_shader_define - Validate an SVGA_3D_CMD_SHADER_DEFINE
1627d5bde956630b86462ee22055f5816a04290aed57Thomas Hellstrom * command
1628d5bde956630b86462ee22055f5816a04290aed57Thomas Hellstrom *
1629d5bde956630b86462ee22055f5816a04290aed57Thomas Hellstrom * @dev_priv: Pointer to a device private struct.
1630d5bde956630b86462ee22055f5816a04290aed57Thomas Hellstrom * @sw_context: The software context being used for this batch.
1631d5bde956630b86462ee22055f5816a04290aed57Thomas Hellstrom * @header: Pointer to the command header in the command stream.
1632d5bde956630b86462ee22055f5816a04290aed57Thomas Hellstrom */
1633d5bde956630b86462ee22055f5816a04290aed57Thomas Hellstromstatic int vmw_cmd_shader_define(struct vmw_private *dev_priv,
1634d5bde956630b86462ee22055f5816a04290aed57Thomas Hellstrom				 struct vmw_sw_context *sw_context,
1635d5bde956630b86462ee22055f5816a04290aed57Thomas Hellstrom				 SVGA3dCmdHeader *header)
1636d5bde956630b86462ee22055f5816a04290aed57Thomas Hellstrom{
1637d5bde956630b86462ee22055f5816a04290aed57Thomas Hellstrom	struct vmw_shader_define_cmd {
1638d5bde956630b86462ee22055f5816a04290aed57Thomas Hellstrom		SVGA3dCmdHeader header;
1639d5bde956630b86462ee22055f5816a04290aed57Thomas Hellstrom		SVGA3dCmdDefineShader body;
1640d5bde956630b86462ee22055f5816a04290aed57Thomas Hellstrom	} *cmd;
1641d5bde956630b86462ee22055f5816a04290aed57Thomas Hellstrom	int ret;
1642d5bde956630b86462ee22055f5816a04290aed57Thomas Hellstrom	size_t size;
164318e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom	struct vmw_resource_val_node *val;
1644d5bde956630b86462ee22055f5816a04290aed57Thomas Hellstrom
1645d5bde956630b86462ee22055f5816a04290aed57Thomas Hellstrom	cmd = container_of(header, struct vmw_shader_define_cmd,
1646d5bde956630b86462ee22055f5816a04290aed57Thomas Hellstrom			   header);
1647d5bde956630b86462ee22055f5816a04290aed57Thomas Hellstrom
1648d5bde956630b86462ee22055f5816a04290aed57Thomas Hellstrom	ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_context,
1649d5bde956630b86462ee22055f5816a04290aed57Thomas Hellstrom				user_context_converter, &cmd->body.cid,
165018e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom				&val);
1651d5bde956630b86462ee22055f5816a04290aed57Thomas Hellstrom	if (unlikely(ret != 0))
1652d5bde956630b86462ee22055f5816a04290aed57Thomas Hellstrom		return ret;
1653d5bde956630b86462ee22055f5816a04290aed57Thomas Hellstrom
1654d5bde956630b86462ee22055f5816a04290aed57Thomas Hellstrom	if (unlikely(!dev_priv->has_mob))
1655d5bde956630b86462ee22055f5816a04290aed57Thomas Hellstrom		return 0;
1656d5bde956630b86462ee22055f5816a04290aed57Thomas Hellstrom
1657d5bde956630b86462ee22055f5816a04290aed57Thomas Hellstrom	size = cmd->header.size - sizeof(cmd->body);
165818e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom	ret = vmw_compat_shader_add(dev_priv,
165918e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom				    vmw_context_res_man(val->res),
1660d5bde956630b86462ee22055f5816a04290aed57Thomas Hellstrom				    cmd->body.shid, cmd + 1,
1661d5bde956630b86462ee22055f5816a04290aed57Thomas Hellstrom				    cmd->body.type, size,
166218e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom				    &sw_context->staged_cmd_res);
1663d5bde956630b86462ee22055f5816a04290aed57Thomas Hellstrom	if (unlikely(ret != 0))
1664d5bde956630b86462ee22055f5816a04290aed57Thomas Hellstrom		return ret;
1665d5bde956630b86462ee22055f5816a04290aed57Thomas Hellstrom
1666d5bde956630b86462ee22055f5816a04290aed57Thomas Hellstrom	return vmw_resource_relocation_add(&sw_context->res_relocations,
1667d5bde956630b86462ee22055f5816a04290aed57Thomas Hellstrom					   NULL, &cmd->header.id -
1668d5bde956630b86462ee22055f5816a04290aed57Thomas Hellstrom					   sw_context->buf_start);
1669d5bde956630b86462ee22055f5816a04290aed57Thomas Hellstrom
1670d5bde956630b86462ee22055f5816a04290aed57Thomas Hellstrom	return 0;
1671d5bde956630b86462ee22055f5816a04290aed57Thomas Hellstrom}
1672d5bde956630b86462ee22055f5816a04290aed57Thomas Hellstrom
1673d5bde956630b86462ee22055f5816a04290aed57Thomas Hellstrom/**
1674d5bde956630b86462ee22055f5816a04290aed57Thomas Hellstrom * vmw_cmd_shader_destroy - Validate an SVGA_3D_CMD_SHADER_DESTROY
1675d5bde956630b86462ee22055f5816a04290aed57Thomas Hellstrom * command
1676d5bde956630b86462ee22055f5816a04290aed57Thomas Hellstrom *
1677d5bde956630b86462ee22055f5816a04290aed57Thomas Hellstrom * @dev_priv: Pointer to a device private struct.
1678d5bde956630b86462ee22055f5816a04290aed57Thomas Hellstrom * @sw_context: The software context being used for this batch.
1679d5bde956630b86462ee22055f5816a04290aed57Thomas Hellstrom * @header: Pointer to the command header in the command stream.
1680d5bde956630b86462ee22055f5816a04290aed57Thomas Hellstrom */
1681d5bde956630b86462ee22055f5816a04290aed57Thomas Hellstromstatic int vmw_cmd_shader_destroy(struct vmw_private *dev_priv,
1682d5bde956630b86462ee22055f5816a04290aed57Thomas Hellstrom				  struct vmw_sw_context *sw_context,
1683d5bde956630b86462ee22055f5816a04290aed57Thomas Hellstrom				  SVGA3dCmdHeader *header)
1684d5bde956630b86462ee22055f5816a04290aed57Thomas Hellstrom{
1685d5bde956630b86462ee22055f5816a04290aed57Thomas Hellstrom	struct vmw_shader_destroy_cmd {
1686d5bde956630b86462ee22055f5816a04290aed57Thomas Hellstrom		SVGA3dCmdHeader header;
1687d5bde956630b86462ee22055f5816a04290aed57Thomas Hellstrom		SVGA3dCmdDestroyShader body;
1688d5bde956630b86462ee22055f5816a04290aed57Thomas Hellstrom	} *cmd;
1689d5bde956630b86462ee22055f5816a04290aed57Thomas Hellstrom	int ret;
169018e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom	struct vmw_resource_val_node *val;
1691d5bde956630b86462ee22055f5816a04290aed57Thomas Hellstrom
1692d5bde956630b86462ee22055f5816a04290aed57Thomas Hellstrom	cmd = container_of(header, struct vmw_shader_destroy_cmd,
1693d5bde956630b86462ee22055f5816a04290aed57Thomas Hellstrom			   header);
1694d5bde956630b86462ee22055f5816a04290aed57Thomas Hellstrom
1695d5bde956630b86462ee22055f5816a04290aed57Thomas Hellstrom	ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_context,
1696d5bde956630b86462ee22055f5816a04290aed57Thomas Hellstrom				user_context_converter, &cmd->body.cid,
169718e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom				&val);
1698d5bde956630b86462ee22055f5816a04290aed57Thomas Hellstrom	if (unlikely(ret != 0))
1699d5bde956630b86462ee22055f5816a04290aed57Thomas Hellstrom		return ret;
1700d5bde956630b86462ee22055f5816a04290aed57Thomas Hellstrom
1701d5bde956630b86462ee22055f5816a04290aed57Thomas Hellstrom	if (unlikely(!dev_priv->has_mob))
1702d5bde956630b86462ee22055f5816a04290aed57Thomas Hellstrom		return 0;
1703d5bde956630b86462ee22055f5816a04290aed57Thomas Hellstrom
170418e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom	ret = vmw_compat_shader_remove(vmw_context_res_man(val->res),
1705d5bde956630b86462ee22055f5816a04290aed57Thomas Hellstrom				       cmd->body.shid,
1706d5bde956630b86462ee22055f5816a04290aed57Thomas Hellstrom				       cmd->body.type,
170718e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom				       &sw_context->staged_cmd_res);
1708d5bde956630b86462ee22055f5816a04290aed57Thomas Hellstrom	if (unlikely(ret != 0))
1709d5bde956630b86462ee22055f5816a04290aed57Thomas Hellstrom		return ret;
1710d5bde956630b86462ee22055f5816a04290aed57Thomas Hellstrom
1711d5bde956630b86462ee22055f5816a04290aed57Thomas Hellstrom	return vmw_resource_relocation_add(&sw_context->res_relocations,
1712d5bde956630b86462ee22055f5816a04290aed57Thomas Hellstrom					   NULL, &cmd->header.id -
1713d5bde956630b86462ee22055f5816a04290aed57Thomas Hellstrom					   sw_context->buf_start);
1714d5bde956630b86462ee22055f5816a04290aed57Thomas Hellstrom
1715d5bde956630b86462ee22055f5816a04290aed57Thomas Hellstrom	return 0;
1716d5bde956630b86462ee22055f5816a04290aed57Thomas Hellstrom}
1717d5bde956630b86462ee22055f5816a04290aed57Thomas Hellstrom
1718a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom/**
1719c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * vmw_cmd_set_shader - Validate an SVGA_3D_CMD_SET_SHADER
1720c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * command
1721c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom *
1722c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * @dev_priv: Pointer to a device private struct.
1723c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * @sw_context: The software context being used for this batch.
1724c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * @header: Pointer to the command header in the command stream.
1725c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom */
1726c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstromstatic int vmw_cmd_set_shader(struct vmw_private *dev_priv,
1727c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom			      struct vmw_sw_context *sw_context,
1728c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom			      SVGA3dCmdHeader *header)
1729c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom{
1730c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	struct vmw_set_shader_cmd {
1731c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom		SVGA3dCmdHeader header;
1732c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom		SVGA3dCmdSetShader body;
1733c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	} *cmd;
173418e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom	struct vmw_resource_val_node *ctx_node, *res_node = NULL;
173518e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom	struct vmw_ctx_bindinfo bi;
173618e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom	struct vmw_resource *res = NULL;
1737c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	int ret;
1738c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom
1739c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	cmd = container_of(header, struct vmw_set_shader_cmd,
1740c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom			   header);
1741c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom
1742b5c3b1a6bfaf71895d656162f29e979c5c904888Thomas Hellstrom	ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_context,
1743b5c3b1a6bfaf71895d656162f29e979c5c904888Thomas Hellstrom				user_context_converter, &cmd->body.cid,
1744b5c3b1a6bfaf71895d656162f29e979c5c904888Thomas Hellstrom				&ctx_node);
1745c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	if (unlikely(ret != 0))
1746c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom		return ret;
1747c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom
174818e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom	if (!dev_priv->has_mob)
174918e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom		return 0;
175018e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom
175118e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom	if (cmd->body.shid != SVGA3D_INVALID_ID) {
175218e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom		res = vmw_compat_shader_lookup
175318e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom			(vmw_context_res_man(ctx_node->res),
175418e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom			 cmd->body.shid,
175518e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom			 cmd->body.type);
175618e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom
175718e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom		if (!IS_ERR(res)) {
175818e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom			ret = vmw_cmd_res_reloc_add(dev_priv, sw_context,
175918e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom						    vmw_res_shader,
176018e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom						    &cmd->body.shid, res,
176118e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom						    &res_node);
176218e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom			vmw_resource_unreference(&res);
176318e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom			if (unlikely(ret != 0))
176418e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom				return ret;
176518e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom		}
176618e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom	}
176718e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom
176818e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom	if (!res_node) {
176918e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom		ret = vmw_cmd_res_check(dev_priv, sw_context,
177018e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom					vmw_res_shader,
177118e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom					user_shader_converter,
177218e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom					&cmd->body.shid, &res_node);
1773b5c3b1a6bfaf71895d656162f29e979c5c904888Thomas Hellstrom		if (unlikely(ret != 0))
1774b5c3b1a6bfaf71895d656162f29e979c5c904888Thomas Hellstrom			return ret;
1775b5c3b1a6bfaf71895d656162f29e979c5c904888Thomas Hellstrom	}
1776c74c162fd99fbe204fe67acd5ba40589c236df6cThomas Hellstrom
177718e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom	bi.ctx = ctx_node->res;
177818e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom	bi.res = res_node ? res_node->res : NULL;
177918e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom	bi.bt = vmw_ctx_binding_shader;
178018e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom	bi.i1.shader_type = cmd->body.type;
178118e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom	return vmw_context_binding_add(ctx_node->staged_bindings, &bi);
1782c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom}
1783c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom
1784c74c162fd99fbe204fe67acd5ba40589c236df6cThomas Hellstrom/**
17850ccbbae43c2dfe45ded1d7ed59b8fc7ac8214fb0Thomas Hellstrom * vmw_cmd_set_shader_const - Validate an SVGA_3D_CMD_SET_SHADER_CONST
17860ccbbae43c2dfe45ded1d7ed59b8fc7ac8214fb0Thomas Hellstrom * command
17870ccbbae43c2dfe45ded1d7ed59b8fc7ac8214fb0Thomas Hellstrom *
17880ccbbae43c2dfe45ded1d7ed59b8fc7ac8214fb0Thomas Hellstrom * @dev_priv: Pointer to a device private struct.
17890ccbbae43c2dfe45ded1d7ed59b8fc7ac8214fb0Thomas Hellstrom * @sw_context: The software context being used for this batch.
17900ccbbae43c2dfe45ded1d7ed59b8fc7ac8214fb0Thomas Hellstrom * @header: Pointer to the command header in the command stream.
17910ccbbae43c2dfe45ded1d7ed59b8fc7ac8214fb0Thomas Hellstrom */
17920ccbbae43c2dfe45ded1d7ed59b8fc7ac8214fb0Thomas Hellstromstatic int vmw_cmd_set_shader_const(struct vmw_private *dev_priv,
17930ccbbae43c2dfe45ded1d7ed59b8fc7ac8214fb0Thomas Hellstrom				    struct vmw_sw_context *sw_context,
17940ccbbae43c2dfe45ded1d7ed59b8fc7ac8214fb0Thomas Hellstrom				    SVGA3dCmdHeader *header)
17950ccbbae43c2dfe45ded1d7ed59b8fc7ac8214fb0Thomas Hellstrom{
17960ccbbae43c2dfe45ded1d7ed59b8fc7ac8214fb0Thomas Hellstrom	struct vmw_set_shader_const_cmd {
17970ccbbae43c2dfe45ded1d7ed59b8fc7ac8214fb0Thomas Hellstrom		SVGA3dCmdHeader header;
17980ccbbae43c2dfe45ded1d7ed59b8fc7ac8214fb0Thomas Hellstrom		SVGA3dCmdSetShaderConst body;
17990ccbbae43c2dfe45ded1d7ed59b8fc7ac8214fb0Thomas Hellstrom	} *cmd;
18000ccbbae43c2dfe45ded1d7ed59b8fc7ac8214fb0Thomas Hellstrom	int ret;
18010ccbbae43c2dfe45ded1d7ed59b8fc7ac8214fb0Thomas Hellstrom
18020ccbbae43c2dfe45ded1d7ed59b8fc7ac8214fb0Thomas Hellstrom	cmd = container_of(header, struct vmw_set_shader_const_cmd,
18030ccbbae43c2dfe45ded1d7ed59b8fc7ac8214fb0Thomas Hellstrom			   header);
18040ccbbae43c2dfe45ded1d7ed59b8fc7ac8214fb0Thomas Hellstrom
18050ccbbae43c2dfe45ded1d7ed59b8fc7ac8214fb0Thomas Hellstrom	ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_context,
18060ccbbae43c2dfe45ded1d7ed59b8fc7ac8214fb0Thomas Hellstrom				user_context_converter, &cmd->body.cid,
18070ccbbae43c2dfe45ded1d7ed59b8fc7ac8214fb0Thomas Hellstrom				NULL);
18080ccbbae43c2dfe45ded1d7ed59b8fc7ac8214fb0Thomas Hellstrom	if (unlikely(ret != 0))
18090ccbbae43c2dfe45ded1d7ed59b8fc7ac8214fb0Thomas Hellstrom		return ret;
18100ccbbae43c2dfe45ded1d7ed59b8fc7ac8214fb0Thomas Hellstrom
18110ccbbae43c2dfe45ded1d7ed59b8fc7ac8214fb0Thomas Hellstrom	if (dev_priv->has_mob)
18120ccbbae43c2dfe45ded1d7ed59b8fc7ac8214fb0Thomas Hellstrom		header->id = SVGA_3D_CMD_SET_GB_SHADERCONSTS_INLINE;
18130ccbbae43c2dfe45ded1d7ed59b8fc7ac8214fb0Thomas Hellstrom
18140ccbbae43c2dfe45ded1d7ed59b8fc7ac8214fb0Thomas Hellstrom	return 0;
18150ccbbae43c2dfe45ded1d7ed59b8fc7ac8214fb0Thomas Hellstrom}
18160ccbbae43c2dfe45ded1d7ed59b8fc7ac8214fb0Thomas Hellstrom
18170ccbbae43c2dfe45ded1d7ed59b8fc7ac8214fb0Thomas Hellstrom/**
1818c74c162fd99fbe204fe67acd5ba40589c236df6cThomas Hellstrom * vmw_cmd_bind_gb_shader - Validate an SVGA_3D_CMD_BIND_GB_SHADER
1819c74c162fd99fbe204fe67acd5ba40589c236df6cThomas Hellstrom * command
1820c74c162fd99fbe204fe67acd5ba40589c236df6cThomas Hellstrom *
1821c74c162fd99fbe204fe67acd5ba40589c236df6cThomas Hellstrom * @dev_priv: Pointer to a device private struct.
1822c74c162fd99fbe204fe67acd5ba40589c236df6cThomas Hellstrom * @sw_context: The software context being used for this batch.
1823c74c162fd99fbe204fe67acd5ba40589c236df6cThomas Hellstrom * @header: Pointer to the command header in the command stream.
1824c74c162fd99fbe204fe67acd5ba40589c236df6cThomas Hellstrom */
1825c74c162fd99fbe204fe67acd5ba40589c236df6cThomas Hellstromstatic int vmw_cmd_bind_gb_shader(struct vmw_private *dev_priv,
1826c74c162fd99fbe204fe67acd5ba40589c236df6cThomas Hellstrom				  struct vmw_sw_context *sw_context,
1827c74c162fd99fbe204fe67acd5ba40589c236df6cThomas Hellstrom				  SVGA3dCmdHeader *header)
1828c74c162fd99fbe204fe67acd5ba40589c236df6cThomas Hellstrom{
1829c74c162fd99fbe204fe67acd5ba40589c236df6cThomas Hellstrom	struct vmw_bind_gb_shader_cmd {
1830c74c162fd99fbe204fe67acd5ba40589c236df6cThomas Hellstrom		SVGA3dCmdHeader header;
1831c74c162fd99fbe204fe67acd5ba40589c236df6cThomas Hellstrom		SVGA3dCmdBindGBShader body;
1832c74c162fd99fbe204fe67acd5ba40589c236df6cThomas Hellstrom	} *cmd;
1833c74c162fd99fbe204fe67acd5ba40589c236df6cThomas Hellstrom
1834c74c162fd99fbe204fe67acd5ba40589c236df6cThomas Hellstrom	cmd = container_of(header, struct vmw_bind_gb_shader_cmd,
1835c74c162fd99fbe204fe67acd5ba40589c236df6cThomas Hellstrom			   header);
1836c74c162fd99fbe204fe67acd5ba40589c236df6cThomas Hellstrom
1837c74c162fd99fbe204fe67acd5ba40589c236df6cThomas Hellstrom	return vmw_cmd_switch_backup(dev_priv, sw_context, vmw_res_shader,
1838c74c162fd99fbe204fe67acd5ba40589c236df6cThomas Hellstrom				     user_shader_converter,
1839c74c162fd99fbe204fe67acd5ba40589c236df6cThomas Hellstrom				     &cmd->body.shid, &cmd->body.mobid,
1840c74c162fd99fbe204fe67acd5ba40589c236df6cThomas Hellstrom				     cmd->body.offsetInBytes);
1841c74c162fd99fbe204fe67acd5ba40589c236df6cThomas Hellstrom}
1842c74c162fd99fbe204fe67acd5ba40589c236df6cThomas Hellstrom
18434084fb89e6b463686219a2369d1d35e6b78f785dJakob Bornecrantzstatic int vmw_cmd_check_not_3d(struct vmw_private *dev_priv,
18444084fb89e6b463686219a2369d1d35e6b78f785dJakob Bornecrantz				struct vmw_sw_context *sw_context,
18454084fb89e6b463686219a2369d1d35e6b78f785dJakob Bornecrantz				void *buf, uint32_t *size)
18464084fb89e6b463686219a2369d1d35e6b78f785dJakob Bornecrantz{
18474084fb89e6b463686219a2369d1d35e6b78f785dJakob Bornecrantz	uint32_t size_remaining = *size;
18484084fb89e6b463686219a2369d1d35e6b78f785dJakob Bornecrantz	uint32_t cmd_id;
18494084fb89e6b463686219a2369d1d35e6b78f785dJakob Bornecrantz
18504084fb89e6b463686219a2369d1d35e6b78f785dJakob Bornecrantz	cmd_id = le32_to_cpu(((uint32_t *)buf)[0]);
18514084fb89e6b463686219a2369d1d35e6b78f785dJakob Bornecrantz	switch (cmd_id) {
18524084fb89e6b463686219a2369d1d35e6b78f785dJakob Bornecrantz	case SVGA_CMD_UPDATE:
18534084fb89e6b463686219a2369d1d35e6b78f785dJakob Bornecrantz		*size = sizeof(uint32_t) + sizeof(SVGAFifoCmdUpdate);
18544084fb89e6b463686219a2369d1d35e6b78f785dJakob Bornecrantz		break;
18554084fb89e6b463686219a2369d1d35e6b78f785dJakob Bornecrantz	case SVGA_CMD_DEFINE_GMRFB:
18564084fb89e6b463686219a2369d1d35e6b78f785dJakob Bornecrantz		*size = sizeof(uint32_t) + sizeof(SVGAFifoCmdDefineGMRFB);
18574084fb89e6b463686219a2369d1d35e6b78f785dJakob Bornecrantz		break;
18584084fb89e6b463686219a2369d1d35e6b78f785dJakob Bornecrantz	case SVGA_CMD_BLIT_GMRFB_TO_SCREEN:
18594084fb89e6b463686219a2369d1d35e6b78f785dJakob Bornecrantz		*size = sizeof(uint32_t) + sizeof(SVGAFifoCmdBlitGMRFBToScreen);
18604084fb89e6b463686219a2369d1d35e6b78f785dJakob Bornecrantz		break;
18614084fb89e6b463686219a2369d1d35e6b78f785dJakob Bornecrantz	case SVGA_CMD_BLIT_SCREEN_TO_GMRFB:
18624084fb89e6b463686219a2369d1d35e6b78f785dJakob Bornecrantz		*size = sizeof(uint32_t) + sizeof(SVGAFifoCmdBlitGMRFBToScreen);
18634084fb89e6b463686219a2369d1d35e6b78f785dJakob Bornecrantz		break;
18644084fb89e6b463686219a2369d1d35e6b78f785dJakob Bornecrantz	default:
18654084fb89e6b463686219a2369d1d35e6b78f785dJakob Bornecrantz		DRM_ERROR("Unsupported SVGA command: %u.\n", cmd_id);
18664084fb89e6b463686219a2369d1d35e6b78f785dJakob Bornecrantz		return -EINVAL;
18674084fb89e6b463686219a2369d1d35e6b78f785dJakob Bornecrantz	}
18684084fb89e6b463686219a2369d1d35e6b78f785dJakob Bornecrantz
18694084fb89e6b463686219a2369d1d35e6b78f785dJakob Bornecrantz	if (*size > size_remaining) {
18704084fb89e6b463686219a2369d1d35e6b78f785dJakob Bornecrantz		DRM_ERROR("Invalid SVGA command (size mismatch):"
18714084fb89e6b463686219a2369d1d35e6b78f785dJakob Bornecrantz			  " %u.\n", cmd_id);
18724084fb89e6b463686219a2369d1d35e6b78f785dJakob Bornecrantz		return -EINVAL;
18734084fb89e6b463686219a2369d1d35e6b78f785dJakob Bornecrantz	}
18744084fb89e6b463686219a2369d1d35e6b78f785dJakob Bornecrantz
18750cff60c625131c64847debc2b4cee33ba33e8d8fJakob Bornecrantz	if (unlikely(!sw_context->kernel)) {
18764084fb89e6b463686219a2369d1d35e6b78f785dJakob Bornecrantz		DRM_ERROR("Kernel only SVGA command: %u.\n", cmd_id);
18774084fb89e6b463686219a2369d1d35e6b78f785dJakob Bornecrantz		return -EPERM;
18784084fb89e6b463686219a2369d1d35e6b78f785dJakob Bornecrantz	}
18794084fb89e6b463686219a2369d1d35e6b78f785dJakob Bornecrantz
18804084fb89e6b463686219a2369d1d35e6b78f785dJakob Bornecrantz	if (cmd_id == SVGA_CMD_DEFINE_GMRFB)
18814084fb89e6b463686219a2369d1d35e6b78f785dJakob Bornecrantz		return vmw_cmd_check_define_gmrfb(dev_priv, sw_context, buf);
18824084fb89e6b463686219a2369d1d35e6b78f785dJakob Bornecrantz
18834084fb89e6b463686219a2369d1d35e6b78f785dJakob Bornecrantz	return 0;
18844084fb89e6b463686219a2369d1d35e6b78f785dJakob Bornecrantz}
1885fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
18864fbd9d2ec2f12ffb292c1489d1402e8b956afc01Thomas Hellstromstatic const struct vmw_cmd_entry vmw_cmd_entries[SVGA_3D_CMD_MAX] = {
1887c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom	VMW_CMD_DEF(SVGA_3D_CMD_SURFACE_DEFINE, &vmw_cmd_invalid,
1888c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom		    false, false, false),
1889c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom	VMW_CMD_DEF(SVGA_3D_CMD_SURFACE_DESTROY, &vmw_cmd_invalid,
1890c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom		    false, false, false),
1891c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom	VMW_CMD_DEF(SVGA_3D_CMD_SURFACE_COPY, &vmw_cmd_surface_copy_check,
1892c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom		    true, false, false),
1893c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom	VMW_CMD_DEF(SVGA_3D_CMD_SURFACE_STRETCHBLT, &vmw_cmd_stretch_blt_check,
1894c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom		    true, false, false),
1895c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom	VMW_CMD_DEF(SVGA_3D_CMD_SURFACE_DMA, &vmw_cmd_dma,
1896c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom		    true, false, false),
1897c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom	VMW_CMD_DEF(SVGA_3D_CMD_CONTEXT_DEFINE, &vmw_cmd_invalid,
1898c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom		    false, false, false),
1899c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom	VMW_CMD_DEF(SVGA_3D_CMD_CONTEXT_DESTROY, &vmw_cmd_invalid,
1900c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom		    false, false, false),
1901c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom	VMW_CMD_DEF(SVGA_3D_CMD_SETTRANSFORM, &vmw_cmd_cid_check,
1902c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom		    true, false, false),
1903c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom	VMW_CMD_DEF(SVGA_3D_CMD_SETZRANGE, &vmw_cmd_cid_check,
1904c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom		    true, false, false),
1905c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom	VMW_CMD_DEF(SVGA_3D_CMD_SETRENDERSTATE, &vmw_cmd_cid_check,
1906c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom		    true, false, false),
1907fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	VMW_CMD_DEF(SVGA_3D_CMD_SETRENDERTARGET,
1908c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom		    &vmw_cmd_set_render_target_check, true, false, false),
1909c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom	VMW_CMD_DEF(SVGA_3D_CMD_SETTEXTURESTATE, &vmw_cmd_tex_state,
1910c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom		    true, false, false),
1911c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom	VMW_CMD_DEF(SVGA_3D_CMD_SETMATERIAL, &vmw_cmd_cid_check,
1912c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom		    true, false, false),
1913c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom	VMW_CMD_DEF(SVGA_3D_CMD_SETLIGHTDATA, &vmw_cmd_cid_check,
1914c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom		    true, false, false),
1915c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom	VMW_CMD_DEF(SVGA_3D_CMD_SETLIGHTENABLED, &vmw_cmd_cid_check,
1916c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom		    true, false, false),
1917c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom	VMW_CMD_DEF(SVGA_3D_CMD_SETVIEWPORT, &vmw_cmd_cid_check,
1918c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom		    true, false, false),
1919c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom	VMW_CMD_DEF(SVGA_3D_CMD_SETCLIPPLANE, &vmw_cmd_cid_check,
1920c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom		    true, false, false),
1921c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom	VMW_CMD_DEF(SVGA_3D_CMD_CLEAR, &vmw_cmd_cid_check,
1922c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom		    true, false, false),
1923c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom	VMW_CMD_DEF(SVGA_3D_CMD_PRESENT, &vmw_cmd_present_check,
1924c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom		    false, false, false),
1925d5bde956630b86462ee22055f5816a04290aed57Thomas Hellstrom	VMW_CMD_DEF(SVGA_3D_CMD_SHADER_DEFINE, &vmw_cmd_shader_define,
1926d5bde956630b86462ee22055f5816a04290aed57Thomas Hellstrom		    true, false, false),
1927d5bde956630b86462ee22055f5816a04290aed57Thomas Hellstrom	VMW_CMD_DEF(SVGA_3D_CMD_SHADER_DESTROY, &vmw_cmd_shader_destroy,
1928d5bde956630b86462ee22055f5816a04290aed57Thomas Hellstrom		    true, false, false),
1929c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom	VMW_CMD_DEF(SVGA_3D_CMD_SET_SHADER, &vmw_cmd_set_shader,
1930c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom		    true, false, false),
19310ccbbae43c2dfe45ded1d7ed59b8fc7ac8214fb0Thomas Hellstrom	VMW_CMD_DEF(SVGA_3D_CMD_SET_SHADER_CONST, &vmw_cmd_set_shader_const,
19320ccbbae43c2dfe45ded1d7ed59b8fc7ac8214fb0Thomas Hellstrom		    true, false, false),
1933c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom	VMW_CMD_DEF(SVGA_3D_CMD_DRAW_PRIMITIVES, &vmw_cmd_draw,
1934c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom		    true, false, false),
1935c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom	VMW_CMD_DEF(SVGA_3D_CMD_SETSCISSORRECT, &vmw_cmd_cid_check,
1936c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom		    true, false, false),
1937c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom	VMW_CMD_DEF(SVGA_3D_CMD_BEGIN_QUERY, &vmw_cmd_begin_query,
1938c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom		    true, false, false),
1939c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom	VMW_CMD_DEF(SVGA_3D_CMD_END_QUERY, &vmw_cmd_end_query,
1940c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom		    true, false, false),
1941c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom	VMW_CMD_DEF(SVGA_3D_CMD_WAIT_FOR_QUERY, &vmw_cmd_wait_query,
1942c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom		    true, false, false),
1943c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom	VMW_CMD_DEF(SVGA_3D_CMD_PRESENT_READBACK, &vmw_cmd_ok,
1944c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom		    true, false, false),
1945fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	VMW_CMD_DEF(SVGA_3D_CMD_BLIT_SURFACE_TO_SCREEN,
1946c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom		    &vmw_cmd_blt_surf_screen_check, false, false, false),
1947c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom	VMW_CMD_DEF(SVGA_3D_CMD_SURFACE_DEFINE_V2, &vmw_cmd_invalid,
1948c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom		    false, false, false),
1949c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom	VMW_CMD_DEF(SVGA_3D_CMD_GENERATE_MIPMAPS, &vmw_cmd_invalid,
1950c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom		    false, false, false),
1951c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom	VMW_CMD_DEF(SVGA_3D_CMD_ACTIVATE_SURFACE, &vmw_cmd_invalid,
1952c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom		    false, false, false),
1953c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom	VMW_CMD_DEF(SVGA_3D_CMD_DEACTIVATE_SURFACE, &vmw_cmd_invalid,
1954c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom		    false, false, false),
1955c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom	VMW_CMD_DEF(SVGA_3D_CMD_SCREEN_DMA, &vmw_cmd_invalid,
1956c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom		    false, false, false),
1957c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom	VMW_CMD_DEF(SVGA_3D_CMD_SET_UNITY_SURFACE_COOKIE, &vmw_cmd_invalid,
1958c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom		    false, false, false),
1959c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom	VMW_CMD_DEF(SVGA_3D_CMD_OPEN_CONTEXT_SURFACE, &vmw_cmd_invalid,
1960c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom		    false, false, false),
1961c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom	VMW_CMD_DEF(SVGA_3D_CMD_LOGICOPS_BITBLT, &vmw_cmd_invalid,
1962c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom		    false, false, false),
1963c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom	VMW_CMD_DEF(SVGA_3D_CMD_LOGICOPS_TRANSBLT, &vmw_cmd_invalid,
1964c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom		    false, false, false),
1965c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom	VMW_CMD_DEF(SVGA_3D_CMD_LOGICOPS_STRETCHBLT, &vmw_cmd_invalid,
1966c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom		    false, false, false),
1967c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom	VMW_CMD_DEF(SVGA_3D_CMD_LOGICOPS_COLORFILL, &vmw_cmd_invalid,
1968c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom		    false, false, false),
1969c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom	VMW_CMD_DEF(SVGA_3D_CMD_LOGICOPS_ALPHABLEND, &vmw_cmd_invalid,
1970c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom		    false, false, false),
1971c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom	VMW_CMD_DEF(SVGA_3D_CMD_LOGICOPS_CLEARTYPEBLEND, &vmw_cmd_invalid,
1972c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom		    false, false, false),
1973c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom	VMW_CMD_DEF(SVGA_3D_CMD_SET_OTABLE_BASE, &vmw_cmd_invalid,
1974c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom		    false, false, true),
1975c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom	VMW_CMD_DEF(SVGA_3D_CMD_READBACK_OTABLE, &vmw_cmd_invalid,
1976c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom		    false, false, true),
1977c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom	VMW_CMD_DEF(SVGA_3D_CMD_DEFINE_GB_MOB, &vmw_cmd_invalid,
1978c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom		    false, false, true),
1979c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom	VMW_CMD_DEF(SVGA_3D_CMD_DESTROY_GB_MOB, &vmw_cmd_invalid,
1980c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom		    false, false, true),
1981c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom	VMW_CMD_DEF(SVGA_3D_CMD_REDEFINE_GB_MOB, &vmw_cmd_invalid,
1982c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom		    false, false, true),
1983c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom	VMW_CMD_DEF(SVGA_3D_CMD_UPDATE_GB_MOB_MAPPING, &vmw_cmd_invalid,
1984c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom		    false, false, true),
1985c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom	VMW_CMD_DEF(SVGA_3D_CMD_DEFINE_GB_SURFACE, &vmw_cmd_invalid,
1986c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom		    false, false, true),
1987c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom	VMW_CMD_DEF(SVGA_3D_CMD_DESTROY_GB_SURFACE, &vmw_cmd_invalid,
1988c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom		    false, false, true),
1989c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom	VMW_CMD_DEF(SVGA_3D_CMD_BIND_GB_SURFACE, &vmw_cmd_bind_gb_surface,
1990c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom		    true, false, true),
1991c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom	VMW_CMD_DEF(SVGA_3D_CMD_COND_BIND_GB_SURFACE, &vmw_cmd_invalid,
1992c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom		    false, false, true),
1993c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom	VMW_CMD_DEF(SVGA_3D_CMD_UPDATE_GB_IMAGE, &vmw_cmd_update_gb_image,
1994c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom		    true, false, true),
1995a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom	VMW_CMD_DEF(SVGA_3D_CMD_UPDATE_GB_SURFACE,
1996c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom		    &vmw_cmd_update_gb_surface, true, false, true),
1997a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom	VMW_CMD_DEF(SVGA_3D_CMD_READBACK_GB_IMAGE,
1998c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom		    &vmw_cmd_readback_gb_image, true, false, true),
1999a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom	VMW_CMD_DEF(SVGA_3D_CMD_READBACK_GB_SURFACE,
2000c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom		    &vmw_cmd_readback_gb_surface, true, false, true),
2001a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom	VMW_CMD_DEF(SVGA_3D_CMD_INVALIDATE_GB_IMAGE,
2002c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom		    &vmw_cmd_invalidate_gb_image, true, false, true),
2003a97e21923b421993258e8487f2a5700c1ba3897fThomas Hellstrom	VMW_CMD_DEF(SVGA_3D_CMD_INVALIDATE_GB_SURFACE,
2004c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom		    &vmw_cmd_invalidate_gb_surface, true, false, true),
2005c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom	VMW_CMD_DEF(SVGA_3D_CMD_DEFINE_GB_CONTEXT, &vmw_cmd_invalid,
2006c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom		    false, false, true),
2007c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom	VMW_CMD_DEF(SVGA_3D_CMD_DESTROY_GB_CONTEXT, &vmw_cmd_invalid,
2008c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom		    false, false, true),
2009c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom	VMW_CMD_DEF(SVGA_3D_CMD_BIND_GB_CONTEXT, &vmw_cmd_invalid,
2010c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom		    false, false, true),
2011c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom	VMW_CMD_DEF(SVGA_3D_CMD_READBACK_GB_CONTEXT, &vmw_cmd_invalid,
2012c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom		    false, false, true),
2013c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom	VMW_CMD_DEF(SVGA_3D_CMD_INVALIDATE_GB_CONTEXT, &vmw_cmd_invalid,
2014c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom		    false, false, true),
2015c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom	VMW_CMD_DEF(SVGA_3D_CMD_DEFINE_GB_SHADER, &vmw_cmd_invalid,
2016c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom		    false, false, true),
2017c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom	VMW_CMD_DEF(SVGA_3D_CMD_BIND_GB_SHADER, &vmw_cmd_bind_gb_shader,
2018c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom		    true, false, true),
2019c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom	VMW_CMD_DEF(SVGA_3D_CMD_DESTROY_GB_SHADER, &vmw_cmd_invalid,
2020c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom		    false, false, true),
2021f2a0dcb1aa23eea8f186b4773a653e61d509b17aThomas Hellstrom	VMW_CMD_DEF(SVGA_3D_CMD_SET_OTABLE_BASE64, &vmw_cmd_invalid,
20228ba07315d3ffcb7dfbb5143a3be03fe4af079969Thomas Hellstrom		    false, false, false),
2023c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom	VMW_CMD_DEF(SVGA_3D_CMD_BEGIN_GB_QUERY, &vmw_cmd_begin_gb_query,
2024c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom		    true, false, true),
2025c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom	VMW_CMD_DEF(SVGA_3D_CMD_END_GB_QUERY, &vmw_cmd_end_gb_query,
2026c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom		    true, false, true),
2027c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom	VMW_CMD_DEF(SVGA_3D_CMD_WAIT_FOR_GB_QUERY, &vmw_cmd_wait_gb_query,
2028c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom		    true, false, true),
2029c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom	VMW_CMD_DEF(SVGA_3D_CMD_NOP, &vmw_cmd_ok,
2030c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom		    true, false, true),
2031c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom	VMW_CMD_DEF(SVGA_3D_CMD_ENABLE_GART, &vmw_cmd_invalid,
2032c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom		    false, false, true),
2033c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom	VMW_CMD_DEF(SVGA_3D_CMD_DISABLE_GART, &vmw_cmd_invalid,
2034c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom		    false, false, true),
2035c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom	VMW_CMD_DEF(SVGA_3D_CMD_MAP_MOB_INTO_GART, &vmw_cmd_invalid,
2036c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom		    false, false, true),
2037c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom	VMW_CMD_DEF(SVGA_3D_CMD_UNMAP_GART_RANGE, &vmw_cmd_invalid,
2038c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom		    false, false, true),
2039c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom	VMW_CMD_DEF(SVGA_3D_CMD_DEFINE_GB_SCREENTARGET, &vmw_cmd_invalid,
2040c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom		    false, false, true),
2041c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom	VMW_CMD_DEF(SVGA_3D_CMD_DESTROY_GB_SCREENTARGET, &vmw_cmd_invalid,
2042c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom		    false, false, true),
2043c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom	VMW_CMD_DEF(SVGA_3D_CMD_BIND_GB_SCREENTARGET, &vmw_cmd_invalid,
2044c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom		    false, false, true),
2045c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom	VMW_CMD_DEF(SVGA_3D_CMD_UPDATE_GB_SCREENTARGET, &vmw_cmd_invalid,
2046c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom		    false, false, true),
2047c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom	VMW_CMD_DEF(SVGA_3D_CMD_READBACK_GB_IMAGE_PARTIAL, &vmw_cmd_invalid,
2048c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom		    false, false, true),
2049c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom	VMW_CMD_DEF(SVGA_3D_CMD_INVALIDATE_GB_IMAGE_PARTIAL, &vmw_cmd_invalid,
2050c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom		    false, false, true),
2051c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom	VMW_CMD_DEF(SVGA_3D_CMD_SET_GB_SHADERCONSTS_INLINE, &vmw_cmd_cid_check,
2052c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom		    true, false, true)
2053fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz};
2054fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
2055fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzstatic int vmw_cmd_check(struct vmw_private *dev_priv,
2056fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz			 struct vmw_sw_context *sw_context,
2057fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz			 void *buf, uint32_t *size)
2058fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{
2059fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	uint32_t cmd_id;
20607a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom	uint32_t size_remaining = *size;
2061fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	SVGA3dCmdHeader *header = (SVGA3dCmdHeader *) buf;
2062fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	int ret;
2063c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom	const struct vmw_cmd_entry *entry;
2064c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom	bool gb = dev_priv->capabilities & SVGA_CAP_GBOBJECTS;
2065fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
20664084fb89e6b463686219a2369d1d35e6b78f785dJakob Bornecrantz	cmd_id = le32_to_cpu(((uint32_t *)buf)[0]);
20674084fb89e6b463686219a2369d1d35e6b78f785dJakob Bornecrantz	/* Handle any none 3D commands */
20684084fb89e6b463686219a2369d1d35e6b78f785dJakob Bornecrantz	if (unlikely(cmd_id < SVGA_CMD_MAX))
20694084fb89e6b463686219a2369d1d35e6b78f785dJakob Bornecrantz		return vmw_cmd_check_not_3d(dev_priv, sw_context, buf, size);
20704084fb89e6b463686219a2369d1d35e6b78f785dJakob Bornecrantz
2071fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
2072fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	cmd_id = le32_to_cpu(header->id);
2073fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	*size = le32_to_cpu(header->size) + sizeof(SVGA3dCmdHeader);
2074fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
2075fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	cmd_id -= SVGA_3D_CMD_BASE;
20767a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom	if (unlikely(*size > size_remaining))
2077c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom		goto out_invalid;
20787a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom
2079fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	if (unlikely(cmd_id >= SVGA_3D_CMD_MAX - SVGA_3D_CMD_BASE))
2080c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom		goto out_invalid;
2081c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom
2082c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom	entry = &vmw_cmd_entries[cmd_id];
208336e952c1ed8ca44bca245c465c8293e175dd9222Thomas Hellstrom	if (unlikely(!entry->func))
208436e952c1ed8ca44bca245c465c8293e175dd9222Thomas Hellstrom		goto out_invalid;
208536e952c1ed8ca44bca245c465c8293e175dd9222Thomas Hellstrom
2086c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom	if (unlikely(!entry->user_allow && !sw_context->kernel))
2087c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom		goto out_privileged;
2088c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom
2089c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom	if (unlikely(entry->gb_disable && gb))
2090c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom		goto out_old;
2091c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom
2092c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom	if (unlikely(entry->gb_enable && !gb))
2093c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom		goto out_new;
2094fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
2095c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom	ret = entry->func(dev_priv, sw_context, header);
2096fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	if (unlikely(ret != 0))
2097c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom		goto out_invalid;
2098fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
2099fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	return 0;
2100c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstromout_invalid:
2101c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom	DRM_ERROR("Invalid SVGA3D command: %d\n",
2102c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom		  cmd_id + SVGA_3D_CMD_BASE);
2103c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom	return -EINVAL;
2104c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstromout_privileged:
2105c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom	DRM_ERROR("Privileged SVGA3D command: %d\n",
2106c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom		  cmd_id + SVGA_3D_CMD_BASE);
2107c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom	return -EPERM;
2108c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstromout_old:
2109c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom	DRM_ERROR("Deprecated (disallowed) SVGA3D command: %d\n",
2110c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom		  cmd_id + SVGA_3D_CMD_BASE);
2111c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom	return -EINVAL;
2112c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstromout_new:
2113c373d4eac4a29b04ec036a0ead75e4a796c911c2Thomas Hellstrom	DRM_ERROR("SVGA3D command: %d not supported by virtual hardware.\n",
2114fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		  cmd_id + SVGA_3D_CMD_BASE);
2115fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	return -EINVAL;
2116fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz}
2117fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
2118fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzstatic int vmw_cmd_check_all(struct vmw_private *dev_priv,
2119fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz			     struct vmw_sw_context *sw_context,
2120922ade0d16d24be2040be7d55dbb734af779a1ddThomas Hellstrom			     void *buf,
2121be38ab6ea7b0de0542a0ff78690d63bb22f66a4dThomas Hellstrom			     uint32_t size)
2122fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{
2123fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	int32_t cur_size = size;
2124fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	int ret;
2125fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
2126c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	sw_context->buf_start = buf;
2127c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom
2128fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	while (cur_size > 0) {
21297a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom		size = cur_size;
2130fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		ret = vmw_cmd_check(dev_priv, sw_context, buf, &size);
2131fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		if (unlikely(ret != 0))
2132fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz			return ret;
2133fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		buf = (void *)((unsigned long) buf + size);
2134fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		cur_size -= size;
2135fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	}
2136fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
2137fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	if (unlikely(cur_size != 0)) {
2138fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		DRM_ERROR("Command verifier out of sync.\n");
2139fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		return -EINVAL;
2140fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	}
2141fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
2142fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	return 0;
2143fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz}
2144fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
2145fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzstatic void vmw_free_relocations(struct vmw_sw_context *sw_context)
2146fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{
2147fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	sw_context->cur_reloc = 0;
2148fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz}
2149fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
2150fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzstatic void vmw_apply_relocations(struct vmw_sw_context *sw_context)
2151fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{
2152fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	uint32_t i;
2153fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	struct vmw_relocation *reloc;
2154fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	struct ttm_validate_buffer *validate;
2155fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	struct ttm_buffer_object *bo;
2156fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
2157fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	for (i = 0; i < sw_context->cur_reloc; ++i) {
2158fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		reloc = &sw_context->relocs[i];
2159c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom		validate = &sw_context->val_bufs[reloc->index].base;
2160fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		bo = validate->bo;
2161c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom		switch (bo->mem.mem_type) {
2162c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom		case TTM_PL_VRAM:
2163135cba0dc399fdd47bd3ae305c1db75fcd77243fThomas Hellstrom			reloc->location->offset += bo->offset;
2164135cba0dc399fdd47bd3ae305c1db75fcd77243fThomas Hellstrom			reloc->location->gmrId = SVGA_GMR_FRAMEBUFFER;
2165c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom			break;
2166c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom		case VMW_PL_GMR:
2167135cba0dc399fdd47bd3ae305c1db75fcd77243fThomas Hellstrom			reloc->location->gmrId = bo->mem.start;
2168c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom			break;
2169ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom		case VMW_PL_MOB:
2170ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom			*reloc->mob_loc = bo->mem.start;
2171ddcda24e3bec1d4c8bcc37e85d1b1b37bf0fecacThomas Hellstrom			break;
2172c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom		default:
2173c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom			BUG();
2174c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom		}
2175fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	}
2176fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	vmw_free_relocations(sw_context);
2177fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz}
2178fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
2179c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom/**
2180c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * vmw_resource_list_unrefererence - Free up a resource list and unreference
2181c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * all resources referenced by it.
2182c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom *
2183c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * @list: The resource list.
2184c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom */
2185c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstromstatic void vmw_resource_list_unreference(struct list_head *list)
2186c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom{
2187c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	struct vmw_resource_val_node *val, *val_next;
2188c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom
2189c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	/*
2190c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	 * Drop references to resources held during command submission.
2191c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	 */
2192c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom
2193c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	list_for_each_entry_safe(val, val_next, list, head) {
2194c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom		list_del_init(&val->head);
2195c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom		vmw_resource_unreference(&val->res);
2196b5c3b1a6bfaf71895d656162f29e979c5c904888Thomas Hellstrom		if (unlikely(val->staged_bindings))
2197b5c3b1a6bfaf71895d656162f29e979c5c904888Thomas Hellstrom			kfree(val->staged_bindings);
2198c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom		kfree(val);
2199c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	}
2200c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom}
2201c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom
2202fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzstatic void vmw_clear_validations(struct vmw_sw_context *sw_context)
2203fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{
2204c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	struct vmw_validate_buffer *entry, *next;
2205c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	struct vmw_resource_val_node *val;
2206fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
2207be38ab6ea7b0de0542a0ff78690d63bb22f66a4dThomas Hellstrom	/*
2208be38ab6ea7b0de0542a0ff78690d63bb22f66a4dThomas Hellstrom	 * Drop references to DMA buffers held during command submission.
2209be38ab6ea7b0de0542a0ff78690d63bb22f66a4dThomas Hellstrom	 */
2210fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	list_for_each_entry_safe(entry, next, &sw_context->validate_nodes,
2211c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom				 base.head) {
2212c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom		list_del(&entry->base.head);
2213c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom		ttm_bo_unref(&entry->base.bo);
2214c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom		(void) drm_ht_remove_item(&sw_context->res_ht, &entry->hash);
2215fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		sw_context->cur_val_buf--;
2216fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	}
2217fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	BUG_ON(sw_context->cur_val_buf != 0);
2218be38ab6ea7b0de0542a0ff78690d63bb22f66a4dThomas Hellstrom
2219c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	list_for_each_entry(val, &sw_context->resource_list, head)
2220c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom		(void) drm_ht_remove_item(&sw_context->res_ht, &val->hash);
2221fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz}
2222fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
2223fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzstatic int vmw_validate_single_buffer(struct vmw_private *dev_priv,
222496c5f0df22aaf1f20075bc6ad3bdd7656e49cf4dThomas Hellstrom				      struct ttm_buffer_object *bo,
222596c5f0df22aaf1f20075bc6ad3bdd7656e49cf4dThomas Hellstrom				      bool validate_as_mob)
2226fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{
2227fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	int ret;
2228fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
2229e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom
2230e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom	/*
2231e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom	 * Don't validate pinned buffers.
2232e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom	 */
2233e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom
2234e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom	if (bo == dev_priv->pinned_bo ||
2235e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom	    (bo == dev_priv->dummy_query_bo &&
2236e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom	     dev_priv->dummy_query_bo_pinned))
2237e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom		return 0;
2238e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom
223996c5f0df22aaf1f20075bc6ad3bdd7656e49cf4dThomas Hellstrom	if (validate_as_mob)
224096c5f0df22aaf1f20075bc6ad3bdd7656e49cf4dThomas Hellstrom		return ttm_bo_validate(bo, &vmw_mob_placement, true, false);
224196c5f0df22aaf1f20075bc6ad3bdd7656e49cf4dThomas Hellstrom
22428ba5152a3acd5914cade42a1c8c9dc58ad8d1a89Thomas Hellstrom	/**
2243135cba0dc399fdd47bd3ae305c1db75fcd77243fThomas Hellstrom	 * Put BO in VRAM if there is space, otherwise as a GMR.
2244135cba0dc399fdd47bd3ae305c1db75fcd77243fThomas Hellstrom	 * If there is no space in VRAM and GMR ids are all used up,
2245135cba0dc399fdd47bd3ae305c1db75fcd77243fThomas Hellstrom	 * start evicting GMRs to make room. If the DMA buffer can't be
2246135cba0dc399fdd47bd3ae305c1db75fcd77243fThomas Hellstrom	 * used as a GMR, this will return -ENOMEM.
22478ba5152a3acd5914cade42a1c8c9dc58ad8d1a89Thomas Hellstrom	 */
22488ba5152a3acd5914cade42a1c8c9dc58ad8d1a89Thomas Hellstrom
224997a875cbdf89a4638eea57c2b456c7cc4e3e8b21Maarten Lankhorst	ret = ttm_bo_validate(bo, &vmw_vram_gmr_placement, true, false);
22503d3a5b3290043618e8409f3fb68a63de6156fdd4Thomas Hellstrom	if (likely(ret == 0 || ret == -ERESTARTSYS))
2251fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		return ret;
2252fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
22538ba5152a3acd5914cade42a1c8c9dc58ad8d1a89Thomas Hellstrom	/**
22548ba5152a3acd5914cade42a1c8c9dc58ad8d1a89Thomas Hellstrom	 * If that failed, try VRAM again, this time evicting
22558ba5152a3acd5914cade42a1c8c9dc58ad8d1a89Thomas Hellstrom	 * previous contents.
22568ba5152a3acd5914cade42a1c8c9dc58ad8d1a89Thomas Hellstrom	 */
2257fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
2258135cba0dc399fdd47bd3ae305c1db75fcd77243fThomas Hellstrom	DRM_INFO("Falling through to VRAM.\n");
225997a875cbdf89a4638eea57c2b456c7cc4e3e8b21Maarten Lankhorst	ret = ttm_bo_validate(bo, &vmw_vram_placement, true, false);
2260fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	return ret;
2261fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz}
2262fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
2263fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzstatic int vmw_validate_buffers(struct vmw_private *dev_priv,
2264fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz				struct vmw_sw_context *sw_context)
2265fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{
2266c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	struct vmw_validate_buffer *entry;
2267fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	int ret;
2268fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
2269c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	list_for_each_entry(entry, &sw_context->validate_nodes, base.head) {
227096c5f0df22aaf1f20075bc6ad3bdd7656e49cf4dThomas Hellstrom		ret = vmw_validate_single_buffer(dev_priv, entry->base.bo,
227196c5f0df22aaf1f20075bc6ad3bdd7656e49cf4dThomas Hellstrom						 entry->validate_as_mob);
2272fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		if (unlikely(ret != 0))
2273fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz			return ret;
2274fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	}
2275fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	return 0;
2276fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz}
2277fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
2278be38ab6ea7b0de0542a0ff78690d63bb22f66a4dThomas Hellstromstatic int vmw_resize_cmd_bounce(struct vmw_sw_context *sw_context,
2279be38ab6ea7b0de0542a0ff78690d63bb22f66a4dThomas Hellstrom				 uint32_t size)
2280be38ab6ea7b0de0542a0ff78690d63bb22f66a4dThomas Hellstrom{
2281be38ab6ea7b0de0542a0ff78690d63bb22f66a4dThomas Hellstrom	if (likely(sw_context->cmd_bounce_size >= size))
2282be38ab6ea7b0de0542a0ff78690d63bb22f66a4dThomas Hellstrom		return 0;
2283be38ab6ea7b0de0542a0ff78690d63bb22f66a4dThomas Hellstrom
2284be38ab6ea7b0de0542a0ff78690d63bb22f66a4dThomas Hellstrom	if (sw_context->cmd_bounce_size == 0)
2285be38ab6ea7b0de0542a0ff78690d63bb22f66a4dThomas Hellstrom		sw_context->cmd_bounce_size = VMWGFX_CMD_BOUNCE_INIT_SIZE;
2286be38ab6ea7b0de0542a0ff78690d63bb22f66a4dThomas Hellstrom
2287be38ab6ea7b0de0542a0ff78690d63bb22f66a4dThomas Hellstrom	while (sw_context->cmd_bounce_size < size) {
2288be38ab6ea7b0de0542a0ff78690d63bb22f66a4dThomas Hellstrom		sw_context->cmd_bounce_size =
2289be38ab6ea7b0de0542a0ff78690d63bb22f66a4dThomas Hellstrom			PAGE_ALIGN(sw_context->cmd_bounce_size +
2290be38ab6ea7b0de0542a0ff78690d63bb22f66a4dThomas Hellstrom				   (sw_context->cmd_bounce_size >> 1));
2291be38ab6ea7b0de0542a0ff78690d63bb22f66a4dThomas Hellstrom	}
2292be38ab6ea7b0de0542a0ff78690d63bb22f66a4dThomas Hellstrom
2293be38ab6ea7b0de0542a0ff78690d63bb22f66a4dThomas Hellstrom	if (sw_context->cmd_bounce != NULL)
2294be38ab6ea7b0de0542a0ff78690d63bb22f66a4dThomas Hellstrom		vfree(sw_context->cmd_bounce);
2295be38ab6ea7b0de0542a0ff78690d63bb22f66a4dThomas Hellstrom
2296be38ab6ea7b0de0542a0ff78690d63bb22f66a4dThomas Hellstrom	sw_context->cmd_bounce = vmalloc(sw_context->cmd_bounce_size);
2297be38ab6ea7b0de0542a0ff78690d63bb22f66a4dThomas Hellstrom
2298be38ab6ea7b0de0542a0ff78690d63bb22f66a4dThomas Hellstrom	if (sw_context->cmd_bounce == NULL) {
2299be38ab6ea7b0de0542a0ff78690d63bb22f66a4dThomas Hellstrom		DRM_ERROR("Failed to allocate command bounce buffer.\n");
2300be38ab6ea7b0de0542a0ff78690d63bb22f66a4dThomas Hellstrom		sw_context->cmd_bounce_size = 0;
2301be38ab6ea7b0de0542a0ff78690d63bb22f66a4dThomas Hellstrom		return -ENOMEM;
2302be38ab6ea7b0de0542a0ff78690d63bb22f66a4dThomas Hellstrom	}
2303be38ab6ea7b0de0542a0ff78690d63bb22f66a4dThomas Hellstrom
2304be38ab6ea7b0de0542a0ff78690d63bb22f66a4dThomas Hellstrom	return 0;
2305be38ab6ea7b0de0542a0ff78690d63bb22f66a4dThomas Hellstrom}
2306be38ab6ea7b0de0542a0ff78690d63bb22f66a4dThomas Hellstrom
2307ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom/**
2308ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom * vmw_execbuf_fence_commands - create and submit a command stream fence
2309ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom *
2310ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom * Creates a fence object and submits a command stream marker.
2311ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom * If this fails for some reason, We sync the fifo and return NULL.
2312ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom * It is then safe to fence buffers with a NULL pointer.
23136070e9fa6d12d465c65a172a2b1c752ebedc5937Jakob Bornecrantz *
23146070e9fa6d12d465c65a172a2b1c752ebedc5937Jakob Bornecrantz * If @p_handle is not NULL @file_priv must also not be NULL. Creates
23156070e9fa6d12d465c65a172a2b1c752ebedc5937Jakob Bornecrantz * a userspace handle if @p_handle is not NULL, otherwise not.
2316ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom */
2317ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom
2318ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstromint vmw_execbuf_fence_commands(struct drm_file *file_priv,
2319ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom			       struct vmw_private *dev_priv,
2320ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom			       struct vmw_fence_obj **p_fence,
2321ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom			       uint32_t *p_handle)
2322ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom{
2323ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom	uint32_t sequence;
2324ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom	int ret;
2325ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom	bool synced = false;
2326ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom
23276070e9fa6d12d465c65a172a2b1c752ebedc5937Jakob Bornecrantz	/* p_handle implies file_priv. */
23286070e9fa6d12d465c65a172a2b1c752ebedc5937Jakob Bornecrantz	BUG_ON(p_handle != NULL && file_priv == NULL);
2329ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom
2330ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom	ret = vmw_fifo_send_fence(dev_priv, &sequence);
2331ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom	if (unlikely(ret != 0)) {
2332ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom		DRM_ERROR("Fence submission error. Syncing.\n");
2333ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom		synced = true;
2334ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom	}
2335ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom
2336ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom	if (p_handle != NULL)
2337ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom		ret = vmw_user_fence_create(file_priv, dev_priv->fman,
2338c060a4e135fdd8a35276f2e318f1e9b3bc2450a9Maarten Lankhorst					    sequence, p_fence, p_handle);
2339ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom	else
2340c060a4e135fdd8a35276f2e318f1e9b3bc2450a9Maarten Lankhorst		ret = vmw_fence_create(dev_priv->fman, sequence, p_fence);
2341ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom
2342ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom	if (unlikely(ret != 0 && !synced)) {
2343ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom		(void) vmw_fallback_wait(dev_priv, false, false,
2344ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom					 sequence, false,
2345ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom					 VMW_FENCE_WAIT_TIMEOUT);
2346ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom		*p_fence = NULL;
2347ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom	}
2348ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom
2349ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom	return 0;
2350ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom}
2351ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom
23528bf445cee3127de3779a395d08d1ada2ad70161eThomas Hellstrom/**
23538bf445cee3127de3779a395d08d1ada2ad70161eThomas Hellstrom * vmw_execbuf_copy_fence_user - copy fence object information to
23548bf445cee3127de3779a395d08d1ada2ad70161eThomas Hellstrom * user-space.
23558bf445cee3127de3779a395d08d1ada2ad70161eThomas Hellstrom *
23568bf445cee3127de3779a395d08d1ada2ad70161eThomas Hellstrom * @dev_priv: Pointer to a vmw_private struct.
23578bf445cee3127de3779a395d08d1ada2ad70161eThomas Hellstrom * @vmw_fp: Pointer to the struct vmw_fpriv representing the calling file.
23588bf445cee3127de3779a395d08d1ada2ad70161eThomas Hellstrom * @ret: Return value from fence object creation.
23598bf445cee3127de3779a395d08d1ada2ad70161eThomas Hellstrom * @user_fence_rep: User space address of a struct drm_vmw_fence_rep to
23608bf445cee3127de3779a395d08d1ada2ad70161eThomas Hellstrom * which the information should be copied.
23618bf445cee3127de3779a395d08d1ada2ad70161eThomas Hellstrom * @fence: Pointer to the fenc object.
23628bf445cee3127de3779a395d08d1ada2ad70161eThomas Hellstrom * @fence_handle: User-space fence handle.
23638bf445cee3127de3779a395d08d1ada2ad70161eThomas Hellstrom *
23648bf445cee3127de3779a395d08d1ada2ad70161eThomas Hellstrom * This function copies fence information to user-space. If copying fails,
23658bf445cee3127de3779a395d08d1ada2ad70161eThomas Hellstrom * The user-space struct drm_vmw_fence_rep::error member is hopefully
23668bf445cee3127de3779a395d08d1ada2ad70161eThomas Hellstrom * left untouched, and if it's preloaded with an -EFAULT by user-space,
23678bf445cee3127de3779a395d08d1ada2ad70161eThomas Hellstrom * the error will hopefully be detected.
23688bf445cee3127de3779a395d08d1ada2ad70161eThomas Hellstrom * Also if copying fails, user-space will be unable to signal the fence
23698bf445cee3127de3779a395d08d1ada2ad70161eThomas Hellstrom * object so we wait for it immediately, and then unreference the
23708bf445cee3127de3779a395d08d1ada2ad70161eThomas Hellstrom * user-space reference.
23718bf445cee3127de3779a395d08d1ada2ad70161eThomas Hellstrom */
237257c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstromvoid
23738bf445cee3127de3779a395d08d1ada2ad70161eThomas Hellstromvmw_execbuf_copy_fence_user(struct vmw_private *dev_priv,
23748bf445cee3127de3779a395d08d1ada2ad70161eThomas Hellstrom			    struct vmw_fpriv *vmw_fp,
23758bf445cee3127de3779a395d08d1ada2ad70161eThomas Hellstrom			    int ret,
23768bf445cee3127de3779a395d08d1ada2ad70161eThomas Hellstrom			    struct drm_vmw_fence_rep __user *user_fence_rep,
23778bf445cee3127de3779a395d08d1ada2ad70161eThomas Hellstrom			    struct vmw_fence_obj *fence,
23788bf445cee3127de3779a395d08d1ada2ad70161eThomas Hellstrom			    uint32_t fence_handle)
23798bf445cee3127de3779a395d08d1ada2ad70161eThomas Hellstrom{
23808bf445cee3127de3779a395d08d1ada2ad70161eThomas Hellstrom	struct drm_vmw_fence_rep fence_rep;
23818bf445cee3127de3779a395d08d1ada2ad70161eThomas Hellstrom
23828bf445cee3127de3779a395d08d1ada2ad70161eThomas Hellstrom	if (user_fence_rep == NULL)
23838bf445cee3127de3779a395d08d1ada2ad70161eThomas Hellstrom		return;
23848bf445cee3127de3779a395d08d1ada2ad70161eThomas Hellstrom
238580d9b24a658c83602aea66e45e2347c5bb3cbd47Dan Carpenter	memset(&fence_rep, 0, sizeof(fence_rep));
238680d9b24a658c83602aea66e45e2347c5bb3cbd47Dan Carpenter
23878bf445cee3127de3779a395d08d1ada2ad70161eThomas Hellstrom	fence_rep.error = ret;
23888bf445cee3127de3779a395d08d1ada2ad70161eThomas Hellstrom	if (ret == 0) {
23898bf445cee3127de3779a395d08d1ada2ad70161eThomas Hellstrom		BUG_ON(fence == NULL);
23908bf445cee3127de3779a395d08d1ada2ad70161eThomas Hellstrom
23918bf445cee3127de3779a395d08d1ada2ad70161eThomas Hellstrom		fence_rep.handle = fence_handle;
23922298e804e96eb3635c39519c8287befd92460303Maarten Lankhorst		fence_rep.seqno = fence->base.seqno;
23938bf445cee3127de3779a395d08d1ada2ad70161eThomas Hellstrom		vmw_update_seqno(dev_priv, &dev_priv->fifo);
23948bf445cee3127de3779a395d08d1ada2ad70161eThomas Hellstrom		fence_rep.passed_seqno = dev_priv->last_read_seqno;
23958bf445cee3127de3779a395d08d1ada2ad70161eThomas Hellstrom	}
23968bf445cee3127de3779a395d08d1ada2ad70161eThomas Hellstrom
23978bf445cee3127de3779a395d08d1ada2ad70161eThomas Hellstrom	/*
23988bf445cee3127de3779a395d08d1ada2ad70161eThomas Hellstrom	 * copy_to_user errors will be detected by user space not
23998bf445cee3127de3779a395d08d1ada2ad70161eThomas Hellstrom	 * seeing fence_rep::error filled in. Typically
24008bf445cee3127de3779a395d08d1ada2ad70161eThomas Hellstrom	 * user-space would have pre-set that member to -EFAULT.
24018bf445cee3127de3779a395d08d1ada2ad70161eThomas Hellstrom	 */
24028bf445cee3127de3779a395d08d1ada2ad70161eThomas Hellstrom	ret = copy_to_user(user_fence_rep, &fence_rep,
24038bf445cee3127de3779a395d08d1ada2ad70161eThomas Hellstrom			   sizeof(fence_rep));
24048bf445cee3127de3779a395d08d1ada2ad70161eThomas Hellstrom
24058bf445cee3127de3779a395d08d1ada2ad70161eThomas Hellstrom	/*
24068bf445cee3127de3779a395d08d1ada2ad70161eThomas Hellstrom	 * User-space lost the fence object. We need to sync
24078bf445cee3127de3779a395d08d1ada2ad70161eThomas Hellstrom	 * and unreference the handle.
24088bf445cee3127de3779a395d08d1ada2ad70161eThomas Hellstrom	 */
24098bf445cee3127de3779a395d08d1ada2ad70161eThomas Hellstrom	if (unlikely(ret != 0) && (fence_rep.error == 0)) {
24108bf445cee3127de3779a395d08d1ada2ad70161eThomas Hellstrom		ttm_ref_object_base_unref(vmw_fp->tfile,
24118bf445cee3127de3779a395d08d1ada2ad70161eThomas Hellstrom					  fence_handle, TTM_REF_USAGE);
24128bf445cee3127de3779a395d08d1ada2ad70161eThomas Hellstrom		DRM_ERROR("Fence copy error. Syncing.\n");
2413c060a4e135fdd8a35276f2e318f1e9b3bc2450a9Maarten Lankhorst		(void) vmw_fence_obj_wait(fence, false, false,
24148bf445cee3127de3779a395d08d1ada2ad70161eThomas Hellstrom					  VMW_FENCE_WAIT_TIMEOUT);
24158bf445cee3127de3779a395d08d1ada2ad70161eThomas Hellstrom	}
24168bf445cee3127de3779a395d08d1ada2ad70161eThomas Hellstrom}
24178bf445cee3127de3779a395d08d1ada2ad70161eThomas Hellstrom
241818e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom
241918e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom
2420922ade0d16d24be2040be7d55dbb734af779a1ddThomas Hellstromint vmw_execbuf_process(struct drm_file *file_priv,
2421922ade0d16d24be2040be7d55dbb734af779a1ddThomas Hellstrom			struct vmw_private *dev_priv,
2422922ade0d16d24be2040be7d55dbb734af779a1ddThomas Hellstrom			void __user *user_commands,
2423922ade0d16d24be2040be7d55dbb734af779a1ddThomas Hellstrom			void *kernel_commands,
2424922ade0d16d24be2040be7d55dbb734af779a1ddThomas Hellstrom			uint32_t command_size,
2425922ade0d16d24be2040be7d55dbb734af779a1ddThomas Hellstrom			uint64_t throttle_us,
2426bb1bd2f43ee15386a1c3f96cbcbb9302a9994443Jakob Bornecrantz			struct drm_vmw_fence_rep __user *user_fence_rep,
2427bb1bd2f43ee15386a1c3f96cbcbb9302a9994443Jakob Bornecrantz			struct vmw_fence_obj **out_fence)
2428fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{
2429fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	struct vmw_sw_context *sw_context = &dev_priv->ctx;
2430bb1bd2f43ee15386a1c3f96cbcbb9302a9994443Jakob Bornecrantz	struct vmw_fence_obj *fence = NULL;
2431c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	struct vmw_resource *error_resource;
2432c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	struct list_head resource_list;
2433ecff665f5e3f1c6909353e00b9420e45ae23d995Maarten Lankhorst	struct ww_acquire_ctx ticket;
2434ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom	uint32_t handle;
2435922ade0d16d24be2040be7d55dbb734af779a1ddThomas Hellstrom	void *cmd;
2436922ade0d16d24be2040be7d55dbb734af779a1ddThomas Hellstrom	int ret;
2437fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
2438922ade0d16d24be2040be7d55dbb734af779a1ddThomas Hellstrom	ret = mutex_lock_interruptible(&dev_priv->cmdbuf_mutex);
2439fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	if (unlikely(ret != 0))
2440922ade0d16d24be2040be7d55dbb734af779a1ddThomas Hellstrom		return -ERESTARTSYS;
2441fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
2442922ade0d16d24be2040be7d55dbb734af779a1ddThomas Hellstrom	if (kernel_commands == NULL) {
2443922ade0d16d24be2040be7d55dbb734af779a1ddThomas Hellstrom		sw_context->kernel = false;
2444fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
2445922ade0d16d24be2040be7d55dbb734af779a1ddThomas Hellstrom		ret = vmw_resize_cmd_bounce(sw_context, command_size);
2446922ade0d16d24be2040be7d55dbb734af779a1ddThomas Hellstrom		if (unlikely(ret != 0))
2447922ade0d16d24be2040be7d55dbb734af779a1ddThomas Hellstrom			goto out_unlock;
2448fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
2449fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
2450922ade0d16d24be2040be7d55dbb734af779a1ddThomas Hellstrom		ret = copy_from_user(sw_context->cmd_bounce,
2451922ade0d16d24be2040be7d55dbb734af779a1ddThomas Hellstrom				     user_commands, command_size);
2452922ade0d16d24be2040be7d55dbb734af779a1ddThomas Hellstrom
2453922ade0d16d24be2040be7d55dbb734af779a1ddThomas Hellstrom		if (unlikely(ret != 0)) {
2454922ade0d16d24be2040be7d55dbb734af779a1ddThomas Hellstrom			ret = -EFAULT;
2455922ade0d16d24be2040be7d55dbb734af779a1ddThomas Hellstrom			DRM_ERROR("Failed copying commands.\n");
2456922ade0d16d24be2040be7d55dbb734af779a1ddThomas Hellstrom			goto out_unlock;
2457922ade0d16d24be2040be7d55dbb734af779a1ddThomas Hellstrom		}
2458922ade0d16d24be2040be7d55dbb734af779a1ddThomas Hellstrom		kernel_commands = sw_context->cmd_bounce;
2459922ade0d16d24be2040be7d55dbb734af779a1ddThomas Hellstrom	} else
2460922ade0d16d24be2040be7d55dbb734af779a1ddThomas Hellstrom		sw_context->kernel = true;
2461fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
2462d5bde956630b86462ee22055f5816a04290aed57Thomas Hellstrom	sw_context->fp = vmw_fpriv(file_priv);
2463fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	sw_context->cur_reloc = 0;
2464fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	sw_context->cur_val_buf = 0;
2465f18c8840bef4195e6f35298b7746563f10d2d502Thomas Hellstrom	INIT_LIST_HEAD(&sw_context->resource_list);
2466e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom	sw_context->cur_query_bo = dev_priv->pinned_bo;
2467c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	sw_context->last_query_ctx = NULL;
2468c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	sw_context->needs_post_query_barrier = false;
2469c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	memset(sw_context->res_cache, 0, sizeof(sw_context->res_cache));
2470fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	INIT_LIST_HEAD(&sw_context->validate_nodes);
2471c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	INIT_LIST_HEAD(&sw_context->res_relocations);
2472c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	if (!sw_context->res_ht_initialized) {
2473c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom		ret = drm_ht_create(&sw_context->res_ht, VMW_RES_HT_ORDER);
2474c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom		if (unlikely(ret != 0))
2475c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom			goto out_unlock;
2476c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom		sw_context->res_ht_initialized = true;
2477c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	}
247818e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom	INIT_LIST_HEAD(&sw_context->staged_cmd_res);
2479fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
2480c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	INIT_LIST_HEAD(&resource_list);
2481922ade0d16d24be2040be7d55dbb734af779a1ddThomas Hellstrom	ret = vmw_cmd_check_all(dev_priv, sw_context, kernel_commands,
2482922ade0d16d24be2040be7d55dbb734af779a1ddThomas Hellstrom				command_size);
2483fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	if (unlikely(ret != 0))
2484cf5e3413337309050c05e13dcebe85b7194a21e5Thomas Hellstrom		goto out_err_nores;
2485be38ab6ea7b0de0542a0ff78690d63bb22f66a4dThomas Hellstrom
2486c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	ret = vmw_resources_reserve(sw_context);
2487c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	if (unlikely(ret != 0))
2488cf5e3413337309050c05e13dcebe85b7194a21e5Thomas Hellstrom		goto out_err_nores;
2489c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom
249058b4d720c1620bbf09e42b4f218dcb2d0d8cdf3eMaarten Lankhorst	ret = ttm_eu_reserve_buffers(&ticket, &sw_context->validate_nodes, true);
2491fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	if (unlikely(ret != 0))
2492fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		goto out_err;
2493fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
2494fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	ret = vmw_validate_buffers(dev_priv, sw_context);
2495fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	if (unlikely(ret != 0))
2496fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		goto out_err;
2497fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
2498c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	ret = vmw_resources_validate(sw_context);
2499c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	if (unlikely(ret != 0))
2500c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom		goto out_err;
25011925d4565888eb313cc923372da6a08bbfb3a859Thomas Hellstrom
2502922ade0d16d24be2040be7d55dbb734af779a1ddThomas Hellstrom	if (throttle_us) {
25036bcd8d3c782b7b2c98c8f414a6bb43cf6b84e53cThomas Hellstrom		ret = vmw_wait_lag(dev_priv, &dev_priv->fifo.marker_queue,
2504922ade0d16d24be2040be7d55dbb734af779a1ddThomas Hellstrom				   throttle_us);
25051925d4565888eb313cc923372da6a08bbfb3a859Thomas Hellstrom
25061925d4565888eb313cc923372da6a08bbfb3a859Thomas Hellstrom		if (unlikely(ret != 0))
2507c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom			goto out_err;
2508be38ab6ea7b0de0542a0ff78690d63bb22f66a4dThomas Hellstrom	}
2509be38ab6ea7b0de0542a0ff78690d63bb22f66a4dThomas Hellstrom
2510173fb7d4e26705a9e8b8e9d197a18ff39bfdad0aThomas Hellstrom	ret = mutex_lock_interruptible(&dev_priv->binding_mutex);
2511173fb7d4e26705a9e8b8e9d197a18ff39bfdad0aThomas Hellstrom	if (unlikely(ret != 0)) {
2512173fb7d4e26705a9e8b8e9d197a18ff39bfdad0aThomas Hellstrom		ret = -ERESTARTSYS;
2513173fb7d4e26705a9e8b8e9d197a18ff39bfdad0aThomas Hellstrom		goto out_err;
2514173fb7d4e26705a9e8b8e9d197a18ff39bfdad0aThomas Hellstrom	}
2515173fb7d4e26705a9e8b8e9d197a18ff39bfdad0aThomas Hellstrom
251630f82d816d2dccfdc2063ac8cca994904c9b612cThomas Hellstrom	if (dev_priv->has_mob) {
251730f82d816d2dccfdc2063ac8cca994904c9b612cThomas Hellstrom		ret = vmw_rebind_contexts(sw_context);
251830f82d816d2dccfdc2063ac8cca994904c9b612cThomas Hellstrom		if (unlikely(ret != 0))
2519b2ad9881d6aeec4f3ee527c00fce34442d6d02d3Dan Carpenter			goto out_unlock_binding;
252030f82d816d2dccfdc2063ac8cca994904c9b612cThomas Hellstrom	}
252130f82d816d2dccfdc2063ac8cca994904c9b612cThomas Hellstrom
2522922ade0d16d24be2040be7d55dbb734af779a1ddThomas Hellstrom	cmd = vmw_fifo_reserve(dev_priv, command_size);
2523be38ab6ea7b0de0542a0ff78690d63bb22f66a4dThomas Hellstrom	if (unlikely(cmd == NULL)) {
2524be38ab6ea7b0de0542a0ff78690d63bb22f66a4dThomas Hellstrom		DRM_ERROR("Failed reserving fifo space for commands.\n");
2525be38ab6ea7b0de0542a0ff78690d63bb22f66a4dThomas Hellstrom		ret = -ENOMEM;
2526173fb7d4e26705a9e8b8e9d197a18ff39bfdad0aThomas Hellstrom		goto out_unlock_binding;
25271925d4565888eb313cc923372da6a08bbfb3a859Thomas Hellstrom	}
25281925d4565888eb313cc923372da6a08bbfb3a859Thomas Hellstrom
2529c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	vmw_apply_relocations(sw_context);
2530922ade0d16d24be2040be7d55dbb734af779a1ddThomas Hellstrom	memcpy(cmd, kernel_commands, command_size);
2531c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom
2532c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	vmw_resource_relocations_apply(cmd, &sw_context->res_relocations);
2533c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	vmw_resource_relocations_free(&sw_context->res_relocations);
2534c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom
2535922ade0d16d24be2040be7d55dbb734af779a1ddThomas Hellstrom	vmw_fifo_commit(dev_priv, command_size);
2536fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
2537e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom	vmw_query_bo_switch_commit(dev_priv, sw_context);
2538ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom	ret = vmw_execbuf_fence_commands(file_priv, dev_priv,
2539ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom					 &fence,
2540ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom					 (user_fence_rep) ? &handle : NULL);
2541fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	/*
2542fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	 * This error is harmless, because if fence submission fails,
2543ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom	 * vmw_fifo_send_fence will sync. The error will be propagated to
2544ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom	 * user-space in @fence_rep
2545fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	 */
2546fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
2547fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	if (ret != 0)
2548fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz		DRM_ERROR("Fence submission error. Syncing.\n");
2549fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
2550c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	vmw_resource_list_unreserve(&sw_context->resource_list, false);
2551173fb7d4e26705a9e8b8e9d197a18ff39bfdad0aThomas Hellstrom	mutex_unlock(&dev_priv->binding_mutex);
2552173fb7d4e26705a9e8b8e9d197a18ff39bfdad0aThomas Hellstrom
2553ecff665f5e3f1c6909353e00b9420e45ae23d995Maarten Lankhorst	ttm_eu_fence_buffer_objects(&ticket, &sw_context->validate_nodes,
2554ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom				    (void *) fence);
2555fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
2556c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	if (unlikely(dev_priv->pinned_bo != NULL &&
2557c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom		     !dev_priv->query_cid_valid))
2558c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom		__vmw_execbuf_release_pinned_bo(dev_priv, fence);
2559c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom
2560ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom	vmw_clear_validations(sw_context);
25618bf445cee3127de3779a395d08d1ada2ad70161eThomas Hellstrom	vmw_execbuf_copy_fence_user(dev_priv, vmw_fpriv(file_priv), ret,
25628bf445cee3127de3779a395d08d1ada2ad70161eThomas Hellstrom				    user_fence_rep, fence, handle);
2563fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
2564bb1bd2f43ee15386a1c3f96cbcbb9302a9994443Jakob Bornecrantz	/* Don't unreference when handing fence out */
2565bb1bd2f43ee15386a1c3f96cbcbb9302a9994443Jakob Bornecrantz	if (unlikely(out_fence != NULL)) {
2566bb1bd2f43ee15386a1c3f96cbcbb9302a9994443Jakob Bornecrantz		*out_fence = fence;
2567bb1bd2f43ee15386a1c3f96cbcbb9302a9994443Jakob Bornecrantz		fence = NULL;
2568bb1bd2f43ee15386a1c3f96cbcbb9302a9994443Jakob Bornecrantz	} else if (likely(fence != NULL)) {
2569ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom		vmw_fence_obj_unreference(&fence);
2570bb1bd2f43ee15386a1c3f96cbcbb9302a9994443Jakob Bornecrantz	}
2571fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz
2572c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	list_splice_init(&sw_context->resource_list, &resource_list);
257318e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom	vmw_cmdbuf_res_commit(&sw_context->staged_cmd_res);
2574922ade0d16d24be2040be7d55dbb734af779a1ddThomas Hellstrom	mutex_unlock(&dev_priv->cmdbuf_mutex);
2575c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom
2576c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	/*
2577c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	 * Unreference resources outside of the cmdbuf_mutex to
2578c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	 * avoid deadlocks in resource destruction paths.
2579c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	 */
2580c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	vmw_resource_list_unreference(&resource_list);
2581c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom
2582fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	return 0;
2583922ade0d16d24be2040be7d55dbb734af779a1ddThomas Hellstrom
2584173fb7d4e26705a9e8b8e9d197a18ff39bfdad0aThomas Hellstromout_unlock_binding:
2585173fb7d4e26705a9e8b8e9d197a18ff39bfdad0aThomas Hellstrom	mutex_unlock(&dev_priv->binding_mutex);
2586fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzout_err:
2587ecff665f5e3f1c6909353e00b9420e45ae23d995Maarten Lankhorst	ttm_eu_backoff_reservation(&ticket, &sw_context->validate_nodes);
2588cf5e3413337309050c05e13dcebe85b7194a21e5Thomas Hellstromout_err_nores:
2589c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	vmw_resource_list_unreserve(&sw_context->resource_list, true);
2590cf5e3413337309050c05e13dcebe85b7194a21e5Thomas Hellstrom	vmw_resource_relocations_free(&sw_context->res_relocations);
2591cf5e3413337309050c05e13dcebe85b7194a21e5Thomas Hellstrom	vmw_free_relocations(sw_context);
2592fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	vmw_clear_validations(sw_context);
2593c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	if (unlikely(dev_priv->pinned_bo != NULL &&
2594c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom		     !dev_priv->query_cid_valid))
2595c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom		__vmw_execbuf_release_pinned_bo(dev_priv, NULL);
2596fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzout_unlock:
2597c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	list_splice_init(&sw_context->resource_list, &resource_list);
2598c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	error_resource = sw_context->error_resource;
2599c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	sw_context->error_resource = NULL;
260018e4a4669c5023eb1157f2a3f1bf6ca2b8535572Thomas Hellstrom	vmw_cmdbuf_res_revert(&sw_context->staged_cmd_res);
2601fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	mutex_unlock(&dev_priv->cmdbuf_mutex);
2602c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom
2603c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	/*
2604c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	 * Unreference resources outside of the cmdbuf_mutex to
2605c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	 * avoid deadlocks in resource destruction paths.
2606c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	 */
2607c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	vmw_resource_list_unreference(&resource_list);
2608c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	if (unlikely(error_resource != NULL))
2609c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom		vmw_resource_unreference(&error_resource);
2610c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom
2611922ade0d16d24be2040be7d55dbb734af779a1ddThomas Hellstrom	return ret;
2612922ade0d16d24be2040be7d55dbb734af779a1ddThomas Hellstrom}
2613922ade0d16d24be2040be7d55dbb734af779a1ddThomas Hellstrom
2614e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom/**
2615e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom * vmw_execbuf_unpin_panic - Idle the fifo and unpin the query buffer.
2616e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom *
2617e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom * @dev_priv: The device private structure.
2618e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom *
2619e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom * This function is called to idle the fifo and unpin the query buffer
2620e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom * if the normal way to do this hits an error, which should typically be
2621e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom * extremely rare.
2622e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom */
2623e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstromstatic void vmw_execbuf_unpin_panic(struct vmw_private *dev_priv)
2624e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom{
2625e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom	DRM_ERROR("Can't unpin query buffer. Trying to recover.\n");
2626e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom
2627e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom	(void) vmw_fallback_wait(dev_priv, false, true, 0, false, 10*HZ);
2628e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom	vmw_bo_pin(dev_priv->pinned_bo, false);
2629e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom	vmw_bo_pin(dev_priv->dummy_query_bo, false);
2630e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom	dev_priv->dummy_query_bo_pinned = false;
2631e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom}
2632e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom
2633e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom
2634e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom/**
2635c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * __vmw_execbuf_release_pinned_bo - Flush queries and unpin the pinned
2636e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom * query bo.
2637e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom *
2638e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom * @dev_priv: The device private structure.
2639c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * @fence: If non-NULL should point to a struct vmw_fence_obj issued
2640c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * _after_ a query barrier that flushes all queries touching the current
2641c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * buffer pointed to by @dev_priv->pinned_bo
2642e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom *
2643e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom * This function should be used to unpin the pinned query bo, or
2644e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom * as a query barrier when we need to make sure that all queries have
2645e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom * finished before the next fifo command. (For example on hardware
2646e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom * context destructions where the hardware may otherwise leak unfinished
2647e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom * queries).
2648e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom *
2649e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom * This function does not return any failure codes, but make attempts
2650e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom * to do safe unpinning in case of errors.
2651e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom *
2652e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom * The function will synchronize on the previous query barrier, and will
2653e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom * thus not finish until that barrier has executed.
2654c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom *
2655c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * the @dev_priv->cmdbuf_mutex needs to be held by the current thread
2656c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * before calling this function.
2657e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom */
2658c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstromvoid __vmw_execbuf_release_pinned_bo(struct vmw_private *dev_priv,
2659c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom				     struct vmw_fence_obj *fence)
2660e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom{
2661e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom	int ret = 0;
2662e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom	struct list_head validate_list;
2663e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom	struct ttm_validate_buffer pinned_val, query_val;
2664c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	struct vmw_fence_obj *lfence = NULL;
2665ecff665f5e3f1c6909353e00b9420e45ae23d995Maarten Lankhorst	struct ww_acquire_ctx ticket;
2666e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom
2667e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom	if (dev_priv->pinned_bo == NULL)
2668e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom		goto out_unlock;
2669e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom
2670e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom	INIT_LIST_HEAD(&validate_list);
2671e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom
2672e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom	pinned_val.bo = ttm_bo_reference(dev_priv->pinned_bo);
2673ae9c0af2c0ea92e57013ab2dd7271ba7d6b2a833Christian König	pinned_val.shared = false;
2674e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom	list_add_tail(&pinned_val.head, &validate_list);
2675e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom
2676e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom	query_val.bo = ttm_bo_reference(dev_priv->dummy_query_bo);
2677ae9c0af2c0ea92e57013ab2dd7271ba7d6b2a833Christian König	query_val.shared = false;
2678e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom	list_add_tail(&query_val.head, &validate_list);
2679e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom
268058b4d720c1620bbf09e42b4f218dcb2d0d8cdf3eMaarten Lankhorst	ret = ttm_eu_reserve_buffers(&ticket, &validate_list, false);
2681e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom	if (unlikely(ret != 0)) {
2682e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom		vmw_execbuf_unpin_panic(dev_priv);
2683e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom		goto out_no_reserve;
2684e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom	}
2685e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom
2686c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	if (dev_priv->query_cid_valid) {
2687c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom		BUG_ON(fence != NULL);
2688c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom		ret = vmw_fifo_emit_dummy_query(dev_priv, dev_priv->query_cid);
2689c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom		if (unlikely(ret != 0)) {
2690c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom			vmw_execbuf_unpin_panic(dev_priv);
2691c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom			goto out_no_emit;
2692c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom		}
2693c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom		dev_priv->query_cid_valid = false;
2694e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom	}
2695e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom
2696e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom	vmw_bo_pin(dev_priv->pinned_bo, false);
2697e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom	vmw_bo_pin(dev_priv->dummy_query_bo, false);
2698e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom	dev_priv->dummy_query_bo_pinned = false;
2699e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom
2700c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	if (fence == NULL) {
2701c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom		(void) vmw_execbuf_fence_commands(NULL, dev_priv, &lfence,
2702c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom						  NULL);
2703c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom		fence = lfence;
2704c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	}
2705ecff665f5e3f1c6909353e00b9420e45ae23d995Maarten Lankhorst	ttm_eu_fence_buffer_objects(&ticket, &validate_list, (void *) fence);
2706c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	if (lfence != NULL)
2707c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom		vmw_fence_obj_unreference(&lfence);
2708e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom
2709e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom	ttm_bo_unref(&query_val.bo);
2710e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom	ttm_bo_unref(&pinned_val.bo);
2711e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom	ttm_bo_unref(&dev_priv->pinned_bo);
2712e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom
2713e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstromout_unlock:
2714e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom	return;
2715e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom
2716e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstromout_no_emit:
2717ecff665f5e3f1c6909353e00b9420e45ae23d995Maarten Lankhorst	ttm_eu_backoff_reservation(&ticket, &validate_list);
2718e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstromout_no_reserve:
2719e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom	ttm_bo_unref(&query_val.bo);
2720e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom	ttm_bo_unref(&pinned_val.bo);
2721e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom	ttm_bo_unref(&dev_priv->pinned_bo);
2722c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom}
2723c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom
2724c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom/**
2725c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * vmw_execbuf_release_pinned_bo - Flush queries and unpin the pinned
2726c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * query bo.
2727c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom *
2728c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * @dev_priv: The device private structure.
2729c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom *
2730c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * This function should be used to unpin the pinned query bo, or
2731c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * as a query barrier when we need to make sure that all queries have
2732c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * finished before the next fifo command. (For example on hardware
2733c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * context destructions where the hardware may otherwise leak unfinished
2734c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * queries).
2735c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom *
2736c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * This function does not return any failure codes, but make attempts
2737c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * to do safe unpinning in case of errors.
2738c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom *
2739c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * The function will synchronize on the previous query barrier, and will
2740c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom * thus not finish until that barrier has executed.
2741c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom */
2742c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstromvoid vmw_execbuf_release_pinned_bo(struct vmw_private *dev_priv)
2743c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom{
2744c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	mutex_lock(&dev_priv->cmdbuf_mutex);
2745c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom	if (dev_priv->query_cid_valid)
2746c0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1Thomas Hellstrom		__vmw_execbuf_release_pinned_bo(dev_priv, NULL);
2747e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom	mutex_unlock(&dev_priv->cmdbuf_mutex);
2748e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom}
2749e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom
2750922ade0d16d24be2040be7d55dbb734af779a1ddThomas Hellstrom
2751922ade0d16d24be2040be7d55dbb734af779a1ddThomas Hellstromint vmw_execbuf_ioctl(struct drm_device *dev, void *data,
2752922ade0d16d24be2040be7d55dbb734af779a1ddThomas Hellstrom		      struct drm_file *file_priv)
2753922ade0d16d24be2040be7d55dbb734af779a1ddThomas Hellstrom{
2754922ade0d16d24be2040be7d55dbb734af779a1ddThomas Hellstrom	struct vmw_private *dev_priv = vmw_priv(dev);
2755922ade0d16d24be2040be7d55dbb734af779a1ddThomas Hellstrom	struct drm_vmw_execbuf_arg *arg = (struct drm_vmw_execbuf_arg *)data;
2756922ade0d16d24be2040be7d55dbb734af779a1ddThomas Hellstrom	int ret;
2757922ade0d16d24be2040be7d55dbb734af779a1ddThomas Hellstrom
2758922ade0d16d24be2040be7d55dbb734af779a1ddThomas Hellstrom	/*
2759922ade0d16d24be2040be7d55dbb734af779a1ddThomas Hellstrom	 * This will allow us to extend the ioctl argument while
2760922ade0d16d24be2040be7d55dbb734af779a1ddThomas Hellstrom	 * maintaining backwards compatibility:
2761922ade0d16d24be2040be7d55dbb734af779a1ddThomas Hellstrom	 * We take different code paths depending on the value of
2762922ade0d16d24be2040be7d55dbb734af779a1ddThomas Hellstrom	 * arg->version.
2763922ade0d16d24be2040be7d55dbb734af779a1ddThomas Hellstrom	 */
2764922ade0d16d24be2040be7d55dbb734af779a1ddThomas Hellstrom
2765922ade0d16d24be2040be7d55dbb734af779a1ddThomas Hellstrom	if (unlikely(arg->version != DRM_VMW_EXECBUF_VERSION)) {
2766922ade0d16d24be2040be7d55dbb734af779a1ddThomas Hellstrom		DRM_ERROR("Incorrect execbuf version.\n");
2767922ade0d16d24be2040be7d55dbb734af779a1ddThomas Hellstrom		DRM_ERROR("You're running outdated experimental "
2768922ade0d16d24be2040be7d55dbb734af779a1ddThomas Hellstrom			  "vmwgfx user-space drivers.");
2769922ade0d16d24be2040be7d55dbb734af779a1ddThomas Hellstrom		return -EINVAL;
2770922ade0d16d24be2040be7d55dbb734af779a1ddThomas Hellstrom	}
2771922ade0d16d24be2040be7d55dbb734af779a1ddThomas Hellstrom
2772294adf7d86226c0e6abeb4475159b03aa315d56fThomas Hellstrom	ret = ttm_read_lock(&dev_priv->reservation_sem, true);
2773922ade0d16d24be2040be7d55dbb734af779a1ddThomas Hellstrom	if (unlikely(ret != 0))
2774922ade0d16d24be2040be7d55dbb734af779a1ddThomas Hellstrom		return ret;
2775922ade0d16d24be2040be7d55dbb734af779a1ddThomas Hellstrom
2776922ade0d16d24be2040be7d55dbb734af779a1ddThomas Hellstrom	ret = vmw_execbuf_process(file_priv, dev_priv,
2777922ade0d16d24be2040be7d55dbb734af779a1ddThomas Hellstrom				  (void __user *)(unsigned long)arg->commands,
2778922ade0d16d24be2040be7d55dbb734af779a1ddThomas Hellstrom				  NULL, arg->command_size, arg->throttle_us,
2779bb1bd2f43ee15386a1c3f96cbcbb9302a9994443Jakob Bornecrantz				  (void __user *)(unsigned long)arg->fence_rep,
2780bb1bd2f43ee15386a1c3f96cbcbb9302a9994443Jakob Bornecrantz				  NULL);
2781922ade0d16d24be2040be7d55dbb734af779a1ddThomas Hellstrom
2782922ade0d16d24be2040be7d55dbb734af779a1ddThomas Hellstrom	if (unlikely(ret != 0))
2783922ade0d16d24be2040be7d55dbb734af779a1ddThomas Hellstrom		goto out_unlock;
2784922ade0d16d24be2040be7d55dbb734af779a1ddThomas Hellstrom
2785922ade0d16d24be2040be7d55dbb734af779a1ddThomas Hellstrom	vmw_kms_cursor_post_execbuf(dev_priv);
2786922ade0d16d24be2040be7d55dbb734af779a1ddThomas Hellstrom
2787922ade0d16d24be2040be7d55dbb734af779a1ddThomas Hellstromout_unlock:
2788294adf7d86226c0e6abeb4475159b03aa315d56fThomas Hellstrom	ttm_read_unlock(&dev_priv->reservation_sem);
2789fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz	return ret;
2790fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz}
2791