GNU Linux-libre 4.19.264-gnu1
[releases.git] / drivers / staging / vboxvideo / vbox_ttm.c
1 /*
2  * Copyright (C) 2013-2017 Oracle Corporation
3  * This file is based on ast_ttm.c
4  * Copyright 2012 Red Hat Inc.
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 SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
17  * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
18  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20  * USE OR OTHER DEALINGS IN THE SOFTWARE.
21  *
22  * The above copyright notice and this permission notice (including the
23  * next paragraph) shall be included in all copies or substantial portions
24  * of the Software.
25  *
26  *
27  * Authors: Dave Airlie <airlied@redhat.com>
28  *          Michael Thayer <michael.thayer@oracle.com>
29  */
30 #include "vbox_drv.h"
31 #include <ttm/ttm_page_alloc.h>
32
33 static inline struct vbox_private *vbox_bdev(struct ttm_bo_device *bd)
34 {
35         return container_of(bd, struct vbox_private, ttm.bdev);
36 }
37
38 static int vbox_ttm_mem_global_init(struct drm_global_reference *ref)
39 {
40         return ttm_mem_global_init(ref->object);
41 }
42
43 static void vbox_ttm_mem_global_release(struct drm_global_reference *ref)
44 {
45         ttm_mem_global_release(ref->object);
46 }
47
48 /**
49  * Adds the vbox memory manager object/structures to the global memory manager.
50  */
51 static int vbox_ttm_global_init(struct vbox_private *vbox)
52 {
53         struct drm_global_reference *global_ref;
54         int ret;
55
56         global_ref = &vbox->ttm.mem_global_ref;
57         global_ref->global_type = DRM_GLOBAL_TTM_MEM;
58         global_ref->size = sizeof(struct ttm_mem_global);
59         global_ref->init = &vbox_ttm_mem_global_init;
60         global_ref->release = &vbox_ttm_mem_global_release;
61         ret = drm_global_item_ref(global_ref);
62         if (ret) {
63                 DRM_ERROR("Failed setting up TTM memory subsystem.\n");
64                 return ret;
65         }
66
67         vbox->ttm.bo_global_ref.mem_glob = vbox->ttm.mem_global_ref.object;
68         global_ref = &vbox->ttm.bo_global_ref.ref;
69         global_ref->global_type = DRM_GLOBAL_TTM_BO;
70         global_ref->size = sizeof(struct ttm_bo_global);
71         global_ref->init = &ttm_bo_global_init;
72         global_ref->release = &ttm_bo_global_release;
73
74         ret = drm_global_item_ref(global_ref);
75         if (ret) {
76                 DRM_ERROR("Failed setting up TTM BO subsystem.\n");
77                 drm_global_item_unref(&vbox->ttm.mem_global_ref);
78                 return ret;
79         }
80
81         return 0;
82 }
83
84 /**
85  * Removes the vbox memory manager object from the global memory manager.
86  */
87 static void vbox_ttm_global_release(struct vbox_private *vbox)
88 {
89         drm_global_item_unref(&vbox->ttm.bo_global_ref.ref);
90         drm_global_item_unref(&vbox->ttm.mem_global_ref);
91 }
92
93 static void vbox_bo_ttm_destroy(struct ttm_buffer_object *tbo)
94 {
95         struct vbox_bo *bo;
96
97         bo = container_of(tbo, struct vbox_bo, bo);
98
99         drm_gem_object_release(&bo->gem);
100         kfree(bo);
101 }
102
103 static bool vbox_ttm_bo_is_vbox_bo(struct ttm_buffer_object *bo)
104 {
105         if (bo->destroy == &vbox_bo_ttm_destroy)
106                 return true;
107
108         return false;
109 }
110
111 static int
112 vbox_bo_init_mem_type(struct ttm_bo_device *bdev, u32 type,
113                       struct ttm_mem_type_manager *man)
114 {
115         switch (type) {
116         case TTM_PL_SYSTEM:
117                 man->flags = TTM_MEMTYPE_FLAG_MAPPABLE;
118                 man->available_caching = TTM_PL_MASK_CACHING;
119                 man->default_caching = TTM_PL_FLAG_CACHED;
120                 break;
121         case TTM_PL_VRAM:
122                 man->func = &ttm_bo_manager_func;
123                 man->flags = TTM_MEMTYPE_FLAG_FIXED | TTM_MEMTYPE_FLAG_MAPPABLE;
124                 man->available_caching = TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_WC;
125                 man->default_caching = TTM_PL_FLAG_WC;
126                 break;
127         default:
128                 DRM_ERROR("Unsupported memory type %u\n", (unsigned int)type);
129                 return -EINVAL;
130         }
131
132         return 0;
133 }
134
135 static void
136 vbox_bo_evict_flags(struct ttm_buffer_object *bo, struct ttm_placement *pl)
137 {
138         struct vbox_bo *vboxbo = vbox_bo(bo);
139
140         if (!vbox_ttm_bo_is_vbox_bo(bo))
141                 return;
142
143         vbox_ttm_placement(vboxbo, TTM_PL_FLAG_SYSTEM);
144         *pl = vboxbo->placement;
145 }
146
147 static int vbox_bo_verify_access(struct ttm_buffer_object *bo,
148                                  struct file *filp)
149 {
150         return 0;
151 }
152
153 static int vbox_ttm_io_mem_reserve(struct ttm_bo_device *bdev,
154                                    struct ttm_mem_reg *mem)
155 {
156         struct ttm_mem_type_manager *man = &bdev->man[mem->mem_type];
157         struct vbox_private *vbox = vbox_bdev(bdev);
158
159         mem->bus.addr = NULL;
160         mem->bus.offset = 0;
161         mem->bus.size = mem->num_pages << PAGE_SHIFT;
162         mem->bus.base = 0;
163         mem->bus.is_iomem = false;
164         if (!(man->flags & TTM_MEMTYPE_FLAG_MAPPABLE))
165                 return -EINVAL;
166         switch (mem->mem_type) {
167         case TTM_PL_SYSTEM:
168                 /* system memory */
169                 return 0;
170         case TTM_PL_VRAM:
171                 mem->bus.offset = mem->start << PAGE_SHIFT;
172                 mem->bus.base = pci_resource_start(vbox->dev->pdev, 0);
173                 mem->bus.is_iomem = true;
174                 break;
175         default:
176                 return -EINVAL;
177         }
178         return 0;
179 }
180
181 static void vbox_ttm_io_mem_free(struct ttm_bo_device *bdev,
182                                  struct ttm_mem_reg *mem)
183 {
184 }
185
186 static void vbox_ttm_backend_destroy(struct ttm_tt *tt)
187 {
188         ttm_tt_fini(tt);
189         kfree(tt);
190 }
191
192 static struct ttm_backend_func vbox_tt_backend_func = {
193         .destroy = &vbox_ttm_backend_destroy,
194 };
195
196 static struct ttm_tt *vbox_ttm_tt_create(struct ttm_buffer_object *bo,
197                                          u32 page_flags)
198 {
199         struct ttm_tt *tt;
200
201         tt = kzalloc(sizeof(*tt), GFP_KERNEL);
202         if (!tt)
203                 return NULL;
204
205         tt->func = &vbox_tt_backend_func;
206         if (ttm_tt_init(tt, bo, page_flags)) {
207                 kfree(tt);
208                 return NULL;
209         }
210
211         return tt;
212 }
213
214 static struct ttm_bo_driver vbox_bo_driver = {
215         .ttm_tt_create = vbox_ttm_tt_create,
216         .init_mem_type = vbox_bo_init_mem_type,
217         .eviction_valuable = ttm_bo_eviction_valuable,
218         .evict_flags = vbox_bo_evict_flags,
219         .verify_access = vbox_bo_verify_access,
220         .io_mem_reserve = &vbox_ttm_io_mem_reserve,
221         .io_mem_free = &vbox_ttm_io_mem_free,
222 };
223
224 int vbox_mm_init(struct vbox_private *vbox)
225 {
226         int ret;
227         struct drm_device *dev = vbox->dev;
228         struct ttm_bo_device *bdev = &vbox->ttm.bdev;
229
230         ret = vbox_ttm_global_init(vbox);
231         if (ret)
232                 return ret;
233
234         ret = ttm_bo_device_init(&vbox->ttm.bdev,
235                                  vbox->ttm.bo_global_ref.ref.object,
236                                  &vbox_bo_driver,
237                                  dev->anon_inode->i_mapping,
238                                  DRM_FILE_PAGE_OFFSET, true);
239         if (ret) {
240                 DRM_ERROR("Error initialising bo driver; %d\n", ret);
241                 goto err_ttm_global_release;
242         }
243
244         ret = ttm_bo_init_mm(bdev, TTM_PL_VRAM,
245                              vbox->available_vram_size >> PAGE_SHIFT);
246         if (ret) {
247                 DRM_ERROR("Failed ttm VRAM init: %d\n", ret);
248                 goto err_device_release;
249         }
250
251 #ifdef DRM_MTRR_WC
252         vbox->fb_mtrr = drm_mtrr_add(pci_resource_start(dev->pdev, 0),
253                                      pci_resource_len(dev->pdev, 0),
254                                      DRM_MTRR_WC);
255 #else
256         vbox->fb_mtrr = arch_phys_wc_add(pci_resource_start(dev->pdev, 0),
257                                          pci_resource_len(dev->pdev, 0));
258 #endif
259         return 0;
260
261 err_device_release:
262         ttm_bo_device_release(&vbox->ttm.bdev);
263 err_ttm_global_release:
264         vbox_ttm_global_release(vbox);
265         return ret;
266 }
267
268 void vbox_mm_fini(struct vbox_private *vbox)
269 {
270 #ifdef DRM_MTRR_WC
271         drm_mtrr_del(vbox->fb_mtrr,
272                      pci_resource_start(vbox->dev->pdev, 0),
273                      pci_resource_len(vbox->dev->pdev, 0), DRM_MTRR_WC);
274 #else
275         arch_phys_wc_del(vbox->fb_mtrr);
276 #endif
277         ttm_bo_device_release(&vbox->ttm.bdev);
278         vbox_ttm_global_release(vbox);
279 }
280
281 void vbox_ttm_placement(struct vbox_bo *bo, int domain)
282 {
283         unsigned int i;
284         u32 c = 0;
285
286         bo->placement.placement = bo->placements;
287         bo->placement.busy_placement = bo->placements;
288
289         if (domain & TTM_PL_FLAG_VRAM)
290                 bo->placements[c++].flags =
291                     TTM_PL_FLAG_WC | TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_VRAM;
292         if (domain & TTM_PL_FLAG_SYSTEM)
293                 bo->placements[c++].flags =
294                     TTM_PL_MASK_CACHING | TTM_PL_FLAG_SYSTEM;
295         if (!c)
296                 bo->placements[c++].flags =
297                     TTM_PL_MASK_CACHING | TTM_PL_FLAG_SYSTEM;
298
299         bo->placement.num_placement = c;
300         bo->placement.num_busy_placement = c;
301
302         for (i = 0; i < c; ++i) {
303                 bo->placements[i].fpfn = 0;
304                 bo->placements[i].lpfn = 0;
305         }
306 }
307
308 int vbox_bo_create(struct drm_device *dev, int size, int align,
309                    u32 flags, struct vbox_bo **pvboxbo)
310 {
311         struct vbox_private *vbox = dev->dev_private;
312         struct vbox_bo *vboxbo;
313         size_t acc_size;
314         int ret;
315
316         vboxbo = kzalloc(sizeof(*vboxbo), GFP_KERNEL);
317         if (!vboxbo)
318                 return -ENOMEM;
319
320         ret = drm_gem_object_init(dev, &vboxbo->gem, size);
321         if (ret)
322                 goto err_free_vboxbo;
323
324         vboxbo->bo.bdev = &vbox->ttm.bdev;
325
326         vbox_ttm_placement(vboxbo, TTM_PL_FLAG_VRAM | TTM_PL_FLAG_SYSTEM);
327
328         acc_size = ttm_bo_dma_acc_size(&vbox->ttm.bdev, size,
329                                        sizeof(struct vbox_bo));
330
331         ret = ttm_bo_init(&vbox->ttm.bdev, &vboxbo->bo, size,
332                           ttm_bo_type_device, &vboxbo->placement,
333                           align >> PAGE_SHIFT, false, acc_size,
334                           NULL, NULL, vbox_bo_ttm_destroy);
335         if (ret)
336                 goto err_free_vboxbo;
337
338         *pvboxbo = vboxbo;
339
340         return 0;
341
342 err_free_vboxbo:
343         kfree(vboxbo);
344         return ret;
345 }
346
347 static inline u64 vbox_bo_gpu_offset(struct vbox_bo *bo)
348 {
349         return bo->bo.offset;
350 }
351
352 int vbox_bo_pin(struct vbox_bo *bo, u32 pl_flag, u64 *gpu_addr)
353 {
354         struct ttm_operation_ctx ctx = { false, false };
355         int i, ret;
356
357         if (bo->pin_count) {
358                 bo->pin_count++;
359                 if (gpu_addr)
360                         *gpu_addr = vbox_bo_gpu_offset(bo);
361
362                 return 0;
363         }
364
365         vbox_ttm_placement(bo, pl_flag);
366
367         for (i = 0; i < bo->placement.num_placement; i++)
368                 bo->placements[i].flags |= TTM_PL_FLAG_NO_EVICT;
369
370         ret = ttm_bo_validate(&bo->bo, &bo->placement, &ctx);
371         if (ret)
372                 return ret;
373
374         bo->pin_count = 1;
375
376         if (gpu_addr)
377                 *gpu_addr = vbox_bo_gpu_offset(bo);
378
379         return 0;
380 }
381
382 int vbox_bo_unpin(struct vbox_bo *bo)
383 {
384         struct ttm_operation_ctx ctx = { false, false };
385         int i, ret;
386
387         if (!bo->pin_count) {
388                 DRM_ERROR("unpin bad %p\n", bo);
389                 return 0;
390         }
391         bo->pin_count--;
392         if (bo->pin_count)
393                 return 0;
394
395         for (i = 0; i < bo->placement.num_placement; i++)
396                 bo->placements[i].flags &= ~TTM_PL_FLAG_NO_EVICT;
397
398         ret = ttm_bo_validate(&bo->bo, &bo->placement, &ctx);
399         if (ret)
400                 return ret;
401
402         return 0;
403 }
404
405 /*
406  * Move a vbox-owned buffer object to system memory if no one else has it
407  * pinned.  The caller must have pinned it previously, and this call will
408  * release the caller's pin.
409  */
410 int vbox_bo_push_sysram(struct vbox_bo *bo)
411 {
412         struct ttm_operation_ctx ctx = { false, false };
413         int i, ret;
414
415         if (!bo->pin_count) {
416                 DRM_ERROR("unpin bad %p\n", bo);
417                 return 0;
418         }
419         bo->pin_count--;
420         if (bo->pin_count)
421                 return 0;
422
423         if (bo->kmap.virtual)
424                 ttm_bo_kunmap(&bo->kmap);
425
426         vbox_ttm_placement(bo, TTM_PL_FLAG_SYSTEM);
427
428         for (i = 0; i < bo->placement.num_placement; i++)
429                 bo->placements[i].flags |= TTM_PL_FLAG_NO_EVICT;
430
431         ret = ttm_bo_validate(&bo->bo, &bo->placement, &ctx);
432         if (ret) {
433                 DRM_ERROR("pushing to VRAM failed\n");
434                 return ret;
435         }
436
437         return 0;
438 }
439
440 int vbox_mmap(struct file *filp, struct vm_area_struct *vma)
441 {
442         struct drm_file *file_priv;
443         struct vbox_private *vbox;
444
445         if (unlikely(vma->vm_pgoff < DRM_FILE_PAGE_OFFSET))
446                 return -EINVAL;
447
448         file_priv = filp->private_data;
449         vbox = file_priv->minor->dev->dev_private;
450
451         return ttm_bo_mmap(filp, vma, &vbox->ttm.bdev);
452 }