Merge branch 'clockevents/fixes' of git://git.linaro.org/people/daniel.lezcano/linux...
[linux-drm-fsl-dcu.git] / drivers / gpu / drm / vmwgfx / vmwgfx_surface.c
1 /**************************************************************************
2  *
3  * Copyright © 2009-2012 VMware, Inc., Palo Alto, CA., USA
4  * All Rights Reserved.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the
8  * "Software"), to deal in the Software without restriction, including
9  * without limitation the rights to use, copy, modify, merge, publish,
10  * distribute, sub license, and/or sell copies of the Software, and to
11  * permit persons to whom the Software is furnished to do so, subject to
12  * the following conditions:
13  *
14  * The above copyright notice and this permission notice (including the
15  * next paragraph) shall be included in all copies or substantial portions
16  * of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
21  * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
22  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
23  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
24  * USE OR OTHER DEALINGS IN THE SOFTWARE.
25  *
26  **************************************************************************/
27
28 #include "vmwgfx_drv.h"
29 #include "vmwgfx_resource_priv.h"
30 #include <ttm/ttm_placement.h>
31 #include "svga3d_surfacedefs.h"
32
33 /**
34  * struct vmw_user_surface - User-space visible surface resource
35  *
36  * @base:           The TTM base object handling user-space visibility.
37  * @srf:            The surface metadata.
38  * @size:           TTM accounting size for the surface.
39  */
40 struct vmw_user_surface {
41         struct ttm_prime_object prime;
42         struct vmw_surface srf;
43         uint32_t size;
44         uint32_t backup_handle;
45 };
46
47 /**
48  * struct vmw_surface_offset - Backing store mip level offset info
49  *
50  * @face:           Surface face.
51  * @mip:            Mip level.
52  * @bo_offset:      Offset into backing store of this mip level.
53  *
54  */
55 struct vmw_surface_offset {
56         uint32_t face;
57         uint32_t mip;
58         uint32_t bo_offset;
59 };
60
61 static void vmw_user_surface_free(struct vmw_resource *res);
62 static struct vmw_resource *
63 vmw_user_surface_base_to_res(struct ttm_base_object *base);
64 static int vmw_legacy_srf_bind(struct vmw_resource *res,
65                                struct ttm_validate_buffer *val_buf);
66 static int vmw_legacy_srf_unbind(struct vmw_resource *res,
67                                  bool readback,
68                                  struct ttm_validate_buffer *val_buf);
69 static int vmw_legacy_srf_create(struct vmw_resource *res);
70 static int vmw_legacy_srf_destroy(struct vmw_resource *res);
71
72 static const struct vmw_user_resource_conv user_surface_conv = {
73         .object_type = VMW_RES_SURFACE,
74         .base_obj_to_res = vmw_user_surface_base_to_res,
75         .res_free = vmw_user_surface_free
76 };
77
78 const struct vmw_user_resource_conv *user_surface_converter =
79         &user_surface_conv;
80
81
82 static uint64_t vmw_user_surface_size;
83
84 static const struct vmw_res_func vmw_legacy_surface_func = {
85         .res_type = vmw_res_surface,
86         .needs_backup = false,
87         .may_evict = true,
88         .type_name = "legacy surfaces",
89         .backup_placement = &vmw_srf_placement,
90         .create = &vmw_legacy_srf_create,
91         .destroy = &vmw_legacy_srf_destroy,
92         .bind = &vmw_legacy_srf_bind,
93         .unbind = &vmw_legacy_srf_unbind
94 };
95
96 /**
97  * struct vmw_surface_dma - SVGA3D DMA command
98  */
99 struct vmw_surface_dma {
100         SVGA3dCmdHeader header;
101         SVGA3dCmdSurfaceDMA body;
102         SVGA3dCopyBox cb;
103         SVGA3dCmdSurfaceDMASuffix suffix;
104 };
105
106 /**
107  * struct vmw_surface_define - SVGA3D Surface Define command
108  */
109 struct vmw_surface_define {
110         SVGA3dCmdHeader header;
111         SVGA3dCmdDefineSurface body;
112 };
113
114 /**
115  * struct vmw_surface_destroy - SVGA3D Surface Destroy command
116  */
117 struct vmw_surface_destroy {
118         SVGA3dCmdHeader header;
119         SVGA3dCmdDestroySurface body;
120 };
121
122
123 /**
124  * vmw_surface_dma_size - Compute fifo size for a dma command.
125  *
126  * @srf: Pointer to a struct vmw_surface
127  *
128  * Computes the required size for a surface dma command for backup or
129  * restoration of the surface represented by @srf.
130  */
131 static inline uint32_t vmw_surface_dma_size(const struct vmw_surface *srf)
132 {
133         return srf->num_sizes * sizeof(struct vmw_surface_dma);
134 }
135
136
137 /**
138  * vmw_surface_define_size - Compute fifo size for a surface define command.
139  *
140  * @srf: Pointer to a struct vmw_surface
141  *
142  * Computes the required size for a surface define command for the definition
143  * of the surface represented by @srf.
144  */
145 static inline uint32_t vmw_surface_define_size(const struct vmw_surface *srf)
146 {
147         return sizeof(struct vmw_surface_define) + srf->num_sizes *
148                 sizeof(SVGA3dSize);
149 }
150
151
152 /**
153  * vmw_surface_destroy_size - Compute fifo size for a surface destroy command.
154  *
155  * Computes the required size for a surface destroy command for the destruction
156  * of a hw surface.
157  */
158 static inline uint32_t vmw_surface_destroy_size(void)
159 {
160         return sizeof(struct vmw_surface_destroy);
161 }
162
163 /**
164  * vmw_surface_destroy_encode - Encode a surface_destroy command.
165  *
166  * @id: The surface id
167  * @cmd_space: Pointer to memory area in which the commands should be encoded.
168  */
169 static void vmw_surface_destroy_encode(uint32_t id,
170                                        void *cmd_space)
171 {
172         struct vmw_surface_destroy *cmd = (struct vmw_surface_destroy *)
173                 cmd_space;
174
175         cmd->header.id = SVGA_3D_CMD_SURFACE_DESTROY;
176         cmd->header.size = sizeof(cmd->body);
177         cmd->body.sid = id;
178 }
179
180 /**
181  * vmw_surface_define_encode - Encode a surface_define command.
182  *
183  * @srf: Pointer to a struct vmw_surface object.
184  * @cmd_space: Pointer to memory area in which the commands should be encoded.
185  */
186 static void vmw_surface_define_encode(const struct vmw_surface *srf,
187                                       void *cmd_space)
188 {
189         struct vmw_surface_define *cmd = (struct vmw_surface_define *)
190                 cmd_space;
191         struct drm_vmw_size *src_size;
192         SVGA3dSize *cmd_size;
193         uint32_t cmd_len;
194         int i;
195
196         cmd_len = sizeof(cmd->body) + srf->num_sizes * sizeof(SVGA3dSize);
197
198         cmd->header.id = SVGA_3D_CMD_SURFACE_DEFINE;
199         cmd->header.size = cmd_len;
200         cmd->body.sid = srf->res.id;
201         cmd->body.surfaceFlags = srf->flags;
202         cmd->body.format = cpu_to_le32(srf->format);
203         for (i = 0; i < DRM_VMW_MAX_SURFACE_FACES; ++i)
204                 cmd->body.face[i].numMipLevels = srf->mip_levels[i];
205
206         cmd += 1;
207         cmd_size = (SVGA3dSize *) cmd;
208         src_size = srf->sizes;
209
210         for (i = 0; i < srf->num_sizes; ++i, cmd_size++, src_size++) {
211                 cmd_size->width = src_size->width;
212                 cmd_size->height = src_size->height;
213                 cmd_size->depth = src_size->depth;
214         }
215 }
216
217 /**
218  * vmw_surface_dma_encode - Encode a surface_dma command.
219  *
220  * @srf: Pointer to a struct vmw_surface object.
221  * @cmd_space: Pointer to memory area in which the commands should be encoded.
222  * @ptr: Pointer to an SVGAGuestPtr indicating where the surface contents
223  * should be placed or read from.
224  * @to_surface: Boolean whether to DMA to the surface or from the surface.
225  */
226 static void vmw_surface_dma_encode(struct vmw_surface *srf,
227                                    void *cmd_space,
228                                    const SVGAGuestPtr *ptr,
229                                    bool to_surface)
230 {
231         uint32_t i;
232         struct vmw_surface_dma *cmd = (struct vmw_surface_dma *)cmd_space;
233         const struct svga3d_surface_desc *desc =
234                 svga3dsurface_get_desc(srf->format);
235
236         for (i = 0; i < srf->num_sizes; ++i) {
237                 SVGA3dCmdHeader *header = &cmd->header;
238                 SVGA3dCmdSurfaceDMA *body = &cmd->body;
239                 SVGA3dCopyBox *cb = &cmd->cb;
240                 SVGA3dCmdSurfaceDMASuffix *suffix = &cmd->suffix;
241                 const struct vmw_surface_offset *cur_offset = &srf->offsets[i];
242                 const struct drm_vmw_size *cur_size = &srf->sizes[i];
243
244                 header->id = SVGA_3D_CMD_SURFACE_DMA;
245                 header->size = sizeof(*body) + sizeof(*cb) + sizeof(*suffix);
246
247                 body->guest.ptr = *ptr;
248                 body->guest.ptr.offset += cur_offset->bo_offset;
249                 body->guest.pitch = svga3dsurface_calculate_pitch(desc,
250                                                                   cur_size);
251                 body->host.sid = srf->res.id;
252                 body->host.face = cur_offset->face;
253                 body->host.mipmap = cur_offset->mip;
254                 body->transfer = ((to_surface) ?  SVGA3D_WRITE_HOST_VRAM :
255                                   SVGA3D_READ_HOST_VRAM);
256                 cb->x = 0;
257                 cb->y = 0;
258                 cb->z = 0;
259                 cb->srcx = 0;
260                 cb->srcy = 0;
261                 cb->srcz = 0;
262                 cb->w = cur_size->width;
263                 cb->h = cur_size->height;
264                 cb->d = cur_size->depth;
265
266                 suffix->suffixSize = sizeof(*suffix);
267                 suffix->maximumOffset =
268                         svga3dsurface_get_image_buffer_size(desc, cur_size,
269                                                             body->guest.pitch);
270                 suffix->flags.discard = 0;
271                 suffix->flags.unsynchronized = 0;
272                 suffix->flags.reserved = 0;
273                 ++cmd;
274         }
275 };
276
277
278 /**
279  * vmw_hw_surface_destroy - destroy a Device surface
280  *
281  * @res:        Pointer to a struct vmw_resource embedded in a struct
282  *              vmw_surface.
283  *
284  * Destroys a the device surface associated with a struct vmw_surface if
285  * any, and adjusts accounting and resource count accordingly.
286  */
287 static void vmw_hw_surface_destroy(struct vmw_resource *res)
288 {
289
290         struct vmw_private *dev_priv = res->dev_priv;
291         struct vmw_surface *srf;
292         void *cmd;
293
294         if (res->id != -1) {
295
296                 cmd = vmw_fifo_reserve(dev_priv, vmw_surface_destroy_size());
297                 if (unlikely(cmd == NULL)) {
298                         DRM_ERROR("Failed reserving FIFO space for surface "
299                                   "destruction.\n");
300                         return;
301                 }
302
303                 vmw_surface_destroy_encode(res->id, cmd);
304                 vmw_fifo_commit(dev_priv, vmw_surface_destroy_size());
305
306                 /*
307                  * used_memory_size_atomic, or separate lock
308                  * to avoid taking dev_priv::cmdbuf_mutex in
309                  * the destroy path.
310                  */
311
312                 mutex_lock(&dev_priv->cmdbuf_mutex);
313                 srf = vmw_res_to_srf(res);
314                 dev_priv->used_memory_size -= res->backup_size;
315                 mutex_unlock(&dev_priv->cmdbuf_mutex);
316         }
317         vmw_3d_resource_dec(dev_priv, false);
318 }
319
320 /**
321  * vmw_legacy_srf_create - Create a device surface as part of the
322  * resource validation process.
323  *
324  * @res: Pointer to a struct vmw_surface.
325  *
326  * If the surface doesn't have a hw id.
327  *
328  * Returns -EBUSY if there wasn't sufficient device resources to
329  * complete the validation. Retry after freeing up resources.
330  *
331  * May return other errors if the kernel is out of guest resources.
332  */
333 static int vmw_legacy_srf_create(struct vmw_resource *res)
334 {
335         struct vmw_private *dev_priv = res->dev_priv;
336         struct vmw_surface *srf;
337         uint32_t submit_size;
338         uint8_t *cmd;
339         int ret;
340
341         if (likely(res->id != -1))
342                 return 0;
343
344         srf = vmw_res_to_srf(res);
345         if (unlikely(dev_priv->used_memory_size + res->backup_size >=
346                      dev_priv->memory_size))
347                 return -EBUSY;
348
349         /*
350          * Alloc id for the resource.
351          */
352
353         ret = vmw_resource_alloc_id(res);
354         if (unlikely(ret != 0)) {
355                 DRM_ERROR("Failed to allocate a surface id.\n");
356                 goto out_no_id;
357         }
358
359         if (unlikely(res->id >= SVGA3D_MAX_SURFACE_IDS)) {
360                 ret = -EBUSY;
361                 goto out_no_fifo;
362         }
363
364         /*
365          * Encode surface define- commands.
366          */
367
368         submit_size = vmw_surface_define_size(srf);
369         cmd = vmw_fifo_reserve(dev_priv, submit_size);
370         if (unlikely(cmd == NULL)) {
371                 DRM_ERROR("Failed reserving FIFO space for surface "
372                           "creation.\n");
373                 ret = -ENOMEM;
374                 goto out_no_fifo;
375         }
376
377         vmw_surface_define_encode(srf, cmd);
378         vmw_fifo_commit(dev_priv, submit_size);
379         /*
380          * Surface memory usage accounting.
381          */
382
383         dev_priv->used_memory_size += res->backup_size;
384         return 0;
385
386 out_no_fifo:
387         vmw_resource_release_id(res);
388 out_no_id:
389         return ret;
390 }
391
392 /**
393  * vmw_legacy_srf_dma - Copy backup data to or from a legacy surface.
394  *
395  * @res:            Pointer to a struct vmw_res embedded in a struct
396  *                  vmw_surface.
397  * @val_buf:        Pointer to a struct ttm_validate_buffer containing
398  *                  information about the backup buffer.
399  * @bind:           Boolean wether to DMA to the surface.
400  *
401  * Transfer backup data to or from a legacy surface as part of the
402  * validation process.
403  * May return other errors if the kernel is out of guest resources.
404  * The backup buffer will be fenced or idle upon successful completion,
405  * and if the surface needs persistent backup storage, the backup buffer
406  * will also be returned reserved iff @bind is true.
407  */
408 static int vmw_legacy_srf_dma(struct vmw_resource *res,
409                               struct ttm_validate_buffer *val_buf,
410                               bool bind)
411 {
412         SVGAGuestPtr ptr;
413         struct vmw_fence_obj *fence;
414         uint32_t submit_size;
415         struct vmw_surface *srf = vmw_res_to_srf(res);
416         uint8_t *cmd;
417         struct vmw_private *dev_priv = res->dev_priv;
418
419         BUG_ON(val_buf->bo == NULL);
420
421         submit_size = vmw_surface_dma_size(srf);
422         cmd = vmw_fifo_reserve(dev_priv, submit_size);
423         if (unlikely(cmd == NULL)) {
424                 DRM_ERROR("Failed reserving FIFO space for surface "
425                           "DMA.\n");
426                 return -ENOMEM;
427         }
428         vmw_bo_get_guest_ptr(val_buf->bo, &ptr);
429         vmw_surface_dma_encode(srf, cmd, &ptr, bind);
430
431         vmw_fifo_commit(dev_priv, submit_size);
432
433         /*
434          * Create a fence object and fence the backup buffer.
435          */
436
437         (void) vmw_execbuf_fence_commands(NULL, dev_priv,
438                                           &fence, NULL);
439
440         vmw_fence_single_bo(val_buf->bo, fence);
441
442         if (likely(fence != NULL))
443                 vmw_fence_obj_unreference(&fence);
444
445         return 0;
446 }
447
448 /**
449  * vmw_legacy_srf_bind - Perform a legacy surface bind as part of the
450  *                       surface validation process.
451  *
452  * @res:            Pointer to a struct vmw_res embedded in a struct
453  *                  vmw_surface.
454  * @val_buf:        Pointer to a struct ttm_validate_buffer containing
455  *                  information about the backup buffer.
456  *
457  * This function will copy backup data to the surface if the
458  * backup buffer is dirty.
459  */
460 static int vmw_legacy_srf_bind(struct vmw_resource *res,
461                                struct ttm_validate_buffer *val_buf)
462 {
463         if (!res->backup_dirty)
464                 return 0;
465
466         return vmw_legacy_srf_dma(res, val_buf, true);
467 }
468
469
470 /**
471  * vmw_legacy_srf_unbind - Perform a legacy surface unbind as part of the
472  *                         surface eviction process.
473  *
474  * @res:            Pointer to a struct vmw_res embedded in a struct
475  *                  vmw_surface.
476  * @val_buf:        Pointer to a struct ttm_validate_buffer containing
477  *                  information about the backup buffer.
478  *
479  * This function will copy backup data from the surface.
480  */
481 static int vmw_legacy_srf_unbind(struct vmw_resource *res,
482                                  bool readback,
483                                  struct ttm_validate_buffer *val_buf)
484 {
485         if (unlikely(readback))
486                 return vmw_legacy_srf_dma(res, val_buf, false);
487         return 0;
488 }
489
490 /**
491  * vmw_legacy_srf_destroy - Destroy a device surface as part of a
492  *                          resource eviction process.
493  *
494  * @res:            Pointer to a struct vmw_res embedded in a struct
495  *                  vmw_surface.
496  */
497 static int vmw_legacy_srf_destroy(struct vmw_resource *res)
498 {
499         struct vmw_private *dev_priv = res->dev_priv;
500         uint32_t submit_size;
501         uint8_t *cmd;
502
503         BUG_ON(res->id == -1);
504
505         /*
506          * Encode the dma- and surface destroy commands.
507          */
508
509         submit_size = vmw_surface_destroy_size();
510         cmd = vmw_fifo_reserve(dev_priv, submit_size);
511         if (unlikely(cmd == NULL)) {
512                 DRM_ERROR("Failed reserving FIFO space for surface "
513                           "eviction.\n");
514                 return -ENOMEM;
515         }
516
517         vmw_surface_destroy_encode(res->id, cmd);
518         vmw_fifo_commit(dev_priv, submit_size);
519
520         /*
521          * Surface memory usage accounting.
522          */
523
524         dev_priv->used_memory_size -= res->backup_size;
525
526         /*
527          * Release the surface ID.
528          */
529
530         vmw_resource_release_id(res);
531
532         return 0;
533 }
534
535
536 /**
537  * vmw_surface_init - initialize a struct vmw_surface
538  *
539  * @dev_priv:       Pointer to a device private struct.
540  * @srf:            Pointer to the struct vmw_surface to initialize.
541  * @res_free:       Pointer to a resource destructor used to free
542  *                  the object.
543  */
544 static int vmw_surface_init(struct vmw_private *dev_priv,
545                             struct vmw_surface *srf,
546                             void (*res_free) (struct vmw_resource *res))
547 {
548         int ret;
549         struct vmw_resource *res = &srf->res;
550
551         BUG_ON(res_free == NULL);
552         (void) vmw_3d_resource_inc(dev_priv, false);
553         ret = vmw_resource_init(dev_priv, res, true, res_free,
554                                 &vmw_legacy_surface_func);
555
556         if (unlikely(ret != 0)) {
557                 vmw_3d_resource_dec(dev_priv, false);
558                 res_free(res);
559                 return ret;
560         }
561
562         /*
563          * The surface won't be visible to hardware until a
564          * surface validate.
565          */
566
567         vmw_resource_activate(res, vmw_hw_surface_destroy);
568         return ret;
569 }
570
571 /**
572  * vmw_user_surface_base_to_res - TTM base object to resource converter for
573  *                                user visible surfaces
574  *
575  * @base:           Pointer to a TTM base object
576  *
577  * Returns the struct vmw_resource embedded in a struct vmw_surface
578  * for the user-visible object identified by the TTM base object @base.
579  */
580 static struct vmw_resource *
581 vmw_user_surface_base_to_res(struct ttm_base_object *base)
582 {
583         return &(container_of(base, struct vmw_user_surface,
584                               prime.base)->srf.res);
585 }
586
587 /**
588  * vmw_user_surface_free - User visible surface resource destructor
589  *
590  * @res:            A struct vmw_resource embedded in a struct vmw_surface.
591  */
592 static void vmw_user_surface_free(struct vmw_resource *res)
593 {
594         struct vmw_surface *srf = vmw_res_to_srf(res);
595         struct vmw_user_surface *user_srf =
596             container_of(srf, struct vmw_user_surface, srf);
597         struct vmw_private *dev_priv = srf->res.dev_priv;
598         uint32_t size = user_srf->size;
599
600         kfree(srf->offsets);
601         kfree(srf->sizes);
602         kfree(srf->snooper.image);
603         ttm_prime_object_kfree(user_srf, prime);
604         ttm_mem_global_free(vmw_mem_glob(dev_priv), size);
605 }
606
607 /**
608  * vmw_user_surface_free - User visible surface TTM base object destructor
609  *
610  * @p_base:         Pointer to a pointer to a TTM base object
611  *                  embedded in a struct vmw_user_surface.
612  *
613  * Drops the base object's reference on its resource, and the
614  * pointer pointed to by *p_base is set to NULL.
615  */
616 static void vmw_user_surface_base_release(struct ttm_base_object **p_base)
617 {
618         struct ttm_base_object *base = *p_base;
619         struct vmw_user_surface *user_srf =
620             container_of(base, struct vmw_user_surface, prime.base);
621         struct vmw_resource *res = &user_srf->srf.res;
622
623         *p_base = NULL;
624         vmw_resource_unreference(&res);
625 }
626
627 /**
628  * vmw_user_surface_destroy_ioctl - Ioctl function implementing
629  *                                  the user surface destroy functionality.
630  *
631  * @dev:            Pointer to a struct drm_device.
632  * @data:           Pointer to data copied from / to user-space.
633  * @file_priv:      Pointer to a drm file private structure.
634  */
635 int vmw_surface_destroy_ioctl(struct drm_device *dev, void *data,
636                               struct drm_file *file_priv)
637 {
638         struct drm_vmw_surface_arg *arg = (struct drm_vmw_surface_arg *)data;
639         struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
640
641         return ttm_ref_object_base_unref(tfile, arg->sid, TTM_REF_USAGE);
642 }
643
644 /**
645  * vmw_user_surface_define_ioctl - Ioctl function implementing
646  *                                  the user surface define functionality.
647  *
648  * @dev:            Pointer to a struct drm_device.
649  * @data:           Pointer to data copied from / to user-space.
650  * @file_priv:      Pointer to a drm file private structure.
651  */
652 int vmw_surface_define_ioctl(struct drm_device *dev, void *data,
653                              struct drm_file *file_priv)
654 {
655         struct vmw_private *dev_priv = vmw_priv(dev);
656         struct vmw_user_surface *user_srf;
657         struct vmw_surface *srf;
658         struct vmw_resource *res;
659         struct vmw_resource *tmp;
660         union drm_vmw_surface_create_arg *arg =
661             (union drm_vmw_surface_create_arg *)data;
662         struct drm_vmw_surface_create_req *req = &arg->req;
663         struct drm_vmw_surface_arg *rep = &arg->rep;
664         struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
665         struct drm_vmw_size __user *user_sizes;
666         int ret;
667         int i, j;
668         uint32_t cur_bo_offset;
669         struct drm_vmw_size *cur_size;
670         struct vmw_surface_offset *cur_offset;
671         uint32_t num_sizes;
672         uint32_t size;
673         struct vmw_master *vmaster = vmw_master(file_priv->master);
674         const struct svga3d_surface_desc *desc;
675
676         if (unlikely(vmw_user_surface_size == 0))
677                 vmw_user_surface_size = ttm_round_pot(sizeof(*user_srf)) +
678                         128;
679
680         num_sizes = 0;
681         for (i = 0; i < DRM_VMW_MAX_SURFACE_FACES; ++i)
682                 num_sizes += req->mip_levels[i];
683
684         if (num_sizes > DRM_VMW_MAX_SURFACE_FACES *
685             DRM_VMW_MAX_MIP_LEVELS)
686                 return -EINVAL;
687
688         size = vmw_user_surface_size + 128 +
689                 ttm_round_pot(num_sizes * sizeof(struct drm_vmw_size)) +
690                 ttm_round_pot(num_sizes * sizeof(struct vmw_surface_offset));
691
692
693         desc = svga3dsurface_get_desc(req->format);
694         if (unlikely(desc->block_desc == SVGA3DBLOCKDESC_NONE)) {
695                 DRM_ERROR("Invalid surface format for surface creation.\n");
696                 return -EINVAL;
697         }
698
699         ret = ttm_read_lock(&vmaster->lock, true);
700         if (unlikely(ret != 0))
701                 return ret;
702
703         ret = ttm_mem_global_alloc(vmw_mem_glob(dev_priv),
704                                    size, false, true);
705         if (unlikely(ret != 0)) {
706                 if (ret != -ERESTARTSYS)
707                         DRM_ERROR("Out of graphics memory for surface"
708                                   " creation.\n");
709                 goto out_unlock;
710         }
711
712         user_srf = kzalloc(sizeof(*user_srf), GFP_KERNEL);
713         if (unlikely(user_srf == NULL)) {
714                 ret = -ENOMEM;
715                 goto out_no_user_srf;
716         }
717
718         srf = &user_srf->srf;
719         res = &srf->res;
720
721         srf->flags = req->flags;
722         srf->format = req->format;
723         srf->scanout = req->scanout;
724
725         memcpy(srf->mip_levels, req->mip_levels, sizeof(srf->mip_levels));
726         srf->num_sizes = num_sizes;
727         user_srf->size = size;
728
729         srf->sizes = kmalloc(srf->num_sizes * sizeof(*srf->sizes), GFP_KERNEL);
730         if (unlikely(srf->sizes == NULL)) {
731                 ret = -ENOMEM;
732                 goto out_no_sizes;
733         }
734         srf->offsets = kmalloc(srf->num_sizes * sizeof(*srf->offsets),
735                                GFP_KERNEL);
736         if (unlikely(srf->sizes == NULL)) {
737                 ret = -ENOMEM;
738                 goto out_no_offsets;
739         }
740
741         user_sizes = (struct drm_vmw_size __user *)(unsigned long)
742             req->size_addr;
743
744         ret = copy_from_user(srf->sizes, user_sizes,
745                              srf->num_sizes * sizeof(*srf->sizes));
746         if (unlikely(ret != 0)) {
747                 ret = -EFAULT;
748                 goto out_no_copy;
749         }
750
751         srf->base_size = *srf->sizes;
752         srf->autogen_filter = SVGA3D_TEX_FILTER_NONE;
753         srf->multisample_count = 1;
754
755         cur_bo_offset = 0;
756         cur_offset = srf->offsets;
757         cur_size = srf->sizes;
758
759         for (i = 0; i < DRM_VMW_MAX_SURFACE_FACES; ++i) {
760                 for (j = 0; j < srf->mip_levels[i]; ++j) {
761                         uint32_t stride = svga3dsurface_calculate_pitch
762                                 (desc, cur_size);
763
764                         cur_offset->face = i;
765                         cur_offset->mip = j;
766                         cur_offset->bo_offset = cur_bo_offset;
767                         cur_bo_offset += svga3dsurface_get_image_buffer_size
768                                 (desc, cur_size, stride);
769                         ++cur_offset;
770                         ++cur_size;
771                 }
772         }
773         res->backup_size = cur_bo_offset;
774         if (srf->scanout &&
775             srf->num_sizes == 1 &&
776             srf->sizes[0].width == 64 &&
777             srf->sizes[0].height == 64 &&
778             srf->format == SVGA3D_A8R8G8B8) {
779
780                 srf->snooper.image = kmalloc(64 * 64 * 4, GFP_KERNEL);
781                 /* clear the image */
782                 if (srf->snooper.image) {
783                         memset(srf->snooper.image, 0x00, 64 * 64 * 4);
784                 } else {
785                         DRM_ERROR("Failed to allocate cursor_image\n");
786                         ret = -ENOMEM;
787                         goto out_no_copy;
788                 }
789         } else {
790                 srf->snooper.image = NULL;
791         }
792         srf->snooper.crtc = NULL;
793
794         user_srf->prime.base.shareable = false;
795         user_srf->prime.base.tfile = NULL;
796
797         /**
798          * From this point, the generic resource management functions
799          * destroy the object on failure.
800          */
801
802         ret = vmw_surface_init(dev_priv, srf, vmw_user_surface_free);
803         if (unlikely(ret != 0))
804                 goto out_unlock;
805
806         tmp = vmw_resource_reference(&srf->res);
807         ret = ttm_prime_object_init(tfile, res->backup_size, &user_srf->prime,
808                                     req->shareable, VMW_RES_SURFACE,
809                                     &vmw_user_surface_base_release, NULL);
810
811         if (unlikely(ret != 0)) {
812                 vmw_resource_unreference(&tmp);
813                 vmw_resource_unreference(&res);
814                 goto out_unlock;
815         }
816
817         rep->sid = user_srf->prime.base.hash.key;
818         vmw_resource_unreference(&res);
819
820         ttm_read_unlock(&vmaster->lock);
821         return 0;
822 out_no_copy:
823         kfree(srf->offsets);
824 out_no_offsets:
825         kfree(srf->sizes);
826 out_no_sizes:
827         ttm_prime_object_kfree(user_srf, prime);
828 out_no_user_srf:
829         ttm_mem_global_free(vmw_mem_glob(dev_priv), size);
830 out_unlock:
831         ttm_read_unlock(&vmaster->lock);
832         return ret;
833 }
834
835 /**
836  * vmw_user_surface_define_ioctl - Ioctl function implementing
837  *                                  the user surface reference functionality.
838  *
839  * @dev:            Pointer to a struct drm_device.
840  * @data:           Pointer to data copied from / to user-space.
841  * @file_priv:      Pointer to a drm file private structure.
842  */
843 int vmw_surface_reference_ioctl(struct drm_device *dev, void *data,
844                                 struct drm_file *file_priv)
845 {
846         union drm_vmw_surface_reference_arg *arg =
847             (union drm_vmw_surface_reference_arg *)data;
848         struct drm_vmw_surface_arg *req = &arg->req;
849         struct drm_vmw_surface_create_req *rep = &arg->rep;
850         struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
851         struct vmw_surface *srf;
852         struct vmw_user_surface *user_srf;
853         struct drm_vmw_size __user *user_sizes;
854         struct ttm_base_object *base;
855         int ret = -EINVAL;
856
857         base = ttm_base_object_lookup(tfile, req->sid);
858         if (unlikely(base == NULL)) {
859                 DRM_ERROR("Could not find surface to reference.\n");
860                 return -EINVAL;
861         }
862
863         if (unlikely(ttm_base_object_type(base) != VMW_RES_SURFACE))
864                 goto out_bad_resource;
865
866         user_srf = container_of(base, struct vmw_user_surface, prime.base);
867         srf = &user_srf->srf;
868
869         ret = ttm_ref_object_add(tfile, &user_srf->prime.base,
870                                  TTM_REF_USAGE, NULL);
871         if (unlikely(ret != 0)) {
872                 DRM_ERROR("Could not add a reference to a surface.\n");
873                 goto out_no_reference;
874         }
875
876         rep->flags = srf->flags;
877         rep->format = srf->format;
878         memcpy(rep->mip_levels, srf->mip_levels, sizeof(srf->mip_levels));
879         user_sizes = (struct drm_vmw_size __user *)(unsigned long)
880             rep->size_addr;
881
882         if (user_sizes)
883                 ret = copy_to_user(user_sizes, srf->sizes,
884                                    srf->num_sizes * sizeof(*srf->sizes));
885         if (unlikely(ret != 0)) {
886                 DRM_ERROR("copy_to_user failed %p %u\n",
887                           user_sizes, srf->num_sizes);
888                 ret = -EFAULT;
889         }
890 out_bad_resource:
891 out_no_reference:
892         ttm_base_object_unref(&base);
893
894         return ret;
895 }