1 /*
2  * Copyright (C) 2012-2018 Rob Clark <robclark@freedesktop.org>
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21  * SOFTWARE.
22  *
23  * Authors:
24  *    Rob Clark <robclark@freedesktop.org>
25  */
26 
27 #include "os/os_mman.h"
28 
29 #include "freedreno_drmif.h"
30 #include "freedreno_priv.h"
31 
32 simple_mtx_t table_lock = _SIMPLE_MTX_INITIALIZER_NP;
33 void bo_del(struct fd_bo *bo);
34 
35 /* set buffer name, and add to table, call w/ table_lock held: */
36 static void
set_name(struct fd_bo * bo,uint32_t name)37 set_name(struct fd_bo *bo, uint32_t name)
38 {
39    bo->name = name;
40    /* add ourself into the handle table: */
41    _mesa_hash_table_insert(bo->dev->name_table, &bo->name, bo);
42 }
43 
44 /* lookup a buffer, call w/ table_lock held: */
45 static struct fd_bo *
lookup_bo(struct hash_table * tbl,uint32_t key)46 lookup_bo(struct hash_table *tbl, uint32_t key)
47 {
48    struct fd_bo *bo = NULL;
49    struct hash_entry *entry = _mesa_hash_table_search(tbl, &key);
50    if (entry) {
51       /* found, incr refcnt and return: */
52       bo = fd_bo_ref(entry->data);
53 
54       /* don't break the bucket if this bo was found in one */
55       list_delinit(&bo->list);
56    }
57    return bo;
58 }
59 
60 /* allocate a new buffer object, call w/ table_lock held */
61 static struct fd_bo *
bo_from_handle(struct fd_device * dev,uint32_t size,uint32_t handle)62 bo_from_handle(struct fd_device *dev, uint32_t size, uint32_t handle)
63 {
64    struct fd_bo *bo;
65 
66    simple_mtx_assert_locked(&table_lock);
67 
68    bo = dev->funcs->bo_from_handle(dev, size, handle);
69    if (!bo) {
70       struct drm_gem_close req = {
71          .handle = handle,
72       };
73       drmIoctl(dev->fd, DRM_IOCTL_GEM_CLOSE, &req);
74       return NULL;
75    }
76    bo->dev = dev;
77    bo->size = size;
78    bo->handle = handle;
79    bo->iova = bo->funcs->iova(bo);
80    bo->reloc_flags = FD_RELOC_FLAGS_INIT;
81 
82    p_atomic_set(&bo->refcnt, 1);
83    list_inithead(&bo->list);
84    /* add ourself into the handle table: */
85    _mesa_hash_table_insert(dev->handle_table, &bo->handle, bo);
86    return bo;
87 }
88 
89 static struct fd_bo *
bo_new(struct fd_device * dev,uint32_t size,uint32_t flags,struct fd_bo_cache * cache)90 bo_new(struct fd_device *dev, uint32_t size, uint32_t flags,
91        struct fd_bo_cache *cache)
92 {
93    struct fd_bo *bo = NULL;
94    uint32_t handle;
95    int ret;
96 
97    /* demote cached-coherent to WC if not supported: */
98    if ((flags & FD_BO_CACHED_COHERENT) && !dev->has_cached_coherent)
99       flags &= ~FD_BO_CACHED_COHERENT;
100 
101    bo = fd_bo_cache_alloc(cache, &size, flags);
102    if (bo)
103       return bo;
104 
105    ret = dev->funcs->bo_new_handle(dev, size, flags, &handle);
106    if (ret)
107       return NULL;
108 
109    simple_mtx_lock(&table_lock);
110    bo = bo_from_handle(dev, size, handle);
111    simple_mtx_unlock(&table_lock);
112 
113    bo->alloc_flags = flags;
114    bo->max_fences = 1;
115    bo->fences = &bo->_inline_fence;
116 
117    VG_BO_ALLOC(bo);
118 
119    return bo;
120 }
121 
122 struct fd_bo *
_fd_bo_new(struct fd_device * dev,uint32_t size,uint32_t flags)123 _fd_bo_new(struct fd_device *dev, uint32_t size, uint32_t flags)
124 {
125    struct fd_bo *bo = bo_new(dev, size, flags, &dev->bo_cache);
126    if (bo)
127       bo->bo_reuse = BO_CACHE;
128    return bo;
129 }
130 
131 void
_fd_bo_set_name(struct fd_bo * bo,const char * fmt,va_list ap)132 _fd_bo_set_name(struct fd_bo *bo, const char *fmt, va_list ap)
133 {
134    bo->funcs->set_name(bo, fmt, ap);
135 }
136 
137 /* internal function to allocate bo's that use the ringbuffer cache
138  * instead of the normal bo_cache.  The purpose is, because cmdstream
139  * bo's get vmap'd on the kernel side, and that is expensive, we want
140  * to re-use cmdstream bo's for cmdstream and not unrelated purposes.
141  */
142 struct fd_bo *
fd_bo_new_ring(struct fd_device * dev,uint32_t size)143 fd_bo_new_ring(struct fd_device *dev, uint32_t size)
144 {
145    uint32_t flags = FD_BO_GPUREADONLY | FD_BO_CACHED_COHERENT;
146    struct fd_bo *bo = bo_new(dev, size, flags, &dev->ring_cache);
147    if (bo) {
148       bo->bo_reuse = RING_CACHE;
149       bo->reloc_flags |= FD_RELOC_DUMP;
150       fd_bo_set_name(bo, "cmdstream");
151    }
152    return bo;
153 }
154 
155 struct fd_bo *
fd_bo_from_handle(struct fd_device * dev,uint32_t handle,uint32_t size)156 fd_bo_from_handle(struct fd_device *dev, uint32_t handle, uint32_t size)
157 {
158    struct fd_bo *bo = NULL;
159 
160    simple_mtx_lock(&table_lock);
161 
162    bo = lookup_bo(dev->handle_table, handle);
163    if (bo)
164       goto out_unlock;
165 
166    bo = bo_from_handle(dev, size, handle);
167 
168    VG_BO_ALLOC(bo);
169 
170 out_unlock:
171    simple_mtx_unlock(&table_lock);
172 
173    return bo;
174 }
175 
176 struct fd_bo *
fd_bo_from_dmabuf(struct fd_device * dev,int fd)177 fd_bo_from_dmabuf(struct fd_device *dev, int fd)
178 {
179    int ret, size;
180    uint32_t handle;
181    struct fd_bo *bo;
182 
183    simple_mtx_lock(&table_lock);
184    ret = drmPrimeFDToHandle(dev->fd, fd, &handle);
185    if (ret) {
186       simple_mtx_unlock(&table_lock);
187       return NULL;
188    }
189 
190    bo = lookup_bo(dev->handle_table, handle);
191    if (bo)
192       goto out_unlock;
193 
194    /* lseek() to get bo size */
195    size = lseek(fd, 0, SEEK_END);
196    lseek(fd, 0, SEEK_CUR);
197 
198    bo = bo_from_handle(dev, size, handle);
199 
200    VG_BO_ALLOC(bo);
201 
202 out_unlock:
203    simple_mtx_unlock(&table_lock);
204 
205    return bo;
206 }
207 
208 struct fd_bo *
fd_bo_from_name(struct fd_device * dev,uint32_t name)209 fd_bo_from_name(struct fd_device *dev, uint32_t name)
210 {
211    struct drm_gem_open req = {
212       .name = name,
213    };
214    struct fd_bo *bo;
215 
216    simple_mtx_lock(&table_lock);
217 
218    /* check name table first, to see if bo is already open: */
219    bo = lookup_bo(dev->name_table, name);
220    if (bo)
221       goto out_unlock;
222 
223    if (drmIoctl(dev->fd, DRM_IOCTL_GEM_OPEN, &req)) {
224       ERROR_MSG("gem-open failed: %s", strerror(errno));
225       goto out_unlock;
226    }
227 
228    bo = lookup_bo(dev->handle_table, req.handle);
229    if (bo)
230       goto out_unlock;
231 
232    bo = bo_from_handle(dev, req.size, req.handle);
233    if (bo) {
234       set_name(bo, name);
235       VG_BO_ALLOC(bo);
236    }
237 
238 out_unlock:
239    simple_mtx_unlock(&table_lock);
240 
241    return bo;
242 }
243 
244 void
fd_bo_mark_for_dump(struct fd_bo * bo)245 fd_bo_mark_for_dump(struct fd_bo *bo)
246 {
247    bo->reloc_flags |= FD_RELOC_DUMP;
248 }
249 
250 uint64_t
fd_bo_get_iova(struct fd_bo * bo)251 fd_bo_get_iova(struct fd_bo *bo)
252 {
253    /* ancient kernels did not support this */
254    assert(bo->iova != 0);
255    return bo->iova;
256 }
257 
258 struct fd_bo *
fd_bo_ref(struct fd_bo * bo)259 fd_bo_ref(struct fd_bo *bo)
260 {
261    p_atomic_inc(&bo->refcnt);
262    return bo;
263 }
264 
265 static void
bo_del_or_recycle(struct fd_bo * bo)266 bo_del_or_recycle(struct fd_bo *bo)
267 {
268    struct fd_device *dev = bo->dev;
269 
270    simple_mtx_assert_locked(&table_lock);
271 
272    if ((bo->bo_reuse == BO_CACHE) &&
273        (fd_bo_cache_free(&dev->bo_cache, bo) == 0))
274       return;
275 
276    if ((bo->bo_reuse == RING_CACHE) &&
277        (fd_bo_cache_free(&dev->ring_cache, bo) == 0))
278       return;
279 
280    bo_del(bo);
281 }
282 
283 void
fd_bo_del_locked(struct fd_bo * bo)284 fd_bo_del_locked(struct fd_bo *bo)
285 {
286    simple_mtx_assert_locked(&table_lock);
287 
288    if (!p_atomic_dec_zero(&bo->refcnt))
289       return;
290 
291    bo_del_or_recycle(bo);
292 }
293 
294 void
fd_bo_del(struct fd_bo * bo)295 fd_bo_del(struct fd_bo *bo)
296 {
297    if (!p_atomic_dec_zero(&bo->refcnt))
298       return;
299 
300    simple_mtx_lock(&table_lock);
301    bo_del_or_recycle(bo);
302    simple_mtx_unlock(&table_lock);
303 }
304 
305 /**
306  * Cleanup fences, dropping pipe references.  If 'expired' is true, only
307  * cleanup expired fences.
308  *
309  * Normally we expect at most a single fence, the exception being bo's
310  * shared between contexts
311  */
312 static void
cleanup_fences(struct fd_bo * bo,bool expired)313 cleanup_fences(struct fd_bo *bo, bool expired)
314 {
315    simple_mtx_assert_locked(&table_lock);
316 
317    for (int i = 0; i < bo->nr_fences; i++) {
318       struct fd_bo_fence *f = &bo->fences[i];
319 
320       if (expired && fd_fence_before(f->pipe->control->fence, f->fence))
321          continue;
322 
323       struct fd_pipe *pipe = f->pipe;
324 
325       bo->nr_fences--;
326 
327       if (bo->nr_fences > 0) {
328          /* Shuffle up the last entry to replace the current slot: */
329          bo->fences[i] = bo->fences[bo->nr_fences];
330          i--;
331       }
332 
333       fd_pipe_del_locked(pipe);
334    }
335 }
336 
337 /* Called under table_lock */
338 void
bo_del(struct fd_bo * bo)339 bo_del(struct fd_bo *bo)
340 {
341    VG_BO_FREE(bo);
342 
343    simple_mtx_assert_locked(&table_lock);
344 
345    cleanup_fences(bo, false);
346    if (bo->fences != &bo->_inline_fence)
347       free(bo->fences);
348 
349    if (bo->map)
350       os_munmap(bo->map, bo->size);
351 
352    /* TODO probably bo's in bucket list get removed from
353     * handle table??
354     */
355 
356    if (bo->handle) {
357       struct drm_gem_close req = {
358          .handle = bo->handle,
359       };
360       _mesa_hash_table_remove_key(bo->dev->handle_table, &bo->handle);
361       if (bo->name)
362          _mesa_hash_table_remove_key(bo->dev->name_table, &bo->name);
363       drmIoctl(bo->dev->fd, DRM_IOCTL_GEM_CLOSE, &req);
364    }
365 
366    bo->funcs->destroy(bo);
367 }
368 
369 static void
bo_flush(struct fd_bo * bo)370 bo_flush(struct fd_bo *bo)
371 {
372    for (int i = 0; i < bo->nr_fences; i++) {
373       struct fd_bo_fence *f = &bo->fences[i];
374       fd_pipe_flush(f->pipe, f->fence);
375    }
376 }
377 
378 int
fd_bo_get_name(struct fd_bo * bo,uint32_t * name)379 fd_bo_get_name(struct fd_bo *bo, uint32_t *name)
380 {
381    if (!bo->name) {
382       struct drm_gem_flink req = {
383          .handle = bo->handle,
384       };
385       int ret;
386 
387       ret = drmIoctl(bo->dev->fd, DRM_IOCTL_GEM_FLINK, &req);
388       if (ret) {
389          return ret;
390       }
391 
392       simple_mtx_lock(&table_lock);
393       set_name(bo, req.name);
394       simple_mtx_unlock(&table_lock);
395       bo->bo_reuse = NO_CACHE;
396       bo->shared = true;
397       bo_flush(bo);
398    }
399 
400    *name = bo->name;
401 
402    return 0;
403 }
404 
405 uint32_t
fd_bo_handle(struct fd_bo * bo)406 fd_bo_handle(struct fd_bo *bo)
407 {
408    bo->bo_reuse = NO_CACHE;
409    bo->shared = true;
410    bo_flush(bo);
411    return bo->handle;
412 }
413 
414 int
fd_bo_dmabuf(struct fd_bo * bo)415 fd_bo_dmabuf(struct fd_bo *bo)
416 {
417    int ret, prime_fd;
418 
419    ret = drmPrimeHandleToFD(bo->dev->fd, bo->handle, DRM_CLOEXEC, &prime_fd);
420    if (ret) {
421       ERROR_MSG("failed to get dmabuf fd: %d", ret);
422       return ret;
423    }
424 
425    bo->bo_reuse = NO_CACHE;
426    bo->shared = true;
427    bo_flush(bo);
428 
429    return prime_fd;
430 }
431 
432 uint32_t
fd_bo_size(struct fd_bo * bo)433 fd_bo_size(struct fd_bo *bo)
434 {
435    return bo->size;
436 }
437 
438 bool
fd_bo_is_cached(struct fd_bo * bo)439 fd_bo_is_cached(struct fd_bo *bo)
440 {
441    return !!(bo->alloc_flags & FD_BO_CACHED_COHERENT);
442 }
443 
444 void *
fd_bo_map(struct fd_bo * bo)445 fd_bo_map(struct fd_bo *bo)
446 {
447    if (!bo->map) {
448       uint64_t offset;
449       int ret;
450 
451       ret = bo->funcs->offset(bo, &offset);
452       if (ret) {
453          return NULL;
454       }
455 
456       bo->map = os_mmap(0, bo->size, PROT_READ | PROT_WRITE, MAP_SHARED,
457                         bo->dev->fd, offset);
458       if (bo->map == MAP_FAILED) {
459          ERROR_MSG("mmap failed: %s", strerror(errno));
460          bo->map = NULL;
461       }
462    }
463    return bo->map;
464 }
465 
466 /* a bit odd to take the pipe as an arg, but it's a, umm, quirk of kgsl.. */
467 int
fd_bo_cpu_prep(struct fd_bo * bo,struct fd_pipe * pipe,uint32_t op)468 fd_bo_cpu_prep(struct fd_bo *bo, struct fd_pipe *pipe, uint32_t op)
469 {
470    if (op & (FD_BO_PREP_NOSYNC | FD_BO_PREP_FLUSH)) {
471       simple_mtx_lock(&table_lock);
472       enum fd_bo_state state = fd_bo_state(bo);
473       simple_mtx_unlock(&table_lock);
474 
475       if (state == FD_BO_STATE_IDLE)
476          return 0;
477 
478       if (op & FD_BO_PREP_FLUSH)
479          bo_flush(bo);
480 
481       /* If we have *only* been asked to flush, then we aren't really
482        * interested about whether shared buffers are busy, so avoid
483        * the kernel ioctl.
484        */
485       if ((state == FD_BO_STATE_BUSY) ||
486           (op == FD_BO_PREP_FLUSH))
487          return -EBUSY;
488    }
489 
490    /* In case the bo is referenced by a deferred submit, flush up to the
491     * required fence now:
492     */
493    bo_flush(bo);
494 
495    /* FD_BO_PREP_FLUSH is purely a frontend flag, and is not seen/handled
496     * by backend or kernel:
497     */
498    return bo->funcs->cpu_prep(bo, pipe, op & ~FD_BO_PREP_FLUSH);
499 }
500 
501 void
fd_bo_cpu_fini(struct fd_bo * bo)502 fd_bo_cpu_fini(struct fd_bo *bo)
503 {
504 // TODO until we have cached buffers, the kernel side ioctl does nothing,
505 //      so just skip it.  When we have cached buffers, we can make the
506 //      ioctl conditional
507 //   bo->funcs->cpu_fini(bo);
508 }
509 
510 void
fd_bo_add_fence(struct fd_bo * bo,struct fd_pipe * pipe,uint32_t fence)511 fd_bo_add_fence(struct fd_bo *bo, struct fd_pipe *pipe, uint32_t fence)
512 {
513    simple_mtx_assert_locked(&table_lock);
514 
515    if (bo->nosync)
516       return;
517 
518    /* The common case is bo re-used on the same pipe it had previously
519     * been used on:
520     */
521    for (int i = 0; i < bo->nr_fences; i++) {
522       struct fd_bo_fence *f = &bo->fences[i];
523       if (f->pipe == pipe) {
524          assert(fd_fence_before(f->fence, fence));
525          f->fence = fence;
526          return;
527       }
528    }
529 
530    cleanup_fences(bo, true);
531 
532    /* The first time we grow past a single fence, we need some special
533     * handling, as we've been using the embedded _inline_fence to avoid
534     * a separate allocation:
535     */
536    if (unlikely((bo->nr_fences == 1) &&
537                 (bo->fences == &bo->_inline_fence))) {
538       bo->nr_fences = bo->max_fences = 0;
539       bo->fences = NULL;
540       APPEND(bo, fences, bo->_inline_fence);
541    }
542 
543    APPEND(bo, fences, (struct fd_bo_fence){
544       .pipe = fd_pipe_ref_locked(pipe),
545       .fence = fence,
546    });
547 }
548 
549 enum fd_bo_state
fd_bo_state(struct fd_bo * bo)550 fd_bo_state(struct fd_bo *bo)
551 {
552    simple_mtx_assert_locked(&table_lock);
553 
554    cleanup_fences(bo, true);
555 
556    if (bo->shared || bo->nosync)
557       return FD_BO_STATE_UNKNOWN;
558 
559    if (!bo->nr_fences)
560       return FD_BO_STATE_IDLE;
561 
562    return FD_BO_STATE_BUSY;
563 }
564 
565