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 void
fd_bo_init_common(struct fd_bo * bo,struct fd_device * dev)61 fd_bo_init_common(struct fd_bo *bo, struct fd_device *dev)
62 {
63 /* Backend should have initialized these: */
64 assert(bo->size);
65 assert(bo->handle);
66
67 bo->dev = dev;
68 bo->iova = bo->funcs->iova(bo);
69 bo->reloc_flags = FD_RELOC_FLAGS_INIT;
70
71 p_atomic_set(&bo->refcnt, 1);
72 list_inithead(&bo->list);
73 }
74
75 /* allocate a new buffer object, call w/ table_lock held */
76 static struct fd_bo *
bo_from_handle(struct fd_device * dev,uint32_t size,uint32_t handle)77 bo_from_handle(struct fd_device *dev, uint32_t size, uint32_t handle)
78 {
79 struct fd_bo *bo;
80
81 simple_mtx_assert_locked(&table_lock);
82
83 bo = dev->funcs->bo_from_handle(dev, size, handle);
84 if (!bo) {
85 struct drm_gem_close req = {
86 .handle = handle,
87 };
88 drmIoctl(dev->fd, DRM_IOCTL_GEM_CLOSE, &req);
89 return NULL;
90 }
91
92 /* add ourself into the handle table: */
93 _mesa_hash_table_insert(dev->handle_table, &bo->handle, bo);
94
95 return bo;
96 }
97
98 static struct fd_bo *
bo_new(struct fd_device * dev,uint32_t size,uint32_t flags,struct fd_bo_cache * cache)99 bo_new(struct fd_device *dev, uint32_t size, uint32_t flags,
100 struct fd_bo_cache *cache)
101 {
102 struct fd_bo *bo = NULL;
103
104 /* demote cached-coherent to WC if not supported: */
105 if ((flags & FD_BO_CACHED_COHERENT) && !dev->has_cached_coherent)
106 flags &= ~FD_BO_CACHED_COHERENT;
107
108 bo = fd_bo_cache_alloc(cache, &size, flags);
109 if (bo)
110 return bo;
111
112 bo = dev->funcs->bo_new(dev, size, flags);
113 if (!bo)
114 return NULL;
115
116 simple_mtx_lock(&table_lock);
117 /* add ourself into the handle table: */
118 _mesa_hash_table_insert(dev->handle_table, &bo->handle, bo);
119 simple_mtx_unlock(&table_lock);
120
121 bo->alloc_flags = flags;
122 bo->max_fences = 1;
123 bo->fences = &bo->_inline_fence;
124
125 VG_BO_ALLOC(bo);
126
127 return bo;
128 }
129
130 struct fd_bo *
_fd_bo_new(struct fd_device * dev,uint32_t size,uint32_t flags)131 _fd_bo_new(struct fd_device *dev, uint32_t size, uint32_t flags)
132 {
133 struct fd_bo *bo = bo_new(dev, size, flags, &dev->bo_cache);
134 if (bo)
135 bo->bo_reuse = BO_CACHE;
136 return bo;
137 }
138
139 void
_fd_bo_set_name(struct fd_bo * bo,const char * fmt,va_list ap)140 _fd_bo_set_name(struct fd_bo *bo, const char *fmt, va_list ap)
141 {
142 bo->funcs->set_name(bo, fmt, ap);
143 }
144
145 /* internal function to allocate bo's that use the ringbuffer cache
146 * instead of the normal bo_cache. The purpose is, because cmdstream
147 * bo's get vmap'd on the kernel side, and that is expensive, we want
148 * to re-use cmdstream bo's for cmdstream and not unrelated purposes.
149 */
150 struct fd_bo *
fd_bo_new_ring(struct fd_device * dev,uint32_t size)151 fd_bo_new_ring(struct fd_device *dev, uint32_t size)
152 {
153 uint32_t flags = FD_BO_GPUREADONLY | FD_BO_CACHED_COHERENT;
154 struct fd_bo *bo = bo_new(dev, size, flags, &dev->ring_cache);
155 if (bo) {
156 bo->bo_reuse = RING_CACHE;
157 bo->reloc_flags |= FD_RELOC_DUMP;
158 fd_bo_set_name(bo, "cmdstream");
159 }
160 return bo;
161 }
162
163 struct fd_bo *
fd_bo_from_handle(struct fd_device * dev,uint32_t handle,uint32_t size)164 fd_bo_from_handle(struct fd_device *dev, uint32_t handle, uint32_t size)
165 {
166 struct fd_bo *bo = NULL;
167
168 simple_mtx_lock(&table_lock);
169
170 bo = lookup_bo(dev->handle_table, handle);
171 if (bo)
172 goto out_unlock;
173
174 bo = bo_from_handle(dev, size, handle);
175
176 VG_BO_ALLOC(bo);
177
178 out_unlock:
179 simple_mtx_unlock(&table_lock);
180
181 return bo;
182 }
183
184 struct fd_bo *
fd_bo_from_dmabuf(struct fd_device * dev,int fd)185 fd_bo_from_dmabuf(struct fd_device *dev, int fd)
186 {
187 int ret, size;
188 uint32_t handle;
189 struct fd_bo *bo;
190
191 simple_mtx_lock(&table_lock);
192 ret = drmPrimeFDToHandle(dev->fd, fd, &handle);
193 if (ret) {
194 simple_mtx_unlock(&table_lock);
195 return NULL;
196 }
197
198 bo = lookup_bo(dev->handle_table, handle);
199 if (bo)
200 goto out_unlock;
201
202 /* lseek() to get bo size */
203 size = lseek(fd, 0, SEEK_END);
204 lseek(fd, 0, SEEK_CUR);
205
206 bo = bo_from_handle(dev, size, handle);
207
208 VG_BO_ALLOC(bo);
209
210 out_unlock:
211 simple_mtx_unlock(&table_lock);
212
213 return bo;
214 }
215
216 struct fd_bo *
fd_bo_from_name(struct fd_device * dev,uint32_t name)217 fd_bo_from_name(struct fd_device *dev, uint32_t name)
218 {
219 struct drm_gem_open req = {
220 .name = name,
221 };
222 struct fd_bo *bo;
223
224 simple_mtx_lock(&table_lock);
225
226 /* check name table first, to see if bo is already open: */
227 bo = lookup_bo(dev->name_table, name);
228 if (bo)
229 goto out_unlock;
230
231 if (drmIoctl(dev->fd, DRM_IOCTL_GEM_OPEN, &req)) {
232 ERROR_MSG("gem-open failed: %s", strerror(errno));
233 goto out_unlock;
234 }
235
236 bo = lookup_bo(dev->handle_table, req.handle);
237 if (bo)
238 goto out_unlock;
239
240 bo = bo_from_handle(dev, req.size, req.handle);
241 if (bo) {
242 set_name(bo, name);
243 VG_BO_ALLOC(bo);
244 }
245
246 out_unlock:
247 simple_mtx_unlock(&table_lock);
248
249 return bo;
250 }
251
252 void
fd_bo_mark_for_dump(struct fd_bo * bo)253 fd_bo_mark_for_dump(struct fd_bo *bo)
254 {
255 bo->reloc_flags |= FD_RELOC_DUMP;
256 }
257
258 uint64_t
fd_bo_get_iova(struct fd_bo * bo)259 fd_bo_get_iova(struct fd_bo *bo)
260 {
261 /* ancient kernels did not support this */
262 assert(bo->iova != 0);
263 return bo->iova;
264 }
265
266 struct fd_bo *
fd_bo_ref(struct fd_bo * bo)267 fd_bo_ref(struct fd_bo *bo)
268 {
269 p_atomic_inc(&bo->refcnt);
270 return bo;
271 }
272
273 static void
bo_del_or_recycle(struct fd_bo * bo)274 bo_del_or_recycle(struct fd_bo *bo)
275 {
276 struct fd_device *dev = bo->dev;
277
278 simple_mtx_assert_locked(&table_lock);
279
280 if ((bo->bo_reuse == BO_CACHE) &&
281 (fd_bo_cache_free(&dev->bo_cache, bo) == 0))
282 return;
283
284 if ((bo->bo_reuse == RING_CACHE) &&
285 (fd_bo_cache_free(&dev->ring_cache, bo) == 0))
286 return;
287
288 bo_del(bo);
289 }
290
291 void
fd_bo_del_locked(struct fd_bo * bo)292 fd_bo_del_locked(struct fd_bo *bo)
293 {
294 simple_mtx_assert_locked(&table_lock);
295
296 if (!p_atomic_dec_zero(&bo->refcnt))
297 return;
298
299 bo_del_or_recycle(bo);
300 }
301
302 void
fd_bo_del(struct fd_bo * bo)303 fd_bo_del(struct fd_bo *bo)
304 {
305 if (!p_atomic_dec_zero(&bo->refcnt))
306 return;
307
308 simple_mtx_lock(&table_lock);
309 bo_del_or_recycle(bo);
310 simple_mtx_unlock(&table_lock);
311 }
312
313 /**
314 * Cleanup fences, dropping pipe references. If 'expired' is true, only
315 * cleanup expired fences.
316 *
317 * Normally we expect at most a single fence, the exception being bo's
318 * shared between contexts
319 */
320 static void
cleanup_fences(struct fd_bo * bo,bool expired)321 cleanup_fences(struct fd_bo *bo, bool expired)
322 {
323 simple_mtx_assert_locked(&table_lock);
324
325 for (int i = 0; i < bo->nr_fences; i++) {
326 struct fd_bo_fence *f = &bo->fences[i];
327
328 if (expired && fd_fence_before(f->pipe->control->fence, f->fence))
329 continue;
330
331 struct fd_pipe *pipe = f->pipe;
332
333 bo->nr_fences--;
334
335 if (bo->nr_fences > 0) {
336 /* Shuffle up the last entry to replace the current slot: */
337 bo->fences[i] = bo->fences[bo->nr_fences];
338 i--;
339 }
340
341 fd_pipe_del_locked(pipe);
342 }
343 }
344
345 /* Called under table_lock */
346 void
bo_del(struct fd_bo * bo)347 bo_del(struct fd_bo *bo)
348 {
349 struct fd_device *dev = bo->dev;
350 uint32_t handle = bo->handle;
351
352 VG_BO_FREE(bo);
353
354 simple_mtx_assert_locked(&table_lock);
355
356 cleanup_fences(bo, false);
357 if (bo->fences != &bo->_inline_fence)
358 free(bo->fences);
359
360 if (bo->map)
361 os_munmap(bo->map, bo->size);
362
363 if (handle) {
364 _mesa_hash_table_remove_key(dev->handle_table, &handle);
365 if (bo->name)
366 _mesa_hash_table_remove_key(dev->name_table, &bo->name);
367 }
368
369 bo->funcs->destroy(bo);
370
371 if (handle) {
372 struct drm_gem_close req = {
373 .handle = handle,
374 };
375 drmIoctl(dev->fd, DRM_IOCTL_GEM_CLOSE, &req);
376 }
377 }
378
379 static void
bo_flush(struct fd_bo * bo)380 bo_flush(struct fd_bo *bo)
381 {
382 for (int i = 0; i < bo->nr_fences; i++) {
383 struct fd_bo_fence *f = &bo->fences[i];
384 fd_pipe_flush(f->pipe, f->fence);
385 }
386 }
387
388 int
fd_bo_get_name(struct fd_bo * bo,uint32_t * name)389 fd_bo_get_name(struct fd_bo *bo, uint32_t *name)
390 {
391 if (!bo->name) {
392 struct drm_gem_flink req = {
393 .handle = bo->handle,
394 };
395 int ret;
396
397 ret = drmIoctl(bo->dev->fd, DRM_IOCTL_GEM_FLINK, &req);
398 if (ret) {
399 return ret;
400 }
401
402 simple_mtx_lock(&table_lock);
403 set_name(bo, req.name);
404 simple_mtx_unlock(&table_lock);
405 bo->bo_reuse = NO_CACHE;
406 bo->shared = true;
407 bo_flush(bo);
408 }
409
410 *name = bo->name;
411
412 return 0;
413 }
414
415 uint32_t
fd_bo_handle(struct fd_bo * bo)416 fd_bo_handle(struct fd_bo *bo)
417 {
418 bo->bo_reuse = NO_CACHE;
419 bo->shared = true;
420 bo_flush(bo);
421 return bo->handle;
422 }
423
424 int
fd_bo_dmabuf(struct fd_bo * bo)425 fd_bo_dmabuf(struct fd_bo *bo)
426 {
427 int ret, prime_fd;
428
429 ret = drmPrimeHandleToFD(bo->dev->fd, bo->handle, DRM_CLOEXEC | DRM_RDWR,
430 &prime_fd);
431 if (ret) {
432 ERROR_MSG("failed to get dmabuf fd: %d", ret);
433 return ret;
434 }
435
436 bo->bo_reuse = NO_CACHE;
437 bo->shared = true;
438 bo_flush(bo);
439
440 return prime_fd;
441 }
442
443 uint32_t
fd_bo_size(struct fd_bo * bo)444 fd_bo_size(struct fd_bo *bo)
445 {
446 return bo->size;
447 }
448
449 bool
fd_bo_is_cached(struct fd_bo * bo)450 fd_bo_is_cached(struct fd_bo *bo)
451 {
452 return !!(bo->alloc_flags & FD_BO_CACHED_COHERENT);
453 }
454
455 static void *
bo_map(struct fd_bo * bo)456 bo_map(struct fd_bo *bo)
457 {
458 if (!bo->map) {
459 uint64_t offset;
460 int ret;
461
462 ret = bo->funcs->offset(bo, &offset);
463 if (ret) {
464 return NULL;
465 }
466
467 bo->map = os_mmap(0, bo->size, PROT_READ | PROT_WRITE, MAP_SHARED,
468 bo->dev->fd, offset);
469 if (bo->map == MAP_FAILED) {
470 ERROR_MSG("mmap failed: %s", strerror(errno));
471 bo->map = NULL;
472 }
473 }
474 return bo->map;
475 }
476
477 void *
fd_bo_map(struct fd_bo * bo)478 fd_bo_map(struct fd_bo *bo)
479 {
480 /* don't allow mmap'ing something allocated with FD_BO_NOMAP
481 * for sanity
482 */
483 if (bo->alloc_flags & FD_BO_NOMAP)
484 return NULL;
485
486 return bo_map(bo);
487 }
488
489 void
fd_bo_upload(struct fd_bo * bo,void * src,unsigned len)490 fd_bo_upload(struct fd_bo *bo, void *src, unsigned len)
491 {
492 if (bo->funcs->upload) {
493 bo->funcs->upload(bo, src, len);
494 return;
495 }
496
497 memcpy(bo_map(bo), src, len);
498 }
499
500 /* a bit odd to take the pipe as an arg, but it's a, umm, quirk of kgsl.. */
501 int
fd_bo_cpu_prep(struct fd_bo * bo,struct fd_pipe * pipe,uint32_t op)502 fd_bo_cpu_prep(struct fd_bo *bo, struct fd_pipe *pipe, uint32_t op)
503 {
504 simple_mtx_lock(&table_lock);
505 enum fd_bo_state state = fd_bo_state(bo);
506 simple_mtx_unlock(&table_lock);
507
508 if (state == FD_BO_STATE_IDLE)
509 return 0;
510
511 if (op & (FD_BO_PREP_NOSYNC | FD_BO_PREP_FLUSH)) {
512 if (op & FD_BO_PREP_FLUSH)
513 bo_flush(bo);
514
515 /* If we have *only* been asked to flush, then we aren't really
516 * interested about whether shared buffers are busy, so avoid
517 * the kernel ioctl.
518 */
519 if ((state == FD_BO_STATE_BUSY) ||
520 (op == FD_BO_PREP_FLUSH))
521 return -EBUSY;
522 }
523
524 /* In case the bo is referenced by a deferred submit, flush up to the
525 * required fence now:
526 */
527 bo_flush(bo);
528
529 /* FD_BO_PREP_FLUSH is purely a frontend flag, and is not seen/handled
530 * by backend or kernel:
531 */
532 return bo->funcs->cpu_prep(bo, pipe, op & ~FD_BO_PREP_FLUSH);
533 }
534
535 void
fd_bo_cpu_fini(struct fd_bo * bo)536 fd_bo_cpu_fini(struct fd_bo *bo)
537 {
538 // TODO until we have cached buffers, the kernel side ioctl does nothing,
539 // so just skip it. When we have cached buffers, we can make the
540 // ioctl conditional
541 // bo->funcs->cpu_fini(bo);
542 }
543
544 void
fd_bo_add_fence(struct fd_bo * bo,struct fd_pipe * pipe,uint32_t fence)545 fd_bo_add_fence(struct fd_bo *bo, struct fd_pipe *pipe, uint32_t fence)
546 {
547 simple_mtx_assert_locked(&table_lock);
548
549 if (bo->nosync)
550 return;
551
552 /* The common case is bo re-used on the same pipe it had previously
553 * been used on:
554 */
555 for (int i = 0; i < bo->nr_fences; i++) {
556 struct fd_bo_fence *f = &bo->fences[i];
557 if (f->pipe == pipe) {
558 assert(fd_fence_before(f->fence, fence));
559 f->fence = fence;
560 return;
561 }
562 }
563
564 cleanup_fences(bo, true);
565
566 /* The first time we grow past a single fence, we need some special
567 * handling, as we've been using the embedded _inline_fence to avoid
568 * a separate allocation:
569 */
570 if (unlikely((bo->nr_fences == 1) &&
571 (bo->fences == &bo->_inline_fence))) {
572 bo->nr_fences = bo->max_fences = 0;
573 bo->fences = NULL;
574 APPEND(bo, fences, bo->_inline_fence);
575 }
576
577 APPEND(bo, fences, (struct fd_bo_fence){
578 .pipe = fd_pipe_ref_locked(pipe),
579 .fence = fence,
580 });
581 }
582
583 enum fd_bo_state
fd_bo_state(struct fd_bo * bo)584 fd_bo_state(struct fd_bo *bo)
585 {
586 simple_mtx_assert_locked(&table_lock);
587
588 cleanup_fences(bo, true);
589
590 if (bo->shared || bo->nosync)
591 return FD_BO_STATE_UNKNOWN;
592
593 if (!bo->nr_fences)
594 return FD_BO_STATE_IDLE;
595
596 return FD_BO_STATE_BUSY;
597 }
598
599