xref: /aosp_15_r20/external/mesa3d/src/freedreno/drm/freedreno_bo.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker  * Copyright © 2012-2018 Rob Clark <[email protected]>
3*61046927SAndroid Build Coastguard Worker  * SPDX-License-Identifier: MIT
4*61046927SAndroid Build Coastguard Worker  *
5*61046927SAndroid Build Coastguard Worker  * Authors:
6*61046927SAndroid Build Coastguard Worker  *    Rob Clark <[email protected]>
7*61046927SAndroid Build Coastguard Worker  */
8*61046927SAndroid Build Coastguard Worker 
9*61046927SAndroid Build Coastguard Worker #include "util/os_mman.h"
10*61046927SAndroid Build Coastguard Worker 
11*61046927SAndroid Build Coastguard Worker #include "freedreno_drmif.h"
12*61046927SAndroid Build Coastguard Worker #include "freedreno_drm_perfetto.h"
13*61046927SAndroid Build Coastguard Worker #include "freedreno_priv.h"
14*61046927SAndroid Build Coastguard Worker 
15*61046927SAndroid Build Coastguard Worker simple_mtx_t table_lock = SIMPLE_MTX_INITIALIZER;
16*61046927SAndroid Build Coastguard Worker simple_mtx_t fence_lock = SIMPLE_MTX_INITIALIZER;
17*61046927SAndroid Build Coastguard Worker 
18*61046927SAndroid Build Coastguard Worker /* set buffer name, and add to table, call w/ table_lock held: */
19*61046927SAndroid Build Coastguard Worker static void
set_name(struct fd_bo * bo,uint32_t name)20*61046927SAndroid Build Coastguard Worker set_name(struct fd_bo *bo, uint32_t name)
21*61046927SAndroid Build Coastguard Worker {
22*61046927SAndroid Build Coastguard Worker    bo->name = name;
23*61046927SAndroid Build Coastguard Worker    /* add ourself into the handle table: */
24*61046927SAndroid Build Coastguard Worker    _mesa_hash_table_insert(bo->dev->name_table, &bo->name, bo);
25*61046927SAndroid Build Coastguard Worker }
26*61046927SAndroid Build Coastguard Worker 
27*61046927SAndroid Build Coastguard Worker static struct fd_bo zombie;
28*61046927SAndroid Build Coastguard Worker 
29*61046927SAndroid Build Coastguard Worker /* lookup a buffer, call w/ table_lock held: */
30*61046927SAndroid Build Coastguard Worker static struct fd_bo *
lookup_bo(struct hash_table * tbl,uint32_t key)31*61046927SAndroid Build Coastguard Worker lookup_bo(struct hash_table *tbl, uint32_t key)
32*61046927SAndroid Build Coastguard Worker {
33*61046927SAndroid Build Coastguard Worker    struct fd_bo *bo = NULL;
34*61046927SAndroid Build Coastguard Worker    struct hash_entry *entry;
35*61046927SAndroid Build Coastguard Worker 
36*61046927SAndroid Build Coastguard Worker    simple_mtx_assert_locked(&table_lock);
37*61046927SAndroid Build Coastguard Worker 
38*61046927SAndroid Build Coastguard Worker    entry = _mesa_hash_table_search(tbl, &key);
39*61046927SAndroid Build Coastguard Worker    if (entry) {
40*61046927SAndroid Build Coastguard Worker       bo = entry->data;
41*61046927SAndroid Build Coastguard Worker 
42*61046927SAndroid Build Coastguard Worker       /* We could be racing with final unref in another thread, and won
43*61046927SAndroid Build Coastguard Worker        * the table_lock preventing the other thread from being able to
44*61046927SAndroid Build Coastguard Worker        * remove an object it is about to free.  Fortunately since table
45*61046927SAndroid Build Coastguard Worker        * lookup and removal are protected by the same lock (and table
46*61046927SAndroid Build Coastguard Worker        * removal happens before obj free) we can easily detect this by
47*61046927SAndroid Build Coastguard Worker        * checking for refcnt==0 (ie. 1 after p_atomic_inc_return).
48*61046927SAndroid Build Coastguard Worker        */
49*61046927SAndroid Build Coastguard Worker       if (p_atomic_inc_return(&bo->refcnt) == 1) {
50*61046927SAndroid Build Coastguard Worker          /* Restore the zombified reference count, so if another thread
51*61046927SAndroid Build Coastguard Worker           * that ends up calling lookup_bo() gets the table_lock before
52*61046927SAndroid Build Coastguard Worker           * the thread deleting the bo does, it doesn't mistakenly see
53*61046927SAndroid Build Coastguard Worker           * that the BO is live.
54*61046927SAndroid Build Coastguard Worker           *
55*61046927SAndroid Build Coastguard Worker           * We are holding the table_lock here so we can't be racing
56*61046927SAndroid Build Coastguard Worker           * with another caller of lookup_bo()
57*61046927SAndroid Build Coastguard Worker           */
58*61046927SAndroid Build Coastguard Worker          p_atomic_dec(&bo->refcnt);
59*61046927SAndroid Build Coastguard Worker          return &zombie;
60*61046927SAndroid Build Coastguard Worker       }
61*61046927SAndroid Build Coastguard Worker 
62*61046927SAndroid Build Coastguard Worker       if (!list_is_empty(&bo->node)) {
63*61046927SAndroid Build Coastguard Worker          mesa_logw("bo was in cache, size=%u, alloc_flags=0x%x\n",
64*61046927SAndroid Build Coastguard Worker                    bo->size, bo->alloc_flags);
65*61046927SAndroid Build Coastguard Worker       }
66*61046927SAndroid Build Coastguard Worker 
67*61046927SAndroid Build Coastguard Worker       /* don't break the bucket if this bo was found in one */
68*61046927SAndroid Build Coastguard Worker       list_delinit(&bo->node);
69*61046927SAndroid Build Coastguard Worker    }
70*61046927SAndroid Build Coastguard Worker    return bo;
71*61046927SAndroid Build Coastguard Worker }
72*61046927SAndroid Build Coastguard Worker 
73*61046927SAndroid Build Coastguard Worker void
fd_bo_init_common(struct fd_bo * bo,struct fd_device * dev)74*61046927SAndroid Build Coastguard Worker fd_bo_init_common(struct fd_bo *bo, struct fd_device *dev)
75*61046927SAndroid Build Coastguard Worker {
76*61046927SAndroid Build Coastguard Worker    /* Backend should have initialized these: */
77*61046927SAndroid Build Coastguard Worker    assert(bo->size);
78*61046927SAndroid Build Coastguard Worker    assert(bo->handle);
79*61046927SAndroid Build Coastguard Worker    assert(bo->funcs);
80*61046927SAndroid Build Coastguard Worker 
81*61046927SAndroid Build Coastguard Worker    bo->dev = dev;
82*61046927SAndroid Build Coastguard Worker    bo->iova = bo->funcs->iova(bo);
83*61046927SAndroid Build Coastguard Worker    bo->reloc_flags = FD_RELOC_FLAGS_INIT;
84*61046927SAndroid Build Coastguard Worker 
85*61046927SAndroid Build Coastguard Worker    p_atomic_set(&bo->refcnt, 1);
86*61046927SAndroid Build Coastguard Worker    list_inithead(&bo->node);
87*61046927SAndroid Build Coastguard Worker 
88*61046927SAndroid Build Coastguard Worker    bo->max_fences = 1;
89*61046927SAndroid Build Coastguard Worker    bo->fences = &bo->_inline_fence;
90*61046927SAndroid Build Coastguard Worker 
91*61046927SAndroid Build Coastguard Worker    if (!bo->map)
92*61046927SAndroid Build Coastguard Worker       VG_BO_ALLOC(bo);
93*61046927SAndroid Build Coastguard Worker }
94*61046927SAndroid Build Coastguard Worker 
95*61046927SAndroid Build Coastguard Worker /* allocate a new buffer object, call w/ table_lock held */
96*61046927SAndroid Build Coastguard Worker static struct fd_bo *
import_bo_from_handle(struct fd_device * dev,uint32_t size,uint32_t handle)97*61046927SAndroid Build Coastguard Worker import_bo_from_handle(struct fd_device *dev, uint32_t size, uint32_t handle)
98*61046927SAndroid Build Coastguard Worker {
99*61046927SAndroid Build Coastguard Worker    struct fd_bo *bo;
100*61046927SAndroid Build Coastguard Worker 
101*61046927SAndroid Build Coastguard Worker    simple_mtx_assert_locked(&table_lock);
102*61046927SAndroid Build Coastguard Worker 
103*61046927SAndroid Build Coastguard Worker    bo = dev->funcs->bo_from_handle(dev, size, handle);
104*61046927SAndroid Build Coastguard Worker    if (!bo) {
105*61046927SAndroid Build Coastguard Worker       struct drm_gem_close req = {
106*61046927SAndroid Build Coastguard Worker          .handle = handle,
107*61046927SAndroid Build Coastguard Worker       };
108*61046927SAndroid Build Coastguard Worker       drmIoctl(dev->fd, DRM_IOCTL_GEM_CLOSE, &req);
109*61046927SAndroid Build Coastguard Worker       return NULL;
110*61046927SAndroid Build Coastguard Worker    }
111*61046927SAndroid Build Coastguard Worker 
112*61046927SAndroid Build Coastguard Worker    bo->alloc_flags |= FD_BO_SHARED;
113*61046927SAndroid Build Coastguard Worker 
114*61046927SAndroid Build Coastguard Worker    /* add ourself into the handle table: */
115*61046927SAndroid Build Coastguard Worker    _mesa_hash_table_insert(dev->handle_table, &bo->handle, bo);
116*61046927SAndroid Build Coastguard Worker 
117*61046927SAndroid Build Coastguard Worker    return bo;
118*61046927SAndroid Build Coastguard Worker }
119*61046927SAndroid Build Coastguard Worker 
120*61046927SAndroid Build Coastguard Worker static struct fd_bo *
bo_new(struct fd_device * dev,uint32_t size,uint32_t flags,struct fd_bo_cache * cache)121*61046927SAndroid Build Coastguard Worker bo_new(struct fd_device *dev, uint32_t size, uint32_t flags,
122*61046927SAndroid Build Coastguard Worker        struct fd_bo_cache *cache)
123*61046927SAndroid Build Coastguard Worker {
124*61046927SAndroid Build Coastguard Worker    struct fd_bo *bo = NULL;
125*61046927SAndroid Build Coastguard Worker 
126*61046927SAndroid Build Coastguard Worker    if (size < FD_BO_HEAP_BLOCK_SIZE) {
127*61046927SAndroid Build Coastguard Worker       uint32_t alloc_flags = flags & ~_FD_BO_HINTS;
128*61046927SAndroid Build Coastguard Worker       if ((alloc_flags == 0) && dev->default_heap)
129*61046927SAndroid Build Coastguard Worker          bo = fd_bo_heap_alloc(dev->default_heap, size, flags);
130*61046927SAndroid Build Coastguard Worker       else if ((flags == RING_FLAGS) && dev->ring_heap)
131*61046927SAndroid Build Coastguard Worker          bo = fd_bo_heap_alloc(dev->ring_heap, size, flags);
132*61046927SAndroid Build Coastguard Worker       if (bo)
133*61046927SAndroid Build Coastguard Worker          return bo;
134*61046927SAndroid Build Coastguard Worker    }
135*61046927SAndroid Build Coastguard Worker 
136*61046927SAndroid Build Coastguard Worker    /* demote cached-coherent to WC if not supported: */
137*61046927SAndroid Build Coastguard Worker    if ((flags & FD_BO_CACHED_COHERENT) && !dev->has_cached_coherent)
138*61046927SAndroid Build Coastguard Worker       flags &= ~FD_BO_CACHED_COHERENT;
139*61046927SAndroid Build Coastguard Worker 
140*61046927SAndroid Build Coastguard Worker    bo = fd_bo_cache_alloc(cache, &size, flags);
141*61046927SAndroid Build Coastguard Worker    if (bo)
142*61046927SAndroid Build Coastguard Worker       return bo;
143*61046927SAndroid Build Coastguard Worker 
144*61046927SAndroid Build Coastguard Worker    bo = dev->funcs->bo_new(dev, size, flags);
145*61046927SAndroid Build Coastguard Worker    if (!bo)
146*61046927SAndroid Build Coastguard Worker       return NULL;
147*61046927SAndroid Build Coastguard Worker 
148*61046927SAndroid Build Coastguard Worker    simple_mtx_lock(&table_lock);
149*61046927SAndroid Build Coastguard Worker    /* add ourself into the handle table: */
150*61046927SAndroid Build Coastguard Worker    _mesa_hash_table_insert(dev->handle_table, &bo->handle, bo);
151*61046927SAndroid Build Coastguard Worker    simple_mtx_unlock(&table_lock);
152*61046927SAndroid Build Coastguard Worker 
153*61046927SAndroid Build Coastguard Worker    bo->alloc_flags = flags;
154*61046927SAndroid Build Coastguard Worker 
155*61046927SAndroid Build Coastguard Worker    fd_alloc_log(bo, FD_ALLOC_NONE, FD_ALLOC_ACTIVE);
156*61046927SAndroid Build Coastguard Worker 
157*61046927SAndroid Build Coastguard Worker    return bo;
158*61046927SAndroid Build Coastguard Worker }
159*61046927SAndroid Build Coastguard Worker 
160*61046927SAndroid Build Coastguard Worker struct fd_bo *
_fd_bo_new(struct fd_device * dev,uint32_t size,uint32_t flags)161*61046927SAndroid Build Coastguard Worker _fd_bo_new(struct fd_device *dev, uint32_t size, uint32_t flags)
162*61046927SAndroid Build Coastguard Worker {
163*61046927SAndroid Build Coastguard Worker    struct fd_bo *bo = bo_new(dev, size, flags, &dev->bo_cache);
164*61046927SAndroid Build Coastguard Worker    if (bo)
165*61046927SAndroid Build Coastguard Worker       bo->bo_reuse = BO_CACHE;
166*61046927SAndroid Build Coastguard Worker    return bo;
167*61046927SAndroid Build Coastguard Worker }
168*61046927SAndroid Build Coastguard Worker 
169*61046927SAndroid Build Coastguard Worker void
_fd_bo_set_name(struct fd_bo * bo,const char * fmt,va_list ap)170*61046927SAndroid Build Coastguard Worker _fd_bo_set_name(struct fd_bo *bo, const char *fmt, va_list ap)
171*61046927SAndroid Build Coastguard Worker {
172*61046927SAndroid Build Coastguard Worker    bo->funcs->set_name(bo, fmt, ap);
173*61046927SAndroid Build Coastguard Worker }
174*61046927SAndroid Build Coastguard Worker 
175*61046927SAndroid Build Coastguard Worker /* internal function to allocate bo's that use the ringbuffer cache
176*61046927SAndroid Build Coastguard Worker  * instead of the normal bo_cache.  The purpose is, because cmdstream
177*61046927SAndroid Build Coastguard Worker  * bo's get vmap'd on the kernel side, and that is expensive, we want
178*61046927SAndroid Build Coastguard Worker  * to re-use cmdstream bo's for cmdstream and not unrelated purposes.
179*61046927SAndroid Build Coastguard Worker  */
180*61046927SAndroid Build Coastguard Worker struct fd_bo *
fd_bo_new_ring(struct fd_device * dev,uint32_t size)181*61046927SAndroid Build Coastguard Worker fd_bo_new_ring(struct fd_device *dev, uint32_t size)
182*61046927SAndroid Build Coastguard Worker {
183*61046927SAndroid Build Coastguard Worker    struct fd_bo *bo = bo_new(dev, size, RING_FLAGS, &dev->ring_cache);
184*61046927SAndroid Build Coastguard Worker    if (bo) {
185*61046927SAndroid Build Coastguard Worker       bo->bo_reuse = RING_CACHE;
186*61046927SAndroid Build Coastguard Worker       bo->reloc_flags |= FD_RELOC_DUMP;
187*61046927SAndroid Build Coastguard Worker       fd_bo_set_name(bo, "cmdstream");
188*61046927SAndroid Build Coastguard Worker    }
189*61046927SAndroid Build Coastguard Worker    return bo;
190*61046927SAndroid Build Coastguard Worker }
191*61046927SAndroid Build Coastguard Worker 
192*61046927SAndroid Build Coastguard Worker struct fd_bo *
fd_bo_from_handle(struct fd_device * dev,uint32_t handle,uint32_t size)193*61046927SAndroid Build Coastguard Worker fd_bo_from_handle(struct fd_device *dev, uint32_t handle, uint32_t size)
194*61046927SAndroid Build Coastguard Worker {
195*61046927SAndroid Build Coastguard Worker    struct fd_bo *bo = NULL;
196*61046927SAndroid Build Coastguard Worker 
197*61046927SAndroid Build Coastguard Worker    simple_mtx_lock(&table_lock);
198*61046927SAndroid Build Coastguard Worker 
199*61046927SAndroid Build Coastguard Worker    bo = lookup_bo(dev->handle_table, handle);
200*61046927SAndroid Build Coastguard Worker    if (bo)
201*61046927SAndroid Build Coastguard Worker       goto out_unlock;
202*61046927SAndroid Build Coastguard Worker 
203*61046927SAndroid Build Coastguard Worker    bo = import_bo_from_handle(dev, size, handle);
204*61046927SAndroid Build Coastguard Worker 
205*61046927SAndroid Build Coastguard Worker    VG_BO_ALLOC(bo);
206*61046927SAndroid Build Coastguard Worker 
207*61046927SAndroid Build Coastguard Worker out_unlock:
208*61046927SAndroid Build Coastguard Worker    simple_mtx_unlock(&table_lock);
209*61046927SAndroid Build Coastguard Worker 
210*61046927SAndroid Build Coastguard Worker    /* We've raced with the handle being closed, so the handle is no longer
211*61046927SAndroid Build Coastguard Worker     * valid.  Friends don't let friends share handles.
212*61046927SAndroid Build Coastguard Worker     */
213*61046927SAndroid Build Coastguard Worker    if (bo == &zombie)
214*61046927SAndroid Build Coastguard Worker       return NULL;
215*61046927SAndroid Build Coastguard Worker 
216*61046927SAndroid Build Coastguard Worker    return bo;
217*61046927SAndroid Build Coastguard Worker }
218*61046927SAndroid Build Coastguard Worker 
219*61046927SAndroid Build Coastguard Worker uint32_t
fd_handle_from_dmabuf_drm(struct fd_device * dev,int fd)220*61046927SAndroid Build Coastguard Worker fd_handle_from_dmabuf_drm(struct fd_device *dev, int fd)
221*61046927SAndroid Build Coastguard Worker {
222*61046927SAndroid Build Coastguard Worker    uint32_t handle;
223*61046927SAndroid Build Coastguard Worker    int ret = drmPrimeFDToHandle(dev->fd, fd, &handle);
224*61046927SAndroid Build Coastguard Worker    if (ret)
225*61046927SAndroid Build Coastguard Worker       return 0;
226*61046927SAndroid Build Coastguard Worker    return handle;
227*61046927SAndroid Build Coastguard Worker }
228*61046927SAndroid Build Coastguard Worker 
229*61046927SAndroid Build Coastguard Worker struct fd_bo *
fd_bo_from_dmabuf_drm(struct fd_device * dev,int fd)230*61046927SAndroid Build Coastguard Worker fd_bo_from_dmabuf_drm(struct fd_device *dev, int fd)
231*61046927SAndroid Build Coastguard Worker {
232*61046927SAndroid Build Coastguard Worker    int size;
233*61046927SAndroid Build Coastguard Worker    uint32_t handle;
234*61046927SAndroid Build Coastguard Worker    struct fd_bo *bo;
235*61046927SAndroid Build Coastguard Worker 
236*61046927SAndroid Build Coastguard Worker restart:
237*61046927SAndroid Build Coastguard Worker    simple_mtx_lock(&table_lock);
238*61046927SAndroid Build Coastguard Worker    handle = dev->funcs->handle_from_dmabuf(dev, fd);
239*61046927SAndroid Build Coastguard Worker    if (!handle) {
240*61046927SAndroid Build Coastguard Worker       simple_mtx_unlock(&table_lock);
241*61046927SAndroid Build Coastguard Worker       return NULL;
242*61046927SAndroid Build Coastguard Worker    }
243*61046927SAndroid Build Coastguard Worker 
244*61046927SAndroid Build Coastguard Worker    bo = lookup_bo(dev->handle_table, handle);
245*61046927SAndroid Build Coastguard Worker    if (bo)
246*61046927SAndroid Build Coastguard Worker       goto out_unlock;
247*61046927SAndroid Build Coastguard Worker 
248*61046927SAndroid Build Coastguard Worker    /* lseek() to get bo size */
249*61046927SAndroid Build Coastguard Worker    size = lseek(fd, 0, SEEK_END);
250*61046927SAndroid Build Coastguard Worker    lseek(fd, 0, SEEK_CUR);
251*61046927SAndroid Build Coastguard Worker 
252*61046927SAndroid Build Coastguard Worker    bo = import_bo_from_handle(dev, size, handle);
253*61046927SAndroid Build Coastguard Worker 
254*61046927SAndroid Build Coastguard Worker    VG_BO_ALLOC(bo);
255*61046927SAndroid Build Coastguard Worker 
256*61046927SAndroid Build Coastguard Worker out_unlock:
257*61046927SAndroid Build Coastguard Worker    simple_mtx_unlock(&table_lock);
258*61046927SAndroid Build Coastguard Worker 
259*61046927SAndroid Build Coastguard Worker    if (bo == &zombie)
260*61046927SAndroid Build Coastguard Worker       goto restart;
261*61046927SAndroid Build Coastguard Worker 
262*61046927SAndroid Build Coastguard Worker    return bo;
263*61046927SAndroid Build Coastguard Worker }
264*61046927SAndroid Build Coastguard Worker 
265*61046927SAndroid Build Coastguard Worker struct fd_bo *
fd_bo_from_dmabuf(struct fd_device * dev,int fd)266*61046927SAndroid Build Coastguard Worker fd_bo_from_dmabuf(struct fd_device *dev, int fd)
267*61046927SAndroid Build Coastguard Worker {
268*61046927SAndroid Build Coastguard Worker    return dev->funcs->bo_from_dmabuf(dev, fd);
269*61046927SAndroid Build Coastguard Worker }
270*61046927SAndroid Build Coastguard Worker 
271*61046927SAndroid Build Coastguard Worker struct fd_bo *
fd_bo_from_name(struct fd_device * dev,uint32_t name)272*61046927SAndroid Build Coastguard Worker fd_bo_from_name(struct fd_device *dev, uint32_t name)
273*61046927SAndroid Build Coastguard Worker {
274*61046927SAndroid Build Coastguard Worker    struct drm_gem_open req = {
275*61046927SAndroid Build Coastguard Worker       .name = name,
276*61046927SAndroid Build Coastguard Worker    };
277*61046927SAndroid Build Coastguard Worker    struct fd_bo *bo;
278*61046927SAndroid Build Coastguard Worker 
279*61046927SAndroid Build Coastguard Worker    simple_mtx_lock(&table_lock);
280*61046927SAndroid Build Coastguard Worker 
281*61046927SAndroid Build Coastguard Worker    /* check name table first, to see if bo is already open: */
282*61046927SAndroid Build Coastguard Worker    bo = lookup_bo(dev->name_table, name);
283*61046927SAndroid Build Coastguard Worker    if (bo)
284*61046927SAndroid Build Coastguard Worker       goto out_unlock;
285*61046927SAndroid Build Coastguard Worker 
286*61046927SAndroid Build Coastguard Worker restart:
287*61046927SAndroid Build Coastguard Worker    if (drmIoctl(dev->fd, DRM_IOCTL_GEM_OPEN, &req)) {
288*61046927SAndroid Build Coastguard Worker       ERROR_MSG("gem-open failed: %s", strerror(errno));
289*61046927SAndroid Build Coastguard Worker       goto out_unlock;
290*61046927SAndroid Build Coastguard Worker    }
291*61046927SAndroid Build Coastguard Worker 
292*61046927SAndroid Build Coastguard Worker    bo = lookup_bo(dev->handle_table, req.handle);
293*61046927SAndroid Build Coastguard Worker    if (bo)
294*61046927SAndroid Build Coastguard Worker       goto out_unlock;
295*61046927SAndroid Build Coastguard Worker 
296*61046927SAndroid Build Coastguard Worker    bo = import_bo_from_handle(dev, req.size, req.handle);
297*61046927SAndroid Build Coastguard Worker    if (bo) {
298*61046927SAndroid Build Coastguard Worker       set_name(bo, name);
299*61046927SAndroid Build Coastguard Worker       VG_BO_ALLOC(bo);
300*61046927SAndroid Build Coastguard Worker    }
301*61046927SAndroid Build Coastguard Worker 
302*61046927SAndroid Build Coastguard Worker out_unlock:
303*61046927SAndroid Build Coastguard Worker    simple_mtx_unlock(&table_lock);
304*61046927SAndroid Build Coastguard Worker 
305*61046927SAndroid Build Coastguard Worker    if (bo == &zombie)
306*61046927SAndroid Build Coastguard Worker       goto restart;
307*61046927SAndroid Build Coastguard Worker 
308*61046927SAndroid Build Coastguard Worker    return bo;
309*61046927SAndroid Build Coastguard Worker }
310*61046927SAndroid Build Coastguard Worker 
311*61046927SAndroid Build Coastguard Worker void
fd_bo_mark_for_dump(struct fd_bo * bo)312*61046927SAndroid Build Coastguard Worker fd_bo_mark_for_dump(struct fd_bo *bo)
313*61046927SAndroid Build Coastguard Worker {
314*61046927SAndroid Build Coastguard Worker    bo->reloc_flags |= FD_RELOC_DUMP;
315*61046927SAndroid Build Coastguard Worker }
316*61046927SAndroid Build Coastguard Worker 
317*61046927SAndroid Build Coastguard Worker struct fd_bo *
fd_bo_ref(struct fd_bo * bo)318*61046927SAndroid Build Coastguard Worker fd_bo_ref(struct fd_bo *bo)
319*61046927SAndroid Build Coastguard Worker {
320*61046927SAndroid Build Coastguard Worker    ref(&bo->refcnt);
321*61046927SAndroid Build Coastguard Worker    return bo;
322*61046927SAndroid Build Coastguard Worker }
323*61046927SAndroid Build Coastguard Worker 
324*61046927SAndroid Build Coastguard Worker static void
bo_finalize(struct fd_bo * bo)325*61046927SAndroid Build Coastguard Worker bo_finalize(struct fd_bo *bo)
326*61046927SAndroid Build Coastguard Worker {
327*61046927SAndroid Build Coastguard Worker    if (bo->funcs->finalize)
328*61046927SAndroid Build Coastguard Worker       bo->funcs->finalize(bo);
329*61046927SAndroid Build Coastguard Worker }
330*61046927SAndroid Build Coastguard Worker 
331*61046927SAndroid Build Coastguard Worker static void
dev_flush(struct fd_device * dev)332*61046927SAndroid Build Coastguard Worker dev_flush(struct fd_device *dev)
333*61046927SAndroid Build Coastguard Worker {
334*61046927SAndroid Build Coastguard Worker    if (dev->funcs->flush)
335*61046927SAndroid Build Coastguard Worker       dev->funcs->flush(dev);
336*61046927SAndroid Build Coastguard Worker }
337*61046927SAndroid Build Coastguard Worker 
338*61046927SAndroid Build Coastguard Worker static void
bo_del(struct fd_bo * bo)339*61046927SAndroid Build Coastguard Worker bo_del(struct fd_bo *bo)
340*61046927SAndroid Build Coastguard Worker {
341*61046927SAndroid Build Coastguard Worker    bo->funcs->destroy(bo);
342*61046927SAndroid Build Coastguard Worker }
343*61046927SAndroid Build Coastguard Worker 
344*61046927SAndroid Build Coastguard Worker static bool
try_recycle(struct fd_bo * bo)345*61046927SAndroid Build Coastguard Worker try_recycle(struct fd_bo *bo)
346*61046927SAndroid Build Coastguard Worker {
347*61046927SAndroid Build Coastguard Worker    struct fd_device *dev = bo->dev;
348*61046927SAndroid Build Coastguard Worker 
349*61046927SAndroid Build Coastguard Worker    /* No point in BO cache for suballocated buffers: */
350*61046927SAndroid Build Coastguard Worker    if (suballoc_bo(bo))
351*61046927SAndroid Build Coastguard Worker       return false;
352*61046927SAndroid Build Coastguard Worker 
353*61046927SAndroid Build Coastguard Worker    if (bo->bo_reuse == BO_CACHE)
354*61046927SAndroid Build Coastguard Worker       return fd_bo_cache_free(&dev->bo_cache, bo) == 0;
355*61046927SAndroid Build Coastguard Worker 
356*61046927SAndroid Build Coastguard Worker    if (bo->bo_reuse == RING_CACHE)
357*61046927SAndroid Build Coastguard Worker       return fd_bo_cache_free(&dev->ring_cache, bo) == 0;
358*61046927SAndroid Build Coastguard Worker 
359*61046927SAndroid Build Coastguard Worker    return false;
360*61046927SAndroid Build Coastguard Worker }
361*61046927SAndroid Build Coastguard Worker 
362*61046927SAndroid Build Coastguard Worker void
fd_bo_del(struct fd_bo * bo)363*61046927SAndroid Build Coastguard Worker fd_bo_del(struct fd_bo *bo)
364*61046927SAndroid Build Coastguard Worker {
365*61046927SAndroid Build Coastguard Worker    if (!unref(&bo->refcnt))
366*61046927SAndroid Build Coastguard Worker       return;
367*61046927SAndroid Build Coastguard Worker 
368*61046927SAndroid Build Coastguard Worker    if (try_recycle(bo))
369*61046927SAndroid Build Coastguard Worker       return;
370*61046927SAndroid Build Coastguard Worker 
371*61046927SAndroid Build Coastguard Worker    struct fd_device *dev = bo->dev;
372*61046927SAndroid Build Coastguard Worker 
373*61046927SAndroid Build Coastguard Worker    bo_finalize(bo);
374*61046927SAndroid Build Coastguard Worker    dev_flush(dev);
375*61046927SAndroid Build Coastguard Worker    fd_alloc_log(bo, FD_ALLOC_ACTIVE, FD_ALLOC_NONE);
376*61046927SAndroid Build Coastguard Worker    bo_del(bo);
377*61046927SAndroid Build Coastguard Worker }
378*61046927SAndroid Build Coastguard Worker 
379*61046927SAndroid Build Coastguard Worker void
fd_bo_del_array(struct fd_bo ** bos,int count)380*61046927SAndroid Build Coastguard Worker fd_bo_del_array(struct fd_bo **bos, int count)
381*61046927SAndroid Build Coastguard Worker {
382*61046927SAndroid Build Coastguard Worker    if (!count)
383*61046927SAndroid Build Coastguard Worker       return;
384*61046927SAndroid Build Coastguard Worker 
385*61046927SAndroid Build Coastguard Worker    struct fd_device *dev = bos[0]->dev;
386*61046927SAndroid Build Coastguard Worker 
387*61046927SAndroid Build Coastguard Worker    /*
388*61046927SAndroid Build Coastguard Worker     * First pass, remove objects from the table that either (a) still have
389*61046927SAndroid Build Coastguard Worker     * a live reference, or (b) no longer have a reference but are released
390*61046927SAndroid Build Coastguard Worker     * to the BO cache:
391*61046927SAndroid Build Coastguard Worker     */
392*61046927SAndroid Build Coastguard Worker 
393*61046927SAndroid Build Coastguard Worker    for (int i = 0; i < count; i++) {
394*61046927SAndroid Build Coastguard Worker       if (!unref(&bos[i]->refcnt) || try_recycle(bos[i])) {
395*61046927SAndroid Build Coastguard Worker          bos[i--] = bos[--count];
396*61046927SAndroid Build Coastguard Worker       } else {
397*61046927SAndroid Build Coastguard Worker          /* We are going to delete this one, so finalize it first: */
398*61046927SAndroid Build Coastguard Worker          bo_finalize(bos[i]);
399*61046927SAndroid Build Coastguard Worker       }
400*61046927SAndroid Build Coastguard Worker    }
401*61046927SAndroid Build Coastguard Worker 
402*61046927SAndroid Build Coastguard Worker    dev_flush(dev);
403*61046927SAndroid Build Coastguard Worker 
404*61046927SAndroid Build Coastguard Worker    /*
405*61046927SAndroid Build Coastguard Worker     * Second pass, delete all of the objects remaining after first pass.
406*61046927SAndroid Build Coastguard Worker     */
407*61046927SAndroid Build Coastguard Worker 
408*61046927SAndroid Build Coastguard Worker    for (int i = 0; i < count; i++) {
409*61046927SAndroid Build Coastguard Worker       fd_alloc_log(bos[i], FD_ALLOC_ACTIVE, FD_ALLOC_NONE);
410*61046927SAndroid Build Coastguard Worker       bo_del(bos[i]);
411*61046927SAndroid Build Coastguard Worker    }
412*61046927SAndroid Build Coastguard Worker }
413*61046927SAndroid Build Coastguard Worker 
414*61046927SAndroid Build Coastguard Worker /**
415*61046927SAndroid Build Coastguard Worker  * Special interface for fd_bo_cache to batch delete a list of handles.
416*61046927SAndroid Build Coastguard Worker  * Similar to fd_bo_del_array() but bypasses the BO cache (since it is
417*61046927SAndroid Build Coastguard Worker  * called from the BO cache to expire a list of BOs).
418*61046927SAndroid Build Coastguard Worker  */
419*61046927SAndroid Build Coastguard Worker void
fd_bo_del_list_nocache(struct list_head * list)420*61046927SAndroid Build Coastguard Worker fd_bo_del_list_nocache(struct list_head *list)
421*61046927SAndroid Build Coastguard Worker {
422*61046927SAndroid Build Coastguard Worker    if (list_is_empty(list))
423*61046927SAndroid Build Coastguard Worker       return;
424*61046927SAndroid Build Coastguard Worker 
425*61046927SAndroid Build Coastguard Worker    struct fd_device *dev = first_bo(list)->dev;
426*61046927SAndroid Build Coastguard Worker 
427*61046927SAndroid Build Coastguard Worker    foreach_bo (bo, list) {
428*61046927SAndroid Build Coastguard Worker       bo_finalize(bo);
429*61046927SAndroid Build Coastguard Worker    }
430*61046927SAndroid Build Coastguard Worker 
431*61046927SAndroid Build Coastguard Worker    dev_flush(dev);
432*61046927SAndroid Build Coastguard Worker 
433*61046927SAndroid Build Coastguard Worker    foreach_bo_safe (bo, list) {
434*61046927SAndroid Build Coastguard Worker       assert(bo->refcnt == 0);
435*61046927SAndroid Build Coastguard Worker       bo_del(bo);
436*61046927SAndroid Build Coastguard Worker    }
437*61046927SAndroid Build Coastguard Worker }
438*61046927SAndroid Build Coastguard Worker 
439*61046927SAndroid Build Coastguard Worker void
fd_bo_fini_fences(struct fd_bo * bo)440*61046927SAndroid Build Coastguard Worker fd_bo_fini_fences(struct fd_bo *bo)
441*61046927SAndroid Build Coastguard Worker {
442*61046927SAndroid Build Coastguard Worker    for (int i = 0; i < bo->nr_fences; i++)
443*61046927SAndroid Build Coastguard Worker       fd_fence_del(bo->fences[i]);
444*61046927SAndroid Build Coastguard Worker 
445*61046927SAndroid Build Coastguard Worker    if (bo->fences != &bo->_inline_fence)
446*61046927SAndroid Build Coastguard Worker       free(bo->fences);
447*61046927SAndroid Build Coastguard Worker }
448*61046927SAndroid Build Coastguard Worker 
449*61046927SAndroid Build Coastguard Worker void
fd_bo_close_handle_drm(struct fd_bo * bo)450*61046927SAndroid Build Coastguard Worker fd_bo_close_handle_drm(struct fd_bo *bo)
451*61046927SAndroid Build Coastguard Worker {
452*61046927SAndroid Build Coastguard Worker    struct drm_gem_close req = {
453*61046927SAndroid Build Coastguard Worker       .handle = bo->handle,
454*61046927SAndroid Build Coastguard Worker    };
455*61046927SAndroid Build Coastguard Worker    drmIoctl(bo->dev->fd, DRM_IOCTL_GEM_CLOSE, &req);
456*61046927SAndroid Build Coastguard Worker }
457*61046927SAndroid Build Coastguard Worker 
458*61046927SAndroid Build Coastguard Worker /**
459*61046927SAndroid Build Coastguard Worker  * Helper called by backends bo->funcs->destroy()
460*61046927SAndroid Build Coastguard Worker  *
461*61046927SAndroid Build Coastguard Worker  * Called under table_lock, bo_del_flush() *must* be called before
462*61046927SAndroid Build Coastguard Worker  * table_lock is released (but bo->funcs->destroy() can be called
463*61046927SAndroid Build Coastguard Worker  * multiple times before bo_del_flush(), as long as table_lock is
464*61046927SAndroid Build Coastguard Worker  * held the entire time)
465*61046927SAndroid Build Coastguard Worker  */
466*61046927SAndroid Build Coastguard Worker void
fd_bo_fini_common(struct fd_bo * bo)467*61046927SAndroid Build Coastguard Worker fd_bo_fini_common(struct fd_bo *bo)
468*61046927SAndroid Build Coastguard Worker {
469*61046927SAndroid Build Coastguard Worker    struct fd_device *dev = bo->dev;
470*61046927SAndroid Build Coastguard Worker    uint32_t handle = bo->handle;
471*61046927SAndroid Build Coastguard Worker 
472*61046927SAndroid Build Coastguard Worker    VG_BO_FREE(bo);
473*61046927SAndroid Build Coastguard Worker 
474*61046927SAndroid Build Coastguard Worker    fd_bo_fini_fences(bo);
475*61046927SAndroid Build Coastguard Worker 
476*61046927SAndroid Build Coastguard Worker    if (bo->map)
477*61046927SAndroid Build Coastguard Worker       os_munmap(bo->map, bo->size);
478*61046927SAndroid Build Coastguard Worker 
479*61046927SAndroid Build Coastguard Worker    if (handle) {
480*61046927SAndroid Build Coastguard Worker       simple_mtx_lock(&table_lock);
481*61046927SAndroid Build Coastguard Worker       dev->funcs->bo_close_handle(bo);
482*61046927SAndroid Build Coastguard Worker       _mesa_hash_table_remove_key(dev->handle_table, &handle);
483*61046927SAndroid Build Coastguard Worker       if (bo->name)
484*61046927SAndroid Build Coastguard Worker          _mesa_hash_table_remove_key(dev->name_table, &bo->name);
485*61046927SAndroid Build Coastguard Worker       simple_mtx_unlock(&table_lock);
486*61046927SAndroid Build Coastguard Worker    }
487*61046927SAndroid Build Coastguard Worker 
488*61046927SAndroid Build Coastguard Worker    free(bo);
489*61046927SAndroid Build Coastguard Worker }
490*61046927SAndroid Build Coastguard Worker 
491*61046927SAndroid Build Coastguard Worker static void
bo_flush(struct fd_bo * bo)492*61046927SAndroid Build Coastguard Worker bo_flush(struct fd_bo *bo)
493*61046927SAndroid Build Coastguard Worker {
494*61046927SAndroid Build Coastguard Worker    MESA_TRACE_FUNC();
495*61046927SAndroid Build Coastguard Worker 
496*61046927SAndroid Build Coastguard Worker    simple_mtx_lock(&fence_lock);
497*61046927SAndroid Build Coastguard Worker    unsigned nr = bo->nr_fences;
498*61046927SAndroid Build Coastguard Worker    struct fd_fence *fences[nr];
499*61046927SAndroid Build Coastguard Worker    for (unsigned i = 0; i < nr; i++)
500*61046927SAndroid Build Coastguard Worker       fences[i] = fd_fence_ref_locked(bo->fences[i]);
501*61046927SAndroid Build Coastguard Worker    simple_mtx_unlock(&fence_lock);
502*61046927SAndroid Build Coastguard Worker 
503*61046927SAndroid Build Coastguard Worker    for (unsigned i = 0; i < nr; i++) {
504*61046927SAndroid Build Coastguard Worker       fd_fence_flush(bo->fences[i]);
505*61046927SAndroid Build Coastguard Worker       fd_fence_del(fences[i]);
506*61046927SAndroid Build Coastguard Worker    }
507*61046927SAndroid Build Coastguard Worker }
508*61046927SAndroid Build Coastguard Worker 
509*61046927SAndroid Build Coastguard Worker int
fd_bo_get_name(struct fd_bo * bo,uint32_t * name)510*61046927SAndroid Build Coastguard Worker fd_bo_get_name(struct fd_bo *bo, uint32_t *name)
511*61046927SAndroid Build Coastguard Worker {
512*61046927SAndroid Build Coastguard Worker    if (suballoc_bo(bo))
513*61046927SAndroid Build Coastguard Worker       return -1;
514*61046927SAndroid Build Coastguard Worker 
515*61046927SAndroid Build Coastguard Worker    if (!bo->name) {
516*61046927SAndroid Build Coastguard Worker       struct drm_gem_flink req = {
517*61046927SAndroid Build Coastguard Worker          .handle = bo->handle,
518*61046927SAndroid Build Coastguard Worker       };
519*61046927SAndroid Build Coastguard Worker       int ret;
520*61046927SAndroid Build Coastguard Worker 
521*61046927SAndroid Build Coastguard Worker       ret = drmIoctl(bo->dev->fd, DRM_IOCTL_GEM_FLINK, &req);
522*61046927SAndroid Build Coastguard Worker       if (ret) {
523*61046927SAndroid Build Coastguard Worker          return ret;
524*61046927SAndroid Build Coastguard Worker       }
525*61046927SAndroid Build Coastguard Worker 
526*61046927SAndroid Build Coastguard Worker       simple_mtx_lock(&table_lock);
527*61046927SAndroid Build Coastguard Worker       set_name(bo, req.name);
528*61046927SAndroid Build Coastguard Worker       simple_mtx_unlock(&table_lock);
529*61046927SAndroid Build Coastguard Worker       bo->bo_reuse = NO_CACHE;
530*61046927SAndroid Build Coastguard Worker       bo->alloc_flags |= FD_BO_SHARED;
531*61046927SAndroid Build Coastguard Worker       bo_flush(bo);
532*61046927SAndroid Build Coastguard Worker    }
533*61046927SAndroid Build Coastguard Worker 
534*61046927SAndroid Build Coastguard Worker    *name = bo->name;
535*61046927SAndroid Build Coastguard Worker 
536*61046927SAndroid Build Coastguard Worker    return 0;
537*61046927SAndroid Build Coastguard Worker }
538*61046927SAndroid Build Coastguard Worker 
539*61046927SAndroid Build Coastguard Worker uint32_t
fd_bo_handle(struct fd_bo * bo)540*61046927SAndroid Build Coastguard Worker fd_bo_handle(struct fd_bo *bo)
541*61046927SAndroid Build Coastguard Worker {
542*61046927SAndroid Build Coastguard Worker    if (suballoc_bo(bo))
543*61046927SAndroid Build Coastguard Worker       return 0;
544*61046927SAndroid Build Coastguard Worker    bo->bo_reuse = NO_CACHE;
545*61046927SAndroid Build Coastguard Worker    bo->alloc_flags |= FD_BO_SHARED;
546*61046927SAndroid Build Coastguard Worker    bo_flush(bo);
547*61046927SAndroid Build Coastguard Worker    return bo->handle;
548*61046927SAndroid Build Coastguard Worker }
549*61046927SAndroid Build Coastguard Worker 
550*61046927SAndroid Build Coastguard Worker int
fd_bo_dmabuf_drm(struct fd_bo * bo)551*61046927SAndroid Build Coastguard Worker fd_bo_dmabuf_drm(struct fd_bo *bo)
552*61046927SAndroid Build Coastguard Worker {
553*61046927SAndroid Build Coastguard Worker    int ret, prime_fd;
554*61046927SAndroid Build Coastguard Worker 
555*61046927SAndroid Build Coastguard Worker    ret = drmPrimeHandleToFD(bo->dev->fd, bo->handle, DRM_CLOEXEC | DRM_RDWR,
556*61046927SAndroid Build Coastguard Worker                             &prime_fd);
557*61046927SAndroid Build Coastguard Worker    if (ret < 0)
558*61046927SAndroid Build Coastguard Worker       return ret;
559*61046927SAndroid Build Coastguard Worker 
560*61046927SAndroid Build Coastguard Worker    return prime_fd;
561*61046927SAndroid Build Coastguard Worker }
562*61046927SAndroid Build Coastguard Worker 
563*61046927SAndroid Build Coastguard Worker int
fd_bo_dmabuf(struct fd_bo * bo)564*61046927SAndroid Build Coastguard Worker fd_bo_dmabuf(struct fd_bo *bo)
565*61046927SAndroid Build Coastguard Worker {
566*61046927SAndroid Build Coastguard Worker    int ret;
567*61046927SAndroid Build Coastguard Worker 
568*61046927SAndroid Build Coastguard Worker    if (suballoc_bo(bo))
569*61046927SAndroid Build Coastguard Worker       return -1;
570*61046927SAndroid Build Coastguard Worker 
571*61046927SAndroid Build Coastguard Worker    ret = bo->funcs->dmabuf(bo);
572*61046927SAndroid Build Coastguard Worker    if (ret < 0) {
573*61046927SAndroid Build Coastguard Worker       ERROR_MSG("failed to get dmabuf fd: %d", ret);
574*61046927SAndroid Build Coastguard Worker       return ret;
575*61046927SAndroid Build Coastguard Worker    }
576*61046927SAndroid Build Coastguard Worker 
577*61046927SAndroid Build Coastguard Worker    bo->bo_reuse = NO_CACHE;
578*61046927SAndroid Build Coastguard Worker    bo->alloc_flags |= FD_BO_SHARED;
579*61046927SAndroid Build Coastguard Worker    bo_flush(bo);
580*61046927SAndroid Build Coastguard Worker 
581*61046927SAndroid Build Coastguard Worker    return ret;
582*61046927SAndroid Build Coastguard Worker }
583*61046927SAndroid Build Coastguard Worker 
584*61046927SAndroid Build Coastguard Worker uint32_t
fd_bo_size(struct fd_bo * bo)585*61046927SAndroid Build Coastguard Worker fd_bo_size(struct fd_bo *bo)
586*61046927SAndroid Build Coastguard Worker {
587*61046927SAndroid Build Coastguard Worker    return bo->size;
588*61046927SAndroid Build Coastguard Worker }
589*61046927SAndroid Build Coastguard Worker 
590*61046927SAndroid Build Coastguard Worker bool
fd_bo_is_cached(struct fd_bo * bo)591*61046927SAndroid Build Coastguard Worker fd_bo_is_cached(struct fd_bo *bo)
592*61046927SAndroid Build Coastguard Worker {
593*61046927SAndroid Build Coastguard Worker    return !!(bo->alloc_flags & FD_BO_CACHED_COHERENT);
594*61046927SAndroid Build Coastguard Worker }
595*61046927SAndroid Build Coastguard Worker 
596*61046927SAndroid Build Coastguard Worker void
fd_bo_set_metadata(struct fd_bo * bo,void * metadata,uint32_t metadata_size)597*61046927SAndroid Build Coastguard Worker fd_bo_set_metadata(struct fd_bo *bo, void *metadata, uint32_t metadata_size)
598*61046927SAndroid Build Coastguard Worker {
599*61046927SAndroid Build Coastguard Worker    if (!bo->funcs->set_metadata)
600*61046927SAndroid Build Coastguard Worker       return;
601*61046927SAndroid Build Coastguard Worker    bo->funcs->set_metadata(bo, metadata, metadata_size);
602*61046927SAndroid Build Coastguard Worker }
603*61046927SAndroid Build Coastguard Worker 
604*61046927SAndroid Build Coastguard Worker int
fd_bo_get_metadata(struct fd_bo * bo,void * metadata,uint32_t metadata_size)605*61046927SAndroid Build Coastguard Worker fd_bo_get_metadata(struct fd_bo *bo, void *metadata, uint32_t metadata_size)
606*61046927SAndroid Build Coastguard Worker {
607*61046927SAndroid Build Coastguard Worker    if (!bo->funcs->get_metadata)
608*61046927SAndroid Build Coastguard Worker       return -ENOSYS;
609*61046927SAndroid Build Coastguard Worker    return bo->funcs->get_metadata(bo, metadata, metadata_size);
610*61046927SAndroid Build Coastguard Worker }
611*61046927SAndroid Build Coastguard Worker 
612*61046927SAndroid Build Coastguard Worker void *
fd_bo_map_os_mmap(struct fd_bo * bo)613*61046927SAndroid Build Coastguard Worker fd_bo_map_os_mmap(struct fd_bo *bo)
614*61046927SAndroid Build Coastguard Worker {
615*61046927SAndroid Build Coastguard Worker    uint64_t offset;
616*61046927SAndroid Build Coastguard Worker    int ret;
617*61046927SAndroid Build Coastguard Worker    ret = bo->funcs->offset(bo, &offset);
618*61046927SAndroid Build Coastguard Worker    if (ret) {
619*61046927SAndroid Build Coastguard Worker       return NULL;
620*61046927SAndroid Build Coastguard Worker    }
621*61046927SAndroid Build Coastguard Worker    return os_mmap(0, bo->size, PROT_READ | PROT_WRITE, MAP_SHARED,
622*61046927SAndroid Build Coastguard Worker                   bo->dev->fd, offset);
623*61046927SAndroid Build Coastguard Worker }
624*61046927SAndroid Build Coastguard Worker 
625*61046927SAndroid Build Coastguard Worker /* For internal use only, does not check FD_BO_NOMAP: */
626*61046927SAndroid Build Coastguard Worker void *
__fd_bo_map(struct fd_bo * bo)627*61046927SAndroid Build Coastguard Worker __fd_bo_map(struct fd_bo *bo)
628*61046927SAndroid Build Coastguard Worker {
629*61046927SAndroid Build Coastguard Worker    if (!bo->map) {
630*61046927SAndroid Build Coastguard Worker       bo->map = bo->funcs->map(bo);
631*61046927SAndroid Build Coastguard Worker       if (bo->map == MAP_FAILED) {
632*61046927SAndroid Build Coastguard Worker          ERROR_MSG("mmap failed: %s", strerror(errno));
633*61046927SAndroid Build Coastguard Worker          bo->map = NULL;
634*61046927SAndroid Build Coastguard Worker       }
635*61046927SAndroid Build Coastguard Worker    }
636*61046927SAndroid Build Coastguard Worker 
637*61046927SAndroid Build Coastguard Worker    return bo->map;
638*61046927SAndroid Build Coastguard Worker }
639*61046927SAndroid Build Coastguard Worker 
640*61046927SAndroid Build Coastguard Worker void *
fd_bo_map(struct fd_bo * bo)641*61046927SAndroid Build Coastguard Worker fd_bo_map(struct fd_bo *bo)
642*61046927SAndroid Build Coastguard Worker {
643*61046927SAndroid Build Coastguard Worker    /* don't allow mmap'ing something allocated with FD_BO_NOMAP
644*61046927SAndroid Build Coastguard Worker     * for sanity
645*61046927SAndroid Build Coastguard Worker     */
646*61046927SAndroid Build Coastguard Worker    if (bo->alloc_flags & FD_BO_NOMAP)
647*61046927SAndroid Build Coastguard Worker       return NULL;
648*61046927SAndroid Build Coastguard Worker 
649*61046927SAndroid Build Coastguard Worker    return __fd_bo_map(bo);
650*61046927SAndroid Build Coastguard Worker }
651*61046927SAndroid Build Coastguard Worker 
652*61046927SAndroid Build Coastguard Worker static void *
fd_bo_map_for_upload(struct fd_bo * bo)653*61046927SAndroid Build Coastguard Worker fd_bo_map_for_upload(struct fd_bo *bo)
654*61046927SAndroid Build Coastguard Worker {
655*61046927SAndroid Build Coastguard Worker    void *addr = __fd_bo_map(bo);
656*61046927SAndroid Build Coastguard Worker    if (bo->alloc_flags & FD_BO_NOMAP)
657*61046927SAndroid Build Coastguard Worker       VG_BO_MAPPED(bo);
658*61046927SAndroid Build Coastguard Worker 
659*61046927SAndroid Build Coastguard Worker    return addr;
660*61046927SAndroid Build Coastguard Worker }
661*61046927SAndroid Build Coastguard Worker 
662*61046927SAndroid Build Coastguard Worker void
fd_bo_upload(struct fd_bo * bo,void * src,unsigned off,unsigned len)663*61046927SAndroid Build Coastguard Worker fd_bo_upload(struct fd_bo *bo, void *src, unsigned off, unsigned len)
664*61046927SAndroid Build Coastguard Worker {
665*61046927SAndroid Build Coastguard Worker    if (bo->funcs->upload) {
666*61046927SAndroid Build Coastguard Worker       bo->funcs->upload(bo, src, off, len);
667*61046927SAndroid Build Coastguard Worker       return;
668*61046927SAndroid Build Coastguard Worker    }
669*61046927SAndroid Build Coastguard Worker 
670*61046927SAndroid Build Coastguard Worker    memcpy((uint8_t *)fd_bo_map_for_upload(bo) + off, src, len);
671*61046927SAndroid Build Coastguard Worker }
672*61046927SAndroid Build Coastguard Worker 
673*61046927SAndroid Build Coastguard Worker bool
fd_bo_prefer_upload(struct fd_bo * bo,unsigned len)674*61046927SAndroid Build Coastguard Worker fd_bo_prefer_upload(struct fd_bo *bo, unsigned len)
675*61046927SAndroid Build Coastguard Worker {
676*61046927SAndroid Build Coastguard Worker    if (bo->funcs->prefer_upload)
677*61046927SAndroid Build Coastguard Worker       return bo->funcs->prefer_upload(bo, len);
678*61046927SAndroid Build Coastguard Worker 
679*61046927SAndroid Build Coastguard Worker    return false;
680*61046927SAndroid Build Coastguard Worker }
681*61046927SAndroid Build Coastguard Worker 
682*61046927SAndroid Build Coastguard Worker /* a bit odd to take the pipe as an arg, but it's a, umm, quirk of kgsl.. */
683*61046927SAndroid Build Coastguard Worker int
fd_bo_cpu_prep(struct fd_bo * bo,struct fd_pipe * pipe,uint32_t op)684*61046927SAndroid Build Coastguard Worker fd_bo_cpu_prep(struct fd_bo *bo, struct fd_pipe *pipe, uint32_t op)
685*61046927SAndroid Build Coastguard Worker {
686*61046927SAndroid Build Coastguard Worker    enum fd_bo_state state = fd_bo_state(bo);
687*61046927SAndroid Build Coastguard Worker 
688*61046927SAndroid Build Coastguard Worker    if (state == FD_BO_STATE_IDLE)
689*61046927SAndroid Build Coastguard Worker       return 0;
690*61046927SAndroid Build Coastguard Worker 
691*61046927SAndroid Build Coastguard Worker    MESA_TRACE_FUNC();
692*61046927SAndroid Build Coastguard Worker 
693*61046927SAndroid Build Coastguard Worker    if (op & (FD_BO_PREP_NOSYNC | FD_BO_PREP_FLUSH)) {
694*61046927SAndroid Build Coastguard Worker       if (op & FD_BO_PREP_FLUSH)
695*61046927SAndroid Build Coastguard Worker          bo_flush(bo);
696*61046927SAndroid Build Coastguard Worker 
697*61046927SAndroid Build Coastguard Worker       /* If we have *only* been asked to flush, then we aren't really
698*61046927SAndroid Build Coastguard Worker        * interested about whether shared buffers are busy, so avoid
699*61046927SAndroid Build Coastguard Worker        * the kernel ioctl.
700*61046927SAndroid Build Coastguard Worker        */
701*61046927SAndroid Build Coastguard Worker       if ((state == FD_BO_STATE_BUSY) ||
702*61046927SAndroid Build Coastguard Worker           (op == FD_BO_PREP_FLUSH))
703*61046927SAndroid Build Coastguard Worker          return -EBUSY;
704*61046927SAndroid Build Coastguard Worker    }
705*61046927SAndroid Build Coastguard Worker 
706*61046927SAndroid Build Coastguard Worker    /* In case the bo is referenced by a deferred submit, flush up to the
707*61046927SAndroid Build Coastguard Worker     * required fence now:
708*61046927SAndroid Build Coastguard Worker     */
709*61046927SAndroid Build Coastguard Worker    bo_flush(bo);
710*61046927SAndroid Build Coastguard Worker 
711*61046927SAndroid Build Coastguard Worker    /* FD_BO_PREP_FLUSH is purely a frontend flag, and is not seen/handled
712*61046927SAndroid Build Coastguard Worker     * by backend or kernel:
713*61046927SAndroid Build Coastguard Worker     */
714*61046927SAndroid Build Coastguard Worker    op &= ~FD_BO_PREP_FLUSH;
715*61046927SAndroid Build Coastguard Worker 
716*61046927SAndroid Build Coastguard Worker    if (!op)
717*61046927SAndroid Build Coastguard Worker       return 0;
718*61046927SAndroid Build Coastguard Worker 
719*61046927SAndroid Build Coastguard Worker    /* Wait on fences.. first grab a reference under the fence lock, and then
720*61046927SAndroid Build Coastguard Worker     * wait and drop ref.
721*61046927SAndroid Build Coastguard Worker     */
722*61046927SAndroid Build Coastguard Worker    simple_mtx_lock(&fence_lock);
723*61046927SAndroid Build Coastguard Worker    unsigned nr = bo->nr_fences;
724*61046927SAndroid Build Coastguard Worker    struct fd_fence *fences[nr];
725*61046927SAndroid Build Coastguard Worker    for (unsigned i = 0; i < nr; i++)
726*61046927SAndroid Build Coastguard Worker       fences[i] = fd_fence_ref_locked(bo->fences[i]);
727*61046927SAndroid Build Coastguard Worker    simple_mtx_unlock(&fence_lock);
728*61046927SAndroid Build Coastguard Worker 
729*61046927SAndroid Build Coastguard Worker    for (unsigned i = 0; i < nr; i++) {
730*61046927SAndroid Build Coastguard Worker       fd_fence_wait(fences[i]);
731*61046927SAndroid Build Coastguard Worker       fd_fence_del(fences[i]);
732*61046927SAndroid Build Coastguard Worker    }
733*61046927SAndroid Build Coastguard Worker 
734*61046927SAndroid Build Coastguard Worker    /* expire completed fences */
735*61046927SAndroid Build Coastguard Worker    fd_bo_state(bo);
736*61046927SAndroid Build Coastguard Worker 
737*61046927SAndroid Build Coastguard Worker    /* None shared buffers will not have any external usage (ie. fences
738*61046927SAndroid Build Coastguard Worker     * that we are not aware of) so nothing more to do.
739*61046927SAndroid Build Coastguard Worker     */
740*61046927SAndroid Build Coastguard Worker    if (!(bo->alloc_flags & FD_BO_SHARED))
741*61046927SAndroid Build Coastguard Worker       return 0;
742*61046927SAndroid Build Coastguard Worker 
743*61046927SAndroid Build Coastguard Worker    /* If buffer is shared, but we are using explicit sync, no need to
744*61046927SAndroid Build Coastguard Worker     * fallback to implicit sync:
745*61046927SAndroid Build Coastguard Worker     */
746*61046927SAndroid Build Coastguard Worker    if (pipe && pipe->no_implicit_sync)
747*61046927SAndroid Build Coastguard Worker       return 0;
748*61046927SAndroid Build Coastguard Worker 
749*61046927SAndroid Build Coastguard Worker    return bo->funcs->cpu_prep(bo, pipe, op);
750*61046927SAndroid Build Coastguard Worker }
751*61046927SAndroid Build Coastguard Worker 
752*61046927SAndroid Build Coastguard Worker /**
753*61046927SAndroid Build Coastguard Worker  * Cleanup fences, dropping pipe references.  If 'expired' is true, only
754*61046927SAndroid Build Coastguard Worker  * cleanup expired fences.
755*61046927SAndroid Build Coastguard Worker  *
756*61046927SAndroid Build Coastguard Worker  * Normally we expect at most a single fence, the exception being bo's
757*61046927SAndroid Build Coastguard Worker  * shared between contexts
758*61046927SAndroid Build Coastguard Worker  */
759*61046927SAndroid Build Coastguard Worker static void
cleanup_fences(struct fd_bo * bo)760*61046927SAndroid Build Coastguard Worker cleanup_fences(struct fd_bo *bo)
761*61046927SAndroid Build Coastguard Worker {
762*61046927SAndroid Build Coastguard Worker    simple_mtx_assert_locked(&fence_lock);
763*61046927SAndroid Build Coastguard Worker 
764*61046927SAndroid Build Coastguard Worker    for (int i = 0; i < bo->nr_fences; i++) {
765*61046927SAndroid Build Coastguard Worker       struct fd_fence *f = bo->fences[i];
766*61046927SAndroid Build Coastguard Worker 
767*61046927SAndroid Build Coastguard Worker       if (fd_fence_before(f->pipe->control->fence, f->ufence))
768*61046927SAndroid Build Coastguard Worker          continue;
769*61046927SAndroid Build Coastguard Worker 
770*61046927SAndroid Build Coastguard Worker       bo->nr_fences--;
771*61046927SAndroid Build Coastguard Worker 
772*61046927SAndroid Build Coastguard Worker       if (bo->nr_fences > 0) {
773*61046927SAndroid Build Coastguard Worker          /* Shuffle up the last entry to replace the current slot: */
774*61046927SAndroid Build Coastguard Worker          bo->fences[i] = bo->fences[bo->nr_fences];
775*61046927SAndroid Build Coastguard Worker          i--;
776*61046927SAndroid Build Coastguard Worker       }
777*61046927SAndroid Build Coastguard Worker 
778*61046927SAndroid Build Coastguard Worker       fd_fence_del_locked(f);
779*61046927SAndroid Build Coastguard Worker    }
780*61046927SAndroid Build Coastguard Worker }
781*61046927SAndroid Build Coastguard Worker 
782*61046927SAndroid Build Coastguard Worker void
fd_bo_add_fence(struct fd_bo * bo,struct fd_fence * fence)783*61046927SAndroid Build Coastguard Worker fd_bo_add_fence(struct fd_bo *bo, struct fd_fence *fence)
784*61046927SAndroid Build Coastguard Worker {
785*61046927SAndroid Build Coastguard Worker    simple_mtx_assert_locked(&fence_lock);
786*61046927SAndroid Build Coastguard Worker 
787*61046927SAndroid Build Coastguard Worker    if (bo->alloc_flags & _FD_BO_NOSYNC)
788*61046927SAndroid Build Coastguard Worker       return;
789*61046927SAndroid Build Coastguard Worker 
790*61046927SAndroid Build Coastguard Worker    /* The common case is bo re-used on the same pipe it had previously
791*61046927SAndroid Build Coastguard Worker     * been used on, so just replace the previous fence.
792*61046927SAndroid Build Coastguard Worker     */
793*61046927SAndroid Build Coastguard Worker    for (int i = 0; i < bo->nr_fences; i++) {
794*61046927SAndroid Build Coastguard Worker       struct fd_fence *f = bo->fences[i];
795*61046927SAndroid Build Coastguard Worker       if (f == fence)
796*61046927SAndroid Build Coastguard Worker          return;
797*61046927SAndroid Build Coastguard Worker       if (f->pipe == fence->pipe) {
798*61046927SAndroid Build Coastguard Worker          assert(fd_fence_before(f->ufence, fence->ufence));
799*61046927SAndroid Build Coastguard Worker          fd_fence_del_locked(f);
800*61046927SAndroid Build Coastguard Worker          bo->fences[i] = fd_fence_ref_locked(fence);
801*61046927SAndroid Build Coastguard Worker          return;
802*61046927SAndroid Build Coastguard Worker       }
803*61046927SAndroid Build Coastguard Worker    }
804*61046927SAndroid Build Coastguard Worker 
805*61046927SAndroid Build Coastguard Worker    cleanup_fences(bo);
806*61046927SAndroid Build Coastguard Worker 
807*61046927SAndroid Build Coastguard Worker    /* The first time we grow past a single fence, we need some special
808*61046927SAndroid Build Coastguard Worker     * handling, as we've been using the embedded _inline_fence to avoid
809*61046927SAndroid Build Coastguard Worker     * a separate allocation:
810*61046927SAndroid Build Coastguard Worker     */
811*61046927SAndroid Build Coastguard Worker    if (unlikely((bo->nr_fences == 1) &&
812*61046927SAndroid Build Coastguard Worker                 (bo->fences == &bo->_inline_fence))) {
813*61046927SAndroid Build Coastguard Worker       bo->nr_fences = bo->max_fences = 0;
814*61046927SAndroid Build Coastguard Worker       bo->fences = NULL;
815*61046927SAndroid Build Coastguard Worker       APPEND(bo, fences, bo->_inline_fence);
816*61046927SAndroid Build Coastguard Worker    }
817*61046927SAndroid Build Coastguard Worker 
818*61046927SAndroid Build Coastguard Worker    APPEND(bo, fences, fd_fence_ref_locked(fence));
819*61046927SAndroid Build Coastguard Worker }
820*61046927SAndroid Build Coastguard Worker 
821*61046927SAndroid Build Coastguard Worker enum fd_bo_state
fd_bo_state(struct fd_bo * bo)822*61046927SAndroid Build Coastguard Worker fd_bo_state(struct fd_bo *bo)
823*61046927SAndroid Build Coastguard Worker {
824*61046927SAndroid Build Coastguard Worker    /* NOTE: check the nosync case before touching fence_lock in case we end
825*61046927SAndroid Build Coastguard Worker     * up here recursively from dropping pipe reference in cleanup_fences().
826*61046927SAndroid Build Coastguard Worker     * The pipe's control buffer is specifically nosync to avoid recursive
827*61046927SAndroid Build Coastguard Worker     * lock problems here.
828*61046927SAndroid Build Coastguard Worker     */
829*61046927SAndroid Build Coastguard Worker    if (bo->alloc_flags & (FD_BO_SHARED | _FD_BO_NOSYNC))
830*61046927SAndroid Build Coastguard Worker       return FD_BO_STATE_UNKNOWN;
831*61046927SAndroid Build Coastguard Worker 
832*61046927SAndroid Build Coastguard Worker    /* Speculatively check, if we already know we're idle, no need to acquire
833*61046927SAndroid Build Coastguard Worker     * lock and do the cleanup_fences() dance:
834*61046927SAndroid Build Coastguard Worker     */
835*61046927SAndroid Build Coastguard Worker    if (!bo->nr_fences)
836*61046927SAndroid Build Coastguard Worker       return FD_BO_STATE_IDLE;
837*61046927SAndroid Build Coastguard Worker 
838*61046927SAndroid Build Coastguard Worker    simple_mtx_lock(&fence_lock);
839*61046927SAndroid Build Coastguard Worker    cleanup_fences(bo);
840*61046927SAndroid Build Coastguard Worker    simple_mtx_unlock(&fence_lock);
841*61046927SAndroid Build Coastguard Worker 
842*61046927SAndroid Build Coastguard Worker    if (!bo->nr_fences)
843*61046927SAndroid Build Coastguard Worker       return FD_BO_STATE_IDLE;
844*61046927SAndroid Build Coastguard Worker 
845*61046927SAndroid Build Coastguard Worker    return FD_BO_STATE_BUSY;
846*61046927SAndroid Build Coastguard Worker }
847*61046927SAndroid Build Coastguard Worker 
848