Merge tag 'sunxi-fixes-for-4.3' of https://git.kernel.org/pub/scm/linux/kernel/git...
[linux-drm-fsl-dcu.git] / drivers / gpu / drm / vmwgfx / vmwgfx_shader.c
1 /**************************************************************************
2  *
3  * Copyright © 2009-2015 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 "vmwgfx_binding.h"
31 #include "ttm/ttm_placement.h"
32
33 struct vmw_shader {
34         struct vmw_resource res;
35         SVGA3dShaderType type;
36         uint32_t size;
37         uint8_t num_input_sig;
38         uint8_t num_output_sig;
39 };
40
41 struct vmw_user_shader {
42         struct ttm_base_object base;
43         struct vmw_shader shader;
44 };
45
46 struct vmw_dx_shader {
47         struct vmw_resource res;
48         struct vmw_resource *ctx;
49         struct vmw_resource *cotable;
50         u32 id;
51         bool committed;
52         struct list_head cotable_head;
53 };
54
55 static uint64_t vmw_user_shader_size;
56 static uint64_t vmw_shader_size;
57 static size_t vmw_shader_dx_size;
58
59 static void vmw_user_shader_free(struct vmw_resource *res);
60 static struct vmw_resource *
61 vmw_user_shader_base_to_res(struct ttm_base_object *base);
62
63 static int vmw_gb_shader_create(struct vmw_resource *res);
64 static int vmw_gb_shader_bind(struct vmw_resource *res,
65                                struct ttm_validate_buffer *val_buf);
66 static int vmw_gb_shader_unbind(struct vmw_resource *res,
67                                  bool readback,
68                                  struct ttm_validate_buffer *val_buf);
69 static int vmw_gb_shader_destroy(struct vmw_resource *res);
70
71 static int vmw_dx_shader_create(struct vmw_resource *res);
72 static int vmw_dx_shader_bind(struct vmw_resource *res,
73                                struct ttm_validate_buffer *val_buf);
74 static int vmw_dx_shader_unbind(struct vmw_resource *res,
75                                  bool readback,
76                                  struct ttm_validate_buffer *val_buf);
77 static void vmw_dx_shader_commit_notify(struct vmw_resource *res,
78                                         enum vmw_cmdbuf_res_state state);
79 static bool vmw_shader_id_ok(u32 user_key, SVGA3dShaderType shader_type);
80 static u32 vmw_shader_key(u32 user_key, SVGA3dShaderType shader_type);
81 static uint64_t vmw_user_shader_size;
82
83 static const struct vmw_user_resource_conv user_shader_conv = {
84         .object_type = VMW_RES_SHADER,
85         .base_obj_to_res = vmw_user_shader_base_to_res,
86         .res_free = vmw_user_shader_free
87 };
88
89 const struct vmw_user_resource_conv *user_shader_converter =
90         &user_shader_conv;
91
92
93 static const struct vmw_res_func vmw_gb_shader_func = {
94         .res_type = vmw_res_shader,
95         .needs_backup = true,
96         .may_evict = true,
97         .type_name = "guest backed shaders",
98         .backup_placement = &vmw_mob_placement,
99         .create = vmw_gb_shader_create,
100         .destroy = vmw_gb_shader_destroy,
101         .bind = vmw_gb_shader_bind,
102         .unbind = vmw_gb_shader_unbind
103 };
104
105 static const struct vmw_res_func vmw_dx_shader_func = {
106         .res_type = vmw_res_shader,
107         .needs_backup = true,
108         .may_evict = false,
109         .type_name = "dx shaders",
110         .backup_placement = &vmw_mob_placement,
111         .create = vmw_dx_shader_create,
112         /*
113          * The destroy callback is only called with a committed resource on
114          * context destroy, in which case we destroy the cotable anyway,
115          * so there's no need to destroy DX shaders separately.
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  * Shader management:
125  */
126
127 static inline struct vmw_shader *
128 vmw_res_to_shader(struct vmw_resource *res)
129 {
130         return container_of(res, struct vmw_shader, res);
131 }
132
133 /**
134  * vmw_res_to_dx_shader - typecast a struct vmw_resource to a
135  * struct vmw_dx_shader
136  *
137  * @res: Pointer to the struct vmw_resource.
138  */
139 static inline struct vmw_dx_shader *
140 vmw_res_to_dx_shader(struct vmw_resource *res)
141 {
142         return container_of(res, struct vmw_dx_shader, res);
143 }
144
145 static 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
154 static 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_dma_buffer *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_dmabuf_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         vmw_resource_activate(res, vmw_hw_shader_destroy);
189         return 0;
190 }
191
192 /*
193  * GB shader code:
194  */
195
196 static 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_fifo_reserve(dev_priv, sizeof(*cmd));
221         if (unlikely(cmd == NULL)) {
222                 DRM_ERROR("Failed reserving FIFO space for shader "
223                           "creation.\n");
224                 ret = -ENOMEM;
225                 goto out_no_fifo;
226         }
227
228         cmd->header.id = SVGA_3D_CMD_DEFINE_GB_SHADER;
229         cmd->header.size = sizeof(cmd->body);
230         cmd->body.shid = res->id;
231         cmd->body.type = shader->type;
232         cmd->body.sizeInBytes = shader->size;
233         vmw_fifo_commit(dev_priv, sizeof(*cmd));
234         vmw_fifo_resource_inc(dev_priv);
235
236         return 0;
237
238 out_no_fifo:
239         vmw_resource_release_id(res);
240 out_no_id:
241         return ret;
242 }
243
244 static int vmw_gb_shader_bind(struct vmw_resource *res,
245                               struct ttm_validate_buffer *val_buf)
246 {
247         struct vmw_private *dev_priv = res->dev_priv;
248         struct {
249                 SVGA3dCmdHeader header;
250                 SVGA3dCmdBindGBShader body;
251         } *cmd;
252         struct ttm_buffer_object *bo = val_buf->bo;
253
254         BUG_ON(bo->mem.mem_type != VMW_PL_MOB);
255
256         cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
257         if (unlikely(cmd == NULL)) {
258                 DRM_ERROR("Failed reserving FIFO space for shader "
259                           "binding.\n");
260                 return -ENOMEM;
261         }
262
263         cmd->header.id = SVGA_3D_CMD_BIND_GB_SHADER;
264         cmd->header.size = sizeof(cmd->body);
265         cmd->body.shid = res->id;
266         cmd->body.mobid = bo->mem.start;
267         cmd->body.offsetInBytes = res->backup_offset;
268         res->backup_dirty = false;
269         vmw_fifo_commit(dev_priv, sizeof(*cmd));
270
271         return 0;
272 }
273
274 static int vmw_gb_shader_unbind(struct vmw_resource *res,
275                                 bool readback,
276                                 struct ttm_validate_buffer *val_buf)
277 {
278         struct vmw_private *dev_priv = res->dev_priv;
279         struct {
280                 SVGA3dCmdHeader header;
281                 SVGA3dCmdBindGBShader body;
282         } *cmd;
283         struct vmw_fence_obj *fence;
284
285         BUG_ON(res->backup->base.mem.mem_type != VMW_PL_MOB);
286
287         cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
288         if (unlikely(cmd == NULL)) {
289                 DRM_ERROR("Failed reserving FIFO space for shader "
290                           "unbinding.\n");
291                 return -ENOMEM;
292         }
293
294         cmd->header.id = SVGA_3D_CMD_BIND_GB_SHADER;
295         cmd->header.size = sizeof(cmd->body);
296         cmd->body.shid = res->id;
297         cmd->body.mobid = SVGA3D_INVALID_ID;
298         cmd->body.offsetInBytes = 0;
299         vmw_fifo_commit(dev_priv, sizeof(*cmd));
300
301         /*
302          * Create a fence object and fence the backup buffer.
303          */
304
305         (void) vmw_execbuf_fence_commands(NULL, dev_priv,
306                                           &fence, NULL);
307
308         vmw_fence_single_bo(val_buf->bo, fence);
309
310         if (likely(fence != NULL))
311                 vmw_fence_obj_unreference(&fence);
312
313         return 0;
314 }
315
316 static int vmw_gb_shader_destroy(struct vmw_resource *res)
317 {
318         struct vmw_private *dev_priv = res->dev_priv;
319         struct {
320                 SVGA3dCmdHeader header;
321                 SVGA3dCmdDestroyGBShader body;
322         } *cmd;
323
324         if (likely(res->id == -1))
325                 return 0;
326
327         mutex_lock(&dev_priv->binding_mutex);
328         vmw_binding_res_list_scrub(&res->binding_head);
329
330         cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
331         if (unlikely(cmd == NULL)) {
332                 DRM_ERROR("Failed reserving FIFO space for shader "
333                           "destruction.\n");
334                 mutex_unlock(&dev_priv->binding_mutex);
335                 return -ENOMEM;
336         }
337
338         cmd->header.id = SVGA_3D_CMD_DESTROY_GB_SHADER;
339         cmd->header.size = sizeof(cmd->body);
340         cmd->body.shid = res->id;
341         vmw_fifo_commit(dev_priv, sizeof(*cmd));
342         mutex_unlock(&dev_priv->binding_mutex);
343         vmw_resource_release_id(res);
344         vmw_fifo_resource_dec(dev_priv);
345
346         return 0;
347 }
348
349 /*
350  * DX shader code:
351  */
352
353 /**
354  * vmw_dx_shader_commit_notify - Notify that a shader operation has been
355  * committed to hardware from a user-supplied command stream.
356  *
357  * @res: Pointer to the shader resource.
358  * @state: Indicating whether a creation or removal has been committed.
359  *
360  */
361 static void vmw_dx_shader_commit_notify(struct vmw_resource *res,
362                                         enum vmw_cmdbuf_res_state state)
363 {
364         struct vmw_dx_shader *shader = vmw_res_to_dx_shader(res);
365         struct vmw_private *dev_priv = res->dev_priv;
366
367         if (state == VMW_CMDBUF_RES_ADD) {
368                 mutex_lock(&dev_priv->binding_mutex);
369                 vmw_cotable_add_resource(shader->cotable,
370                                          &shader->cotable_head);
371                 shader->committed = true;
372                 res->id = shader->id;
373                 mutex_unlock(&dev_priv->binding_mutex);
374         } else {
375                 mutex_lock(&dev_priv->binding_mutex);
376                 list_del_init(&shader->cotable_head);
377                 shader->committed = false;
378                 res->id = -1;
379                 mutex_unlock(&dev_priv->binding_mutex);
380         }
381 }
382
383 /**
384  * vmw_dx_shader_unscrub - Have the device reattach a MOB to a DX shader.
385  *
386  * @res: The shader resource
387  *
388  * This function reverts a scrub operation.
389  */
390 static int vmw_dx_shader_unscrub(struct vmw_resource *res)
391 {
392         struct vmw_dx_shader *shader = vmw_res_to_dx_shader(res);
393         struct vmw_private *dev_priv = res->dev_priv;
394         struct {
395                 SVGA3dCmdHeader header;
396                 SVGA3dCmdDXBindShader body;
397         } *cmd;
398
399         if (!list_empty(&shader->cotable_head) || !shader->committed)
400                 return 0;
401
402         cmd = vmw_fifo_reserve_dx(dev_priv, sizeof(*cmd),
403                                   shader->ctx->id);
404         if (unlikely(cmd == NULL)) {
405                 DRM_ERROR("Failed reserving FIFO space for shader "
406                           "scrubbing.\n");
407                 return -ENOMEM;
408         }
409
410         cmd->header.id = SVGA_3D_CMD_DX_BIND_SHADER;
411         cmd->header.size = sizeof(cmd->body);
412         cmd->body.cid = shader->ctx->id;
413         cmd->body.shid = shader->id;
414         cmd->body.mobid = res->backup->base.mem.start;
415         cmd->body.offsetInBytes = res->backup_offset;
416         vmw_fifo_commit(dev_priv, sizeof(*cmd));
417
418         vmw_cotable_add_resource(shader->cotable, &shader->cotable_head);
419
420         return 0;
421 }
422
423 /**
424  * vmw_dx_shader_create - The DX shader create callback
425  *
426  * @res: The DX shader resource
427  *
428  * The create callback is called as part of resource validation and
429  * makes sure that we unscrub the shader if it's previously been scrubbed.
430  */
431 static int vmw_dx_shader_create(struct vmw_resource *res)
432 {
433         struct vmw_private *dev_priv = res->dev_priv;
434         struct vmw_dx_shader *shader = vmw_res_to_dx_shader(res);
435         int ret = 0;
436
437         WARN_ON_ONCE(!shader->committed);
438
439         if (!list_empty(&res->mob_head)) {
440                 mutex_lock(&dev_priv->binding_mutex);
441                 ret = vmw_dx_shader_unscrub(res);
442                 mutex_unlock(&dev_priv->binding_mutex);
443         }
444
445         res->id = shader->id;
446         return ret;
447 }
448
449 /**
450  * vmw_dx_shader_bind - The DX shader bind callback
451  *
452  * @res: The DX shader resource
453  * @val_buf: Pointer to the validate buffer.
454  *
455  */
456 static int vmw_dx_shader_bind(struct vmw_resource *res,
457                               struct ttm_validate_buffer *val_buf)
458 {
459         struct vmw_private *dev_priv = res->dev_priv;
460         struct ttm_buffer_object *bo = val_buf->bo;
461
462         BUG_ON(bo->mem.mem_type != VMW_PL_MOB);
463         mutex_lock(&dev_priv->binding_mutex);
464         vmw_dx_shader_unscrub(res);
465         mutex_unlock(&dev_priv->binding_mutex);
466
467         return 0;
468 }
469
470 /**
471  * vmw_dx_shader_scrub - Have the device unbind a MOB from a DX shader.
472  *
473  * @res: The shader resource
474  *
475  * This function unbinds a MOB from the DX shader without requiring the
476  * MOB dma_buffer to be reserved. The driver still considers the MOB bound.
477  * However, once the driver eventually decides to unbind the MOB, it doesn't
478  * need to access the context.
479  */
480 static int vmw_dx_shader_scrub(struct vmw_resource *res)
481 {
482         struct vmw_dx_shader *shader = vmw_res_to_dx_shader(res);
483         struct vmw_private *dev_priv = res->dev_priv;
484         struct {
485                 SVGA3dCmdHeader header;
486                 SVGA3dCmdDXBindShader body;
487         } *cmd;
488
489         if (list_empty(&shader->cotable_head))
490                 return 0;
491
492         WARN_ON_ONCE(!shader->committed);
493         cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
494         if (unlikely(cmd == NULL)) {
495                 DRM_ERROR("Failed reserving FIFO space for shader "
496                           "scrubbing.\n");
497                 return -ENOMEM;
498         }
499
500         cmd->header.id = SVGA_3D_CMD_DX_BIND_SHADER;
501         cmd->header.size = sizeof(cmd->body);
502         cmd->body.cid = shader->ctx->id;
503         cmd->body.shid = res->id;
504         cmd->body.mobid = SVGA3D_INVALID_ID;
505         cmd->body.offsetInBytes = 0;
506         vmw_fifo_commit(dev_priv, sizeof(*cmd));
507         res->id = -1;
508         list_del_init(&shader->cotable_head);
509
510         return 0;
511 }
512
513 /**
514  * vmw_dx_shader_unbind - The dx shader unbind callback.
515  *
516  * @res: The shader resource
517  * @readback: Whether this is a readback unbind. Currently unused.
518  * @val_buf: MOB buffer information.
519  */
520 static int vmw_dx_shader_unbind(struct vmw_resource *res,
521                                 bool readback,
522                                 struct ttm_validate_buffer *val_buf)
523 {
524         struct vmw_private *dev_priv = res->dev_priv;
525         struct vmw_fence_obj *fence;
526         int ret;
527
528         BUG_ON(res->backup->base.mem.mem_type != VMW_PL_MOB);
529
530         mutex_lock(&dev_priv->binding_mutex);
531         ret = vmw_dx_shader_scrub(res);
532         mutex_unlock(&dev_priv->binding_mutex);
533
534         if (ret)
535                 return ret;
536
537         (void) vmw_execbuf_fence_commands(NULL, dev_priv,
538                                           &fence, NULL);
539         vmw_fence_single_bo(val_buf->bo, fence);
540
541         if (likely(fence != NULL))
542                 vmw_fence_obj_unreference(&fence);
543
544         return 0;
545 }
546
547 /**
548  * vmw_dx_shader_cotable_list_scrub - The cotable unbind_func callback for
549  * DX shaders.
550  *
551  * @dev_priv: Pointer to device private structure.
552  * @list: The list of cotable resources.
553  * @readback: Whether the call was part of a readback unbind.
554  *
555  * Scrubs all shader MOBs so that any subsequent shader unbind or shader
556  * destroy operation won't need to swap in the context.
557  */
558 void vmw_dx_shader_cotable_list_scrub(struct vmw_private *dev_priv,
559                                       struct list_head *list,
560                                       bool readback)
561 {
562         struct vmw_dx_shader *entry, *next;
563
564         WARN_ON_ONCE(!mutex_is_locked(&dev_priv->binding_mutex));
565
566         list_for_each_entry_safe(entry, next, list, cotable_head) {
567                 WARN_ON(vmw_dx_shader_scrub(&entry->res));
568                 if (!readback)
569                         entry->committed = false;
570         }
571 }
572
573 /**
574  * vmw_dx_shader_res_free - The DX shader free callback
575  *
576  * @res: The shader resource
577  *
578  * Frees the DX shader resource and updates memory accounting.
579  */
580 static void vmw_dx_shader_res_free(struct vmw_resource *res)
581 {
582         struct vmw_private *dev_priv = res->dev_priv;
583         struct vmw_dx_shader *shader = vmw_res_to_dx_shader(res);
584
585         vmw_resource_unreference(&shader->cotable);
586         kfree(shader);
587         ttm_mem_global_free(vmw_mem_glob(dev_priv), vmw_shader_dx_size);
588 }
589
590 /**
591  * vmw_dx_shader_add - Add a shader resource as a command buffer managed
592  * resource.
593  *
594  * @man: The command buffer resource manager.
595  * @ctx: Pointer to the context resource.
596  * @user_key: The id used for this shader.
597  * @shader_type: The shader type.
598  * @list: The list of staged command buffer managed resources.
599  */
600 int vmw_dx_shader_add(struct vmw_cmdbuf_res_manager *man,
601                       struct vmw_resource *ctx,
602                       u32 user_key,
603                       SVGA3dShaderType shader_type,
604                       struct list_head *list)
605 {
606         struct vmw_dx_shader *shader;
607         struct vmw_resource *res;
608         struct vmw_private *dev_priv = ctx->dev_priv;
609         int ret;
610
611         if (!vmw_shader_dx_size)
612                 vmw_shader_dx_size = ttm_round_pot(sizeof(*shader));
613
614         if (!vmw_shader_id_ok(user_key, shader_type))
615                 return -EINVAL;
616
617         ret = ttm_mem_global_alloc(vmw_mem_glob(dev_priv), vmw_shader_dx_size,
618                                    false, true);
619         if (ret) {
620                 if (ret != -ERESTARTSYS)
621                         DRM_ERROR("Out of graphics memory for shader "
622                                   "creation.\n");
623                 return ret;
624         }
625
626         shader = kmalloc(sizeof(*shader), GFP_KERNEL);
627         if (!shader) {
628                 ttm_mem_global_free(vmw_mem_glob(dev_priv), vmw_shader_dx_size);
629                 return -ENOMEM;
630         }
631
632         res = &shader->res;
633         shader->ctx = ctx;
634         shader->cotable = vmw_context_cotable(ctx, SVGA_COTABLE_DXSHADER);
635         shader->id = user_key;
636         shader->committed = false;
637         INIT_LIST_HEAD(&shader->cotable_head);
638         ret = vmw_resource_init(dev_priv, res, true,
639                                 vmw_dx_shader_res_free, &vmw_dx_shader_func);
640         if (ret)
641                 goto out_resource_init;
642
643         /*
644          * The user_key name-space is not per shader type for DX shaders,
645          * so when hashing, use a single zero shader type.
646          */
647         ret = vmw_cmdbuf_res_add(man, vmw_cmdbuf_res_shader,
648                                  vmw_shader_key(user_key, 0),
649                                  res, list);
650         if (ret)
651                 goto out_resource_init;
652
653         res->id = shader->id;
654         vmw_resource_activate(res, vmw_hw_shader_destroy);
655
656 out_resource_init:
657         vmw_resource_unreference(&res);
658
659         return ret;
660 }
661
662
663
664 /**
665  * User-space shader management:
666  */
667
668 static struct vmw_resource *
669 vmw_user_shader_base_to_res(struct ttm_base_object *base)
670 {
671         return &(container_of(base, struct vmw_user_shader, base)->
672                  shader.res);
673 }
674
675 static void vmw_user_shader_free(struct vmw_resource *res)
676 {
677         struct vmw_user_shader *ushader =
678                 container_of(res, struct vmw_user_shader, shader.res);
679         struct vmw_private *dev_priv = res->dev_priv;
680
681         ttm_base_object_kfree(ushader, base);
682         ttm_mem_global_free(vmw_mem_glob(dev_priv),
683                             vmw_user_shader_size);
684 }
685
686 static void vmw_shader_free(struct vmw_resource *res)
687 {
688         struct vmw_shader *shader = vmw_res_to_shader(res);
689         struct vmw_private *dev_priv = res->dev_priv;
690
691         kfree(shader);
692         ttm_mem_global_free(vmw_mem_glob(dev_priv),
693                             vmw_shader_size);
694 }
695
696 /**
697  * This function is called when user space has no more references on the
698  * base object. It releases the base-object's reference on the resource object.
699  */
700
701 static void vmw_user_shader_base_release(struct ttm_base_object **p_base)
702 {
703         struct ttm_base_object *base = *p_base;
704         struct vmw_resource *res = vmw_user_shader_base_to_res(base);
705
706         *p_base = NULL;
707         vmw_resource_unreference(&res);
708 }
709
710 int vmw_shader_destroy_ioctl(struct drm_device *dev, void *data,
711                               struct drm_file *file_priv)
712 {
713         struct drm_vmw_shader_arg *arg = (struct drm_vmw_shader_arg *)data;
714         struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
715
716         return ttm_ref_object_base_unref(tfile, arg->handle,
717                                          TTM_REF_USAGE);
718 }
719
720 static int vmw_user_shader_alloc(struct vmw_private *dev_priv,
721                                  struct vmw_dma_buffer *buffer,
722                                  size_t shader_size,
723                                  size_t offset,
724                                  SVGA3dShaderType shader_type,
725                                  uint8_t num_input_sig,
726                                  uint8_t num_output_sig,
727                                  struct ttm_object_file *tfile,
728                                  u32 *handle)
729 {
730         struct vmw_user_shader *ushader;
731         struct vmw_resource *res, *tmp;
732         int ret;
733
734         /*
735          * Approximate idr memory usage with 128 bytes. It will be limited
736          * by maximum number_of shaders anyway.
737          */
738         if (unlikely(vmw_user_shader_size == 0))
739                 vmw_user_shader_size =
740                         ttm_round_pot(sizeof(struct vmw_user_shader)) + 128;
741
742         ret = ttm_mem_global_alloc(vmw_mem_glob(dev_priv),
743                                    vmw_user_shader_size,
744                                    false, true);
745         if (unlikely(ret != 0)) {
746                 if (ret != -ERESTARTSYS)
747                         DRM_ERROR("Out of graphics memory for shader "
748                                   "creation.\n");
749                 goto out;
750         }
751
752         ushader = kzalloc(sizeof(*ushader), GFP_KERNEL);
753         if (unlikely(ushader == NULL)) {
754                 ttm_mem_global_free(vmw_mem_glob(dev_priv),
755                                     vmw_user_shader_size);
756                 ret = -ENOMEM;
757                 goto out;
758         }
759
760         res = &ushader->shader.res;
761         ushader->base.shareable = false;
762         ushader->base.tfile = NULL;
763
764         /*
765          * From here on, the destructor takes over resource freeing.
766          */
767
768         ret = vmw_gb_shader_init(dev_priv, res, shader_size,
769                                  offset, shader_type, num_input_sig,
770                                  num_output_sig, buffer,
771                                  vmw_user_shader_free);
772         if (unlikely(ret != 0))
773                 goto out;
774
775         tmp = vmw_resource_reference(res);
776         ret = ttm_base_object_init(tfile, &ushader->base, false,
777                                    VMW_RES_SHADER,
778                                    &vmw_user_shader_base_release, NULL);
779
780         if (unlikely(ret != 0)) {
781                 vmw_resource_unreference(&tmp);
782                 goto out_err;
783         }
784
785         if (handle)
786                 *handle = ushader->base.hash.key;
787 out_err:
788         vmw_resource_unreference(&res);
789 out:
790         return ret;
791 }
792
793
794 static struct vmw_resource *vmw_shader_alloc(struct vmw_private *dev_priv,
795                                              struct vmw_dma_buffer *buffer,
796                                              size_t shader_size,
797                                              size_t offset,
798                                              SVGA3dShaderType shader_type)
799 {
800         struct vmw_shader *shader;
801         struct vmw_resource *res;
802         int ret;
803
804         /*
805          * Approximate idr memory usage with 128 bytes. It will be limited
806          * by maximum number_of shaders anyway.
807          */
808         if (unlikely(vmw_shader_size == 0))
809                 vmw_shader_size =
810                         ttm_round_pot(sizeof(struct vmw_shader)) + 128;
811
812         ret = ttm_mem_global_alloc(vmw_mem_glob(dev_priv),
813                                    vmw_shader_size,
814                                    false, true);
815         if (unlikely(ret != 0)) {
816                 if (ret != -ERESTARTSYS)
817                         DRM_ERROR("Out of graphics memory for shader "
818                                   "creation.\n");
819                 goto out_err;
820         }
821
822         shader = kzalloc(sizeof(*shader), GFP_KERNEL);
823         if (unlikely(shader == NULL)) {
824                 ttm_mem_global_free(vmw_mem_glob(dev_priv),
825                                     vmw_shader_size);
826                 ret = -ENOMEM;
827                 goto out_err;
828         }
829
830         res = &shader->res;
831
832         /*
833          * From here on, the destructor takes over resource freeing.
834          */
835         ret = vmw_gb_shader_init(dev_priv, res, shader_size,
836                                  offset, shader_type, 0, 0, buffer,
837                                  vmw_shader_free);
838
839 out_err:
840         return ret ? ERR_PTR(ret) : res;
841 }
842
843
844 static int vmw_shader_define(struct drm_device *dev, struct drm_file *file_priv,
845                              enum drm_vmw_shader_type shader_type_drm,
846                              u32 buffer_handle, size_t size, size_t offset,
847                              uint8_t num_input_sig, uint8_t num_output_sig,
848                              uint32_t *shader_handle)
849 {
850         struct vmw_private *dev_priv = vmw_priv(dev);
851         struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
852         struct vmw_dma_buffer *buffer = NULL;
853         SVGA3dShaderType shader_type;
854         int ret;
855
856         if (buffer_handle != SVGA3D_INVALID_ID) {
857                 ret = vmw_user_dmabuf_lookup(tfile, buffer_handle,
858                                              &buffer, NULL);
859                 if (unlikely(ret != 0)) {
860                         DRM_ERROR("Could not find buffer for shader "
861                                   "creation.\n");
862                         return ret;
863                 }
864
865                 if ((u64)buffer->base.num_pages * PAGE_SIZE <
866                     (u64)size + (u64)offset) {
867                         DRM_ERROR("Illegal buffer- or shader size.\n");
868                         ret = -EINVAL;
869                         goto out_bad_arg;
870                 }
871         }
872
873         switch (shader_type_drm) {
874         case drm_vmw_shader_type_vs:
875                 shader_type = SVGA3D_SHADERTYPE_VS;
876                 break;
877         case drm_vmw_shader_type_ps:
878                 shader_type = SVGA3D_SHADERTYPE_PS;
879                 break;
880         default:
881                 DRM_ERROR("Illegal shader type.\n");
882                 ret = -EINVAL;
883                 goto out_bad_arg;
884         }
885
886         ret = ttm_read_lock(&dev_priv->reservation_sem, true);
887         if (unlikely(ret != 0))
888                 goto out_bad_arg;
889
890         ret = vmw_user_shader_alloc(dev_priv, buffer, size, offset,
891                                     shader_type, num_input_sig,
892                                     num_output_sig, tfile, shader_handle);
893
894         ttm_read_unlock(&dev_priv->reservation_sem);
895 out_bad_arg:
896         vmw_dmabuf_unreference(&buffer);
897         return ret;
898 }
899
900 /**
901  * vmw_shader_id_ok - Check whether a compat shader user key and
902  * shader type are within valid bounds.
903  *
904  * @user_key: User space id of the shader.
905  * @shader_type: Shader type.
906  *
907  * Returns true if valid false if not.
908  */
909 static bool vmw_shader_id_ok(u32 user_key, SVGA3dShaderType shader_type)
910 {
911         return user_key <= ((1 << 20) - 1) && (unsigned) shader_type < 16;
912 }
913
914 /**
915  * vmw_shader_key - Compute a hash key suitable for a compat shader.
916  *
917  * @user_key: User space id of the shader.
918  * @shader_type: Shader type.
919  *
920  * Returns a hash key suitable for a command buffer managed resource
921  * manager hash table.
922  */
923 static u32 vmw_shader_key(u32 user_key, SVGA3dShaderType shader_type)
924 {
925         return user_key | (shader_type << 20);
926 }
927
928 /**
929  * vmw_shader_remove - Stage a compat shader for removal.
930  *
931  * @man: Pointer to the compat shader manager identifying the shader namespace.
932  * @user_key: The key that is used to identify the shader. The key is
933  * unique to the shader type.
934  * @shader_type: Shader type.
935  * @list: Caller's list of staged command buffer resource actions.
936  */
937 int vmw_shader_remove(struct vmw_cmdbuf_res_manager *man,
938                       u32 user_key, SVGA3dShaderType shader_type,
939                       struct list_head *list)
940 {
941         struct vmw_resource *dummy;
942
943         if (!vmw_shader_id_ok(user_key, shader_type))
944                 return -EINVAL;
945
946         return vmw_cmdbuf_res_remove(man, vmw_cmdbuf_res_shader,
947                                      vmw_shader_key(user_key, shader_type),
948                                      list, &dummy);
949 }
950
951 /**
952  * vmw_compat_shader_add - Create a compat shader and stage it for addition
953  * as a command buffer managed resource.
954  *
955  * @man: Pointer to the compat shader manager identifying the shader namespace.
956  * @user_key: The key that is used to identify the shader. The key is
957  * unique to the shader type.
958  * @bytecode: Pointer to the bytecode of the shader.
959  * @shader_type: Shader type.
960  * @tfile: Pointer to a struct ttm_object_file that the guest-backed shader is
961  * to be created with.
962  * @list: Caller's list of staged command buffer resource actions.
963  *
964  */
965 int vmw_compat_shader_add(struct vmw_private *dev_priv,
966                           struct vmw_cmdbuf_res_manager *man,
967                           u32 user_key, const void *bytecode,
968                           SVGA3dShaderType shader_type,
969                           size_t size,
970                           struct list_head *list)
971 {
972         struct vmw_dma_buffer *buf;
973         struct ttm_bo_kmap_obj map;
974         bool is_iomem;
975         int ret;
976         struct vmw_resource *res;
977
978         if (!vmw_shader_id_ok(user_key, shader_type))
979                 return -EINVAL;
980
981         /* Allocate and pin a DMA buffer */
982         buf = kzalloc(sizeof(*buf), GFP_KERNEL);
983         if (unlikely(buf == NULL))
984                 return -ENOMEM;
985
986         ret = vmw_dmabuf_init(dev_priv, buf, size, &vmw_sys_ne_placement,
987                               true, vmw_dmabuf_bo_free);
988         if (unlikely(ret != 0))
989                 goto out;
990
991         ret = ttm_bo_reserve(&buf->base, false, true, false, NULL);
992         if (unlikely(ret != 0))
993                 goto no_reserve;
994
995         /* Map and copy shader bytecode. */
996         ret = ttm_bo_kmap(&buf->base, 0, PAGE_ALIGN(size) >> PAGE_SHIFT,
997                           &map);
998         if (unlikely(ret != 0)) {
999                 ttm_bo_unreserve(&buf->base);
1000                 goto no_reserve;
1001         }
1002
1003         memcpy(ttm_kmap_obj_virtual(&map, &is_iomem), bytecode, size);
1004         WARN_ON(is_iomem);
1005
1006         ttm_bo_kunmap(&map);
1007         ret = ttm_bo_validate(&buf->base, &vmw_sys_placement, false, true);
1008         WARN_ON(ret != 0);
1009         ttm_bo_unreserve(&buf->base);
1010
1011         res = vmw_shader_alloc(dev_priv, buf, size, 0, shader_type);
1012         if (unlikely(ret != 0))
1013                 goto no_reserve;
1014
1015         ret = vmw_cmdbuf_res_add(man, vmw_cmdbuf_res_shader,
1016                                  vmw_shader_key(user_key, shader_type),
1017                                  res, list);
1018         vmw_resource_unreference(&res);
1019 no_reserve:
1020         vmw_dmabuf_unreference(&buf);
1021 out:
1022         return ret;
1023 }
1024
1025 /**
1026  * vmw_shader_lookup - Look up a compat shader
1027  *
1028  * @man: Pointer to the command buffer managed resource manager identifying
1029  * the shader namespace.
1030  * @user_key: The user space id of the shader.
1031  * @shader_type: The shader type.
1032  *
1033  * Returns a refcounted pointer to a struct vmw_resource if the shader was
1034  * found. An error pointer otherwise.
1035  */
1036 struct vmw_resource *
1037 vmw_shader_lookup(struct vmw_cmdbuf_res_manager *man,
1038                   u32 user_key,
1039                   SVGA3dShaderType shader_type)
1040 {
1041         if (!vmw_shader_id_ok(user_key, shader_type))
1042                 return ERR_PTR(-EINVAL);
1043
1044         return vmw_cmdbuf_res_lookup(man, vmw_cmdbuf_res_shader,
1045                                      vmw_shader_key(user_key, shader_type));
1046 }
1047
1048 int vmw_shader_define_ioctl(struct drm_device *dev, void *data,
1049                              struct drm_file *file_priv)
1050 {
1051         struct drm_vmw_shader_create_arg *arg =
1052                 (struct drm_vmw_shader_create_arg *)data;
1053
1054         return vmw_shader_define(dev, file_priv, arg->shader_type,
1055                                  arg->buffer_handle,
1056                                  arg->size, arg->offset,
1057                                  0, 0,
1058                                  &arg->shader_handle);
1059 }