Merge git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-2.6-nmw
[pandora-kernel.git] / drivers / gpu / drm / vmwgfx / vmwgfx_resource.c
1 /**************************************************************************
2  *
3  * Copyright © 2009 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_drm.h"
30 #include "ttm/ttm_object.h"
31 #include "ttm/ttm_placement.h"
32 #include "drmP.h"
33
34 #define VMW_RES_CONTEXT ttm_driver_type0
35 #define VMW_RES_SURFACE ttm_driver_type1
36 #define VMW_RES_STREAM ttm_driver_type2
37
38 struct vmw_user_context {
39         struct ttm_base_object base;
40         struct vmw_resource res;
41 };
42
43 struct vmw_user_surface {
44         struct ttm_base_object base;
45         struct vmw_surface srf;
46 };
47
48 struct vmw_user_dma_buffer {
49         struct ttm_base_object base;
50         struct vmw_dma_buffer dma;
51 };
52
53 struct vmw_bo_user_rep {
54         uint32_t handle;
55         uint64_t map_handle;
56 };
57
58 struct vmw_stream {
59         struct vmw_resource res;
60         uint32_t stream_id;
61 };
62
63 struct vmw_user_stream {
64         struct ttm_base_object base;
65         struct vmw_stream stream;
66 };
67
68 static inline struct vmw_dma_buffer *
69 vmw_dma_buffer(struct ttm_buffer_object *bo)
70 {
71         return container_of(bo, struct vmw_dma_buffer, base);
72 }
73
74 static inline struct vmw_user_dma_buffer *
75 vmw_user_dma_buffer(struct ttm_buffer_object *bo)
76 {
77         struct vmw_dma_buffer *vmw_bo = vmw_dma_buffer(bo);
78         return container_of(vmw_bo, struct vmw_user_dma_buffer, dma);
79 }
80
81 struct vmw_resource *vmw_resource_reference(struct vmw_resource *res)
82 {
83         kref_get(&res->kref);
84         return res;
85 }
86
87 static void vmw_resource_release(struct kref *kref)
88 {
89         struct vmw_resource *res =
90             container_of(kref, struct vmw_resource, kref);
91         struct vmw_private *dev_priv = res->dev_priv;
92
93         idr_remove(res->idr, res->id);
94         write_unlock(&dev_priv->resource_lock);
95
96         if (likely(res->hw_destroy != NULL))
97                 res->hw_destroy(res);
98
99         if (res->res_free != NULL)
100                 res->res_free(res);
101         else
102                 kfree(res);
103
104         write_lock(&dev_priv->resource_lock);
105 }
106
107 void vmw_resource_unreference(struct vmw_resource **p_res)
108 {
109         struct vmw_resource *res = *p_res;
110         struct vmw_private *dev_priv = res->dev_priv;
111
112         *p_res = NULL;
113         write_lock(&dev_priv->resource_lock);
114         kref_put(&res->kref, vmw_resource_release);
115         write_unlock(&dev_priv->resource_lock);
116 }
117
118 static int vmw_resource_init(struct vmw_private *dev_priv,
119                              struct vmw_resource *res,
120                              struct idr *idr,
121                              enum ttm_object_type obj_type,
122                              void (*res_free) (struct vmw_resource *res))
123 {
124         int ret;
125
126         kref_init(&res->kref);
127         res->hw_destroy = NULL;
128         res->res_free = res_free;
129         res->res_type = obj_type;
130         res->idr = idr;
131         res->avail = false;
132         res->dev_priv = dev_priv;
133
134         do {
135                 if (unlikely(idr_pre_get(idr, GFP_KERNEL) == 0))
136                         return -ENOMEM;
137
138                 write_lock(&dev_priv->resource_lock);
139                 ret = idr_get_new_above(idr, res, 1, &res->id);
140                 write_unlock(&dev_priv->resource_lock);
141
142         } while (ret == -EAGAIN);
143
144         return ret;
145 }
146
147 /**
148  * vmw_resource_activate
149  *
150  * @res:        Pointer to the newly created resource
151  * @hw_destroy: Destroy function. NULL if none.
152  *
153  * Activate a resource after the hardware has been made aware of it.
154  * Set tye destroy function to @destroy. Typically this frees the
155  * resource and destroys the hardware resources associated with it.
156  * Activate basically means that the function vmw_resource_lookup will
157  * find it.
158  */
159
160 static void vmw_resource_activate(struct vmw_resource *res,
161                                   void (*hw_destroy) (struct vmw_resource *))
162 {
163         struct vmw_private *dev_priv = res->dev_priv;
164
165         write_lock(&dev_priv->resource_lock);
166         res->avail = true;
167         res->hw_destroy = hw_destroy;
168         write_unlock(&dev_priv->resource_lock);
169 }
170
171 struct vmw_resource *vmw_resource_lookup(struct vmw_private *dev_priv,
172                                          struct idr *idr, int id)
173 {
174         struct vmw_resource *res;
175
176         read_lock(&dev_priv->resource_lock);
177         res = idr_find(idr, id);
178         if (res && res->avail)
179                 kref_get(&res->kref);
180         else
181                 res = NULL;
182         read_unlock(&dev_priv->resource_lock);
183
184         if (unlikely(res == NULL))
185                 return NULL;
186
187         return res;
188 }
189
190 /**
191  * Context management:
192  */
193
194 static void vmw_hw_context_destroy(struct vmw_resource *res)
195 {
196
197         struct vmw_private *dev_priv = res->dev_priv;
198         struct {
199                 SVGA3dCmdHeader header;
200                 SVGA3dCmdDestroyContext body;
201         } *cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
202
203         if (unlikely(cmd == NULL)) {
204                 DRM_ERROR("Failed reserving FIFO space for surface "
205                           "destruction.\n");
206                 return;
207         }
208
209         cmd->header.id = cpu_to_le32(SVGA_3D_CMD_CONTEXT_DESTROY);
210         cmd->header.size = cpu_to_le32(sizeof(cmd->body));
211         cmd->body.cid = cpu_to_le32(res->id);
212
213         vmw_fifo_commit(dev_priv, sizeof(*cmd));
214         vmw_3d_resource_dec(dev_priv);
215 }
216
217 static int vmw_context_init(struct vmw_private *dev_priv,
218                             struct vmw_resource *res,
219                             void (*res_free) (struct vmw_resource *res))
220 {
221         int ret;
222
223         struct {
224                 SVGA3dCmdHeader header;
225                 SVGA3dCmdDefineContext body;
226         } *cmd;
227
228         ret = vmw_resource_init(dev_priv, res, &dev_priv->context_idr,
229                                 VMW_RES_CONTEXT, res_free);
230
231         if (unlikely(ret != 0)) {
232                 if (res_free == NULL)
233                         kfree(res);
234                 else
235                         res_free(res);
236                 return ret;
237         }
238
239         cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
240         if (unlikely(cmd == NULL)) {
241                 DRM_ERROR("Fifo reserve failed.\n");
242                 vmw_resource_unreference(&res);
243                 return -ENOMEM;
244         }
245
246         cmd->header.id = cpu_to_le32(SVGA_3D_CMD_CONTEXT_DEFINE);
247         cmd->header.size = cpu_to_le32(sizeof(cmd->body));
248         cmd->body.cid = cpu_to_le32(res->id);
249
250         vmw_fifo_commit(dev_priv, sizeof(*cmd));
251         (void) vmw_3d_resource_inc(dev_priv);
252         vmw_resource_activate(res, vmw_hw_context_destroy);
253         return 0;
254 }
255
256 struct vmw_resource *vmw_context_alloc(struct vmw_private *dev_priv)
257 {
258         struct vmw_resource *res = kmalloc(sizeof(*res), GFP_KERNEL);
259         int ret;
260
261         if (unlikely(res == NULL))
262                 return NULL;
263
264         ret = vmw_context_init(dev_priv, res, NULL);
265         return (ret == 0) ? res : NULL;
266 }
267
268 /**
269  * User-space context management:
270  */
271
272 static void vmw_user_context_free(struct vmw_resource *res)
273 {
274         struct vmw_user_context *ctx =
275             container_of(res, struct vmw_user_context, res);
276
277         kfree(ctx);
278 }
279
280 /**
281  * This function is called when user space has no more references on the
282  * base object. It releases the base-object's reference on the resource object.
283  */
284
285 static void vmw_user_context_base_release(struct ttm_base_object **p_base)
286 {
287         struct ttm_base_object *base = *p_base;
288         struct vmw_user_context *ctx =
289             container_of(base, struct vmw_user_context, base);
290         struct vmw_resource *res = &ctx->res;
291
292         *p_base = NULL;
293         vmw_resource_unreference(&res);
294 }
295
296 int vmw_context_destroy_ioctl(struct drm_device *dev, void *data,
297                               struct drm_file *file_priv)
298 {
299         struct vmw_private *dev_priv = vmw_priv(dev);
300         struct vmw_resource *res;
301         struct vmw_user_context *ctx;
302         struct drm_vmw_context_arg *arg = (struct drm_vmw_context_arg *)data;
303         struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
304         int ret = 0;
305
306         res = vmw_resource_lookup(dev_priv, &dev_priv->context_idr, arg->cid);
307         if (unlikely(res == NULL))
308                 return -EINVAL;
309
310         if (res->res_free != &vmw_user_context_free) {
311                 ret = -EINVAL;
312                 goto out;
313         }
314
315         ctx = container_of(res, struct vmw_user_context, res);
316         if (ctx->base.tfile != tfile && !ctx->base.shareable) {
317                 ret = -EPERM;
318                 goto out;
319         }
320
321         ttm_ref_object_base_unref(tfile, ctx->base.hash.key, TTM_REF_USAGE);
322 out:
323         vmw_resource_unreference(&res);
324         return ret;
325 }
326
327 int vmw_context_define_ioctl(struct drm_device *dev, void *data,
328                              struct drm_file *file_priv)
329 {
330         struct vmw_private *dev_priv = vmw_priv(dev);
331         struct vmw_user_context *ctx = kmalloc(sizeof(*ctx), GFP_KERNEL);
332         struct vmw_resource *res;
333         struct vmw_resource *tmp;
334         struct drm_vmw_context_arg *arg = (struct drm_vmw_context_arg *)data;
335         struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
336         int ret;
337
338         if (unlikely(ctx == NULL))
339                 return -ENOMEM;
340
341         res = &ctx->res;
342         ctx->base.shareable = false;
343         ctx->base.tfile = NULL;
344
345         ret = vmw_context_init(dev_priv, res, vmw_user_context_free);
346         if (unlikely(ret != 0))
347                 return ret;
348
349         tmp = vmw_resource_reference(&ctx->res);
350         ret = ttm_base_object_init(tfile, &ctx->base, false, VMW_RES_CONTEXT,
351                                    &vmw_user_context_base_release, NULL);
352
353         if (unlikely(ret != 0)) {
354                 vmw_resource_unreference(&tmp);
355                 goto out_err;
356         }
357
358         arg->cid = res->id;
359 out_err:
360         vmw_resource_unreference(&res);
361         return ret;
362
363 }
364
365 int vmw_context_check(struct vmw_private *dev_priv,
366                       struct ttm_object_file *tfile,
367                       int id)
368 {
369         struct vmw_resource *res;
370         int ret = 0;
371
372         read_lock(&dev_priv->resource_lock);
373         res = idr_find(&dev_priv->context_idr, id);
374         if (res && res->avail) {
375                 struct vmw_user_context *ctx =
376                         container_of(res, struct vmw_user_context, res);
377                 if (ctx->base.tfile != tfile && !ctx->base.shareable)
378                         ret = -EPERM;
379         } else
380                 ret = -EINVAL;
381         read_unlock(&dev_priv->resource_lock);
382
383         return ret;
384 }
385
386
387 /**
388  * Surface management.
389  */
390
391 static void vmw_hw_surface_destroy(struct vmw_resource *res)
392 {
393
394         struct vmw_private *dev_priv = res->dev_priv;
395         struct {
396                 SVGA3dCmdHeader header;
397                 SVGA3dCmdDestroySurface body;
398         } *cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
399
400         if (unlikely(cmd == NULL)) {
401                 DRM_ERROR("Failed reserving FIFO space for surface "
402                           "destruction.\n");
403                 return;
404         }
405
406         cmd->header.id = cpu_to_le32(SVGA_3D_CMD_SURFACE_DESTROY);
407         cmd->header.size = cpu_to_le32(sizeof(cmd->body));
408         cmd->body.sid = cpu_to_le32(res->id);
409
410         vmw_fifo_commit(dev_priv, sizeof(*cmd));
411         vmw_3d_resource_dec(dev_priv);
412 }
413
414 void vmw_surface_res_free(struct vmw_resource *res)
415 {
416         struct vmw_surface *srf = container_of(res, struct vmw_surface, res);
417
418         kfree(srf->sizes);
419         kfree(srf->snooper.image);
420         kfree(srf);
421 }
422
423 int vmw_surface_init(struct vmw_private *dev_priv,
424                      struct vmw_surface *srf,
425                      void (*res_free) (struct vmw_resource *res))
426 {
427         int ret;
428         struct {
429                 SVGA3dCmdHeader header;
430                 SVGA3dCmdDefineSurface body;
431         } *cmd;
432         SVGA3dSize *cmd_size;
433         struct vmw_resource *res = &srf->res;
434         struct drm_vmw_size *src_size;
435         size_t submit_size;
436         uint32_t cmd_len;
437         int i;
438
439         BUG_ON(res_free == NULL);
440         ret = vmw_resource_init(dev_priv, res, &dev_priv->surface_idr,
441                                 VMW_RES_SURFACE, res_free);
442
443         if (unlikely(ret != 0)) {
444                 res_free(res);
445                 return ret;
446         }
447
448         submit_size = sizeof(*cmd) + srf->num_sizes * sizeof(SVGA3dSize);
449         cmd_len = sizeof(cmd->body) + srf->num_sizes * sizeof(SVGA3dSize);
450
451         cmd = vmw_fifo_reserve(dev_priv, submit_size);
452         if (unlikely(cmd == NULL)) {
453                 DRM_ERROR("Fifo reserve failed for create surface.\n");
454                 vmw_resource_unreference(&res);
455                 return -ENOMEM;
456         }
457
458         cmd->header.id = cpu_to_le32(SVGA_3D_CMD_SURFACE_DEFINE);
459         cmd->header.size = cpu_to_le32(cmd_len);
460         cmd->body.sid = cpu_to_le32(res->id);
461         cmd->body.surfaceFlags = cpu_to_le32(srf->flags);
462         cmd->body.format = cpu_to_le32(srf->format);
463         for (i = 0; i < DRM_VMW_MAX_SURFACE_FACES; ++i) {
464                 cmd->body.face[i].numMipLevels =
465                     cpu_to_le32(srf->mip_levels[i]);
466         }
467
468         cmd += 1;
469         cmd_size = (SVGA3dSize *) cmd;
470         src_size = srf->sizes;
471
472         for (i = 0; i < srf->num_sizes; ++i, cmd_size++, src_size++) {
473                 cmd_size->width = cpu_to_le32(src_size->width);
474                 cmd_size->height = cpu_to_le32(src_size->height);
475                 cmd_size->depth = cpu_to_le32(src_size->depth);
476         }
477
478         vmw_fifo_commit(dev_priv, submit_size);
479         (void) vmw_3d_resource_inc(dev_priv);
480         vmw_resource_activate(res, vmw_hw_surface_destroy);
481         return 0;
482 }
483
484 static void vmw_user_surface_free(struct vmw_resource *res)
485 {
486         struct vmw_surface *srf = container_of(res, struct vmw_surface, res);
487         struct vmw_user_surface *user_srf =
488             container_of(srf, struct vmw_user_surface, srf);
489
490         kfree(srf->sizes);
491         kfree(srf->snooper.image);
492         kfree(user_srf);
493 }
494
495 int vmw_user_surface_lookup_handle(struct vmw_private *dev_priv,
496                                    struct ttm_object_file *tfile,
497                                    uint32_t handle, struct vmw_surface **out)
498 {
499         struct vmw_resource *res;
500         struct vmw_surface *srf;
501         struct vmw_user_surface *user_srf;
502         struct ttm_base_object *base;
503         int ret = -EINVAL;
504
505         base = ttm_base_object_lookup(tfile, handle);
506         if (unlikely(base == NULL))
507                 return -EINVAL;
508
509         if (unlikely(base->object_type != VMW_RES_SURFACE))
510                 goto out_bad_resource;
511
512         user_srf = container_of(base, struct vmw_user_surface, base);
513         srf = &user_srf->srf;
514         res = &srf->res;
515
516         read_lock(&dev_priv->resource_lock);
517
518         if (!res->avail || res->res_free != &vmw_user_surface_free) {
519                 read_unlock(&dev_priv->resource_lock);
520                 goto out_bad_resource;
521         }
522
523         kref_get(&res->kref);
524         read_unlock(&dev_priv->resource_lock);
525
526         *out = srf;
527         ret = 0;
528
529 out_bad_resource:
530         ttm_base_object_unref(&base);
531
532         return ret;
533 }
534
535 static void vmw_user_surface_base_release(struct ttm_base_object **p_base)
536 {
537         struct ttm_base_object *base = *p_base;
538         struct vmw_user_surface *user_srf =
539             container_of(base, struct vmw_user_surface, base);
540         struct vmw_resource *res = &user_srf->srf.res;
541
542         *p_base = NULL;
543         vmw_resource_unreference(&res);
544 }
545
546 int vmw_surface_destroy_ioctl(struct drm_device *dev, void *data,
547                               struct drm_file *file_priv)
548 {
549         struct drm_vmw_surface_arg *arg = (struct drm_vmw_surface_arg *)data;
550         struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
551
552         return ttm_ref_object_base_unref(tfile, arg->sid, TTM_REF_USAGE);
553 }
554
555 int vmw_surface_define_ioctl(struct drm_device *dev, void *data,
556                              struct drm_file *file_priv)
557 {
558         struct vmw_private *dev_priv = vmw_priv(dev);
559         struct vmw_user_surface *user_srf =
560             kmalloc(sizeof(*user_srf), GFP_KERNEL);
561         struct vmw_surface *srf;
562         struct vmw_resource *res;
563         struct vmw_resource *tmp;
564         union drm_vmw_surface_create_arg *arg =
565             (union drm_vmw_surface_create_arg *)data;
566         struct drm_vmw_surface_create_req *req = &arg->req;
567         struct drm_vmw_surface_arg *rep = &arg->rep;
568         struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
569         struct drm_vmw_size __user *user_sizes;
570         int ret;
571         int i;
572
573         if (unlikely(user_srf == NULL))
574                 return -ENOMEM;
575
576         srf = &user_srf->srf;
577         res = &srf->res;
578
579         srf->flags = req->flags;
580         srf->format = req->format;
581         srf->scanout = req->scanout;
582         memcpy(srf->mip_levels, req->mip_levels, sizeof(srf->mip_levels));
583         srf->num_sizes = 0;
584         for (i = 0; i < DRM_VMW_MAX_SURFACE_FACES; ++i)
585                 srf->num_sizes += srf->mip_levels[i];
586
587         if (srf->num_sizes > DRM_VMW_MAX_SURFACE_FACES *
588             DRM_VMW_MAX_MIP_LEVELS) {
589                 ret = -EINVAL;
590                 goto out_err0;
591         }
592
593         srf->sizes = kmalloc(srf->num_sizes * sizeof(*srf->sizes), GFP_KERNEL);
594         if (unlikely(srf->sizes == NULL)) {
595                 ret = -ENOMEM;
596                 goto out_err0;
597         }
598
599         user_sizes = (struct drm_vmw_size __user *)(unsigned long)
600             req->size_addr;
601
602         ret = copy_from_user(srf->sizes, user_sizes,
603                              srf->num_sizes * sizeof(*srf->sizes));
604         if (unlikely(ret != 0)) {
605                 ret = -EFAULT;
606                 goto out_err1;
607         }
608
609         if (srf->scanout &&
610             srf->num_sizes == 1 &&
611             srf->sizes[0].width == 64 &&
612             srf->sizes[0].height == 64 &&
613             srf->format == SVGA3D_A8R8G8B8) {
614
615                 srf->snooper.image = kmalloc(64 * 64 * 4, GFP_KERNEL);
616                 /* clear the image */
617                 if (srf->snooper.image) {
618                         memset(srf->snooper.image, 0x00, 64 * 64 * 4);
619                 } else {
620                         DRM_ERROR("Failed to allocate cursor_image\n");
621                         ret = -ENOMEM;
622                         goto out_err1;
623                 }
624         } else {
625                 srf->snooper.image = NULL;
626         }
627         srf->snooper.crtc = NULL;
628
629         user_srf->base.shareable = false;
630         user_srf->base.tfile = NULL;
631
632         /**
633          * From this point, the generic resource management functions
634          * destroy the object on failure.
635          */
636
637         ret = vmw_surface_init(dev_priv, srf, vmw_user_surface_free);
638         if (unlikely(ret != 0))
639                 return ret;
640
641         tmp = vmw_resource_reference(&srf->res);
642         ret = ttm_base_object_init(tfile, &user_srf->base,
643                                    req->shareable, VMW_RES_SURFACE,
644                                    &vmw_user_surface_base_release, NULL);
645
646         if (unlikely(ret != 0)) {
647                 vmw_resource_unreference(&tmp);
648                 vmw_resource_unreference(&res);
649                 return ret;
650         }
651
652         rep->sid = user_srf->base.hash.key;
653         if (rep->sid == SVGA3D_INVALID_ID)
654                 DRM_ERROR("Created bad Surface ID.\n");
655
656         vmw_resource_unreference(&res);
657         return 0;
658 out_err1:
659         kfree(srf->sizes);
660 out_err0:
661         kfree(user_srf);
662         return ret;
663 }
664
665 int vmw_surface_reference_ioctl(struct drm_device *dev, void *data,
666                                 struct drm_file *file_priv)
667 {
668         union drm_vmw_surface_reference_arg *arg =
669             (union drm_vmw_surface_reference_arg *)data;
670         struct drm_vmw_surface_arg *req = &arg->req;
671         struct drm_vmw_surface_create_req *rep = &arg->rep;
672         struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
673         struct vmw_surface *srf;
674         struct vmw_user_surface *user_srf;
675         struct drm_vmw_size __user *user_sizes;
676         struct ttm_base_object *base;
677         int ret = -EINVAL;
678
679         base = ttm_base_object_lookup(tfile, req->sid);
680         if (unlikely(base == NULL)) {
681                 DRM_ERROR("Could not find surface to reference.\n");
682                 return -EINVAL;
683         }
684
685         if (unlikely(base->object_type != VMW_RES_SURFACE))
686                 goto out_bad_resource;
687
688         user_srf = container_of(base, struct vmw_user_surface, base);
689         srf = &user_srf->srf;
690
691         ret = ttm_ref_object_add(tfile, &user_srf->base, TTM_REF_USAGE, NULL);
692         if (unlikely(ret != 0)) {
693                 DRM_ERROR("Could not add a reference to a surface.\n");
694                 goto out_no_reference;
695         }
696
697         rep->flags = srf->flags;
698         rep->format = srf->format;
699         memcpy(rep->mip_levels, srf->mip_levels, sizeof(srf->mip_levels));
700         user_sizes = (struct drm_vmw_size __user *)(unsigned long)
701             rep->size_addr;
702
703         if (user_sizes)
704                 ret = copy_to_user(user_sizes, srf->sizes,
705                                    srf->num_sizes * sizeof(*srf->sizes));
706         if (unlikely(ret != 0)) {
707                 DRM_ERROR("copy_to_user failed %p %u\n",
708                           user_sizes, srf->num_sizes);
709                 ret = -EFAULT;
710         }
711 out_bad_resource:
712 out_no_reference:
713         ttm_base_object_unref(&base);
714
715         return ret;
716 }
717
718 int vmw_surface_check(struct vmw_private *dev_priv,
719                       struct ttm_object_file *tfile,
720                       uint32_t handle, int *id)
721 {
722         struct ttm_base_object *base;
723         struct vmw_user_surface *user_srf;
724
725         int ret = -EPERM;
726
727         base = ttm_base_object_lookup(tfile, handle);
728         if (unlikely(base == NULL))
729                 return -EINVAL;
730
731         if (unlikely(base->object_type != VMW_RES_SURFACE))
732                 goto out_bad_surface;
733
734         user_srf = container_of(base, struct vmw_user_surface, base);
735         *id = user_srf->srf.res.id;
736         ret = 0;
737
738 out_bad_surface:
739         /**
740          * FIXME: May deadlock here when called from the
741          * command parsing code.
742          */
743
744         ttm_base_object_unref(&base);
745         return ret;
746 }
747
748 /**
749  * Buffer management.
750  */
751
752 static size_t vmw_dmabuf_acc_size(struct ttm_bo_global *glob,
753                                   unsigned long num_pages)
754 {
755         static size_t bo_user_size = ~0;
756
757         size_t page_array_size =
758             (num_pages * sizeof(void *) + PAGE_SIZE - 1) & PAGE_MASK;
759
760         if (unlikely(bo_user_size == ~0)) {
761                 bo_user_size = glob->ttm_bo_extra_size +
762                     ttm_round_pot(sizeof(struct vmw_dma_buffer));
763         }
764
765         return bo_user_size + page_array_size;
766 }
767
768 void vmw_dmabuf_gmr_unbind(struct ttm_buffer_object *bo)
769 {
770         struct vmw_dma_buffer *vmw_bo = vmw_dma_buffer(bo);
771         struct ttm_bo_global *glob = bo->glob;
772         struct vmw_private *dev_priv =
773                 container_of(bo->bdev, struct vmw_private, bdev);
774
775         if (vmw_bo->gmr_bound) {
776                 vmw_gmr_unbind(dev_priv, vmw_bo->gmr_id);
777                 spin_lock(&glob->lru_lock);
778                 ida_remove(&dev_priv->gmr_ida, vmw_bo->gmr_id);
779                 spin_unlock(&glob->lru_lock);
780                 vmw_bo->gmr_bound = false;
781         }
782 }
783
784 void vmw_dmabuf_bo_free(struct ttm_buffer_object *bo)
785 {
786         struct vmw_dma_buffer *vmw_bo = vmw_dma_buffer(bo);
787         struct ttm_bo_global *glob = bo->glob;
788
789         vmw_dmabuf_gmr_unbind(bo);
790         ttm_mem_global_free(glob->mem_glob, bo->acc_size);
791         kfree(vmw_bo);
792 }
793
794 int vmw_dmabuf_init(struct vmw_private *dev_priv,
795                     struct vmw_dma_buffer *vmw_bo,
796                     size_t size, struct ttm_placement *placement,
797                     bool interruptible,
798                     void (*bo_free) (struct ttm_buffer_object *bo))
799 {
800         struct ttm_bo_device *bdev = &dev_priv->bdev;
801         struct ttm_mem_global *mem_glob = bdev->glob->mem_glob;
802         size_t acc_size;
803         int ret;
804
805         BUG_ON(!bo_free);
806
807         acc_size =
808             vmw_dmabuf_acc_size(bdev->glob,
809                                 (size + PAGE_SIZE - 1) >> PAGE_SHIFT);
810
811         ret = ttm_mem_global_alloc(mem_glob, acc_size, false, false);
812         if (unlikely(ret != 0)) {
813                 /* we must free the bo here as
814                  * ttm_buffer_object_init does so as well */
815                 bo_free(&vmw_bo->base);
816                 return ret;
817         }
818
819         memset(vmw_bo, 0, sizeof(*vmw_bo));
820
821         INIT_LIST_HEAD(&vmw_bo->gmr_lru);
822         INIT_LIST_HEAD(&vmw_bo->validate_list);
823         vmw_bo->gmr_id = 0;
824         vmw_bo->gmr_bound = false;
825
826         ret = ttm_bo_init(bdev, &vmw_bo->base, size,
827                           ttm_bo_type_device, placement,
828                           0, 0, interruptible,
829                           NULL, acc_size, bo_free);
830         return ret;
831 }
832
833 static void vmw_user_dmabuf_destroy(struct ttm_buffer_object *bo)
834 {
835         struct vmw_user_dma_buffer *vmw_user_bo = vmw_user_dma_buffer(bo);
836         struct ttm_bo_global *glob = bo->glob;
837
838         vmw_dmabuf_gmr_unbind(bo);
839         ttm_mem_global_free(glob->mem_glob, bo->acc_size);
840         kfree(vmw_user_bo);
841 }
842
843 static void vmw_user_dmabuf_release(struct ttm_base_object **p_base)
844 {
845         struct vmw_user_dma_buffer *vmw_user_bo;
846         struct ttm_base_object *base = *p_base;
847         struct ttm_buffer_object *bo;
848
849         *p_base = NULL;
850
851         if (unlikely(base == NULL))
852                 return;
853
854         vmw_user_bo = container_of(base, struct vmw_user_dma_buffer, base);
855         bo = &vmw_user_bo->dma.base;
856         ttm_bo_unref(&bo);
857 }
858
859 int vmw_dmabuf_alloc_ioctl(struct drm_device *dev, void *data,
860                            struct drm_file *file_priv)
861 {
862         struct vmw_private *dev_priv = vmw_priv(dev);
863         union drm_vmw_alloc_dmabuf_arg *arg =
864             (union drm_vmw_alloc_dmabuf_arg *)data;
865         struct drm_vmw_alloc_dmabuf_req *req = &arg->req;
866         struct drm_vmw_dmabuf_rep *rep = &arg->rep;
867         struct vmw_user_dma_buffer *vmw_user_bo;
868         struct ttm_buffer_object *tmp;
869         struct vmw_master *vmaster = vmw_master(file_priv->master);
870         int ret;
871
872         vmw_user_bo = kzalloc(sizeof(*vmw_user_bo), GFP_KERNEL);
873         if (unlikely(vmw_user_bo == NULL))
874                 return -ENOMEM;
875
876         ret = ttm_read_lock(&vmaster->lock, true);
877         if (unlikely(ret != 0)) {
878                 kfree(vmw_user_bo);
879                 return ret;
880         }
881
882         ret = vmw_dmabuf_init(dev_priv, &vmw_user_bo->dma, req->size,
883                               &vmw_vram_sys_placement, true,
884                               &vmw_user_dmabuf_destroy);
885         if (unlikely(ret != 0))
886                 return ret;
887
888         tmp = ttm_bo_reference(&vmw_user_bo->dma.base);
889         ret = ttm_base_object_init(vmw_fpriv(file_priv)->tfile,
890                                    &vmw_user_bo->base,
891                                    false,
892                                    ttm_buffer_type,
893                                    &vmw_user_dmabuf_release, NULL);
894         if (unlikely(ret != 0)) {
895                 ttm_bo_unref(&tmp);
896         } else {
897                 rep->handle = vmw_user_bo->base.hash.key;
898                 rep->map_handle = vmw_user_bo->dma.base.addr_space_offset;
899                 rep->cur_gmr_id = vmw_user_bo->base.hash.key;
900                 rep->cur_gmr_offset = 0;
901         }
902         ttm_bo_unref(&tmp);
903
904         ttm_read_unlock(&vmaster->lock);
905
906         return 0;
907 }
908
909 int vmw_dmabuf_unref_ioctl(struct drm_device *dev, void *data,
910                            struct drm_file *file_priv)
911 {
912         struct drm_vmw_unref_dmabuf_arg *arg =
913             (struct drm_vmw_unref_dmabuf_arg *)data;
914
915         return ttm_ref_object_base_unref(vmw_fpriv(file_priv)->tfile,
916                                          arg->handle,
917                                          TTM_REF_USAGE);
918 }
919
920 uint32_t vmw_dmabuf_validate_node(struct ttm_buffer_object *bo,
921                                   uint32_t cur_validate_node)
922 {
923         struct vmw_dma_buffer *vmw_bo = vmw_dma_buffer(bo);
924
925         if (likely(vmw_bo->on_validate_list))
926                 return vmw_bo->cur_validate_node;
927
928         vmw_bo->cur_validate_node = cur_validate_node;
929         vmw_bo->on_validate_list = true;
930
931         return cur_validate_node;
932 }
933
934 void vmw_dmabuf_validate_clear(struct ttm_buffer_object *bo)
935 {
936         struct vmw_dma_buffer *vmw_bo = vmw_dma_buffer(bo);
937
938         vmw_bo->on_validate_list = false;
939 }
940
941 uint32_t vmw_dmabuf_gmr(struct ttm_buffer_object *bo)
942 {
943         struct vmw_dma_buffer *vmw_bo;
944
945         if (bo->mem.mem_type == TTM_PL_VRAM)
946                 return SVGA_GMR_FRAMEBUFFER;
947
948         vmw_bo = vmw_dma_buffer(bo);
949
950         return (vmw_bo->gmr_bound) ? vmw_bo->gmr_id : SVGA_GMR_NULL;
951 }
952
953 void vmw_dmabuf_set_gmr(struct ttm_buffer_object *bo, uint32_t id)
954 {
955         struct vmw_dma_buffer *vmw_bo = vmw_dma_buffer(bo);
956         vmw_bo->gmr_bound = true;
957         vmw_bo->gmr_id = id;
958 }
959
960 int vmw_user_dmabuf_lookup(struct ttm_object_file *tfile,
961                            uint32_t handle, struct vmw_dma_buffer **out)
962 {
963         struct vmw_user_dma_buffer *vmw_user_bo;
964         struct ttm_base_object *base;
965
966         base = ttm_base_object_lookup(tfile, handle);
967         if (unlikely(base == NULL)) {
968                 printk(KERN_ERR "Invalid buffer object handle 0x%08lx.\n",
969                        (unsigned long)handle);
970                 return -ESRCH;
971         }
972
973         if (unlikely(base->object_type != ttm_buffer_type)) {
974                 ttm_base_object_unref(&base);
975                 printk(KERN_ERR "Invalid buffer object handle 0x%08lx.\n",
976                        (unsigned long)handle);
977                 return -EINVAL;
978         }
979
980         vmw_user_bo = container_of(base, struct vmw_user_dma_buffer, base);
981         (void)ttm_bo_reference(&vmw_user_bo->dma.base);
982         ttm_base_object_unref(&base);
983         *out = &vmw_user_bo->dma;
984
985         return 0;
986 }
987
988 /**
989  * TODO: Implement a gmr id eviction mechanism. Currently we just fail
990  * when we're out of ids, causing GMR space to be allocated
991  * out of VRAM.
992  */
993
994 int vmw_gmr_id_alloc(struct vmw_private *dev_priv, uint32_t *p_id)
995 {
996         struct ttm_bo_global *glob = dev_priv->bdev.glob;
997         int id;
998         int ret;
999
1000         do {
1001                 if (unlikely(ida_pre_get(&dev_priv->gmr_ida, GFP_KERNEL) == 0))
1002                         return -ENOMEM;
1003
1004                 spin_lock(&glob->lru_lock);
1005                 ret = ida_get_new(&dev_priv->gmr_ida, &id);
1006                 spin_unlock(&glob->lru_lock);
1007         } while (ret == -EAGAIN);
1008
1009         if (unlikely(ret != 0))
1010                 return ret;
1011
1012         if (unlikely(id >= dev_priv->max_gmr_ids)) {
1013                 spin_lock(&glob->lru_lock);
1014                 ida_remove(&dev_priv->gmr_ida, id);
1015                 spin_unlock(&glob->lru_lock);
1016                 return -EBUSY;
1017         }
1018
1019         *p_id = (uint32_t) id;
1020         return 0;
1021 }
1022
1023 /*
1024  * Stream management
1025  */
1026
1027 static void vmw_stream_destroy(struct vmw_resource *res)
1028 {
1029         struct vmw_private *dev_priv = res->dev_priv;
1030         struct vmw_stream *stream;
1031         int ret;
1032
1033         DRM_INFO("%s: unref\n", __func__);
1034         stream = container_of(res, struct vmw_stream, res);
1035
1036         ret = vmw_overlay_unref(dev_priv, stream->stream_id);
1037         WARN_ON(ret != 0);
1038 }
1039
1040 static int vmw_stream_init(struct vmw_private *dev_priv,
1041                            struct vmw_stream *stream,
1042                            void (*res_free) (struct vmw_resource *res))
1043 {
1044         struct vmw_resource *res = &stream->res;
1045         int ret;
1046
1047         ret = vmw_resource_init(dev_priv, res, &dev_priv->stream_idr,
1048                                 VMW_RES_STREAM, res_free);
1049
1050         if (unlikely(ret != 0)) {
1051                 if (res_free == NULL)
1052                         kfree(stream);
1053                 else
1054                         res_free(&stream->res);
1055                 return ret;
1056         }
1057
1058         ret = vmw_overlay_claim(dev_priv, &stream->stream_id);
1059         if (ret) {
1060                 vmw_resource_unreference(&res);
1061                 return ret;
1062         }
1063
1064         DRM_INFO("%s: claimed\n", __func__);
1065
1066         vmw_resource_activate(&stream->res, vmw_stream_destroy);
1067         return 0;
1068 }
1069
1070 /**
1071  * User-space context management:
1072  */
1073
1074 static void vmw_user_stream_free(struct vmw_resource *res)
1075 {
1076         struct vmw_user_stream *stream =
1077             container_of(res, struct vmw_user_stream, stream.res);
1078
1079         kfree(stream);
1080 }
1081
1082 /**
1083  * This function is called when user space has no more references on the
1084  * base object. It releases the base-object's reference on the resource object.
1085  */
1086
1087 static void vmw_user_stream_base_release(struct ttm_base_object **p_base)
1088 {
1089         struct ttm_base_object *base = *p_base;
1090         struct vmw_user_stream *stream =
1091             container_of(base, struct vmw_user_stream, base);
1092         struct vmw_resource *res = &stream->stream.res;
1093
1094         *p_base = NULL;
1095         vmw_resource_unreference(&res);
1096 }
1097
1098 int vmw_stream_unref_ioctl(struct drm_device *dev, void *data,
1099                            struct drm_file *file_priv)
1100 {
1101         struct vmw_private *dev_priv = vmw_priv(dev);
1102         struct vmw_resource *res;
1103         struct vmw_user_stream *stream;
1104         struct drm_vmw_stream_arg *arg = (struct drm_vmw_stream_arg *)data;
1105         struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
1106         int ret = 0;
1107
1108         res = vmw_resource_lookup(dev_priv, &dev_priv->stream_idr, arg->stream_id);
1109         if (unlikely(res == NULL))
1110                 return -EINVAL;
1111
1112         if (res->res_free != &vmw_user_stream_free) {
1113                 ret = -EINVAL;
1114                 goto out;
1115         }
1116
1117         stream = container_of(res, struct vmw_user_stream, stream.res);
1118         if (stream->base.tfile != tfile) {
1119                 ret = -EINVAL;
1120                 goto out;
1121         }
1122
1123         ttm_ref_object_base_unref(tfile, stream->base.hash.key, TTM_REF_USAGE);
1124 out:
1125         vmw_resource_unreference(&res);
1126         return ret;
1127 }
1128
1129 int vmw_stream_claim_ioctl(struct drm_device *dev, void *data,
1130                            struct drm_file *file_priv)
1131 {
1132         struct vmw_private *dev_priv = vmw_priv(dev);
1133         struct vmw_user_stream *stream = kmalloc(sizeof(*stream), GFP_KERNEL);
1134         struct vmw_resource *res;
1135         struct vmw_resource *tmp;
1136         struct drm_vmw_stream_arg *arg = (struct drm_vmw_stream_arg *)data;
1137         struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
1138         int ret;
1139
1140         if (unlikely(stream == NULL))
1141                 return -ENOMEM;
1142
1143         res = &stream->stream.res;
1144         stream->base.shareable = false;
1145         stream->base.tfile = NULL;
1146
1147         ret = vmw_stream_init(dev_priv, &stream->stream, vmw_user_stream_free);
1148         if (unlikely(ret != 0))
1149                 return ret;
1150
1151         tmp = vmw_resource_reference(res);
1152         ret = ttm_base_object_init(tfile, &stream->base, false, VMW_RES_STREAM,
1153                                    &vmw_user_stream_base_release, NULL);
1154
1155         if (unlikely(ret != 0)) {
1156                 vmw_resource_unreference(&tmp);
1157                 goto out_err;
1158         }
1159
1160         arg->stream_id = res->id;
1161 out_err:
1162         vmw_resource_unreference(&res);
1163         return ret;
1164 }
1165
1166 int vmw_user_stream_lookup(struct vmw_private *dev_priv,
1167                            struct ttm_object_file *tfile,
1168                            uint32_t *inout_id, struct vmw_resource **out)
1169 {
1170         struct vmw_user_stream *stream;
1171         struct vmw_resource *res;
1172         int ret;
1173
1174         res = vmw_resource_lookup(dev_priv, &dev_priv->stream_idr, *inout_id);
1175         if (unlikely(res == NULL))
1176                 return -EINVAL;
1177
1178         if (res->res_free != &vmw_user_stream_free) {
1179                 ret = -EINVAL;
1180                 goto err_ref;
1181         }
1182
1183         stream = container_of(res, struct vmw_user_stream, stream.res);
1184         if (stream->base.tfile != tfile) {
1185                 ret = -EPERM;
1186                 goto err_ref;
1187         }
1188
1189         *inout_id = stream->stream.stream_id;
1190         *out = res;
1191         return 0;
1192 err_ref:
1193         vmw_resource_unreference(&res);
1194         return ret;
1195 }