Subversion Repositories Kolibri OS

Rev

Rev 5078 | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 5078 Rev 6296
1
/**************************************************************************
1
/**************************************************************************
2
 *
2
 *
3
 * Copyright © 2009-2012 VMware, Inc., Palo Alto, CA., USA
3
 * Copyright © 2009-2015 VMware, Inc., Palo Alto, CA., USA
4
 * All Rights Reserved.
4
 * All Rights Reserved.
5
 *
5
 *
6
 * Permission is hereby granted, free of charge, to any person obtaining a
6
 * Permission is hereby granted, free of charge, to any person obtaining a
7
 * copy of this software and associated documentation files (the
7
 * copy of this software and associated documentation files (the
8
 * "Software"), to deal in the Software without restriction, including
8
 * "Software"), to deal in the Software without restriction, including
9
 * without limitation the rights to use, copy, modify, merge, publish,
9
 * without limitation the rights to use, copy, modify, merge, publish,
10
 * distribute, sub license, and/or sell copies of the Software, and to
10
 * distribute, sub license, and/or sell copies of the Software, and to
11
 * permit persons to whom the Software is furnished to do so, subject to
11
 * permit persons to whom the Software is furnished to do so, subject to
12
 * the following conditions:
12
 * the following conditions:
13
 *
13
 *
14
 * The above copyright notice and this permission notice (including the
14
 * The above copyright notice and this permission notice (including the
15
 * next paragraph) shall be included in all copies or substantial portions
15
 * next paragraph) shall be included in all copies or substantial portions
16
 * of the Software.
16
 * of the Software.
17
 *
17
 *
18
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
20
 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
21
 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
21
 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
22
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
22
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
23
 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
23
 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
24
 * USE OR OTHER DEALINGS IN THE SOFTWARE.
24
 * USE OR OTHER DEALINGS IN THE SOFTWARE.
25
 *
25
 *
26
 **************************************************************************/
26
 **************************************************************************/
27
 
27
 
28
#include "vmwgfx_drv.h"
28
#include "vmwgfx_drv.h"
29
#include "vmwgfx_resource_priv.h"
29
#include "vmwgfx_resource_priv.h"
-
 
30
#include "vmwgfx_binding.h"
30
#include "ttm/ttm_placement.h"
31
#include "ttm/ttm_placement.h"
31
 
32
 
32
#define VMW_COMPAT_SHADER_HT_ORDER 12
33
#define VMW_COMPAT_SHADER_HT_ORDER 12
33
 
34
 
34
#if 0
35
#if 0
35
struct vmw_shader {
36
struct vmw_shader {
36
	struct vmw_resource res;
37
	struct vmw_resource res;
37
	SVGA3dShaderType type;
38
	SVGA3dShaderType type;
38
	uint32_t size;
39
	uint32_t size;
-
 
40
	uint8_t num_input_sig;
-
 
41
	uint8_t num_output_sig;
39
};
42
};
40
 
43
 
41
struct vmw_user_shader {
44
struct vmw_user_shader {
42
	struct ttm_base_object base;
45
	struct ttm_base_object base;
43
	struct vmw_shader shader;
46
	struct vmw_shader shader;
44
};
47
};
45
 
-
 
46
/**
-
 
47
 * enum vmw_compat_shader_state - Staging state for compat shaders
-
 
48
 */
48
 
49
enum vmw_compat_shader_state {
-
 
50
	VMW_COMPAT_COMMITED,
-
 
51
	VMW_COMPAT_ADD,
-
 
52
	VMW_COMPAT_DEL
-
 
53
};
-
 
54
 
-
 
55
/**
49
struct vmw_dx_shader {
56
 * struct vmw_compat_shader - Metadata for compat shaders.
-
 
57
 *
-
 
58
 * @handle: The TTM handle of the guest backed shader.
-
 
59
 * @tfile: The struct ttm_object_file the guest backed shader is registered
-
 
60
 * with.
-
 
61
 * @hash: Hash item for lookup.
-
 
62
 * @head: List head for staging lists or the compat shader manager list.
50
	struct vmw_resource res;
63
 * @state: Staging state.
-
 
64
 *
-
 
65
 * The structure is protected by the cmdbuf lock.
-
 
66
 */
51
	struct vmw_resource *ctx;
67
struct vmw_compat_shader {
52
	struct vmw_resource *cotable;
68
	u32 handle;
-
 
69
	struct ttm_object_file *tfile;
53
	u32 id;
70
	struct drm_hash_item hash;
54
	bool committed;
71
	struct list_head head;
-
 
72
	enum vmw_compat_shader_state state;
55
	struct list_head cotable_head;
73
};
-
 
74
 
-
 
75
/**
-
 
76
 * struct vmw_compat_shader_manager - Compat shader manager.
-
 
77
 *
-
 
78
 * @shaders: Hash table containing staged and commited compat shaders
-
 
79
 * @list: List of commited shaders.
-
 
80
 * @dev_priv: Pointer to a device private structure.
-
 
81
 *
-
 
82
 * @shaders and @list are protected by the cmdbuf mutex for now.
56
};
83
 */
57
 
84
struct vmw_compat_shader_manager {
-
 
85
	struct drm_open_hash shaders;
58
static uint64_t vmw_user_shader_size;
86
	struct list_head list;
-
 
87
	struct vmw_private *dev_priv;
59
static uint64_t vmw_shader_size;
88
};
60
static size_t vmw_shader_dx_size;
89
 
61
 
90
static void vmw_user_shader_free(struct vmw_resource *res);
62
static void vmw_user_shader_free(struct vmw_resource *res);
91
static struct vmw_resource *
63
static struct vmw_resource *
92
vmw_user_shader_base_to_res(struct ttm_base_object *base);
64
vmw_user_shader_base_to_res(struct ttm_base_object *base);
93
 
65
 
94
static int vmw_gb_shader_create(struct vmw_resource *res);
66
static int vmw_gb_shader_create(struct vmw_resource *res);
95
static int vmw_gb_shader_bind(struct vmw_resource *res,
67
static int vmw_gb_shader_bind(struct vmw_resource *res,
96
			       struct ttm_validate_buffer *val_buf);
68
			       struct ttm_validate_buffer *val_buf);
97
static int vmw_gb_shader_unbind(struct vmw_resource *res,
69
static int vmw_gb_shader_unbind(struct vmw_resource *res,
98
				 bool readback,
70
				 bool readback,
99
				 struct ttm_validate_buffer *val_buf);
71
				 struct ttm_validate_buffer *val_buf);
100
static int vmw_gb_shader_destroy(struct vmw_resource *res);
72
static int vmw_gb_shader_destroy(struct vmw_resource *res);
-
 
73
 
-
 
74
static int vmw_dx_shader_create(struct vmw_resource *res);
-
 
75
static int vmw_dx_shader_bind(struct vmw_resource *res,
-
 
76
			       struct ttm_validate_buffer *val_buf);
-
 
77
static int vmw_dx_shader_unbind(struct vmw_resource *res,
-
 
78
				 bool readback,
-
 
79
				 struct ttm_validate_buffer *val_buf);
-
 
80
static void vmw_dx_shader_commit_notify(struct vmw_resource *res,
-
 
81
					enum vmw_cmdbuf_res_state state);
-
 
82
static bool vmw_shader_id_ok(u32 user_key, SVGA3dShaderType shader_type);
-
 
83
static u32 vmw_shader_key(u32 user_key, SVGA3dShaderType shader_type);
-
 
84
static uint64_t vmw_user_shader_size;
101
 
85
 
102
static const struct vmw_user_resource_conv user_shader_conv = {
86
static const struct vmw_user_resource_conv user_shader_conv = {
103
	.object_type = VMW_RES_SHADER,
87
	.object_type = VMW_RES_SHADER,
104
	.base_obj_to_res = vmw_user_shader_base_to_res,
88
	.base_obj_to_res = vmw_user_shader_base_to_res,
105
	.res_free = vmw_user_shader_free
89
	.res_free = vmw_user_shader_free
106
};
90
};
107
 
91
 
108
const struct vmw_user_resource_conv *user_shader_converter =
92
const struct vmw_user_resource_conv *user_shader_converter =
109
	&user_shader_conv;
93
	&user_shader_conv;
110
 
94
 
111
 
95
 
112
static const struct vmw_res_func vmw_gb_shader_func = {
96
static const struct vmw_res_func vmw_gb_shader_func = {
113
	.res_type = vmw_res_shader,
97
	.res_type = vmw_res_shader,
114
	.needs_backup = true,
98
	.needs_backup = true,
115
	.may_evict = true,
99
	.may_evict = true,
116
	.type_name = "guest backed shaders",
100
	.type_name = "guest backed shaders",
117
	.backup_placement = &vmw_mob_placement,
101
	.backup_placement = &vmw_mob_placement,
118
	.create = vmw_gb_shader_create,
102
	.create = vmw_gb_shader_create,
119
	.destroy = vmw_gb_shader_destroy,
103
	.destroy = vmw_gb_shader_destroy,
120
	.bind = vmw_gb_shader_bind,
104
	.bind = vmw_gb_shader_bind,
121
	.unbind = vmw_gb_shader_unbind
105
	.unbind = vmw_gb_shader_unbind
122
};
106
};
-
 
107
 
-
 
108
static const struct vmw_res_func vmw_dx_shader_func = {
-
 
109
	.res_type = vmw_res_shader,
-
 
110
	.needs_backup = true,
-
 
111
	.may_evict = false,
-
 
112
	.type_name = "dx shaders",
-
 
113
	.backup_placement = &vmw_mob_placement,
-
 
114
	.create = vmw_dx_shader_create,
-
 
115
	/*
-
 
116
	 * The destroy callback is only called with a committed resource on
-
 
117
	 * context destroy, in which case we destroy the cotable anyway,
-
 
118
	 * so there's no need to destroy DX shaders separately.
-
 
119
	 */
-
 
120
	.destroy = NULL,
-
 
121
	.bind = vmw_dx_shader_bind,
-
 
122
	.unbind = vmw_dx_shader_unbind,
-
 
123
	.commit_notify = vmw_dx_shader_commit_notify,
-
 
124
};
123
 
125
 
124
/**
126
/**
125
 * Shader management:
127
 * Shader management:
126
 */
128
 */
127
 
129
 
128
static inline struct vmw_shader *
130
static inline struct vmw_shader *
129
vmw_res_to_shader(struct vmw_resource *res)
131
vmw_res_to_shader(struct vmw_resource *res)
130
{
132
{
131
	return container_of(res, struct vmw_shader, res);
133
	return container_of(res, struct vmw_shader, res);
132
}
134
}
-
 
135
 
-
 
136
/**
-
 
137
 * vmw_res_to_dx_shader - typecast a struct vmw_resource to a
-
 
138
 * struct vmw_dx_shader
-
 
139
 *
-
 
140
 * @res: Pointer to the struct vmw_resource.
-
 
141
 */
-
 
142
static inline struct vmw_dx_shader *
-
 
143
vmw_res_to_dx_shader(struct vmw_resource *res)
-
 
144
{
-
 
145
	return container_of(res, struct vmw_dx_shader, res);
-
 
146
}
133
 
147
 
134
static void vmw_hw_shader_destroy(struct vmw_resource *res)
148
static void vmw_hw_shader_destroy(struct vmw_resource *res)
-
 
149
{
135
{
150
	if (likely(res->func->destroy))
-
 
151
		(void) res->func->destroy(res);
-
 
152
	else
136
	(void) vmw_gb_shader_destroy(res);
153
		res->id = -1;
-
 
154
}
137
}
155
 
138
 
156
 
139
static int vmw_gb_shader_init(struct vmw_private *dev_priv,
157
static int vmw_gb_shader_init(struct vmw_private *dev_priv,
140
			      struct vmw_resource *res,
158
			      struct vmw_resource *res,
141
			      uint32_t size,
159
			      uint32_t size,
142
			      uint64_t offset,
160
			      uint64_t offset,
143
			      SVGA3dShaderType type,
161
			      SVGA3dShaderType type,
-
 
162
			      uint8_t num_input_sig,
-
 
163
			      uint8_t num_output_sig,
144
			      struct vmw_dma_buffer *byte_code,
164
			      struct vmw_dma_buffer *byte_code,
145
			      void (*res_free) (struct vmw_resource *res))
165
			      void (*res_free) (struct vmw_resource *res))
146
{
166
{
147
	struct vmw_shader *shader = vmw_res_to_shader(res);
167
	struct vmw_shader *shader = vmw_res_to_shader(res);
148
	int ret;
168
	int ret;
149
 
169
 
150
	ret = vmw_resource_init(dev_priv, res, true,
170
	ret = vmw_resource_init(dev_priv, res, true, res_free,
151
				res_free, &vmw_gb_shader_func);
-
 
152
 
171
				&vmw_gb_shader_func);
153
 
172
 
154
	if (unlikely(ret != 0)) {
173
	if (unlikely(ret != 0)) {
155
		if (res_free)
174
		if (res_free)
156
			res_free(res);
175
			res_free(res);
157
		else
176
		else
158
			kfree(res);
177
			kfree(res);
159
		return ret;
178
		return ret;
160
	}
179
	}
161
 
180
 
162
	res->backup_size = size;
181
	res->backup_size = size;
163
	if (byte_code) {
182
	if (byte_code) {
164
		res->backup = vmw_dmabuf_reference(byte_code);
183
		res->backup = vmw_dmabuf_reference(byte_code);
165
		res->backup_offset = offset;
184
		res->backup_offset = offset;
166
	}
185
	}
167
	shader->size = size;
186
	shader->size = size;
168
	shader->type = type;
187
	shader->type = type;
-
 
188
	shader->num_input_sig = num_input_sig;
-
 
189
	shader->num_output_sig = num_output_sig;
169
 
190
 
170
	vmw_resource_activate(res, vmw_hw_shader_destroy);
191
	vmw_resource_activate(res, vmw_hw_shader_destroy);
171
	return 0;
192
	return 0;
172
}
193
}
-
 
194
 
-
 
195
/*
-
 
196
 * GB shader code:
-
 
197
 */
173
 
198
 
174
static int vmw_gb_shader_create(struct vmw_resource *res)
199
static int vmw_gb_shader_create(struct vmw_resource *res)
175
{
200
{
176
	struct vmw_private *dev_priv = res->dev_priv;
201
	struct vmw_private *dev_priv = res->dev_priv;
177
	struct vmw_shader *shader = vmw_res_to_shader(res);
202
	struct vmw_shader *shader = vmw_res_to_shader(res);
178
	int ret;
203
	int ret;
179
	struct {
204
	struct {
180
		SVGA3dCmdHeader header;
205
		SVGA3dCmdHeader header;
181
		SVGA3dCmdDefineGBShader body;
206
		SVGA3dCmdDefineGBShader body;
182
	} *cmd;
207
	} *cmd;
183
 
208
 
184
	if (likely(res->id != -1))
209
	if (likely(res->id != -1))
185
		return 0;
210
		return 0;
186
 
211
 
187
	ret = vmw_resource_alloc_id(res);
212
	ret = vmw_resource_alloc_id(res);
188
	if (unlikely(ret != 0)) {
213
	if (unlikely(ret != 0)) {
189
		DRM_ERROR("Failed to allocate a shader id.\n");
214
		DRM_ERROR("Failed to allocate a shader id.\n");
190
		goto out_no_id;
215
		goto out_no_id;
191
	}
216
	}
192
 
217
 
193
	if (unlikely(res->id >= VMWGFX_NUM_GB_SHADER)) {
218
	if (unlikely(res->id >= VMWGFX_NUM_GB_SHADER)) {
194
		ret = -EBUSY;
219
		ret = -EBUSY;
195
		goto out_no_fifo;
220
		goto out_no_fifo;
196
	}
221
	}
197
 
222
 
198
	cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
223
	cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
199
	if (unlikely(cmd == NULL)) {
224
	if (unlikely(cmd == NULL)) {
200
		DRM_ERROR("Failed reserving FIFO space for shader "
225
		DRM_ERROR("Failed reserving FIFO space for shader "
201
			  "creation.\n");
226
			  "creation.\n");
202
		ret = -ENOMEM;
227
		ret = -ENOMEM;
203
		goto out_no_fifo;
228
		goto out_no_fifo;
204
	}
229
	}
205
 
230
 
206
	cmd->header.id = SVGA_3D_CMD_DEFINE_GB_SHADER;
231
	cmd->header.id = SVGA_3D_CMD_DEFINE_GB_SHADER;
207
	cmd->header.size = sizeof(cmd->body);
232
	cmd->header.size = sizeof(cmd->body);
208
	cmd->body.shid = res->id;
233
	cmd->body.shid = res->id;
209
	cmd->body.type = shader->type;
234
	cmd->body.type = shader->type;
210
	cmd->body.sizeInBytes = shader->size;
235
	cmd->body.sizeInBytes = shader->size;
211
	vmw_fifo_commit(dev_priv, sizeof(*cmd));
236
	vmw_fifo_commit(dev_priv, sizeof(*cmd));
212
	(void) vmw_3d_resource_inc(dev_priv, false);
237
	vmw_fifo_resource_inc(dev_priv);
213
 
238
 
214
	return 0;
239
	return 0;
215
 
240
 
216
out_no_fifo:
241
out_no_fifo:
217
	vmw_resource_release_id(res);
242
	vmw_resource_release_id(res);
218
out_no_id:
243
out_no_id:
219
	return ret;
244
	return ret;
220
}
245
}
221
 
246
 
222
static int vmw_gb_shader_bind(struct vmw_resource *res,
247
static int vmw_gb_shader_bind(struct vmw_resource *res,
223
			      struct ttm_validate_buffer *val_buf)
248
			      struct ttm_validate_buffer *val_buf)
224
{
249
{
225
	struct vmw_private *dev_priv = res->dev_priv;
250
	struct vmw_private *dev_priv = res->dev_priv;
226
	struct {
251
	struct {
227
		SVGA3dCmdHeader header;
252
		SVGA3dCmdHeader header;
228
		SVGA3dCmdBindGBShader body;
253
		SVGA3dCmdBindGBShader body;
229
	} *cmd;
254
	} *cmd;
230
	struct ttm_buffer_object *bo = val_buf->bo;
255
	struct ttm_buffer_object *bo = val_buf->bo;
231
 
256
 
232
	BUG_ON(bo->mem.mem_type != VMW_PL_MOB);
257
	BUG_ON(bo->mem.mem_type != VMW_PL_MOB);
233
 
258
 
234
	cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
259
	cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
235
	if (unlikely(cmd == NULL)) {
260
	if (unlikely(cmd == NULL)) {
236
		DRM_ERROR("Failed reserving FIFO space for shader "
261
		DRM_ERROR("Failed reserving FIFO space for shader "
237
			  "binding.\n");
262
			  "binding.\n");
238
		return -ENOMEM;
263
		return -ENOMEM;
239
	}
264
	}
240
 
265
 
241
	cmd->header.id = SVGA_3D_CMD_BIND_GB_SHADER;
266
	cmd->header.id = SVGA_3D_CMD_BIND_GB_SHADER;
242
	cmd->header.size = sizeof(cmd->body);
267
	cmd->header.size = sizeof(cmd->body);
243
	cmd->body.shid = res->id;
268
	cmd->body.shid = res->id;
244
	cmd->body.mobid = bo->mem.start;
269
	cmd->body.mobid = bo->mem.start;
245
	cmd->body.offsetInBytes = 0;
270
	cmd->body.offsetInBytes = res->backup_offset;
246
	res->backup_dirty = false;
271
	res->backup_dirty = false;
247
	vmw_fifo_commit(dev_priv, sizeof(*cmd));
272
	vmw_fifo_commit(dev_priv, sizeof(*cmd));
248
 
273
 
249
	return 0;
274
	return 0;
250
}
275
}
251
 
276
 
252
static int vmw_gb_shader_unbind(struct vmw_resource *res,
277
static int vmw_gb_shader_unbind(struct vmw_resource *res,
253
				bool readback,
278
				bool readback,
254
				struct ttm_validate_buffer *val_buf)
279
				struct ttm_validate_buffer *val_buf)
255
{
280
{
256
	struct vmw_private *dev_priv = res->dev_priv;
281
	struct vmw_private *dev_priv = res->dev_priv;
257
	struct {
282
	struct {
258
		SVGA3dCmdHeader header;
283
		SVGA3dCmdHeader header;
259
		SVGA3dCmdBindGBShader body;
284
		SVGA3dCmdBindGBShader body;
260
	} *cmd;
285
	} *cmd;
261
	struct vmw_fence_obj *fence;
286
	struct vmw_fence_obj *fence;
262
 
287
 
263
	BUG_ON(res->backup->base.mem.mem_type != VMW_PL_MOB);
288
	BUG_ON(res->backup->base.mem.mem_type != VMW_PL_MOB);
264
 
289
 
265
	cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
290
	cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
266
	if (unlikely(cmd == NULL)) {
291
	if (unlikely(cmd == NULL)) {
267
		DRM_ERROR("Failed reserving FIFO space for shader "
292
		DRM_ERROR("Failed reserving FIFO space for shader "
268
			  "unbinding.\n");
293
			  "unbinding.\n");
269
		return -ENOMEM;
294
		return -ENOMEM;
270
	}
295
	}
271
 
296
 
272
	cmd->header.id = SVGA_3D_CMD_BIND_GB_SHADER;
297
	cmd->header.id = SVGA_3D_CMD_BIND_GB_SHADER;
273
	cmd->header.size = sizeof(cmd->body);
298
	cmd->header.size = sizeof(cmd->body);
274
	cmd->body.shid = res->id;
299
	cmd->body.shid = res->id;
275
	cmd->body.mobid = SVGA3D_INVALID_ID;
300
	cmd->body.mobid = SVGA3D_INVALID_ID;
276
	cmd->body.offsetInBytes = 0;
301
	cmd->body.offsetInBytes = 0;
277
	vmw_fifo_commit(dev_priv, sizeof(*cmd));
302
	vmw_fifo_commit(dev_priv, sizeof(*cmd));
278
 
303
 
279
	/*
304
	/*
280
	 * Create a fence object and fence the backup buffer.
305
	 * Create a fence object and fence the backup buffer.
281
	 */
306
	 */
282
 
307
 
283
	(void) vmw_execbuf_fence_commands(NULL, dev_priv,
308
	(void) vmw_execbuf_fence_commands(NULL, dev_priv,
284
					  &fence, NULL);
309
					  &fence, NULL);
285
 
310
 
286
	vmw_fence_single_bo(val_buf->bo, fence);
311
	vmw_fence_single_bo(val_buf->bo, fence);
287
 
312
 
288
	if (likely(fence != NULL))
313
	if (likely(fence != NULL))
289
		vmw_fence_obj_unreference(&fence);
314
		vmw_fence_obj_unreference(&fence);
290
 
315
 
291
	return 0;
316
	return 0;
292
}
317
}
293
 
318
 
294
static int vmw_gb_shader_destroy(struct vmw_resource *res)
319
static int vmw_gb_shader_destroy(struct vmw_resource *res)
295
{
320
{
296
	struct vmw_private *dev_priv = res->dev_priv;
321
	struct vmw_private *dev_priv = res->dev_priv;
297
	struct {
322
	struct {
298
		SVGA3dCmdHeader header;
323
		SVGA3dCmdHeader header;
299
		SVGA3dCmdDestroyGBShader body;
324
		SVGA3dCmdDestroyGBShader body;
300
	} *cmd;
325
	} *cmd;
301
 
326
 
302
	if (likely(res->id == -1))
327
	if (likely(res->id == -1))
303
		return 0;
328
		return 0;
304
 
329
 
305
	mutex_lock(&dev_priv->binding_mutex);
330
	mutex_lock(&dev_priv->binding_mutex);
306
	vmw_context_binding_res_list_scrub(&res->binding_head);
331
	vmw_binding_res_list_scrub(&res->binding_head);
307
 
332
 
308
	cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
333
	cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
309
	if (unlikely(cmd == NULL)) {
334
	if (unlikely(cmd == NULL)) {
310
		DRM_ERROR("Failed reserving FIFO space for shader "
335
		DRM_ERROR("Failed reserving FIFO space for shader "
311
			  "destruction.\n");
336
			  "destruction.\n");
312
		mutex_unlock(&dev_priv->binding_mutex);
337
		mutex_unlock(&dev_priv->binding_mutex);
313
		return -ENOMEM;
338
		return -ENOMEM;
314
	}
339
	}
315
 
340
 
316
	cmd->header.id = SVGA_3D_CMD_DESTROY_GB_SHADER;
341
	cmd->header.id = SVGA_3D_CMD_DESTROY_GB_SHADER;
317
	cmd->header.size = sizeof(cmd->body);
342
	cmd->header.size = sizeof(cmd->body);
318
	cmd->body.shid = res->id;
343
	cmd->body.shid = res->id;
319
	vmw_fifo_commit(dev_priv, sizeof(*cmd));
344
	vmw_fifo_commit(dev_priv, sizeof(*cmd));
320
	mutex_unlock(&dev_priv->binding_mutex);
345
	mutex_unlock(&dev_priv->binding_mutex);
321
	vmw_resource_release_id(res);
346
	vmw_resource_release_id(res);
322
	vmw_3d_resource_dec(dev_priv, false);
347
	vmw_fifo_resource_dec(dev_priv);
323
 
348
 
324
	return 0;
349
	return 0;
325
}
350
}
326
 
351
 
327
/**
352
/**
328
 * User-space shader management:
353
 * User-space shader management:
329
 */
354
 */
330
 
355
 
331
static struct vmw_resource *
356
static struct vmw_resource *
332
vmw_user_shader_base_to_res(struct ttm_base_object *base)
357
vmw_user_shader_base_to_res(struct ttm_base_object *base)
333
{
358
{
334
	return &(container_of(base, struct vmw_user_shader, base)->
359
	return &(container_of(base, struct vmw_user_shader, base)->
335
		 shader.res);
360
		 shader.res);
336
}
361
}
337
 
362
 
338
static void vmw_user_shader_free(struct vmw_resource *res)
363
static void vmw_user_shader_free(struct vmw_resource *res)
339
{
364
{
340
	struct vmw_user_shader *ushader =
365
	struct vmw_user_shader *ushader =
341
		container_of(res, struct vmw_user_shader, shader.res);
366
		container_of(res, struct vmw_user_shader, shader.res);
342
	struct vmw_private *dev_priv = res->dev_priv;
367
	struct vmw_private *dev_priv = res->dev_priv;
343
 
368
 
344
	ttm_base_object_kfree(ushader, base);
369
	ttm_base_object_kfree(ushader, base);
345
	ttm_mem_global_free(vmw_mem_glob(dev_priv),
370
	ttm_mem_global_free(vmw_mem_glob(dev_priv),
346
			    vmw_user_shader_size);
371
			    vmw_user_shader_size);
347
}
372
}
348
 
373
 
349
/**
374
/**
350
 * This function is called when user space has no more references on the
375
 * This function is called when user space has no more references on the
351
 * base object. It releases the base-object's reference on the resource object.
376
 * base object. It releases the base-object's reference on the resource object.
352
 */
377
 */
353
 
378
 
354
static void vmw_user_shader_base_release(struct ttm_base_object **p_base)
379
static void vmw_user_shader_base_release(struct ttm_base_object **p_base)
355
{
380
{
356
	struct ttm_base_object *base = *p_base;
381
	struct ttm_base_object *base = *p_base;
357
	struct vmw_resource *res = vmw_user_shader_base_to_res(base);
382
	struct vmw_resource *res = vmw_user_shader_base_to_res(base);
358
 
383
 
359
	*p_base = NULL;
384
	*p_base = NULL;
360
	vmw_resource_unreference(&res);
385
	vmw_resource_unreference(&res);
361
}
386
}
362
 
387
 
363
int vmw_shader_destroy_ioctl(struct drm_device *dev, void *data,
388
int vmw_shader_destroy_ioctl(struct drm_device *dev, void *data,
364
			      struct drm_file *file_priv)
389
			      struct drm_file *file_priv)
365
{
390
{
366
	struct drm_vmw_shader_arg *arg = (struct drm_vmw_shader_arg *)data;
391
	struct drm_vmw_shader_arg *arg = (struct drm_vmw_shader_arg *)data;
367
	struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
392
	struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
368
 
393
 
369
	return ttm_ref_object_base_unref(tfile, arg->handle,
394
	return ttm_ref_object_base_unref(tfile, arg->handle,
370
					 TTM_REF_USAGE);
395
					 TTM_REF_USAGE);
371
}
396
}
372
 
397
 
373
static int vmw_user_shader_alloc(struct vmw_private *dev_priv,
398
static int vmw_user_shader_alloc(struct vmw_private *dev_priv,
374
		     struct vmw_dma_buffer *buffer,
399
				 struct vmw_dma_buffer *buffer,
375
		     size_t shader_size,
400
				 size_t shader_size,
376
		     size_t offset,
401
				 size_t offset,
377
		     SVGA3dShaderType shader_type,
402
				 SVGA3dShaderType shader_type,
-
 
403
				 uint8_t num_input_sig,
-
 
404
				 uint8_t num_output_sig,
378
		     struct ttm_object_file *tfile,
405
				 struct ttm_object_file *tfile,
379
		     u32 *handle)
406
				 u32 *handle)
380
{
407
{
381
	struct vmw_user_shader *ushader;
408
	struct vmw_user_shader *ushader;
382
	struct vmw_resource *res, *tmp;
409
	struct vmw_resource *res, *tmp;
383
	int ret;
410
	int ret;
384
 
411
 
385
	/*
412
	/*
386
	 * Approximate idr memory usage with 128 bytes. It will be limited
413
	 * Approximate idr memory usage with 128 bytes. It will be limited
387
	 * by maximum number_of shaders anyway.
414
	 * by maximum number_of shaders anyway.
388
	 */
415
	 */
389
	if (unlikely(vmw_user_shader_size == 0))
416
	if (unlikely(vmw_user_shader_size == 0))
390
		vmw_user_shader_size =
417
		vmw_user_shader_size =
391
			ttm_round_pot(sizeof(struct vmw_user_shader)) + 128;
418
			ttm_round_pot(sizeof(struct vmw_user_shader)) + 128;
392
 
419
 
393
	ret = ttm_mem_global_alloc(vmw_mem_glob(dev_priv),
420
	ret = ttm_mem_global_alloc(vmw_mem_glob(dev_priv),
394
				   vmw_user_shader_size,
421
				   vmw_user_shader_size,
395
				   false, true);
422
				   false, true);
396
	if (unlikely(ret != 0)) {
423
	if (unlikely(ret != 0)) {
397
		if (ret != -ERESTARTSYS)
424
		if (ret != -ERESTARTSYS)
398
			DRM_ERROR("Out of graphics memory for shader "
425
			DRM_ERROR("Out of graphics memory for shader "
399
				  "creation.\n");
426
				  "creation.\n");
400
		goto out;
427
		goto out;
401
	}
428
	}
402
 
429
 
403
	ushader = kzalloc(sizeof(*ushader), GFP_KERNEL);
430
	ushader = kzalloc(sizeof(*ushader), GFP_KERNEL);
404
	if (unlikely(ushader == NULL)) {
431
	if (unlikely(ushader == NULL)) {
405
		ttm_mem_global_free(vmw_mem_glob(dev_priv),
432
		ttm_mem_global_free(vmw_mem_glob(dev_priv),
406
				    vmw_user_shader_size);
433
				    vmw_user_shader_size);
407
		ret = -ENOMEM;
434
		ret = -ENOMEM;
408
		goto out;
435
		goto out;
409
	}
436
	}
410
 
437
 
411
	res = &ushader->shader.res;
438
	res = &ushader->shader.res;
412
	ushader->base.shareable = false;
439
	ushader->base.shareable = false;
413
	ushader->base.tfile = NULL;
440
	ushader->base.tfile = NULL;
414
 
441
 
415
	/*
442
	/*
416
	 * From here on, the destructor takes over resource freeing.
443
	 * From here on, the destructor takes over resource freeing.
417
	 */
444
	 */
418
 
445
 
419
	ret = vmw_gb_shader_init(dev_priv, res, shader_size,
446
	ret = vmw_gb_shader_init(dev_priv, res, shader_size,
420
				 offset, shader_type, buffer,
447
				 offset, shader_type, num_input_sig,
-
 
448
				 num_output_sig, buffer,
421
				 vmw_user_shader_free);
449
				 vmw_user_shader_free);
422
	if (unlikely(ret != 0))
450
	if (unlikely(ret != 0))
423
		goto out;
451
		goto out;
424
 
452
 
425
	tmp = vmw_resource_reference(res);
453
	tmp = vmw_resource_reference(res);
426
	ret = ttm_base_object_init(tfile, &ushader->base, false,
454
	ret = ttm_base_object_init(tfile, &ushader->base, false,
427
				   VMW_RES_SHADER,
455
				   VMW_RES_SHADER,
428
				   &vmw_user_shader_base_release, NULL);
456
				   &vmw_user_shader_base_release, NULL);
429
 
457
 
430
	if (unlikely(ret != 0)) {
458
	if (unlikely(ret != 0)) {
431
		vmw_resource_unreference(&tmp);
459
		vmw_resource_unreference(&tmp);
432
		goto out_err;
460
		goto out_err;
433
	}
461
	}
434
 
462
 
435
	if (handle)
463
	if (handle)
436
		*handle = ushader->base.hash.key;
464
		*handle = ushader->base.hash.key;
437
out_err:
465
out_err:
438
	vmw_resource_unreference(&res);
466
	vmw_resource_unreference(&res);
439
out:
467
out:
440
	return ret;
468
	return ret;
441
}
469
}
442
 
470
 
-
 
471
 
-
 
472
static struct vmw_resource *vmw_shader_alloc(struct vmw_private *dev_priv,
-
 
473
					     struct vmw_dma_buffer *buffer,
-
 
474
					     size_t shader_size,
-
 
475
					     size_t offset,
-
 
476
					     SVGA3dShaderType shader_type)
-
 
477
{
-
 
478
	struct vmw_shader *shader;
-
 
479
	struct vmw_resource *res;
-
 
480
	int ret;
-
 
481
 
-
 
482
	/*
-
 
483
	 * Approximate idr memory usage with 128 bytes. It will be limited
-
 
484
	 * by maximum number_of shaders anyway.
-
 
485
	 */
-
 
486
	if (unlikely(vmw_shader_size == 0))
-
 
487
		vmw_shader_size =
-
 
488
			ttm_round_pot(sizeof(struct vmw_shader)) + 128;
-
 
489
 
-
 
490
	ret = ttm_mem_global_alloc(vmw_mem_glob(dev_priv),
-
 
491
				   vmw_shader_size,
-
 
492
				   false, true);
-
 
493
	if (unlikely(ret != 0)) {
-
 
494
		if (ret != -ERESTARTSYS)
-
 
495
			DRM_ERROR("Out of graphics memory for shader "
-
 
496
				  "creation.\n");
-
 
497
		goto out_err;
-
 
498
	}
-
 
499
 
-
 
500
	shader = kzalloc(sizeof(*shader), GFP_KERNEL);
-
 
501
	if (unlikely(shader == NULL)) {
-
 
502
		ttm_mem_global_free(vmw_mem_glob(dev_priv),
-
 
503
				    vmw_shader_size);
-
 
504
		ret = -ENOMEM;
-
 
505
		goto out_err;
-
 
506
	}
-
 
507
 
-
 
508
	res = &shader->res;
-
 
509
 
-
 
510
	/*
-
 
511
	 * From here on, the destructor takes over resource freeing.
-
 
512
	 */
-
 
513
	ret = vmw_gb_shader_init(dev_priv, res, shader_size,
-
 
514
				 offset, shader_type, 0, 0, buffer,
-
 
515
				 vmw_shader_free);
-
 
516
 
-
 
517
out_err:
-
 
518
	return ret ? ERR_PTR(ret) : res;
-
 
519
}
-
 
520
 
443
 
521
 
-
 
522
static int vmw_shader_define(struct drm_device *dev, struct drm_file *file_priv,
-
 
523
			     enum drm_vmw_shader_type shader_type_drm,
-
 
524
			     u32 buffer_handle, size_t size, size_t offset,
444
int vmw_shader_define_ioctl(struct drm_device *dev, void *data,
525
			     uint8_t num_input_sig, uint8_t num_output_sig,
445
			     struct drm_file *file_priv)
526
			     uint32_t *shader_handle)
446
{
527
{
447
	struct vmw_private *dev_priv = vmw_priv(dev);
-
 
448
	struct drm_vmw_shader_create_arg *arg =
-
 
449
		(struct drm_vmw_shader_create_arg *)data;
528
	struct vmw_private *dev_priv = vmw_priv(dev);
450
	struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
529
	struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
451
	struct vmw_dma_buffer *buffer = NULL;
530
	struct vmw_dma_buffer *buffer = NULL;
452
	SVGA3dShaderType shader_type;
531
	SVGA3dShaderType shader_type;
453
	int ret;
532
	int ret;
454
 
533
 
455
	if (arg->buffer_handle != SVGA3D_INVALID_ID) {
534
	if (buffer_handle != SVGA3D_INVALID_ID) {
456
		ret = vmw_user_dmabuf_lookup(tfile, arg->buffer_handle,
535
		ret = vmw_user_dmabuf_lookup(tfile, buffer_handle,
457
					     &buffer);
536
					     &buffer, NULL);
458
		if (unlikely(ret != 0)) {
537
		if (unlikely(ret != 0)) {
459
			DRM_ERROR("Could not find buffer for shader "
538
			DRM_ERROR("Could not find buffer for shader "
460
				  "creation.\n");
539
				  "creation.\n");
461
			return ret;
540
			return ret;
462
		}
541
		}
463
 
542
 
464
		if ((u64)buffer->base.num_pages * PAGE_SIZE <
543
		if ((u64)buffer->base.num_pages * PAGE_SIZE <
465
		    (u64)arg->size + (u64)arg->offset) {
544
		    (u64)size + (u64)offset) {
466
			DRM_ERROR("Illegal buffer- or shader size.\n");
545
			DRM_ERROR("Illegal buffer- or shader size.\n");
467
			ret = -EINVAL;
546
			ret = -EINVAL;
468
			goto out_bad_arg;
547
			goto out_bad_arg;
469
		}
548
		}
470
	}
549
	}
471
 
550
 
472
	switch (arg->shader_type) {
551
	switch (shader_type_drm) {
473
	case drm_vmw_shader_type_vs:
552
	case drm_vmw_shader_type_vs:
474
		shader_type = SVGA3D_SHADERTYPE_VS;
553
		shader_type = SVGA3D_SHADERTYPE_VS;
475
		break;
554
		break;
476
	case drm_vmw_shader_type_ps:
555
	case drm_vmw_shader_type_ps:
477
		shader_type = SVGA3D_SHADERTYPE_PS;
556
		shader_type = SVGA3D_SHADERTYPE_PS;
478
		break;
557
		break;
479
	case drm_vmw_shader_type_gs:
-
 
480
		shader_type = SVGA3D_SHADERTYPE_GS;
-
 
481
		break;
-
 
482
	default:
558
	default:
483
		DRM_ERROR("Illegal shader type.\n");
559
		DRM_ERROR("Illegal shader type.\n");
484
		ret = -EINVAL;
560
		ret = -EINVAL;
485
		goto out_bad_arg;
561
		goto out_bad_arg;
486
	}
562
	}
487
 
563
 
488
	ret = ttm_read_lock(&dev_priv->reservation_sem, true);
564
	ret = ttm_read_lock(&dev_priv->reservation_sem, true);
489
	if (unlikely(ret != 0))
565
	if (unlikely(ret != 0))
490
		goto out_bad_arg;
566
		goto out_bad_arg;
491
 
567
 
-
 
568
	ret = vmw_user_shader_alloc(dev_priv, buffer, size, offset,
492
	ret = vmw_user_shader_alloc(dev_priv, buffer, arg->size, arg->offset,
569
				    shader_type, num_input_sig,
493
			       shader_type, tfile, &arg->shader_handle);
570
				    num_output_sig, tfile, shader_handle);
494
 
571
 
495
	ttm_read_unlock(&dev_priv->reservation_sem);
572
	ttm_read_unlock(&dev_priv->reservation_sem);
496
out_bad_arg:
573
out_bad_arg:
497
	vmw_dmabuf_unreference(&buffer);
574
	vmw_dmabuf_unreference(&buffer);
498
	return ret;
575
	return ret;
499
}
576
}
500
 
577
 
501
/**
578
/**
502
 * vmw_compat_shader_id_ok - Check whether a compat shader user key and
579
 * vmw_shader_id_ok - Check whether a compat shader user key and
503
 * shader type are within valid bounds.
580
 * shader type are within valid bounds.
504
 *
581
 *
505
 * @user_key: User space id of the shader.
582
 * @user_key: User space id of the shader.
506
 * @shader_type: Shader type.
583
 * @shader_type: Shader type.
507
 *
584
 *
508
 * Returns true if valid false if not.
585
 * Returns true if valid false if not.
509
	 */
586
 */
510
static bool vmw_compat_shader_id_ok(u32 user_key, SVGA3dShaderType shader_type)
587
static bool vmw_shader_id_ok(u32 user_key, SVGA3dShaderType shader_type)
511
{
588
{
512
	return user_key <= ((1 << 20) - 1) && (unsigned) shader_type < 16;
589
	return user_key <= ((1 << 20) - 1) && (unsigned) shader_type < 16;
513
}
590
}
514
 
591
 
515
/**
592
/**
516
 * vmw_compat_shader_key - Compute a hash key suitable for a compat shader.
593
 * vmw_shader_key - Compute a hash key suitable for a compat shader.
517
 *
594
 *
518
 * @user_key: User space id of the shader.
595
 * @user_key: User space id of the shader.
519
 * @shader_type: Shader type.
596
 * @shader_type: Shader type.
520
 *
597
 *
521
 * Returns a hash key suitable for a command buffer managed resource
598
 * Returns a hash key suitable for a command buffer managed resource
522
 * manager hash table.
599
 * manager hash table.
523
 */
600
 */
524
static u32 vmw_compat_shader_key(u32 user_key, SVGA3dShaderType shader_type)
601
static u32 vmw_shader_key(u32 user_key, SVGA3dShaderType shader_type)
525
{
602
{
526
	return user_key | (shader_type << 20);
603
	return user_key | (shader_type << 20);
527
}
604
}
528
 
605
 
529
/**
606
/**
530
 * vmw_compat_shader_remove - Stage a compat shader for removal.
607
 * vmw_shader_remove - Stage a compat shader for removal.
531
 *
608
 *
532
 * @man: Pointer to the compat shader manager identifying the shader namespace.
609
 * @man: Pointer to the compat shader manager identifying the shader namespace.
533
 * @user_key: The key that is used to identify the shader. The key is
610
 * @user_key: The key that is used to identify the shader. The key is
534
 * unique to the shader type.
611
 * unique to the shader type.
535
 * @shader_type: Shader type.
612
 * @shader_type: Shader type.
536
 * @list: Caller's list of staged command buffer resource actions.
613
 * @list: Caller's list of staged command buffer resource actions.
537
 */
614
 */
538
int vmw_compat_shader_remove(struct vmw_cmdbuf_res_manager *man,
615
int vmw_shader_remove(struct vmw_cmdbuf_res_manager *man,
539
			     u32 user_key, SVGA3dShaderType shader_type,
616
		      u32 user_key, SVGA3dShaderType shader_type,
540
			     struct list_head *list)
617
		      struct list_head *list)
541
{
618
{
-
 
619
	struct vmw_resource *dummy;
-
 
620
 
542
	if (!vmw_compat_shader_id_ok(user_key, shader_type))
621
	if (!vmw_shader_id_ok(user_key, shader_type))
543
		return -EINVAL;
622
		return -EINVAL;
544
 
623
 
545
	return vmw_cmdbuf_res_remove(man, vmw_cmdbuf_res_compat_shader,
624
	return vmw_cmdbuf_res_remove(man, vmw_cmdbuf_res_shader,
546
				     vmw_compat_shader_key(user_key,
-
 
547
							   shader_type),
625
				     vmw_shader_key(user_key, shader_type),
548
				     list);
626
				     list, &dummy);
549
}
627
}
550
 
628
 
551
/**
629
/**
552
 * vmw_compat_shader_add - Create a compat shader and stage it for addition
630
 * vmw_compat_shader_add - Create a compat shader and stage it for addition
553
 * as a command buffer managed resource.
631
 * as a command buffer managed resource.
554
 *
632
 *
555
 * @man: Pointer to the compat shader manager identifying the shader namespace.
633
 * @man: Pointer to the compat shader manager identifying the shader namespace.
556
 * @user_key: The key that is used to identify the shader. The key is
634
 * @user_key: The key that is used to identify the shader. The key is
557
 * unique to the shader type.
635
 * unique to the shader type.
558
 * @bytecode: Pointer to the bytecode of the shader.
636
 * @bytecode: Pointer to the bytecode of the shader.
559
 * @shader_type: Shader type.
637
 * @shader_type: Shader type.
560
 * @tfile: Pointer to a struct ttm_object_file that the guest-backed shader is
638
 * @tfile: Pointer to a struct ttm_object_file that the guest-backed shader is
561
 * to be created with.
639
 * to be created with.
562
 * @list: Caller's list of staged command buffer resource actions.
640
 * @list: Caller's list of staged command buffer resource actions.
563
 *
641
 *
564
	 */
642
 */
565
int vmw_compat_shader_add(struct vmw_private *dev_priv,
643
int vmw_compat_shader_add(struct vmw_private *dev_priv,
566
			  struct vmw_cmdbuf_res_manager *man,
644
			  struct vmw_cmdbuf_res_manager *man,
567
			  u32 user_key, const void *bytecode,
645
			  u32 user_key, const void *bytecode,
568
			  SVGA3dShaderType shader_type,
646
			  SVGA3dShaderType shader_type,
569
			  size_t size,
647
			  size_t size,
570
			  struct list_head *list)
648
			  struct list_head *list)
571
{
649
{
572
	struct vmw_dma_buffer *buf;
650
	struct vmw_dma_buffer *buf;
573
	struct ttm_bo_kmap_obj map;
651
	struct ttm_bo_kmap_obj map;
574
	bool is_iomem;
652
	bool is_iomem;
575
	int ret;
653
	int ret;
576
	struct vmw_resource *res;
654
	struct vmw_resource *res;
577
 
655
 
578
	if (!vmw_compat_shader_id_ok(user_key, shader_type))
656
	if (!vmw_shader_id_ok(user_key, shader_type))
579
		return -EINVAL;
657
		return -EINVAL;
580
 
658
 
581
	/* Allocate and pin a DMA buffer */
659
	/* Allocate and pin a DMA buffer */
582
	buf = kzalloc(sizeof(*buf), GFP_KERNEL);
660
	buf = kzalloc(sizeof(*buf), GFP_KERNEL);
583
	if (unlikely(buf == NULL))
661
	if (unlikely(buf == NULL))
584
		return -ENOMEM;
662
		return -ENOMEM;
585
 
663
 
586
	ret = vmw_dmabuf_init(dev_priv, buf, size, &vmw_sys_ne_placement,
664
	ret = vmw_dmabuf_init(dev_priv, buf, size, &vmw_sys_ne_placement,
587
			      true, vmw_dmabuf_bo_free);
665
			      true, vmw_dmabuf_bo_free);
588
	if (unlikely(ret != 0))
666
	if (unlikely(ret != 0))
589
		goto out;
667
		goto out;
590
 
668
 
591
	ret = ttm_bo_reserve(&buf->base, false, true, false, NULL);
669
	ret = ttm_bo_reserve(&buf->base, false, true, false, NULL);
592
	if (unlikely(ret != 0))
670
	if (unlikely(ret != 0))
593
		goto no_reserve;
671
		goto no_reserve;
594
 
672
 
595
	/* Map and copy shader bytecode. */
673
	/* Map and copy shader bytecode. */
596
	ret = ttm_bo_kmap(&buf->base, 0, PAGE_ALIGN(size) >> PAGE_SHIFT,
674
	ret = ttm_bo_kmap(&buf->base, 0, PAGE_ALIGN(size) >> PAGE_SHIFT,
597
			  &map);
675
			  &map);
598
	if (unlikely(ret != 0)) {
676
	if (unlikely(ret != 0)) {
599
		ttm_bo_unreserve(&buf->base);
677
		ttm_bo_unreserve(&buf->base);
600
		goto no_reserve;
678
		goto no_reserve;
601
	}
679
	}
602
 
680
 
603
	memcpy(ttm_kmap_obj_virtual(&map, &is_iomem), bytecode, size);
681
	memcpy(ttm_kmap_obj_virtual(&map, &is_iomem), bytecode, size);
604
	WARN_ON(is_iomem);
682
	WARN_ON(is_iomem);
605
 
683
 
606
	ttm_bo_kunmap(&map);
684
	ttm_bo_kunmap(&map);
607
	ret = ttm_bo_validate(&buf->base, &vmw_sys_placement, false, true);
685
	ret = ttm_bo_validate(&buf->base, &vmw_sys_placement, false, true);
608
	WARN_ON(ret != 0);
686
	WARN_ON(ret != 0);
609
	ttm_bo_unreserve(&buf->base);
687
	ttm_bo_unreserve(&buf->base);
610
 
688
 
611
	res = vmw_shader_alloc(dev_priv, buf, size, 0, shader_type);
689
	res = vmw_shader_alloc(dev_priv, buf, size, 0, shader_type);
612
	if (unlikely(ret != 0))
690
	if (unlikely(ret != 0))
613
		goto no_reserve;
691
		goto no_reserve;
614
 
692
 
615
	ret = vmw_cmdbuf_res_add(man, vmw_cmdbuf_res_compat_shader,
693
	ret = vmw_cmdbuf_res_add(man, vmw_cmdbuf_res_shader,
616
				 vmw_compat_shader_key(user_key, shader_type),
694
				 vmw_shader_key(user_key, shader_type),
617
				 res, list);
695
				 res, list);
618
	vmw_resource_unreference(&res);
696
	vmw_resource_unreference(&res);
619
no_reserve:
697
no_reserve:
620
	vmw_dmabuf_unreference(&buf);
698
	vmw_dmabuf_unreference(&buf);
621
out:
699
out:
622
	return ret;
700
	return ret;
623
}
701
}
624
 
702
 
625
/**
703
/**
626
 * vmw_compat_shader_lookup - Look up a compat shader
704
 * vmw_shader_lookup - Look up a compat shader
627
 *
705
 *
628
 * @man: Pointer to the command buffer managed resource manager identifying
706
 * @man: Pointer to the command buffer managed resource manager identifying
629
 * the shader namespace.
707
 * the shader namespace.
630
 * @user_key: The user space id of the shader.
708
 * @user_key: The user space id of the shader.
631
 * @shader_type: The shader type.
709
 * @shader_type: The shader type.
632
 *
710
 *
633
 * Returns a refcounted pointer to a struct vmw_resource if the shader was
711
 * Returns a refcounted pointer to a struct vmw_resource if the shader was
634
 * found. An error pointer otherwise.
712
 * found. An error pointer otherwise.
635
 */
713
 */
636
struct vmw_resource *
714
struct vmw_resource *
637
vmw_compat_shader_lookup(struct vmw_cmdbuf_res_manager *man,
715
vmw_shader_lookup(struct vmw_cmdbuf_res_manager *man,
638
			 u32 user_key,
716
		  u32 user_key,
639
			 SVGA3dShaderType shader_type)
717
		  SVGA3dShaderType shader_type)
640
{
718
{
641
	if (!vmw_compat_shader_id_ok(user_key, shader_type))
719
	if (!vmw_shader_id_ok(user_key, shader_type))
642
		return ERR_PTR(-EINVAL);
720
		return ERR_PTR(-EINVAL);
643
 
721
 
644
	return vmw_cmdbuf_res_lookup(man, vmw_cmdbuf_res_compat_shader,
722
	return vmw_cmdbuf_res_lookup(man, vmw_cmdbuf_res_shader,
-
 
723
				     vmw_shader_key(user_key, shader_type));
-
 
724
}
-
 
725
 
-
 
726
int vmw_shader_define_ioctl(struct drm_device *dev, void *data,
-
 
727
			     struct drm_file *file_priv)
-
 
728
{
-
 
729
	struct drm_vmw_shader_create_arg *arg =
-
 
730
		(struct drm_vmw_shader_create_arg *)data;
-
 
731
 
-
 
732
	return vmw_shader_define(dev, file_priv, arg->shader_type,
-
 
733
				 arg->buffer_handle,
-
 
734
				 arg->size, arg->offset,
645
				     vmw_compat_shader_key(user_key,
735
				 0, 0,
646
							   shader_type));
736
				 &arg->shader_handle);
647
}
737
}
648
#endif
738
#endif
649
>
739
>