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