1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28#include <drm/ttm/ttm_placement.h>
29
30#include "vmwgfx_drv.h"
31#include "vmwgfx_resource_priv.h"
32#include "vmwgfx_binding.h"
33
34struct vmw_shader {
35 struct vmw_resource res;
36 SVGA3dShaderType type;
37 uint32_t size;
38 uint8_t num_input_sig;
39 uint8_t num_output_sig;
40};
41
42struct vmw_user_shader {
43 struct ttm_base_object base;
44 struct vmw_shader shader;
45};
46
47struct vmw_dx_shader {
48 struct vmw_resource res;
49 struct vmw_resource *ctx;
50 struct vmw_resource *cotable;
51 u32 id;
52 bool committed;
53 struct list_head cotable_head;
54};
55
56static uint64_t vmw_user_shader_size;
57static uint64_t vmw_shader_size;
58static size_t vmw_shader_dx_size;
59
60static void vmw_user_shader_free(struct vmw_resource *res);
61static struct vmw_resource *
62vmw_user_shader_base_to_res(struct ttm_base_object *base);
63
64static int vmw_gb_shader_create(struct vmw_resource *res);
65static int vmw_gb_shader_bind(struct vmw_resource *res,
66 struct ttm_validate_buffer *val_buf);
67static int vmw_gb_shader_unbind(struct vmw_resource *res,
68 bool readback,
69 struct ttm_validate_buffer *val_buf);
70static int vmw_gb_shader_destroy(struct vmw_resource *res);
71
72static int vmw_dx_shader_create(struct vmw_resource *res);
73static int vmw_dx_shader_bind(struct vmw_resource *res,
74 struct ttm_validate_buffer *val_buf);
75static int vmw_dx_shader_unbind(struct vmw_resource *res,
76 bool readback,
77 struct ttm_validate_buffer *val_buf);
78static void vmw_dx_shader_commit_notify(struct vmw_resource *res,
79 enum vmw_cmdbuf_res_state state);
80static bool vmw_shader_id_ok(u32 user_key, SVGA3dShaderType shader_type);
81static u32 vmw_shader_key(u32 user_key, SVGA3dShaderType shader_type);
82static uint64_t vmw_user_shader_size;
83
84static const struct vmw_user_resource_conv user_shader_conv = {
85 .object_type = VMW_RES_SHADER,
86 .base_obj_to_res = vmw_user_shader_base_to_res,
87 .res_free = vmw_user_shader_free
88};
89
90const struct vmw_user_resource_conv *user_shader_converter =
91 &user_shader_conv;
92
93
94static const struct vmw_res_func vmw_gb_shader_func = {
95 .res_type = vmw_res_shader,
96 .needs_backup = true,
97 .may_evict = true,
98 .type_name = "guest backed shaders",
99 .backup_placement = &vmw_mob_placement,
100 .create = vmw_gb_shader_create,
101 .destroy = vmw_gb_shader_destroy,
102 .bind = vmw_gb_shader_bind,
103 .unbind = vmw_gb_shader_unbind
104};
105
106static const struct vmw_res_func vmw_dx_shader_func = {
107 .res_type = vmw_res_shader,
108 .needs_backup = true,
109 .may_evict = false,
110 .type_name = "dx shaders",
111 .backup_placement = &vmw_mob_placement,
112 .create = vmw_dx_shader_create,
113
114
115
116
117
118 .destroy = NULL,
119 .bind = vmw_dx_shader_bind,
120 .unbind = vmw_dx_shader_unbind,
121 .commit_notify = vmw_dx_shader_commit_notify,
122};
123
124
125
126
127
128static inline struct vmw_shader *
129vmw_res_to_shader(struct vmw_resource *res)
130{
131 return container_of(res, struct vmw_shader, res);
132}
133
134
135
136
137
138
139
140static inline struct vmw_dx_shader *
141vmw_res_to_dx_shader(struct vmw_resource *res)
142{
143 return container_of(res, struct vmw_dx_shader, res);
144}
145
146static void vmw_hw_shader_destroy(struct vmw_resource *res)
147{
148 if (likely(res->func->destroy))
149 (void) res->func->destroy(res);
150 else
151 res->id = -1;
152}
153
154
155static int vmw_gb_shader_init(struct vmw_private *dev_priv,
156 struct vmw_resource *res,
157 uint32_t size,
158 uint64_t offset,
159 SVGA3dShaderType type,
160 uint8_t num_input_sig,
161 uint8_t num_output_sig,
162 struct vmw_buffer_object *byte_code,
163 void (*res_free) (struct vmw_resource *res))
164{
165 struct vmw_shader *shader = vmw_res_to_shader(res);
166 int ret;
167
168 ret = vmw_resource_init(dev_priv, res, true, res_free,
169 &vmw_gb_shader_func);
170
171 if (unlikely(ret != 0)) {
172 if (res_free)
173 res_free(res);
174 else
175 kfree(res);
176 return ret;
177 }
178
179 res->backup_size = size;
180 if (byte_code) {
181 res->backup = vmw_bo_reference(byte_code);
182 res->backup_offset = offset;
183 }
184 shader->size = size;
185 shader->type = type;
186 shader->num_input_sig = num_input_sig;
187 shader->num_output_sig = num_output_sig;
188
189 res->hw_destroy = vmw_hw_shader_destroy;
190 return 0;
191}
192
193
194
195
196
197static int vmw_gb_shader_create(struct vmw_resource *res)
198{
199 struct vmw_private *dev_priv = res->dev_priv;
200 struct vmw_shader *shader = vmw_res_to_shader(res);
201 int ret;
202 struct {
203 SVGA3dCmdHeader header;
204 SVGA3dCmdDefineGBShader body;
205 } *cmd;
206
207 if (likely(res->id != -1))
208 return 0;
209
210 ret = vmw_resource_alloc_id(res);
211 if (unlikely(ret != 0)) {
212 DRM_ERROR("Failed to allocate a shader id.\n");
213 goto out_no_id;
214 }
215
216 if (unlikely(res->id >= VMWGFX_NUM_GB_SHADER)) {
217 ret = -EBUSY;
218 goto out_no_fifo;
219 }
220
221 cmd = VMW_FIFO_RESERVE(dev_priv, sizeof(*cmd));
222 if (unlikely(cmd == NULL)) {
223 ret = -ENOMEM;
224 goto out_no_fifo;
225 }
226
227 cmd->header.id = SVGA_3D_CMD_DEFINE_GB_SHADER;
228 cmd->header.size = sizeof(cmd->body);
229 cmd->body.shid = res->id;
230 cmd->body.type = shader->type;
231 cmd->body.sizeInBytes = shader->size;
232 vmw_fifo_commit(dev_priv, sizeof(*cmd));
233 vmw_fifo_resource_inc(dev_priv);
234
235 return 0;
236
237out_no_fifo:
238 vmw_resource_release_id(res);
239out_no_id:
240 return ret;
241}
242
243static int vmw_gb_shader_bind(struct vmw_resource *res,
244 struct ttm_validate_buffer *val_buf)
245{
246 struct vmw_private *dev_priv = res->dev_priv;
247 struct {
248 SVGA3dCmdHeader header;
249 SVGA3dCmdBindGBShader body;
250 } *cmd;
251 struct ttm_buffer_object *bo = val_buf->bo;
252
253 BUG_ON(bo->mem.mem_type != VMW_PL_MOB);
254
255 cmd = VMW_FIFO_RESERVE(dev_priv, sizeof(*cmd));
256 if (unlikely(cmd == NULL))
257 return -ENOMEM;
258
259 cmd->header.id = SVGA_3D_CMD_BIND_GB_SHADER;
260 cmd->header.size = sizeof(cmd->body);
261 cmd->body.shid = res->id;
262 cmd->body.mobid = bo->mem.start;
263 cmd->body.offsetInBytes = res->backup_offset;
264 res->backup_dirty = false;
265 vmw_fifo_commit(dev_priv, sizeof(*cmd));
266
267 return 0;
268}
269
270static int vmw_gb_shader_unbind(struct vmw_resource *res,
271 bool readback,
272 struct ttm_validate_buffer *val_buf)
273{
274 struct vmw_private *dev_priv = res->dev_priv;
275 struct {
276 SVGA3dCmdHeader header;
277 SVGA3dCmdBindGBShader body;
278 } *cmd;
279 struct vmw_fence_obj *fence;
280
281 BUG_ON(res->backup->base.mem.mem_type != VMW_PL_MOB);
282
283 cmd = VMW_FIFO_RESERVE(dev_priv, sizeof(*cmd));
284 if (unlikely(cmd == NULL))
285 return -ENOMEM;
286
287 cmd->header.id = SVGA_3D_CMD_BIND_GB_SHADER;
288 cmd->header.size = sizeof(cmd->body);
289 cmd->body.shid = res->id;
290 cmd->body.mobid = SVGA3D_INVALID_ID;
291 cmd->body.offsetInBytes = 0;
292 vmw_fifo_commit(dev_priv, sizeof(*cmd));
293
294
295
296
297
298 (void) vmw_execbuf_fence_commands(NULL, dev_priv,
299 &fence, NULL);
300
301 vmw_bo_fence_single(val_buf->bo, fence);
302
303 if (likely(fence != NULL))
304 vmw_fence_obj_unreference(&fence);
305
306 return 0;
307}
308
309static int vmw_gb_shader_destroy(struct vmw_resource *res)
310{
311 struct vmw_private *dev_priv = res->dev_priv;
312 struct {
313 SVGA3dCmdHeader header;
314 SVGA3dCmdDestroyGBShader body;
315 } *cmd;
316
317 if (likely(res->id == -1))
318 return 0;
319
320 mutex_lock(&dev_priv->binding_mutex);
321 vmw_binding_res_list_scrub(&res->binding_head);
322
323 cmd = VMW_FIFO_RESERVE(dev_priv, sizeof(*cmd));
324 if (unlikely(cmd == NULL)) {
325 mutex_unlock(&dev_priv->binding_mutex);
326 return -ENOMEM;
327 }
328
329 cmd->header.id = SVGA_3D_CMD_DESTROY_GB_SHADER;
330 cmd->header.size = sizeof(cmd->body);
331 cmd->body.shid = res->id;
332 vmw_fifo_commit(dev_priv, sizeof(*cmd));
333 mutex_unlock(&dev_priv->binding_mutex);
334 vmw_resource_release_id(res);
335 vmw_fifo_resource_dec(dev_priv);
336
337 return 0;
338}
339
340
341
342
343
344
345
346
347
348
349
350
351
352static void vmw_dx_shader_commit_notify(struct vmw_resource *res,
353 enum vmw_cmdbuf_res_state state)
354{
355 struct vmw_dx_shader *shader = vmw_res_to_dx_shader(res);
356 struct vmw_private *dev_priv = res->dev_priv;
357
358 if (state == VMW_CMDBUF_RES_ADD) {
359 mutex_lock(&dev_priv->binding_mutex);
360 vmw_cotable_add_resource(shader->cotable,
361 &shader->cotable_head);
362 shader->committed = true;
363 res->id = shader->id;
364 mutex_unlock(&dev_priv->binding_mutex);
365 } else {
366 mutex_lock(&dev_priv->binding_mutex);
367 list_del_init(&shader->cotable_head);
368 shader->committed = false;
369 res->id = -1;
370 mutex_unlock(&dev_priv->binding_mutex);
371 }
372}
373
374
375
376
377
378
379
380
381static int vmw_dx_shader_unscrub(struct vmw_resource *res)
382{
383 struct vmw_dx_shader *shader = vmw_res_to_dx_shader(res);
384 struct vmw_private *dev_priv = res->dev_priv;
385 struct {
386 SVGA3dCmdHeader header;
387 SVGA3dCmdDXBindShader body;
388 } *cmd;
389
390 if (!list_empty(&shader->cotable_head) || !shader->committed)
391 return 0;
392
393 cmd = VMW_FIFO_RESERVE_DX(dev_priv, sizeof(*cmd), shader->ctx->id);
394 if (unlikely(cmd == NULL))
395 return -ENOMEM;
396
397 cmd->header.id = SVGA_3D_CMD_DX_BIND_SHADER;
398 cmd->header.size = sizeof(cmd->body);
399 cmd->body.cid = shader->ctx->id;
400 cmd->body.shid = shader->id;
401 cmd->body.mobid = res->backup->base.mem.start;
402 cmd->body.offsetInBytes = res->backup_offset;
403 vmw_fifo_commit(dev_priv, sizeof(*cmd));
404
405 vmw_cotable_add_resource(shader->cotable, &shader->cotable_head);
406
407 return 0;
408}
409
410
411
412
413
414
415
416
417
418static int vmw_dx_shader_create(struct vmw_resource *res)
419{
420 struct vmw_private *dev_priv = res->dev_priv;
421 struct vmw_dx_shader *shader = vmw_res_to_dx_shader(res);
422 int ret = 0;
423
424 WARN_ON_ONCE(!shader->committed);
425
426 if (!list_empty(&res->mob_head)) {
427 mutex_lock(&dev_priv->binding_mutex);
428 ret = vmw_dx_shader_unscrub(res);
429 mutex_unlock(&dev_priv->binding_mutex);
430 }
431
432 res->id = shader->id;
433 return ret;
434}
435
436
437
438
439
440
441
442
443static int vmw_dx_shader_bind(struct vmw_resource *res,
444 struct ttm_validate_buffer *val_buf)
445{
446 struct vmw_private *dev_priv = res->dev_priv;
447 struct ttm_buffer_object *bo = val_buf->bo;
448
449 BUG_ON(bo->mem.mem_type != VMW_PL_MOB);
450 mutex_lock(&dev_priv->binding_mutex);
451 vmw_dx_shader_unscrub(res);
452 mutex_unlock(&dev_priv->binding_mutex);
453
454 return 0;
455}
456
457
458
459
460
461
462
463
464
465
466
467static int vmw_dx_shader_scrub(struct vmw_resource *res)
468{
469 struct vmw_dx_shader *shader = vmw_res_to_dx_shader(res);
470 struct vmw_private *dev_priv = res->dev_priv;
471 struct {
472 SVGA3dCmdHeader header;
473 SVGA3dCmdDXBindShader body;
474 } *cmd;
475
476 if (list_empty(&shader->cotable_head))
477 return 0;
478
479 WARN_ON_ONCE(!shader->committed);
480 cmd = VMW_FIFO_RESERVE(dev_priv, sizeof(*cmd));
481 if (unlikely(cmd == NULL))
482 return -ENOMEM;
483
484 cmd->header.id = SVGA_3D_CMD_DX_BIND_SHADER;
485 cmd->header.size = sizeof(cmd->body);
486 cmd->body.cid = shader->ctx->id;
487 cmd->body.shid = res->id;
488 cmd->body.mobid = SVGA3D_INVALID_ID;
489 cmd->body.offsetInBytes = 0;
490 vmw_fifo_commit(dev_priv, sizeof(*cmd));
491 res->id = -1;
492 list_del_init(&shader->cotable_head);
493
494 return 0;
495}
496
497
498
499
500
501
502
503
504static int vmw_dx_shader_unbind(struct vmw_resource *res,
505 bool readback,
506 struct ttm_validate_buffer *val_buf)
507{
508 struct vmw_private *dev_priv = res->dev_priv;
509 struct vmw_fence_obj *fence;
510 int ret;
511
512 BUG_ON(res->backup->base.mem.mem_type != VMW_PL_MOB);
513
514 mutex_lock(&dev_priv->binding_mutex);
515 ret = vmw_dx_shader_scrub(res);
516 mutex_unlock(&dev_priv->binding_mutex);
517
518 if (ret)
519 return ret;
520
521 (void) vmw_execbuf_fence_commands(NULL, dev_priv,
522 &fence, NULL);
523 vmw_bo_fence_single(val_buf->bo, fence);
524
525 if (likely(fence != NULL))
526 vmw_fence_obj_unreference(&fence);
527
528 return 0;
529}
530
531
532
533
534
535
536
537
538
539
540
541
542void vmw_dx_shader_cotable_list_scrub(struct vmw_private *dev_priv,
543 struct list_head *list,
544 bool readback)
545{
546 struct vmw_dx_shader *entry, *next;
547
548 lockdep_assert_held_once(&dev_priv->binding_mutex);
549
550 list_for_each_entry_safe(entry, next, list, cotable_head) {
551 WARN_ON(vmw_dx_shader_scrub(&entry->res));
552 if (!readback)
553 entry->committed = false;
554 }
555}
556
557
558
559
560
561
562
563
564static void vmw_dx_shader_res_free(struct vmw_resource *res)
565{
566 struct vmw_private *dev_priv = res->dev_priv;
567 struct vmw_dx_shader *shader = vmw_res_to_dx_shader(res);
568
569 vmw_resource_unreference(&shader->cotable);
570 kfree(shader);
571 ttm_mem_global_free(vmw_mem_glob(dev_priv), vmw_shader_dx_size);
572}
573
574
575
576
577
578
579
580
581
582
583
584int vmw_dx_shader_add(struct vmw_cmdbuf_res_manager *man,
585 struct vmw_resource *ctx,
586 u32 user_key,
587 SVGA3dShaderType shader_type,
588 struct list_head *list)
589{
590 struct vmw_dx_shader *shader;
591 struct vmw_resource *res;
592 struct vmw_private *dev_priv = ctx->dev_priv;
593 struct ttm_operation_ctx ttm_opt_ctx = {
594 .interruptible = true,
595 .no_wait_gpu = false
596 };
597 int ret;
598
599 if (!vmw_shader_dx_size)
600 vmw_shader_dx_size = ttm_round_pot(sizeof(*shader));
601
602 if (!vmw_shader_id_ok(user_key, shader_type))
603 return -EINVAL;
604
605 ret = ttm_mem_global_alloc(vmw_mem_glob(dev_priv), vmw_shader_dx_size,
606 &ttm_opt_ctx);
607 if (ret) {
608 if (ret != -ERESTARTSYS)
609 DRM_ERROR("Out of graphics memory for shader "
610 "creation.\n");
611 return ret;
612 }
613
614 shader = kmalloc(sizeof(*shader), GFP_KERNEL);
615 if (!shader) {
616 ttm_mem_global_free(vmw_mem_glob(dev_priv), vmw_shader_dx_size);
617 return -ENOMEM;
618 }
619
620 res = &shader->res;
621 shader->ctx = ctx;
622 shader->cotable = vmw_resource_reference
623 (vmw_context_cotable(ctx, SVGA_COTABLE_DXSHADER));
624 shader->id = user_key;
625 shader->committed = false;
626 INIT_LIST_HEAD(&shader->cotable_head);
627 ret = vmw_resource_init(dev_priv, res, true,
628 vmw_dx_shader_res_free, &vmw_dx_shader_func);
629 if (ret)
630 goto out_resource_init;
631
632
633
634
635
636 ret = vmw_cmdbuf_res_add(man, vmw_cmdbuf_res_shader,
637 vmw_shader_key(user_key, 0),
638 res, list);
639 if (ret)
640 goto out_resource_init;
641
642 res->id = shader->id;
643 res->hw_destroy = vmw_hw_shader_destroy;
644
645out_resource_init:
646 vmw_resource_unreference(&res);
647
648 return ret;
649}
650
651
652
653
654
655
656
657static struct vmw_resource *
658vmw_user_shader_base_to_res(struct ttm_base_object *base)
659{
660 return &(container_of(base, struct vmw_user_shader, base)->
661 shader.res);
662}
663
664static void vmw_user_shader_free(struct vmw_resource *res)
665{
666 struct vmw_user_shader *ushader =
667 container_of(res, struct vmw_user_shader, shader.res);
668 struct vmw_private *dev_priv = res->dev_priv;
669
670 ttm_base_object_kfree(ushader, base);
671 ttm_mem_global_free(vmw_mem_glob(dev_priv),
672 vmw_user_shader_size);
673}
674
675static void vmw_shader_free(struct vmw_resource *res)
676{
677 struct vmw_shader *shader = vmw_res_to_shader(res);
678 struct vmw_private *dev_priv = res->dev_priv;
679
680 kfree(shader);
681 ttm_mem_global_free(vmw_mem_glob(dev_priv),
682 vmw_shader_size);
683}
684
685
686
687
688
689
690static void vmw_user_shader_base_release(struct ttm_base_object **p_base)
691{
692 struct ttm_base_object *base = *p_base;
693 struct vmw_resource *res = vmw_user_shader_base_to_res(base);
694
695 *p_base = NULL;
696 vmw_resource_unreference(&res);
697}
698
699int vmw_shader_destroy_ioctl(struct drm_device *dev, void *data,
700 struct drm_file *file_priv)
701{
702 struct drm_vmw_shader_arg *arg = (struct drm_vmw_shader_arg *)data;
703 struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
704
705 return ttm_ref_object_base_unref(tfile, arg->handle,
706 TTM_REF_USAGE);
707}
708
709static int vmw_user_shader_alloc(struct vmw_private *dev_priv,
710 struct vmw_buffer_object *buffer,
711 size_t shader_size,
712 size_t offset,
713 SVGA3dShaderType shader_type,
714 uint8_t num_input_sig,
715 uint8_t num_output_sig,
716 struct ttm_object_file *tfile,
717 u32 *handle)
718{
719 struct vmw_user_shader *ushader;
720 struct vmw_resource *res, *tmp;
721 struct ttm_operation_ctx ctx = {
722 .interruptible = true,
723 .no_wait_gpu = false
724 };
725 int ret;
726
727 if (unlikely(vmw_user_shader_size == 0))
728 vmw_user_shader_size =
729 ttm_round_pot(sizeof(struct vmw_user_shader)) +
730 VMW_IDA_ACC_SIZE + TTM_OBJ_EXTRA_SIZE;
731
732 ret = ttm_mem_global_alloc(vmw_mem_glob(dev_priv),
733 vmw_user_shader_size,
734 &ctx);
735 if (unlikely(ret != 0)) {
736 if (ret != -ERESTARTSYS)
737 DRM_ERROR("Out of graphics memory for shader "
738 "creation.\n");
739 goto out;
740 }
741
742 ushader = kzalloc(sizeof(*ushader), GFP_KERNEL);
743 if (unlikely(!ushader)) {
744 ttm_mem_global_free(vmw_mem_glob(dev_priv),
745 vmw_user_shader_size);
746 ret = -ENOMEM;
747 goto out;
748 }
749
750 res = &ushader->shader.res;
751 ushader->base.shareable = false;
752 ushader->base.tfile = NULL;
753
754
755
756
757
758 ret = vmw_gb_shader_init(dev_priv, res, shader_size,
759 offset, shader_type, num_input_sig,
760 num_output_sig, buffer,
761 vmw_user_shader_free);
762 if (unlikely(ret != 0))
763 goto out;
764
765 tmp = vmw_resource_reference(res);
766 ret = ttm_base_object_init(tfile, &ushader->base, false,
767 VMW_RES_SHADER,
768 &vmw_user_shader_base_release, NULL);
769
770 if (unlikely(ret != 0)) {
771 vmw_resource_unreference(&tmp);
772 goto out_err;
773 }
774
775 if (handle)
776 *handle = ushader->base.handle;
777out_err:
778 vmw_resource_unreference(&res);
779out:
780 return ret;
781}
782
783
784static struct vmw_resource *vmw_shader_alloc(struct vmw_private *dev_priv,
785 struct vmw_buffer_object *buffer,
786 size_t shader_size,
787 size_t offset,
788 SVGA3dShaderType shader_type)
789{
790 struct vmw_shader *shader;
791 struct vmw_resource *res;
792 struct ttm_operation_ctx ctx = {
793 .interruptible = true,
794 .no_wait_gpu = false
795 };
796 int ret;
797
798 if (unlikely(vmw_shader_size == 0))
799 vmw_shader_size =
800 ttm_round_pot(sizeof(struct vmw_shader)) +
801 VMW_IDA_ACC_SIZE;
802
803 ret = ttm_mem_global_alloc(vmw_mem_glob(dev_priv),
804 vmw_shader_size,
805 &ctx);
806 if (unlikely(ret != 0)) {
807 if (ret != -ERESTARTSYS)
808 DRM_ERROR("Out of graphics memory for shader "
809 "creation.\n");
810 goto out_err;
811 }
812
813 shader = kzalloc(sizeof(*shader), GFP_KERNEL);
814 if (unlikely(!shader)) {
815 ttm_mem_global_free(vmw_mem_glob(dev_priv),
816 vmw_shader_size);
817 ret = -ENOMEM;
818 goto out_err;
819 }
820
821 res = &shader->res;
822
823
824
825
826 ret = vmw_gb_shader_init(dev_priv, res, shader_size,
827 offset, shader_type, 0, 0, buffer,
828 vmw_shader_free);
829
830out_err:
831 return ret ? ERR_PTR(ret) : res;
832}
833
834
835static int vmw_shader_define(struct drm_device *dev, struct drm_file *file_priv,
836 enum drm_vmw_shader_type shader_type_drm,
837 u32 buffer_handle, size_t size, size_t offset,
838 uint8_t num_input_sig, uint8_t num_output_sig,
839 uint32_t *shader_handle)
840{
841 struct vmw_private *dev_priv = vmw_priv(dev);
842 struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
843 struct vmw_buffer_object *buffer = NULL;
844 SVGA3dShaderType shader_type;
845 int ret;
846
847 if (buffer_handle != SVGA3D_INVALID_ID) {
848 ret = vmw_user_bo_lookup(tfile, buffer_handle,
849 &buffer, NULL);
850 if (unlikely(ret != 0)) {
851 VMW_DEBUG_USER("Couldn't find buffer for shader creation.\n");
852 return ret;
853 }
854
855 if ((u64)buffer->base.num_pages * PAGE_SIZE <
856 (u64)size + (u64)offset) {
857 VMW_DEBUG_USER("Illegal buffer- or shader size.\n");
858 ret = -EINVAL;
859 goto out_bad_arg;
860 }
861 }
862
863 switch (shader_type_drm) {
864 case drm_vmw_shader_type_vs:
865 shader_type = SVGA3D_SHADERTYPE_VS;
866 break;
867 case drm_vmw_shader_type_ps:
868 shader_type = SVGA3D_SHADERTYPE_PS;
869 break;
870 default:
871 VMW_DEBUG_USER("Illegal shader type.\n");
872 ret = -EINVAL;
873 goto out_bad_arg;
874 }
875
876 ret = ttm_read_lock(&dev_priv->reservation_sem, true);
877 if (unlikely(ret != 0))
878 goto out_bad_arg;
879
880 ret = vmw_user_shader_alloc(dev_priv, buffer, size, offset,
881 shader_type, num_input_sig,
882 num_output_sig, tfile, shader_handle);
883
884 ttm_read_unlock(&dev_priv->reservation_sem);
885out_bad_arg:
886 vmw_bo_unreference(&buffer);
887 return ret;
888}
889
890
891
892
893
894
895
896
897
898
899static bool vmw_shader_id_ok(u32 user_key, SVGA3dShaderType shader_type)
900{
901 return user_key <= ((1 << 20) - 1) && (unsigned) shader_type < 16;
902}
903
904
905
906
907
908
909
910
911
912
913static u32 vmw_shader_key(u32 user_key, SVGA3dShaderType shader_type)
914{
915 return user_key | (shader_type << 20);
916}
917
918
919
920
921
922
923
924
925
926
927int vmw_shader_remove(struct vmw_cmdbuf_res_manager *man,
928 u32 user_key, SVGA3dShaderType shader_type,
929 struct list_head *list)
930{
931 struct vmw_resource *dummy;
932
933 if (!vmw_shader_id_ok(user_key, shader_type))
934 return -EINVAL;
935
936 return vmw_cmdbuf_res_remove(man, vmw_cmdbuf_res_shader,
937 vmw_shader_key(user_key, shader_type),
938 list, &dummy);
939}
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955int vmw_compat_shader_add(struct vmw_private *dev_priv,
956 struct vmw_cmdbuf_res_manager *man,
957 u32 user_key, const void *bytecode,
958 SVGA3dShaderType shader_type,
959 size_t size,
960 struct list_head *list)
961{
962 struct ttm_operation_ctx ctx = { false, true };
963 struct vmw_buffer_object *buf;
964 struct ttm_bo_kmap_obj map;
965 bool is_iomem;
966 int ret;
967 struct vmw_resource *res;
968
969 if (!vmw_shader_id_ok(user_key, shader_type))
970 return -EINVAL;
971
972
973 buf = kzalloc(sizeof(*buf), GFP_KERNEL);
974 if (unlikely(!buf))
975 return -ENOMEM;
976
977 ret = vmw_bo_init(dev_priv, buf, size, &vmw_sys_ne_placement,
978 true, vmw_bo_bo_free);
979 if (unlikely(ret != 0))
980 goto out;
981
982 ret = ttm_bo_reserve(&buf->base, false, true, NULL);
983 if (unlikely(ret != 0))
984 goto no_reserve;
985
986
987 ret = ttm_bo_kmap(&buf->base, 0, PAGE_ALIGN(size) >> PAGE_SHIFT,
988 &map);
989 if (unlikely(ret != 0)) {
990 ttm_bo_unreserve(&buf->base);
991 goto no_reserve;
992 }
993
994 memcpy(ttm_kmap_obj_virtual(&map, &is_iomem), bytecode, size);
995 WARN_ON(is_iomem);
996
997 ttm_bo_kunmap(&map);
998 ret = ttm_bo_validate(&buf->base, &vmw_sys_placement, &ctx);
999 WARN_ON(ret != 0);
1000 ttm_bo_unreserve(&buf->base);
1001
1002 res = vmw_shader_alloc(dev_priv, buf, size, 0, shader_type);
1003 if (unlikely(ret != 0))
1004 goto no_reserve;
1005
1006 ret = vmw_cmdbuf_res_add(man, vmw_cmdbuf_res_shader,
1007 vmw_shader_key(user_key, shader_type),
1008 res, list);
1009 vmw_resource_unreference(&res);
1010no_reserve:
1011 vmw_bo_unreference(&buf);
1012out:
1013 return ret;
1014}
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027struct vmw_resource *
1028vmw_shader_lookup(struct vmw_cmdbuf_res_manager *man,
1029 u32 user_key,
1030 SVGA3dShaderType shader_type)
1031{
1032 if (!vmw_shader_id_ok(user_key, shader_type))
1033 return ERR_PTR(-EINVAL);
1034
1035 return vmw_cmdbuf_res_lookup(man, vmw_cmdbuf_res_shader,
1036 vmw_shader_key(user_key, shader_type));
1037}
1038
1039int vmw_shader_define_ioctl(struct drm_device *dev, void *data,
1040 struct drm_file *file_priv)
1041{
1042 struct drm_vmw_shader_create_arg *arg =
1043 (struct drm_vmw_shader_create_arg *)data;
1044
1045 return vmw_shader_define(dev, file_priv, arg->shader_type,
1046 arg->buffer_handle,
1047 arg->size, arg->offset,
1048 0, 0,
1049 &arg->shader_handle);
1050}
1051