1 /**************************************************************************
2  *
3  * Copyright © 2009-2012 VMware, Inc., Palo Alto, CA., USA
4  * All Rights Reserved.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the
8  * "Software"), to deal in the Software without restriction, including
9  * without limitation the rights to use, copy, modify, merge, publish,
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
12  * the following conditions:
13  *
14  * The above copyright notice and this permission notice (including the
15  * next paragraph) shall be included in all copies or substantial portions
16  * of the Software.
17  *
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,
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,
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
24  * USE OR OTHER DEALINGS IN THE SOFTWARE.
25  *
26  **************************************************************************/
27 
28 #include "vmwgfx_drv.h"
29 #include "vmwgfx_resource_priv.h"
30 #include "ttm/ttm_placement.h"
31 
32 struct vmw_user_context {
33 	struct ttm_base_object base;
34 	struct vmw_resource res;
35 	struct vmw_ctx_binding_state cbs;
36 };
37 
38 
39 
40 typedef int (*vmw_scrub_func)(struct vmw_ctx_bindinfo *, bool);
41 
42 static void vmw_user_context_free(struct vmw_resource *res);
43 static struct vmw_resource *
44 vmw_user_context_base_to_res(struct ttm_base_object *base);
45 
46 static int vmw_gb_context_create(struct vmw_resource *res);
47 static int vmw_gb_context_bind(struct vmw_resource *res,
48 			       struct ttm_validate_buffer *val_buf);
49 static int vmw_gb_context_unbind(struct vmw_resource *res,
50 				 bool readback,
51 				 struct ttm_validate_buffer *val_buf);
52 static int vmw_gb_context_destroy(struct vmw_resource *res);
53 static int vmw_context_scrub_shader(struct vmw_ctx_bindinfo *bi, bool rebind);
54 static int vmw_context_scrub_render_target(struct vmw_ctx_bindinfo *bi,
55 					   bool rebind);
56 static int vmw_context_scrub_texture(struct vmw_ctx_bindinfo *bi, bool rebind);
57 static void vmw_context_binding_state_scrub(struct vmw_ctx_binding_state *cbs);
58 static void vmw_context_binding_state_kill(struct vmw_ctx_binding_state *cbs);
59 static uint64_t vmw_user_context_size;
60 
61 static const struct vmw_user_resource_conv user_context_conv = {
62 	.object_type = VMW_RES_CONTEXT,
63 	.base_obj_to_res = vmw_user_context_base_to_res,
64 	.res_free = vmw_user_context_free
65 };
66 
67 const struct vmw_user_resource_conv *user_context_converter =
68 	&user_context_conv;
69 
70 
71 static const struct vmw_res_func vmw_legacy_context_func = {
72 	.res_type = vmw_res_context,
73 	.needs_backup = false,
74 	.may_evict = false,
75 	.type_name = "legacy contexts",
76 	.backup_placement = NULL,
77 	.create = NULL,
78 	.destroy = NULL,
79 	.bind = NULL,
80 	.unbind = NULL
81 };
82 
83 static const struct vmw_res_func vmw_gb_context_func = {
84 	.res_type = vmw_res_context,
85 	.needs_backup = true,
86 	.may_evict = true,
87 	.type_name = "guest backed contexts",
88 	.backup_placement = &vmw_mob_placement,
89 	.create = vmw_gb_context_create,
90 	.destroy = vmw_gb_context_destroy,
91 	.bind = vmw_gb_context_bind,
92 	.unbind = vmw_gb_context_unbind
93 };
94 
95 static const vmw_scrub_func vmw_scrub_funcs[vmw_ctx_binding_max] = {
96 	[vmw_ctx_binding_shader] = vmw_context_scrub_shader,
97 	[vmw_ctx_binding_rt] = vmw_context_scrub_render_target,
98 	[vmw_ctx_binding_tex] = vmw_context_scrub_texture };
99 
100 /**
101  * Context management:
102  */
103 
104 static void vmw_hw_context_destroy(struct vmw_resource *res)
105 {
106 
107 	struct vmw_private *dev_priv = res->dev_priv;
108 	struct {
109 		SVGA3dCmdHeader header;
110 		SVGA3dCmdDestroyContext body;
111 	} *cmd;
112 
113 
114 	if (res->func->destroy == vmw_gb_context_destroy) {
115 		mutex_lock(&dev_priv->cmdbuf_mutex);
116 		mutex_lock(&dev_priv->binding_mutex);
117 		(void) vmw_context_binding_state_kill
118 			(&container_of(res, struct vmw_user_context, res)->cbs);
119 		(void) vmw_gb_context_destroy(res);
120 		mutex_unlock(&dev_priv->binding_mutex);
121 		if (dev_priv->pinned_bo != NULL &&
122 		    !dev_priv->query_cid_valid)
123 			__vmw_execbuf_release_pinned_bo(dev_priv, NULL);
124 		mutex_unlock(&dev_priv->cmdbuf_mutex);
125 		return;
126 	}
127 
128 	vmw_execbuf_release_pinned_bo(dev_priv);
129 	cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
130 	if (unlikely(cmd == NULL)) {
131 		DRM_ERROR("Failed reserving FIFO space for surface "
132 			  "destruction.\n");
133 		return;
134 	}
135 
136 	cmd->header.id = cpu_to_le32(SVGA_3D_CMD_CONTEXT_DESTROY);
137 	cmd->header.size = cpu_to_le32(sizeof(cmd->body));
138 	cmd->body.cid = cpu_to_le32(res->id);
139 
140 	vmw_fifo_commit(dev_priv, sizeof(*cmd));
141 	vmw_3d_resource_dec(dev_priv, false);
142 }
143 
144 static int vmw_gb_context_init(struct vmw_private *dev_priv,
145 			       struct vmw_resource *res,
146 			       void (*res_free) (struct vmw_resource *res))
147 {
148 	int ret;
149 	struct vmw_user_context *uctx =
150 		container_of(res, struct vmw_user_context, res);
151 
152 	ret = vmw_resource_init(dev_priv, res, true,
153 				res_free, &vmw_gb_context_func);
154 	res->backup_size = SVGA3D_CONTEXT_DATA_SIZE;
155 
156 	if (unlikely(ret != 0)) {
157 		if (res_free)
158 			res_free(res);
159 		else
160 			kfree(res);
161 		return ret;
162 	}
163 
164 	memset(&uctx->cbs, 0, sizeof(uctx->cbs));
165 	INIT_LIST_HEAD(&uctx->cbs.list);
166 
167 	vmw_resource_activate(res, vmw_hw_context_destroy);
168 	return 0;
169 }
170 
171 static int vmw_context_init(struct vmw_private *dev_priv,
172 			    struct vmw_resource *res,
173 			    void (*res_free) (struct vmw_resource *res))
174 {
175 	int ret;
176 
177 	struct {
178 		SVGA3dCmdHeader header;
179 		SVGA3dCmdDefineContext body;
180 	} *cmd;
181 
182 	if (dev_priv->has_mob)
183 		return vmw_gb_context_init(dev_priv, res, res_free);
184 
185 	ret = vmw_resource_init(dev_priv, res, false,
186 				res_free, &vmw_legacy_context_func);
187 
188 	if (unlikely(ret != 0)) {
189 		DRM_ERROR("Failed to allocate a resource id.\n");
190 		goto out_early;
191 	}
192 
193 	if (unlikely(res->id >= SVGA3D_MAX_CONTEXT_IDS)) {
194 		DRM_ERROR("Out of hw context ids.\n");
195 		vmw_resource_unreference(&res);
196 		return -ENOMEM;
197 	}
198 
199 	cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
200 	if (unlikely(cmd == NULL)) {
201 		DRM_ERROR("Fifo reserve failed.\n");
202 		vmw_resource_unreference(&res);
203 		return -ENOMEM;
204 	}
205 
206 	cmd->header.id = cpu_to_le32(SVGA_3D_CMD_CONTEXT_DEFINE);
207 	cmd->header.size = cpu_to_le32(sizeof(cmd->body));
208 	cmd->body.cid = cpu_to_le32(res->id);
209 
210 	vmw_fifo_commit(dev_priv, sizeof(*cmd));
211 	(void) vmw_3d_resource_inc(dev_priv, false);
212 	vmw_resource_activate(res, vmw_hw_context_destroy);
213 	return 0;
214 
215 out_early:
216 	if (res_free == NULL)
217 		kfree(res);
218 	else
219 		res_free(res);
220 	return ret;
221 }
222 
223 struct vmw_resource *vmw_context_alloc(struct vmw_private *dev_priv)
224 {
225 	struct vmw_resource *res = kmalloc(sizeof(*res), GFP_KERNEL);
226 	int ret;
227 
228 	if (unlikely(res == NULL))
229 		return NULL;
230 
231 	ret = vmw_context_init(dev_priv, res, NULL);
232 
233 	return (ret == 0) ? res : NULL;
234 }
235 
236 
237 static int vmw_gb_context_create(struct vmw_resource *res)
238 {
239 	struct vmw_private *dev_priv = res->dev_priv;
240 	int ret;
241 	struct {
242 		SVGA3dCmdHeader header;
243 		SVGA3dCmdDefineGBContext body;
244 	} *cmd;
245 
246 	if (likely(res->id != -1))
247 		return 0;
248 
249 	ret = vmw_resource_alloc_id(res);
250 	if (unlikely(ret != 0)) {
251 		DRM_ERROR("Failed to allocate a context id.\n");
252 		goto out_no_id;
253 	}
254 
255 	if (unlikely(res->id >= VMWGFX_NUM_GB_CONTEXT)) {
256 		ret = -EBUSY;
257 		goto out_no_fifo;
258 	}
259 
260 	cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
261 	if (unlikely(cmd == NULL)) {
262 		DRM_ERROR("Failed reserving FIFO space for context "
263 			  "creation.\n");
264 		ret = -ENOMEM;
265 		goto out_no_fifo;
266 	}
267 
268 	cmd->header.id = SVGA_3D_CMD_DEFINE_GB_CONTEXT;
269 	cmd->header.size = sizeof(cmd->body);
270 	cmd->body.cid = res->id;
271 	vmw_fifo_commit(dev_priv, sizeof(*cmd));
272 	(void) vmw_3d_resource_inc(dev_priv, false);
273 
274 	return 0;
275 
276 out_no_fifo:
277 	vmw_resource_release_id(res);
278 out_no_id:
279 	return ret;
280 }
281 
282 static int vmw_gb_context_bind(struct vmw_resource *res,
283 			       struct ttm_validate_buffer *val_buf)
284 {
285 	struct vmw_private *dev_priv = res->dev_priv;
286 	struct {
287 		SVGA3dCmdHeader header;
288 		SVGA3dCmdBindGBContext body;
289 	} *cmd;
290 	struct ttm_buffer_object *bo = val_buf->bo;
291 
292 	BUG_ON(bo->mem.mem_type != VMW_PL_MOB);
293 
294 	cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
295 	if (unlikely(cmd == NULL)) {
296 		DRM_ERROR("Failed reserving FIFO space for context "
297 			  "binding.\n");
298 		return -ENOMEM;
299 	}
300 
301 	cmd->header.id = SVGA_3D_CMD_BIND_GB_CONTEXT;
302 	cmd->header.size = sizeof(cmd->body);
303 	cmd->body.cid = res->id;
304 	cmd->body.mobid = bo->mem.start;
305 	cmd->body.validContents = res->backup_dirty;
306 	res->backup_dirty = false;
307 	vmw_fifo_commit(dev_priv, sizeof(*cmd));
308 
309 	return 0;
310 }
311 
312 static int vmw_gb_context_unbind(struct vmw_resource *res,
313 				 bool readback,
314 				 struct ttm_validate_buffer *val_buf)
315 {
316 	struct vmw_private *dev_priv = res->dev_priv;
317 	struct ttm_buffer_object *bo = val_buf->bo;
318 	struct vmw_fence_obj *fence;
319 	struct vmw_user_context *uctx =
320 		container_of(res, struct vmw_user_context, res);
321 
322 	struct {
323 		SVGA3dCmdHeader header;
324 		SVGA3dCmdReadbackGBContext body;
325 	} *cmd1;
326 	struct {
327 		SVGA3dCmdHeader header;
328 		SVGA3dCmdBindGBContext body;
329 	} *cmd2;
330 	uint32_t submit_size;
331 	uint8_t *cmd;
332 
333 
334 	BUG_ON(bo->mem.mem_type != VMW_PL_MOB);
335 
336 	mutex_lock(&dev_priv->binding_mutex);
337 	vmw_context_binding_state_scrub(&uctx->cbs);
338 
339 	submit_size = sizeof(*cmd2) + (readback ? sizeof(*cmd1) : 0);
340 
341 	cmd = vmw_fifo_reserve(dev_priv, submit_size);
342 	if (unlikely(cmd == NULL)) {
343 		DRM_ERROR("Failed reserving FIFO space for context "
344 			  "unbinding.\n");
345 		mutex_unlock(&dev_priv->binding_mutex);
346 		return -ENOMEM;
347 	}
348 
349 	cmd2 = (void *) cmd;
350 	if (readback) {
351 		cmd1 = (void *) cmd;
352 		cmd1->header.id = SVGA_3D_CMD_READBACK_GB_CONTEXT;
353 		cmd1->header.size = sizeof(cmd1->body);
354 		cmd1->body.cid = res->id;
355 		cmd2 = (void *) (&cmd1[1]);
356 	}
357 	cmd2->header.id = SVGA_3D_CMD_BIND_GB_CONTEXT;
358 	cmd2->header.size = sizeof(cmd2->body);
359 	cmd2->body.cid = res->id;
360 	cmd2->body.mobid = SVGA3D_INVALID_ID;
361 
362 	vmw_fifo_commit(dev_priv, submit_size);
363 	mutex_unlock(&dev_priv->binding_mutex);
364 
365 	/*
366 	 * Create a fence object and fence the backup buffer.
367 	 */
368 
369 	(void) vmw_execbuf_fence_commands(NULL, dev_priv,
370 					  &fence, NULL);
371 
372 	vmw_fence_single_bo(bo, fence);
373 
374 	if (likely(fence != NULL))
375 		vmw_fence_obj_unreference(&fence);
376 
377 	return 0;
378 }
379 
380 static int vmw_gb_context_destroy(struct vmw_resource *res)
381 {
382 	struct vmw_private *dev_priv = res->dev_priv;
383 	struct {
384 		SVGA3dCmdHeader header;
385 		SVGA3dCmdDestroyGBContext body;
386 	} *cmd;
387 
388 	if (likely(res->id == -1))
389 		return 0;
390 
391 	cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
392 	if (unlikely(cmd == NULL)) {
393 		DRM_ERROR("Failed reserving FIFO space for context "
394 			  "destruction.\n");
395 		return -ENOMEM;
396 	}
397 
398 	cmd->header.id = SVGA_3D_CMD_DESTROY_GB_CONTEXT;
399 	cmd->header.size = sizeof(cmd->body);
400 	cmd->body.cid = res->id;
401 	vmw_fifo_commit(dev_priv, sizeof(*cmd));
402 	if (dev_priv->query_cid == res->id)
403 		dev_priv->query_cid_valid = false;
404 	vmw_resource_release_id(res);
405 	vmw_3d_resource_dec(dev_priv, false);
406 
407 	return 0;
408 }
409 
410 /**
411  * User-space context management:
412  */
413 
414 static struct vmw_resource *
415 vmw_user_context_base_to_res(struct ttm_base_object *base)
416 {
417 	return &(container_of(base, struct vmw_user_context, base)->res);
418 }
419 
420 static void vmw_user_context_free(struct vmw_resource *res)
421 {
422 	struct vmw_user_context *ctx =
423 	    container_of(res, struct vmw_user_context, res);
424 	struct vmw_private *dev_priv = res->dev_priv;
425 
426 	ttm_base_object_kfree(ctx, base);
427 	ttm_mem_global_free(vmw_mem_glob(dev_priv),
428 			    vmw_user_context_size);
429 }
430 
431 /**
432  * This function is called when user space has no more references on the
433  * base object. It releases the base-object's reference on the resource object.
434  */
435 
436 static void vmw_user_context_base_release(struct ttm_base_object **p_base)
437 {
438 	struct ttm_base_object *base = *p_base;
439 	struct vmw_user_context *ctx =
440 	    container_of(base, struct vmw_user_context, base);
441 	struct vmw_resource *res = &ctx->res;
442 
443 	*p_base = NULL;
444 	vmw_resource_unreference(&res);
445 }
446 
447 int vmw_context_destroy_ioctl(struct drm_device *dev, void *data,
448 			      struct drm_file *file_priv)
449 {
450 	struct drm_vmw_context_arg *arg = (struct drm_vmw_context_arg *)data;
451 	struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
452 
453 	return ttm_ref_object_base_unref(tfile, arg->cid, TTM_REF_USAGE);
454 }
455 
456 int vmw_context_define_ioctl(struct drm_device *dev, void *data,
457 			     struct drm_file *file_priv)
458 {
459 	struct vmw_private *dev_priv = vmw_priv(dev);
460 	struct vmw_user_context *ctx;
461 	struct vmw_resource *res;
462 	struct vmw_resource *tmp;
463 	struct drm_vmw_context_arg *arg = (struct drm_vmw_context_arg *)data;
464 	struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
465 	int ret;
466 
467 
468 	/*
469 	 * Approximate idr memory usage with 128 bytes. It will be limited
470 	 * by maximum number_of contexts anyway.
471 	 */
472 
473 	if (unlikely(vmw_user_context_size == 0))
474 		vmw_user_context_size = ttm_round_pot(sizeof(*ctx)) + 128;
475 
476 	ret = ttm_read_lock(&dev_priv->reservation_sem, true);
477 	if (unlikely(ret != 0))
478 		return ret;
479 
480 	ret = ttm_mem_global_alloc(vmw_mem_glob(dev_priv),
481 				   vmw_user_context_size,
482 				   false, true);
483 	if (unlikely(ret != 0)) {
484 		if (ret != -ERESTARTSYS)
485 			DRM_ERROR("Out of graphics memory for context"
486 				  " creation.\n");
487 		goto out_unlock;
488 	}
489 
490 	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
491 	if (unlikely(ctx == NULL)) {
492 		ttm_mem_global_free(vmw_mem_glob(dev_priv),
493 				    vmw_user_context_size);
494 		ret = -ENOMEM;
495 		goto out_unlock;
496 	}
497 
498 	res = &ctx->res;
499 	ctx->base.shareable = false;
500 	ctx->base.tfile = NULL;
501 
502 	/*
503 	 * From here on, the destructor takes over resource freeing.
504 	 */
505 
506 	ret = vmw_context_init(dev_priv, res, vmw_user_context_free);
507 	if (unlikely(ret != 0))
508 		goto out_unlock;
509 
510 	tmp = vmw_resource_reference(&ctx->res);
511 	ret = ttm_base_object_init(tfile, &ctx->base, false, VMW_RES_CONTEXT,
512 				   &vmw_user_context_base_release, NULL);
513 
514 	if (unlikely(ret != 0)) {
515 		vmw_resource_unreference(&tmp);
516 		goto out_err;
517 	}
518 
519 	arg->cid = ctx->base.hash.key;
520 out_err:
521 	vmw_resource_unreference(&res);
522 out_unlock:
523 	ttm_read_unlock(&dev_priv->reservation_sem);
524 	return ret;
525 
526 }
527 
528 /**
529  * vmw_context_scrub_shader - scrub a shader binding from a context.
530  *
531  * @bi: single binding information.
532  * @rebind: Whether to issue a bind instead of scrub command.
533  */
534 static int vmw_context_scrub_shader(struct vmw_ctx_bindinfo *bi, bool rebind)
535 {
536 	struct vmw_private *dev_priv = bi->ctx->dev_priv;
537 	struct {
538 		SVGA3dCmdHeader header;
539 		SVGA3dCmdSetShader body;
540 	} *cmd;
541 
542 	cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
543 	if (unlikely(cmd == NULL)) {
544 		DRM_ERROR("Failed reserving FIFO space for shader "
545 			  "unbinding.\n");
546 		return -ENOMEM;
547 	}
548 
549 	cmd->header.id = SVGA_3D_CMD_SET_SHADER;
550 	cmd->header.size = sizeof(cmd->body);
551 	cmd->body.cid = bi->ctx->id;
552 	cmd->body.type = bi->i1.shader_type;
553 	cmd->body.shid = ((rebind) ? bi->res->id : SVGA3D_INVALID_ID);
554 	vmw_fifo_commit(dev_priv, sizeof(*cmd));
555 
556 	return 0;
557 }
558 
559 /**
560  * vmw_context_scrub_render_target - scrub a render target binding
561  * from a context.
562  *
563  * @bi: single binding information.
564  * @rebind: Whether to issue a bind instead of scrub command.
565  */
566 static int vmw_context_scrub_render_target(struct vmw_ctx_bindinfo *bi,
567 					   bool rebind)
568 {
569 	struct vmw_private *dev_priv = bi->ctx->dev_priv;
570 	struct {
571 		SVGA3dCmdHeader header;
572 		SVGA3dCmdSetRenderTarget body;
573 	} *cmd;
574 
575 	cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
576 	if (unlikely(cmd == NULL)) {
577 		DRM_ERROR("Failed reserving FIFO space for render target "
578 			  "unbinding.\n");
579 		return -ENOMEM;
580 	}
581 
582 	cmd->header.id = SVGA_3D_CMD_SETRENDERTARGET;
583 	cmd->header.size = sizeof(cmd->body);
584 	cmd->body.cid = bi->ctx->id;
585 	cmd->body.type = bi->i1.rt_type;
586 	cmd->body.target.sid = ((rebind) ? bi->res->id : SVGA3D_INVALID_ID);
587 	cmd->body.target.face = 0;
588 	cmd->body.target.mipmap = 0;
589 	vmw_fifo_commit(dev_priv, sizeof(*cmd));
590 
591 	return 0;
592 }
593 
594 /**
595  * vmw_context_scrub_texture - scrub a texture binding from a context.
596  *
597  * @bi: single binding information.
598  * @rebind: Whether to issue a bind instead of scrub command.
599  *
600  * TODO: Possibly complement this function with a function that takes
601  * a list of texture bindings and combines them to a single command.
602  */
603 static int vmw_context_scrub_texture(struct vmw_ctx_bindinfo *bi,
604 				     bool rebind)
605 {
606 	struct vmw_private *dev_priv = bi->ctx->dev_priv;
607 	struct {
608 		SVGA3dCmdHeader header;
609 		struct {
610 			SVGA3dCmdSetTextureState c;
611 			SVGA3dTextureState s1;
612 		} body;
613 	} *cmd;
614 
615 	cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
616 	if (unlikely(cmd == NULL)) {
617 		DRM_ERROR("Failed reserving FIFO space for texture "
618 			  "unbinding.\n");
619 		return -ENOMEM;
620 	}
621 
622 
623 	cmd->header.id = SVGA_3D_CMD_SETTEXTURESTATE;
624 	cmd->header.size = sizeof(cmd->body);
625 	cmd->body.c.cid = bi->ctx->id;
626 	cmd->body.s1.stage = bi->i1.texture_stage;
627 	cmd->body.s1.name = SVGA3D_TS_BIND_TEXTURE;
628 	cmd->body.s1.value = ((rebind) ? bi->res->id : SVGA3D_INVALID_ID);
629 	vmw_fifo_commit(dev_priv, sizeof(*cmd));
630 
631 	return 0;
632 }
633 
634 /**
635  * vmw_context_binding_drop: Stop tracking a context binding
636  *
637  * @cb: Pointer to binding tracker storage.
638  *
639  * Stops tracking a context binding, and re-initializes its storage.
640  * Typically used when the context binding is replaced with a binding to
641  * another (or the same, for that matter) resource.
642  */
643 static void vmw_context_binding_drop(struct vmw_ctx_binding *cb)
644 {
645 	list_del(&cb->ctx_list);
646 	if (!list_empty(&cb->res_list))
647 		list_del(&cb->res_list);
648 	cb->bi.ctx = NULL;
649 }
650 
651 /**
652  * vmw_context_binding_add: Start tracking a context binding
653  *
654  * @cbs: Pointer to the context binding state tracker.
655  * @bi: Information about the binding to track.
656  *
657  * Performs basic checks on the binding to make sure arguments are within
658  * bounds and then starts tracking the binding in the context binding
659  * state structure @cbs.
660  */
661 int vmw_context_binding_add(struct vmw_ctx_binding_state *cbs,
662 			    const struct vmw_ctx_bindinfo *bi)
663 {
664 	struct vmw_ctx_binding *loc;
665 
666 	switch (bi->bt) {
667 	case vmw_ctx_binding_rt:
668 		if (unlikely((unsigned)bi->i1.rt_type >= SVGA3D_RT_MAX)) {
669 			DRM_ERROR("Illegal render target type %u.\n",
670 				  (unsigned) bi->i1.rt_type);
671 			return -EINVAL;
672 		}
673 		loc = &cbs->render_targets[bi->i1.rt_type];
674 		break;
675 	case vmw_ctx_binding_tex:
676 		if (unlikely((unsigned)bi->i1.texture_stage >=
677 			     SVGA3D_NUM_TEXTURE_UNITS)) {
678 			DRM_ERROR("Illegal texture/sampler unit %u.\n",
679 				  (unsigned) bi->i1.texture_stage);
680 			return -EINVAL;
681 		}
682 		loc = &cbs->texture_units[bi->i1.texture_stage];
683 		break;
684 	case vmw_ctx_binding_shader:
685 		if (unlikely((unsigned)bi->i1.shader_type >=
686 			     SVGA3D_SHADERTYPE_MAX)) {
687 			DRM_ERROR("Illegal shader type %u.\n",
688 				  (unsigned) bi->i1.shader_type);
689 			return -EINVAL;
690 		}
691 		loc = &cbs->shaders[bi->i1.shader_type];
692 		break;
693 	default:
694 		BUG();
695 	}
696 
697 	if (loc->bi.ctx != NULL)
698 		vmw_context_binding_drop(loc);
699 
700 	loc->bi = *bi;
701 	loc->bi.scrubbed = false;
702 	list_add_tail(&loc->ctx_list, &cbs->list);
703 	INIT_LIST_HEAD(&loc->res_list);
704 
705 	return 0;
706 }
707 
708 /**
709  * vmw_context_binding_transfer: Transfer a context binding tracking entry.
710  *
711  * @cbs: Pointer to the persistent context binding state tracker.
712  * @bi: Information about the binding to track.
713  *
714  */
715 static void vmw_context_binding_transfer(struct vmw_ctx_binding_state *cbs,
716 					 const struct vmw_ctx_bindinfo *bi)
717 {
718 	struct vmw_ctx_binding *loc;
719 
720 	switch (bi->bt) {
721 	case vmw_ctx_binding_rt:
722 		loc = &cbs->render_targets[bi->i1.rt_type];
723 		break;
724 	case vmw_ctx_binding_tex:
725 		loc = &cbs->texture_units[bi->i1.texture_stage];
726 		break;
727 	case vmw_ctx_binding_shader:
728 		loc = &cbs->shaders[bi->i1.shader_type];
729 		break;
730 	default:
731 		BUG();
732 	}
733 
734 	if (loc->bi.ctx != NULL)
735 		vmw_context_binding_drop(loc);
736 
737 	if (bi->res != NULL) {
738 		loc->bi = *bi;
739 		list_add_tail(&loc->ctx_list, &cbs->list);
740 		list_add_tail(&loc->res_list, &bi->res->binding_head);
741 	}
742 }
743 
744 /**
745  * vmw_context_binding_kill - Kill a binding on the device
746  * and stop tracking it.
747  *
748  * @cb: Pointer to binding tracker storage.
749  *
750  * Emits FIFO commands to scrub a binding represented by @cb.
751  * Then stops tracking the binding and re-initializes its storage.
752  */
753 static void vmw_context_binding_kill(struct vmw_ctx_binding *cb)
754 {
755 	if (!cb->bi.scrubbed) {
756 		(void) vmw_scrub_funcs[cb->bi.bt](&cb->bi, false);
757 		cb->bi.scrubbed = true;
758 	}
759 	vmw_context_binding_drop(cb);
760 }
761 
762 /**
763  * vmw_context_binding_state_kill - Kill all bindings associated with a
764  * struct vmw_ctx_binding state structure, and re-initialize the structure.
765  *
766  * @cbs: Pointer to the context binding state tracker.
767  *
768  * Emits commands to scrub all bindings associated with the
769  * context binding state tracker. Then re-initializes the whole structure.
770  */
771 static void vmw_context_binding_state_kill(struct vmw_ctx_binding_state *cbs)
772 {
773 	struct vmw_ctx_binding *entry, *next;
774 
775 	list_for_each_entry_safe(entry, next, &cbs->list, ctx_list)
776 		vmw_context_binding_kill(entry);
777 }
778 
779 /**
780  * vmw_context_binding_state_scrub - Scrub all bindings associated with a
781  * struct vmw_ctx_binding state structure.
782  *
783  * @cbs: Pointer to the context binding state tracker.
784  *
785  * Emits commands to scrub all bindings associated with the
786  * context binding state tracker.
787  */
788 static void vmw_context_binding_state_scrub(struct vmw_ctx_binding_state *cbs)
789 {
790 	struct vmw_ctx_binding *entry;
791 
792 	list_for_each_entry(entry, &cbs->list, ctx_list) {
793 		if (!entry->bi.scrubbed) {
794 			(void) vmw_scrub_funcs[entry->bi.bt](&entry->bi, false);
795 			entry->bi.scrubbed = true;
796 		}
797 	}
798 }
799 
800 /**
801  * vmw_context_binding_res_list_kill - Kill all bindings on a
802  * resource binding list
803  *
804  * @head: list head of resource binding list
805  *
806  * Kills all bindings associated with a specific resource. Typically
807  * called before the resource is destroyed.
808  */
809 void vmw_context_binding_res_list_kill(struct list_head *head)
810 {
811 	struct vmw_ctx_binding *entry, *next;
812 
813 	list_for_each_entry_safe(entry, next, head, res_list)
814 		vmw_context_binding_kill(entry);
815 }
816 
817 /**
818  * vmw_context_binding_res_list_scrub - Scrub all bindings on a
819  * resource binding list
820  *
821  * @head: list head of resource binding list
822  *
823  * Scrub all bindings associated with a specific resource. Typically
824  * called before the resource is evicted.
825  */
826 void vmw_context_binding_res_list_scrub(struct list_head *head)
827 {
828 	struct vmw_ctx_binding *entry;
829 
830 	list_for_each_entry(entry, head, res_list) {
831 		if (!entry->bi.scrubbed) {
832 			(void) vmw_scrub_funcs[entry->bi.bt](&entry->bi, false);
833 			entry->bi.scrubbed = true;
834 		}
835 	}
836 }
837 
838 /**
839  * vmw_context_binding_state_transfer - Commit staged binding info
840  *
841  * @ctx: Pointer to context to commit the staged binding info to.
842  * @from: Staged binding info built during execbuf.
843  *
844  * Transfers binding info from a temporary structure to the persistent
845  * structure in the context. This can be done once commands
846  */
847 void vmw_context_binding_state_transfer(struct vmw_resource *ctx,
848 					struct vmw_ctx_binding_state *from)
849 {
850 	struct vmw_user_context *uctx =
851 		container_of(ctx, struct vmw_user_context, res);
852 	struct vmw_ctx_binding *entry, *next;
853 
854 	list_for_each_entry_safe(entry, next, &from->list, ctx_list)
855 		vmw_context_binding_transfer(&uctx->cbs, &entry->bi);
856 }
857 
858 /**
859  * vmw_context_rebind_all - Rebind all scrubbed bindings of a context
860  *
861  * @ctx: The context resource
862  *
863  * Walks through the context binding list and rebinds all scrubbed
864  * resources.
865  */
866 int vmw_context_rebind_all(struct vmw_resource *ctx)
867 {
868 	struct vmw_ctx_binding *entry;
869 	struct vmw_user_context *uctx =
870 		container_of(ctx, struct vmw_user_context, res);
871 	struct vmw_ctx_binding_state *cbs = &uctx->cbs;
872 	int ret;
873 
874 	list_for_each_entry(entry, &cbs->list, ctx_list) {
875 		if (likely(!entry->bi.scrubbed))
876 			continue;
877 
878 		if (WARN_ON(entry->bi.res == NULL || entry->bi.res->id ==
879 			    SVGA3D_INVALID_ID))
880 			continue;
881 
882 		ret = vmw_scrub_funcs[entry->bi.bt](&entry->bi, true);
883 		if (unlikely(ret != 0))
884 			return ret;
885 
886 		entry->bi.scrubbed = false;
887 	}
888 
889 	return 0;
890 }
891 
892 /**
893  * vmw_context_binding_list - Return a list of context bindings
894  *
895  * @ctx: The context resource
896  *
897  * Returns the current list of bindings of the given context. Note that
898  * this list becomes stale as soon as the dev_priv::binding_mutex is unlocked.
899  */
900 struct list_head *vmw_context_binding_list(struct vmw_resource *ctx)
901 {
902 	return &(container_of(ctx, struct vmw_user_context, res)->cbs.list);
903 }
904