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