1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci * Copyright (C) 2012-2018 Rob Clark <robclark@freedesktop.org>
3bf215546Sopenharmony_ci *
4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation
7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions:
10bf215546Sopenharmony_ci *
11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next
12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the
13bf215546Sopenharmony_ci * Software.
14bf215546Sopenharmony_ci *
15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20bf215546Sopenharmony_ci * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21bf215546Sopenharmony_ci * SOFTWARE.
22bf215546Sopenharmony_ci *
23bf215546Sopenharmony_ci * Authors:
24bf215546Sopenharmony_ci *    Rob Clark <robclark@freedesktop.org>
25bf215546Sopenharmony_ci */
26bf215546Sopenharmony_ci
27bf215546Sopenharmony_ci#include <assert.h>
28bf215546Sopenharmony_ci#include <inttypes.h>
29bf215546Sopenharmony_ci
30bf215546Sopenharmony_ci#include "util/hash_table.h"
31bf215546Sopenharmony_ci#include "util/set.h"
32bf215546Sopenharmony_ci#include "util/slab.h"
33bf215546Sopenharmony_ci
34bf215546Sopenharmony_ci#include "drm/freedreno_ringbuffer.h"
35bf215546Sopenharmony_ci#include "msm_priv.h"
36bf215546Sopenharmony_ci
37bf215546Sopenharmony_ci/* The legacy implementation of submit/ringbuffer, which still does the
38bf215546Sopenharmony_ci * traditional reloc and cmd tracking
39bf215546Sopenharmony_ci */
40bf215546Sopenharmony_ci
41bf215546Sopenharmony_ci#define INIT_SIZE 0x1000
42bf215546Sopenharmony_ci
43bf215546Sopenharmony_cistruct msm_submit {
44bf215546Sopenharmony_ci   struct fd_submit base;
45bf215546Sopenharmony_ci
46bf215546Sopenharmony_ci   DECLARE_ARRAY(struct drm_msm_gem_submit_bo, submit_bos);
47bf215546Sopenharmony_ci   DECLARE_ARRAY(struct fd_bo *, bos);
48bf215546Sopenharmony_ci
49bf215546Sopenharmony_ci   /* maps fd_bo to idx in bos table: */
50bf215546Sopenharmony_ci   struct hash_table *bo_table;
51bf215546Sopenharmony_ci
52bf215546Sopenharmony_ci   struct slab_mempool ring_pool;
53bf215546Sopenharmony_ci
54bf215546Sopenharmony_ci   /* hash-set of associated rings: */
55bf215546Sopenharmony_ci   struct set *ring_set;
56bf215546Sopenharmony_ci
57bf215546Sopenharmony_ci   /* Allow for sub-allocation of stateobj ring buffers (ie. sharing
58bf215546Sopenharmony_ci    * the same underlying bo)..
59bf215546Sopenharmony_ci    *
60bf215546Sopenharmony_ci    * We also rely on previous stateobj having been fully constructed
61bf215546Sopenharmony_ci    * so we can reclaim extra space at it's end.
62bf215546Sopenharmony_ci    */
63bf215546Sopenharmony_ci   struct fd_ringbuffer *suballoc_ring;
64bf215546Sopenharmony_ci};
65bf215546Sopenharmony_ciFD_DEFINE_CAST(fd_submit, msm_submit);
66bf215546Sopenharmony_ci
67bf215546Sopenharmony_ci/* for FD_RINGBUFFER_GROWABLE rb's, tracks the 'finalized' cmdstream buffers
68bf215546Sopenharmony_ci * and sizes.  Ie. a finalized buffer can have no more commands appended to
69bf215546Sopenharmony_ci * it.
70bf215546Sopenharmony_ci */
71bf215546Sopenharmony_cistruct msm_cmd {
72bf215546Sopenharmony_ci   struct fd_bo *ring_bo;
73bf215546Sopenharmony_ci   unsigned size;
74bf215546Sopenharmony_ci   DECLARE_ARRAY(struct drm_msm_gem_submit_reloc, relocs);
75bf215546Sopenharmony_ci};
76bf215546Sopenharmony_ci
77bf215546Sopenharmony_cistatic struct msm_cmd *
78bf215546Sopenharmony_cicmd_new(struct fd_bo *ring_bo)
79bf215546Sopenharmony_ci{
80bf215546Sopenharmony_ci   struct msm_cmd *cmd = malloc(sizeof(*cmd));
81bf215546Sopenharmony_ci   cmd->ring_bo = fd_bo_ref(ring_bo);
82bf215546Sopenharmony_ci   cmd->size = 0;
83bf215546Sopenharmony_ci   cmd->nr_relocs = cmd->max_relocs = 0;
84bf215546Sopenharmony_ci   cmd->relocs = NULL;
85bf215546Sopenharmony_ci   return cmd;
86bf215546Sopenharmony_ci}
87bf215546Sopenharmony_ci
88bf215546Sopenharmony_cistatic void
89bf215546Sopenharmony_cicmd_free(struct msm_cmd *cmd)
90bf215546Sopenharmony_ci{
91bf215546Sopenharmony_ci   fd_bo_del(cmd->ring_bo);
92bf215546Sopenharmony_ci   free(cmd->relocs);
93bf215546Sopenharmony_ci   free(cmd);
94bf215546Sopenharmony_ci}
95bf215546Sopenharmony_ci
96bf215546Sopenharmony_cistruct msm_ringbuffer {
97bf215546Sopenharmony_ci   struct fd_ringbuffer base;
98bf215546Sopenharmony_ci
99bf215546Sopenharmony_ci   /* for FD_RINGBUFFER_STREAMING rb's which are sub-allocated */
100bf215546Sopenharmony_ci   unsigned offset;
101bf215546Sopenharmony_ci
102bf215546Sopenharmony_ci   union {
103bf215546Sopenharmony_ci      /* for _FD_RINGBUFFER_OBJECT case: */
104bf215546Sopenharmony_ci      struct {
105bf215546Sopenharmony_ci         struct fd_pipe *pipe;
106bf215546Sopenharmony_ci         DECLARE_ARRAY(struct fd_bo *, reloc_bos);
107bf215546Sopenharmony_ci         struct set *ring_set;
108bf215546Sopenharmony_ci      };
109bf215546Sopenharmony_ci      /* for other cases: */
110bf215546Sopenharmony_ci      struct {
111bf215546Sopenharmony_ci         struct fd_submit *submit;
112bf215546Sopenharmony_ci         DECLARE_ARRAY(struct msm_cmd *, cmds);
113bf215546Sopenharmony_ci      };
114bf215546Sopenharmony_ci   } u;
115bf215546Sopenharmony_ci
116bf215546Sopenharmony_ci   struct msm_cmd *cmd; /* current cmd */
117bf215546Sopenharmony_ci   struct fd_bo *ring_bo;
118bf215546Sopenharmony_ci};
119bf215546Sopenharmony_ciFD_DEFINE_CAST(fd_ringbuffer, msm_ringbuffer);
120bf215546Sopenharmony_ci
121bf215546Sopenharmony_cistatic void finalize_current_cmd(struct fd_ringbuffer *ring);
122bf215546Sopenharmony_cistatic struct fd_ringbuffer *
123bf215546Sopenharmony_cimsm_ringbuffer_init(struct msm_ringbuffer *msm_ring, uint32_t size,
124bf215546Sopenharmony_ci                    enum fd_ringbuffer_flags flags);
125bf215546Sopenharmony_ci
126bf215546Sopenharmony_ci/* add (if needed) bo to submit and return index: */
127bf215546Sopenharmony_cistatic uint32_t
128bf215546Sopenharmony_ciappend_bo(struct msm_submit *submit, struct fd_bo *bo)
129bf215546Sopenharmony_ci{
130bf215546Sopenharmony_ci   uint32_t idx;
131bf215546Sopenharmony_ci
132bf215546Sopenharmony_ci   /* NOTE: it is legal to use the same bo on different threads for
133bf215546Sopenharmony_ci    * different submits.  But it is not legal to use the same submit
134bf215546Sopenharmony_ci    * from given threads.
135bf215546Sopenharmony_ci    */
136bf215546Sopenharmony_ci   idx = READ_ONCE(bo->idx);
137bf215546Sopenharmony_ci
138bf215546Sopenharmony_ci   if (unlikely((idx >= submit->nr_submit_bos) ||
139bf215546Sopenharmony_ci                (submit->submit_bos[idx].handle != bo->handle))) {
140bf215546Sopenharmony_ci      uint32_t hash = _mesa_hash_pointer(bo);
141bf215546Sopenharmony_ci      struct hash_entry *entry;
142bf215546Sopenharmony_ci
143bf215546Sopenharmony_ci      entry = _mesa_hash_table_search_pre_hashed(submit->bo_table, hash, bo);
144bf215546Sopenharmony_ci      if (entry) {
145bf215546Sopenharmony_ci         /* found */
146bf215546Sopenharmony_ci         idx = (uint32_t)(uintptr_t)entry->data;
147bf215546Sopenharmony_ci      } else {
148bf215546Sopenharmony_ci         idx = APPEND(
149bf215546Sopenharmony_ci            submit, submit_bos,
150bf215546Sopenharmony_ci            (struct drm_msm_gem_submit_bo){
151bf215546Sopenharmony_ci               .flags = bo->reloc_flags & (MSM_SUBMIT_BO_READ | MSM_SUBMIT_BO_WRITE),
152bf215546Sopenharmony_ci               .handle = bo->handle,
153bf215546Sopenharmony_ci               .presumed = 0,
154bf215546Sopenharmony_ci            });
155bf215546Sopenharmony_ci         APPEND(submit, bos, fd_bo_ref(bo));
156bf215546Sopenharmony_ci
157bf215546Sopenharmony_ci         _mesa_hash_table_insert_pre_hashed(submit->bo_table, hash, bo,
158bf215546Sopenharmony_ci                                            (void *)(uintptr_t)idx);
159bf215546Sopenharmony_ci      }
160bf215546Sopenharmony_ci      bo->idx = idx;
161bf215546Sopenharmony_ci   }
162bf215546Sopenharmony_ci
163bf215546Sopenharmony_ci   return idx;
164bf215546Sopenharmony_ci}
165bf215546Sopenharmony_ci
166bf215546Sopenharmony_cistatic void
167bf215546Sopenharmony_ciappend_ring(struct set *set, struct fd_ringbuffer *ring)
168bf215546Sopenharmony_ci{
169bf215546Sopenharmony_ci   uint32_t hash = _mesa_hash_pointer(ring);
170bf215546Sopenharmony_ci
171bf215546Sopenharmony_ci   if (!_mesa_set_search_pre_hashed(set, hash, ring)) {
172bf215546Sopenharmony_ci      fd_ringbuffer_ref(ring);
173bf215546Sopenharmony_ci      _mesa_set_add_pre_hashed(set, hash, ring);
174bf215546Sopenharmony_ci   }
175bf215546Sopenharmony_ci}
176bf215546Sopenharmony_ci
177bf215546Sopenharmony_cistatic void
178bf215546Sopenharmony_cimsm_submit_suballoc_ring_bo(struct fd_submit *submit,
179bf215546Sopenharmony_ci                            struct msm_ringbuffer *msm_ring, uint32_t size)
180bf215546Sopenharmony_ci{
181bf215546Sopenharmony_ci   struct msm_submit *msm_submit = to_msm_submit(submit);
182bf215546Sopenharmony_ci   unsigned suballoc_offset = 0;
183bf215546Sopenharmony_ci   struct fd_bo *suballoc_bo = NULL;
184bf215546Sopenharmony_ci
185bf215546Sopenharmony_ci   if (msm_submit->suballoc_ring) {
186bf215546Sopenharmony_ci      struct msm_ringbuffer *suballoc_ring =
187bf215546Sopenharmony_ci         to_msm_ringbuffer(msm_submit->suballoc_ring);
188bf215546Sopenharmony_ci
189bf215546Sopenharmony_ci      suballoc_bo = suballoc_ring->ring_bo;
190bf215546Sopenharmony_ci      suballoc_offset =
191bf215546Sopenharmony_ci         fd_ringbuffer_size(msm_submit->suballoc_ring) + suballoc_ring->offset;
192bf215546Sopenharmony_ci
193bf215546Sopenharmony_ci      suballoc_offset = align(suballoc_offset, 0x10);
194bf215546Sopenharmony_ci
195bf215546Sopenharmony_ci      if ((size + suballoc_offset) > suballoc_bo->size) {
196bf215546Sopenharmony_ci         suballoc_bo = NULL;
197bf215546Sopenharmony_ci      }
198bf215546Sopenharmony_ci   }
199bf215546Sopenharmony_ci
200bf215546Sopenharmony_ci   if (!suballoc_bo) {
201bf215546Sopenharmony_ci      // TODO possibly larger size for streaming bo?
202bf215546Sopenharmony_ci      msm_ring->ring_bo = fd_bo_new_ring(submit->pipe->dev, 0x8000);
203bf215546Sopenharmony_ci      msm_ring->offset = 0;
204bf215546Sopenharmony_ci   } else {
205bf215546Sopenharmony_ci      msm_ring->ring_bo = fd_bo_ref(suballoc_bo);
206bf215546Sopenharmony_ci      msm_ring->offset = suballoc_offset;
207bf215546Sopenharmony_ci   }
208bf215546Sopenharmony_ci
209bf215546Sopenharmony_ci   struct fd_ringbuffer *old_suballoc_ring = msm_submit->suballoc_ring;
210bf215546Sopenharmony_ci
211bf215546Sopenharmony_ci   msm_submit->suballoc_ring = fd_ringbuffer_ref(&msm_ring->base);
212bf215546Sopenharmony_ci
213bf215546Sopenharmony_ci   if (old_suballoc_ring)
214bf215546Sopenharmony_ci      fd_ringbuffer_del(old_suballoc_ring);
215bf215546Sopenharmony_ci}
216bf215546Sopenharmony_ci
217bf215546Sopenharmony_cistatic struct fd_ringbuffer *
218bf215546Sopenharmony_cimsm_submit_new_ringbuffer(struct fd_submit *submit, uint32_t size,
219bf215546Sopenharmony_ci                          enum fd_ringbuffer_flags flags)
220bf215546Sopenharmony_ci{
221bf215546Sopenharmony_ci   struct msm_submit *msm_submit = to_msm_submit(submit);
222bf215546Sopenharmony_ci   struct msm_ringbuffer *msm_ring;
223bf215546Sopenharmony_ci
224bf215546Sopenharmony_ci   msm_ring = slab_alloc_st(&msm_submit->ring_pool);
225bf215546Sopenharmony_ci
226bf215546Sopenharmony_ci   msm_ring->u.submit = submit;
227bf215546Sopenharmony_ci
228bf215546Sopenharmony_ci   /* NOTE: needs to be before _suballoc_ring_bo() since it could
229bf215546Sopenharmony_ci    * increment the refcnt of the current ring
230bf215546Sopenharmony_ci    */
231bf215546Sopenharmony_ci   msm_ring->base.refcnt = 1;
232bf215546Sopenharmony_ci
233bf215546Sopenharmony_ci   if (flags & FD_RINGBUFFER_STREAMING) {
234bf215546Sopenharmony_ci      msm_submit_suballoc_ring_bo(submit, msm_ring, size);
235bf215546Sopenharmony_ci   } else {
236bf215546Sopenharmony_ci      if (flags & FD_RINGBUFFER_GROWABLE)
237bf215546Sopenharmony_ci         size = INIT_SIZE;
238bf215546Sopenharmony_ci
239bf215546Sopenharmony_ci      msm_ring->offset = 0;
240bf215546Sopenharmony_ci      msm_ring->ring_bo = fd_bo_new_ring(submit->pipe->dev, size);
241bf215546Sopenharmony_ci   }
242bf215546Sopenharmony_ci
243bf215546Sopenharmony_ci   if (!msm_ringbuffer_init(msm_ring, size, flags))
244bf215546Sopenharmony_ci      return NULL;
245bf215546Sopenharmony_ci
246bf215546Sopenharmony_ci   return &msm_ring->base;
247bf215546Sopenharmony_ci}
248bf215546Sopenharmony_ci
249bf215546Sopenharmony_cistatic struct drm_msm_gem_submit_reloc *
250bf215546Sopenharmony_cihandle_stateobj_relocs(struct msm_submit *submit, struct msm_ringbuffer *ring)
251bf215546Sopenharmony_ci{
252bf215546Sopenharmony_ci   struct msm_cmd *cmd = ring->cmd;
253bf215546Sopenharmony_ci   struct drm_msm_gem_submit_reloc *relocs;
254bf215546Sopenharmony_ci
255bf215546Sopenharmony_ci   relocs = malloc(cmd->nr_relocs * sizeof(*relocs));
256bf215546Sopenharmony_ci
257bf215546Sopenharmony_ci   for (unsigned i = 0; i < cmd->nr_relocs; i++) {
258bf215546Sopenharmony_ci      unsigned idx = cmd->relocs[i].reloc_idx;
259bf215546Sopenharmony_ci      struct fd_bo *bo = ring->u.reloc_bos[idx];
260bf215546Sopenharmony_ci
261bf215546Sopenharmony_ci      relocs[i] = cmd->relocs[i];
262bf215546Sopenharmony_ci      relocs[i].reloc_idx = append_bo(submit, bo);
263bf215546Sopenharmony_ci   }
264bf215546Sopenharmony_ci
265bf215546Sopenharmony_ci   return relocs;
266bf215546Sopenharmony_ci}
267bf215546Sopenharmony_ci
268bf215546Sopenharmony_cistatic int
269bf215546Sopenharmony_cimsm_submit_flush(struct fd_submit *submit, int in_fence_fd,
270bf215546Sopenharmony_ci                 struct fd_submit_fence *out_fence)
271bf215546Sopenharmony_ci{
272bf215546Sopenharmony_ci   struct msm_submit *msm_submit = to_msm_submit(submit);
273bf215546Sopenharmony_ci   struct msm_pipe *msm_pipe = to_msm_pipe(submit->pipe);
274bf215546Sopenharmony_ci   struct drm_msm_gem_submit req = {
275bf215546Sopenharmony_ci      .flags = msm_pipe->pipe,
276bf215546Sopenharmony_ci      .queueid = msm_pipe->queue_id,
277bf215546Sopenharmony_ci   };
278bf215546Sopenharmony_ci   int ret;
279bf215546Sopenharmony_ci
280bf215546Sopenharmony_ci   finalize_current_cmd(submit->primary);
281bf215546Sopenharmony_ci   append_ring(msm_submit->ring_set, submit->primary);
282bf215546Sopenharmony_ci
283bf215546Sopenharmony_ci   unsigned nr_cmds = 0;
284bf215546Sopenharmony_ci   unsigned nr_objs = 0;
285bf215546Sopenharmony_ci
286bf215546Sopenharmony_ci   set_foreach (msm_submit->ring_set, entry) {
287bf215546Sopenharmony_ci      struct fd_ringbuffer *ring = (void *)entry->key;
288bf215546Sopenharmony_ci      if (ring->flags & _FD_RINGBUFFER_OBJECT) {
289bf215546Sopenharmony_ci         nr_cmds += 1;
290bf215546Sopenharmony_ci         nr_objs += 1;
291bf215546Sopenharmony_ci      } else {
292bf215546Sopenharmony_ci         if (ring != submit->primary)
293bf215546Sopenharmony_ci            finalize_current_cmd(ring);
294bf215546Sopenharmony_ci         nr_cmds += to_msm_ringbuffer(ring)->u.nr_cmds;
295bf215546Sopenharmony_ci      }
296bf215546Sopenharmony_ci   }
297bf215546Sopenharmony_ci
298bf215546Sopenharmony_ci   void *obj_relocs[nr_objs];
299bf215546Sopenharmony_ci   struct drm_msm_gem_submit_cmd cmds[nr_cmds];
300bf215546Sopenharmony_ci   unsigned i = 0, o = 0;
301bf215546Sopenharmony_ci
302bf215546Sopenharmony_ci   set_foreach (msm_submit->ring_set, entry) {
303bf215546Sopenharmony_ci      struct fd_ringbuffer *ring = (void *)entry->key;
304bf215546Sopenharmony_ci      struct msm_ringbuffer *msm_ring = to_msm_ringbuffer(ring);
305bf215546Sopenharmony_ci
306bf215546Sopenharmony_ci      assert(i < nr_cmds);
307bf215546Sopenharmony_ci
308bf215546Sopenharmony_ci      // TODO handle relocs:
309bf215546Sopenharmony_ci      if (ring->flags & _FD_RINGBUFFER_OBJECT) {
310bf215546Sopenharmony_ci
311bf215546Sopenharmony_ci         assert(o < nr_objs);
312bf215546Sopenharmony_ci
313bf215546Sopenharmony_ci         void *relocs = handle_stateobj_relocs(msm_submit, msm_ring);
314bf215546Sopenharmony_ci         obj_relocs[o++] = relocs;
315bf215546Sopenharmony_ci
316bf215546Sopenharmony_ci         cmds[i].type = MSM_SUBMIT_CMD_IB_TARGET_BUF;
317bf215546Sopenharmony_ci         cmds[i].submit_idx = append_bo(msm_submit, msm_ring->ring_bo);
318bf215546Sopenharmony_ci         cmds[i].submit_offset = msm_ring->offset;
319bf215546Sopenharmony_ci         cmds[i].size = offset_bytes(ring->cur, ring->start);
320bf215546Sopenharmony_ci         cmds[i].pad = 0;
321bf215546Sopenharmony_ci         cmds[i].nr_relocs = msm_ring->cmd->nr_relocs;
322bf215546Sopenharmony_ci         cmds[i].relocs = VOID2U64(relocs);
323bf215546Sopenharmony_ci
324bf215546Sopenharmony_ci         i++;
325bf215546Sopenharmony_ci      } else {
326bf215546Sopenharmony_ci         for (unsigned j = 0; j < msm_ring->u.nr_cmds; j++) {
327bf215546Sopenharmony_ci            if (ring->flags & FD_RINGBUFFER_PRIMARY) {
328bf215546Sopenharmony_ci               cmds[i].type = MSM_SUBMIT_CMD_BUF;
329bf215546Sopenharmony_ci            } else {
330bf215546Sopenharmony_ci               cmds[i].type = MSM_SUBMIT_CMD_IB_TARGET_BUF;
331bf215546Sopenharmony_ci            }
332bf215546Sopenharmony_ci            cmds[i].submit_idx =
333bf215546Sopenharmony_ci               append_bo(msm_submit, msm_ring->u.cmds[j]->ring_bo);
334bf215546Sopenharmony_ci            cmds[i].submit_offset = msm_ring->offset;
335bf215546Sopenharmony_ci            cmds[i].size = msm_ring->u.cmds[j]->size;
336bf215546Sopenharmony_ci            cmds[i].pad = 0;
337bf215546Sopenharmony_ci            cmds[i].nr_relocs = msm_ring->u.cmds[j]->nr_relocs;
338bf215546Sopenharmony_ci            cmds[i].relocs = VOID2U64(msm_ring->u.cmds[j]->relocs);
339bf215546Sopenharmony_ci
340bf215546Sopenharmony_ci            i++;
341bf215546Sopenharmony_ci         }
342bf215546Sopenharmony_ci      }
343bf215546Sopenharmony_ci   }
344bf215546Sopenharmony_ci
345bf215546Sopenharmony_ci   simple_mtx_lock(&table_lock);
346bf215546Sopenharmony_ci   for (unsigned j = 0; j < msm_submit->nr_bos; j++) {
347bf215546Sopenharmony_ci      fd_bo_add_fence(msm_submit->bos[j], submit->pipe, submit->fence);
348bf215546Sopenharmony_ci   }
349bf215546Sopenharmony_ci   simple_mtx_unlock(&table_lock);
350bf215546Sopenharmony_ci
351bf215546Sopenharmony_ci   if (in_fence_fd != -1) {
352bf215546Sopenharmony_ci      req.flags |= MSM_SUBMIT_FENCE_FD_IN | MSM_SUBMIT_NO_IMPLICIT;
353bf215546Sopenharmony_ci      req.fence_fd = in_fence_fd;
354bf215546Sopenharmony_ci   }
355bf215546Sopenharmony_ci
356bf215546Sopenharmony_ci   if (out_fence && out_fence->use_fence_fd) {
357bf215546Sopenharmony_ci      req.flags |= MSM_SUBMIT_FENCE_FD_OUT;
358bf215546Sopenharmony_ci   }
359bf215546Sopenharmony_ci
360bf215546Sopenharmony_ci   /* needs to be after get_cmd() as that could create bos/cmds table: */
361bf215546Sopenharmony_ci   req.bos = VOID2U64(msm_submit->submit_bos),
362bf215546Sopenharmony_ci   req.nr_bos = msm_submit->nr_submit_bos;
363bf215546Sopenharmony_ci   req.cmds = VOID2U64(cmds), req.nr_cmds = nr_cmds;
364bf215546Sopenharmony_ci
365bf215546Sopenharmony_ci   DEBUG_MSG("nr_cmds=%u, nr_bos=%u", req.nr_cmds, req.nr_bos);
366bf215546Sopenharmony_ci
367bf215546Sopenharmony_ci   ret = drmCommandWriteRead(submit->pipe->dev->fd, DRM_MSM_GEM_SUBMIT, &req,
368bf215546Sopenharmony_ci                             sizeof(req));
369bf215546Sopenharmony_ci   if (ret) {
370bf215546Sopenharmony_ci      ERROR_MSG("submit failed: %d (%s)", ret, strerror(errno));
371bf215546Sopenharmony_ci      msm_dump_submit(&req);
372bf215546Sopenharmony_ci   } else if (!ret && out_fence) {
373bf215546Sopenharmony_ci      out_fence->fence.kfence = req.fence;
374bf215546Sopenharmony_ci      out_fence->fence.ufence = submit->fence;
375bf215546Sopenharmony_ci      out_fence->fence_fd = req.fence_fd;
376bf215546Sopenharmony_ci   }
377bf215546Sopenharmony_ci
378bf215546Sopenharmony_ci   for (unsigned o = 0; o < nr_objs; o++)
379bf215546Sopenharmony_ci      free(obj_relocs[o]);
380bf215546Sopenharmony_ci
381bf215546Sopenharmony_ci   return ret;
382bf215546Sopenharmony_ci}
383bf215546Sopenharmony_ci
384bf215546Sopenharmony_cistatic void
385bf215546Sopenharmony_ciunref_rings(struct set_entry *entry)
386bf215546Sopenharmony_ci{
387bf215546Sopenharmony_ci   struct fd_ringbuffer *ring = (void *)entry->key;
388bf215546Sopenharmony_ci   fd_ringbuffer_del(ring);
389bf215546Sopenharmony_ci}
390bf215546Sopenharmony_ci
391bf215546Sopenharmony_cistatic void
392bf215546Sopenharmony_cimsm_submit_destroy(struct fd_submit *submit)
393bf215546Sopenharmony_ci{
394bf215546Sopenharmony_ci   struct msm_submit *msm_submit = to_msm_submit(submit);
395bf215546Sopenharmony_ci
396bf215546Sopenharmony_ci   if (msm_submit->suballoc_ring)
397bf215546Sopenharmony_ci      fd_ringbuffer_del(msm_submit->suballoc_ring);
398bf215546Sopenharmony_ci
399bf215546Sopenharmony_ci   _mesa_hash_table_destroy(msm_submit->bo_table, NULL);
400bf215546Sopenharmony_ci   _mesa_set_destroy(msm_submit->ring_set, unref_rings);
401bf215546Sopenharmony_ci
402bf215546Sopenharmony_ci   // TODO it would be nice to have a way to assert() if all
403bf215546Sopenharmony_ci   // rb's haven't been free'd back to the slab, because that is
404bf215546Sopenharmony_ci   // an indication that we are leaking bo's
405bf215546Sopenharmony_ci   slab_destroy(&msm_submit->ring_pool);
406bf215546Sopenharmony_ci
407bf215546Sopenharmony_ci   for (unsigned i = 0; i < msm_submit->nr_bos; i++)
408bf215546Sopenharmony_ci      fd_bo_del(msm_submit->bos[i]);
409bf215546Sopenharmony_ci
410bf215546Sopenharmony_ci   free(msm_submit->submit_bos);
411bf215546Sopenharmony_ci   free(msm_submit->bos);
412bf215546Sopenharmony_ci   free(msm_submit);
413bf215546Sopenharmony_ci}
414bf215546Sopenharmony_ci
415bf215546Sopenharmony_cistatic const struct fd_submit_funcs submit_funcs = {
416bf215546Sopenharmony_ci   .new_ringbuffer = msm_submit_new_ringbuffer,
417bf215546Sopenharmony_ci   .flush = msm_submit_flush,
418bf215546Sopenharmony_ci   .destroy = msm_submit_destroy,
419bf215546Sopenharmony_ci};
420bf215546Sopenharmony_ci
421bf215546Sopenharmony_cistruct fd_submit *
422bf215546Sopenharmony_cimsm_submit_new(struct fd_pipe *pipe)
423bf215546Sopenharmony_ci{
424bf215546Sopenharmony_ci   struct msm_submit *msm_submit = calloc(1, sizeof(*msm_submit));
425bf215546Sopenharmony_ci   struct fd_submit *submit;
426bf215546Sopenharmony_ci
427bf215546Sopenharmony_ci   msm_submit->bo_table = _mesa_hash_table_create(NULL, _mesa_hash_pointer,
428bf215546Sopenharmony_ci                                                  _mesa_key_pointer_equal);
429bf215546Sopenharmony_ci   msm_submit->ring_set =
430bf215546Sopenharmony_ci      _mesa_set_create(NULL, _mesa_hash_pointer, _mesa_key_pointer_equal);
431bf215546Sopenharmony_ci   // TODO tune size:
432bf215546Sopenharmony_ci   slab_create(&msm_submit->ring_pool, sizeof(struct msm_ringbuffer), 16);
433bf215546Sopenharmony_ci
434bf215546Sopenharmony_ci   submit = &msm_submit->base;
435bf215546Sopenharmony_ci   submit->funcs = &submit_funcs;
436bf215546Sopenharmony_ci
437bf215546Sopenharmony_ci   return submit;
438bf215546Sopenharmony_ci}
439bf215546Sopenharmony_ci
440bf215546Sopenharmony_cistatic void
441bf215546Sopenharmony_cifinalize_current_cmd(struct fd_ringbuffer *ring)
442bf215546Sopenharmony_ci{
443bf215546Sopenharmony_ci   struct msm_ringbuffer *msm_ring = to_msm_ringbuffer(ring);
444bf215546Sopenharmony_ci
445bf215546Sopenharmony_ci   assert(!(ring->flags & _FD_RINGBUFFER_OBJECT));
446bf215546Sopenharmony_ci
447bf215546Sopenharmony_ci   if (!msm_ring->cmd)
448bf215546Sopenharmony_ci      return;
449bf215546Sopenharmony_ci
450bf215546Sopenharmony_ci   assert(msm_ring->cmd->ring_bo == msm_ring->ring_bo);
451bf215546Sopenharmony_ci
452bf215546Sopenharmony_ci   msm_ring->cmd->size = offset_bytes(ring->cur, ring->start);
453bf215546Sopenharmony_ci   APPEND(&msm_ring->u, cmds, msm_ring->cmd);
454bf215546Sopenharmony_ci   msm_ring->cmd = NULL;
455bf215546Sopenharmony_ci}
456bf215546Sopenharmony_ci
457bf215546Sopenharmony_cistatic void
458bf215546Sopenharmony_cimsm_ringbuffer_grow(struct fd_ringbuffer *ring, uint32_t size)
459bf215546Sopenharmony_ci{
460bf215546Sopenharmony_ci   struct msm_ringbuffer *msm_ring = to_msm_ringbuffer(ring);
461bf215546Sopenharmony_ci   struct fd_pipe *pipe = msm_ring->u.submit->pipe;
462bf215546Sopenharmony_ci
463bf215546Sopenharmony_ci   assert(ring->flags & FD_RINGBUFFER_GROWABLE);
464bf215546Sopenharmony_ci
465bf215546Sopenharmony_ci   finalize_current_cmd(ring);
466bf215546Sopenharmony_ci
467bf215546Sopenharmony_ci   fd_bo_del(msm_ring->ring_bo);
468bf215546Sopenharmony_ci   msm_ring->ring_bo = fd_bo_new_ring(pipe->dev, size);
469bf215546Sopenharmony_ci   msm_ring->cmd = cmd_new(msm_ring->ring_bo);
470bf215546Sopenharmony_ci
471bf215546Sopenharmony_ci   ring->start = fd_bo_map(msm_ring->ring_bo);
472bf215546Sopenharmony_ci   ring->end = &(ring->start[size / 4]);
473bf215546Sopenharmony_ci   ring->cur = ring->start;
474bf215546Sopenharmony_ci   ring->size = size;
475bf215546Sopenharmony_ci}
476bf215546Sopenharmony_ci
477bf215546Sopenharmony_cistatic void
478bf215546Sopenharmony_cimsm_ringbuffer_emit_reloc(struct fd_ringbuffer *ring,
479bf215546Sopenharmony_ci                          const struct fd_reloc *reloc)
480bf215546Sopenharmony_ci{
481bf215546Sopenharmony_ci   struct msm_ringbuffer *msm_ring = to_msm_ringbuffer(ring);
482bf215546Sopenharmony_ci   struct fd_pipe *pipe;
483bf215546Sopenharmony_ci   unsigned reloc_idx;
484bf215546Sopenharmony_ci
485bf215546Sopenharmony_ci   if (ring->flags & _FD_RINGBUFFER_OBJECT) {
486bf215546Sopenharmony_ci      unsigned idx = APPEND(&msm_ring->u, reloc_bos, fd_bo_ref(reloc->bo));
487bf215546Sopenharmony_ci
488bf215546Sopenharmony_ci      /* this gets fixed up at submit->flush() time, since this state-
489bf215546Sopenharmony_ci       * object rb can be used with many different submits
490bf215546Sopenharmony_ci       */
491bf215546Sopenharmony_ci      reloc_idx = idx;
492bf215546Sopenharmony_ci
493bf215546Sopenharmony_ci      pipe = msm_ring->u.pipe;
494bf215546Sopenharmony_ci   } else {
495bf215546Sopenharmony_ci      struct msm_submit *msm_submit = to_msm_submit(msm_ring->u.submit);
496bf215546Sopenharmony_ci
497bf215546Sopenharmony_ci      reloc_idx = append_bo(msm_submit, reloc->bo);
498bf215546Sopenharmony_ci
499bf215546Sopenharmony_ci      pipe = msm_ring->u.submit->pipe;
500bf215546Sopenharmony_ci   }
501bf215546Sopenharmony_ci
502bf215546Sopenharmony_ci   APPEND(msm_ring->cmd, relocs,
503bf215546Sopenharmony_ci          (struct drm_msm_gem_submit_reloc){
504bf215546Sopenharmony_ci             .reloc_idx = reloc_idx,
505bf215546Sopenharmony_ci             .reloc_offset = reloc->offset,
506bf215546Sopenharmony_ci             .or = reloc->orval,
507bf215546Sopenharmony_ci             .shift = reloc->shift,
508bf215546Sopenharmony_ci             .submit_offset =
509bf215546Sopenharmony_ci                offset_bytes(ring->cur, ring->start) + msm_ring->offset,
510bf215546Sopenharmony_ci          });
511bf215546Sopenharmony_ci
512bf215546Sopenharmony_ci   ring->cur++;
513bf215546Sopenharmony_ci
514bf215546Sopenharmony_ci   if (fd_dev_64b(&pipe->dev_id)) {
515bf215546Sopenharmony_ci      APPEND(msm_ring->cmd, relocs,
516bf215546Sopenharmony_ci             (struct drm_msm_gem_submit_reloc){
517bf215546Sopenharmony_ci                .reloc_idx = reloc_idx,
518bf215546Sopenharmony_ci                .reloc_offset = reloc->offset,
519bf215546Sopenharmony_ci                .or = reloc->orval >> 32,
520bf215546Sopenharmony_ci                .shift = reloc->shift - 32,
521bf215546Sopenharmony_ci                .submit_offset =
522bf215546Sopenharmony_ci                   offset_bytes(ring->cur, ring->start) + msm_ring->offset,
523bf215546Sopenharmony_ci             });
524bf215546Sopenharmony_ci
525bf215546Sopenharmony_ci      ring->cur++;
526bf215546Sopenharmony_ci   }
527bf215546Sopenharmony_ci}
528bf215546Sopenharmony_ci
529bf215546Sopenharmony_cistatic void
530bf215546Sopenharmony_ciappend_stateobj_rings(struct msm_submit *submit, struct fd_ringbuffer *target)
531bf215546Sopenharmony_ci{
532bf215546Sopenharmony_ci   struct msm_ringbuffer *msm_target = to_msm_ringbuffer(target);
533bf215546Sopenharmony_ci
534bf215546Sopenharmony_ci   assert(target->flags & _FD_RINGBUFFER_OBJECT);
535bf215546Sopenharmony_ci
536bf215546Sopenharmony_ci   set_foreach (msm_target->u.ring_set, entry) {
537bf215546Sopenharmony_ci      struct fd_ringbuffer *ring = (void *)entry->key;
538bf215546Sopenharmony_ci
539bf215546Sopenharmony_ci      append_ring(submit->ring_set, ring);
540bf215546Sopenharmony_ci
541bf215546Sopenharmony_ci      if (ring->flags & _FD_RINGBUFFER_OBJECT) {
542bf215546Sopenharmony_ci         append_stateobj_rings(submit, ring);
543bf215546Sopenharmony_ci      }
544bf215546Sopenharmony_ci   }
545bf215546Sopenharmony_ci}
546bf215546Sopenharmony_ci
547bf215546Sopenharmony_cistatic uint32_t
548bf215546Sopenharmony_cimsm_ringbuffer_emit_reloc_ring(struct fd_ringbuffer *ring,
549bf215546Sopenharmony_ci                               struct fd_ringbuffer *target, uint32_t cmd_idx)
550bf215546Sopenharmony_ci{
551bf215546Sopenharmony_ci   struct msm_ringbuffer *msm_target = to_msm_ringbuffer(target);
552bf215546Sopenharmony_ci   struct msm_ringbuffer *msm_ring = to_msm_ringbuffer(ring);
553bf215546Sopenharmony_ci   struct fd_bo *bo;
554bf215546Sopenharmony_ci   uint32_t size;
555bf215546Sopenharmony_ci
556bf215546Sopenharmony_ci   if ((target->flags & FD_RINGBUFFER_GROWABLE) &&
557bf215546Sopenharmony_ci       (cmd_idx < msm_target->u.nr_cmds)) {
558bf215546Sopenharmony_ci      bo = msm_target->u.cmds[cmd_idx]->ring_bo;
559bf215546Sopenharmony_ci      size = msm_target->u.cmds[cmd_idx]->size;
560bf215546Sopenharmony_ci   } else {
561bf215546Sopenharmony_ci      bo = msm_target->ring_bo;
562bf215546Sopenharmony_ci      size = offset_bytes(target->cur, target->start);
563bf215546Sopenharmony_ci   }
564bf215546Sopenharmony_ci
565bf215546Sopenharmony_ci   msm_ringbuffer_emit_reloc(ring, &(struct fd_reloc){
566bf215546Sopenharmony_ci                                      .bo = bo,
567bf215546Sopenharmony_ci                                      .iova = bo->iova + msm_target->offset,
568bf215546Sopenharmony_ci                                      .offset = msm_target->offset,
569bf215546Sopenharmony_ci                                   });
570bf215546Sopenharmony_ci
571bf215546Sopenharmony_ci   if (!size)
572bf215546Sopenharmony_ci      return 0;
573bf215546Sopenharmony_ci
574bf215546Sopenharmony_ci   if ((target->flags & _FD_RINGBUFFER_OBJECT) &&
575bf215546Sopenharmony_ci       !(ring->flags & _FD_RINGBUFFER_OBJECT)) {
576bf215546Sopenharmony_ci      struct msm_submit *msm_submit = to_msm_submit(msm_ring->u.submit);
577bf215546Sopenharmony_ci
578bf215546Sopenharmony_ci      append_stateobj_rings(msm_submit, target);
579bf215546Sopenharmony_ci   }
580bf215546Sopenharmony_ci
581bf215546Sopenharmony_ci   if (ring->flags & _FD_RINGBUFFER_OBJECT) {
582bf215546Sopenharmony_ci      append_ring(msm_ring->u.ring_set, target);
583bf215546Sopenharmony_ci   } else {
584bf215546Sopenharmony_ci      struct msm_submit *msm_submit = to_msm_submit(msm_ring->u.submit);
585bf215546Sopenharmony_ci      append_ring(msm_submit->ring_set, target);
586bf215546Sopenharmony_ci   }
587bf215546Sopenharmony_ci
588bf215546Sopenharmony_ci   return size;
589bf215546Sopenharmony_ci}
590bf215546Sopenharmony_ci
591bf215546Sopenharmony_cistatic uint32_t
592bf215546Sopenharmony_cimsm_ringbuffer_cmd_count(struct fd_ringbuffer *ring)
593bf215546Sopenharmony_ci{
594bf215546Sopenharmony_ci   if (ring->flags & FD_RINGBUFFER_GROWABLE)
595bf215546Sopenharmony_ci      return to_msm_ringbuffer(ring)->u.nr_cmds + 1;
596bf215546Sopenharmony_ci   return 1;
597bf215546Sopenharmony_ci}
598bf215546Sopenharmony_ci
599bf215546Sopenharmony_cistatic bool
600bf215546Sopenharmony_cimsm_ringbuffer_check_size(struct fd_ringbuffer *ring)
601bf215546Sopenharmony_ci{
602bf215546Sopenharmony_ci   assert(!(ring->flags & _FD_RINGBUFFER_OBJECT));
603bf215546Sopenharmony_ci   struct msm_ringbuffer *msm_ring = to_msm_ringbuffer(ring);
604bf215546Sopenharmony_ci   struct fd_submit *submit = msm_ring->u.submit;
605bf215546Sopenharmony_ci   struct fd_pipe *pipe = submit->pipe;
606bf215546Sopenharmony_ci
607bf215546Sopenharmony_ci   if ((fd_device_version(pipe->dev) < FD_VERSION_UNLIMITED_CMDS) &&
608bf215546Sopenharmony_ci       ((ring->cur - ring->start) > (ring->size / 4 - 0x1000))) {
609bf215546Sopenharmony_ci      return false;
610bf215546Sopenharmony_ci   }
611bf215546Sopenharmony_ci
612bf215546Sopenharmony_ci   if (to_msm_submit(submit)->nr_bos > MAX_ARRAY_SIZE/2) {
613bf215546Sopenharmony_ci      return false;
614bf215546Sopenharmony_ci   }
615bf215546Sopenharmony_ci
616bf215546Sopenharmony_ci   return true;
617bf215546Sopenharmony_ci}
618bf215546Sopenharmony_ci
619bf215546Sopenharmony_cistatic void
620bf215546Sopenharmony_cimsm_ringbuffer_destroy(struct fd_ringbuffer *ring)
621bf215546Sopenharmony_ci{
622bf215546Sopenharmony_ci   struct msm_ringbuffer *msm_ring = to_msm_ringbuffer(ring);
623bf215546Sopenharmony_ci
624bf215546Sopenharmony_ci   fd_bo_del(msm_ring->ring_bo);
625bf215546Sopenharmony_ci   if (msm_ring->cmd)
626bf215546Sopenharmony_ci      cmd_free(msm_ring->cmd);
627bf215546Sopenharmony_ci
628bf215546Sopenharmony_ci   if (ring->flags & _FD_RINGBUFFER_OBJECT) {
629bf215546Sopenharmony_ci      for (unsigned i = 0; i < msm_ring->u.nr_reloc_bos; i++) {
630bf215546Sopenharmony_ci         fd_bo_del(msm_ring->u.reloc_bos[i]);
631bf215546Sopenharmony_ci      }
632bf215546Sopenharmony_ci
633bf215546Sopenharmony_ci      _mesa_set_destroy(msm_ring->u.ring_set, unref_rings);
634bf215546Sopenharmony_ci
635bf215546Sopenharmony_ci      free(msm_ring->u.reloc_bos);
636bf215546Sopenharmony_ci      free(msm_ring);
637bf215546Sopenharmony_ci   } else {
638bf215546Sopenharmony_ci      struct fd_submit *submit = msm_ring->u.submit;
639bf215546Sopenharmony_ci
640bf215546Sopenharmony_ci      for (unsigned i = 0; i < msm_ring->u.nr_cmds; i++) {
641bf215546Sopenharmony_ci         cmd_free(msm_ring->u.cmds[i]);
642bf215546Sopenharmony_ci      }
643bf215546Sopenharmony_ci
644bf215546Sopenharmony_ci      free(msm_ring->u.cmds);
645bf215546Sopenharmony_ci      slab_free_st(&to_msm_submit(submit)->ring_pool, msm_ring);
646bf215546Sopenharmony_ci   }
647bf215546Sopenharmony_ci}
648bf215546Sopenharmony_ci
649bf215546Sopenharmony_cistatic const struct fd_ringbuffer_funcs ring_funcs = {
650bf215546Sopenharmony_ci   .grow = msm_ringbuffer_grow,
651bf215546Sopenharmony_ci   .emit_reloc = msm_ringbuffer_emit_reloc,
652bf215546Sopenharmony_ci   .emit_reloc_ring = msm_ringbuffer_emit_reloc_ring,
653bf215546Sopenharmony_ci   .cmd_count = msm_ringbuffer_cmd_count,
654bf215546Sopenharmony_ci   .check_size = msm_ringbuffer_check_size,
655bf215546Sopenharmony_ci   .destroy = msm_ringbuffer_destroy,
656bf215546Sopenharmony_ci};
657bf215546Sopenharmony_ci
658bf215546Sopenharmony_cistatic inline struct fd_ringbuffer *
659bf215546Sopenharmony_cimsm_ringbuffer_init(struct msm_ringbuffer *msm_ring, uint32_t size,
660bf215546Sopenharmony_ci                    enum fd_ringbuffer_flags flags)
661bf215546Sopenharmony_ci{
662bf215546Sopenharmony_ci   struct fd_ringbuffer *ring = &msm_ring->base;
663bf215546Sopenharmony_ci
664bf215546Sopenharmony_ci   assert(msm_ring->ring_bo);
665bf215546Sopenharmony_ci
666bf215546Sopenharmony_ci   uint8_t *base = fd_bo_map(msm_ring->ring_bo);
667bf215546Sopenharmony_ci   ring->start = (void *)(base + msm_ring->offset);
668bf215546Sopenharmony_ci   ring->end = &(ring->start[size / 4]);
669bf215546Sopenharmony_ci   ring->cur = ring->start;
670bf215546Sopenharmony_ci
671bf215546Sopenharmony_ci   ring->size = size;
672bf215546Sopenharmony_ci   ring->flags = flags;
673bf215546Sopenharmony_ci
674bf215546Sopenharmony_ci   ring->funcs = &ring_funcs;
675bf215546Sopenharmony_ci
676bf215546Sopenharmony_ci   msm_ring->u.cmds = NULL;
677bf215546Sopenharmony_ci   msm_ring->u.nr_cmds = msm_ring->u.max_cmds = 0;
678bf215546Sopenharmony_ci
679bf215546Sopenharmony_ci   msm_ring->cmd = cmd_new(msm_ring->ring_bo);
680bf215546Sopenharmony_ci
681bf215546Sopenharmony_ci   return ring;
682bf215546Sopenharmony_ci}
683bf215546Sopenharmony_ci
684bf215546Sopenharmony_cistruct fd_ringbuffer *
685bf215546Sopenharmony_cimsm_ringbuffer_new_object(struct fd_pipe *pipe, uint32_t size)
686bf215546Sopenharmony_ci{
687bf215546Sopenharmony_ci   struct msm_ringbuffer *msm_ring = malloc(sizeof(*msm_ring));
688bf215546Sopenharmony_ci
689bf215546Sopenharmony_ci   msm_ring->u.pipe = pipe;
690bf215546Sopenharmony_ci   msm_ring->offset = 0;
691bf215546Sopenharmony_ci   msm_ring->ring_bo = fd_bo_new_ring(pipe->dev, size);
692bf215546Sopenharmony_ci   msm_ring->base.refcnt = 1;
693bf215546Sopenharmony_ci
694bf215546Sopenharmony_ci   msm_ring->u.reloc_bos = NULL;
695bf215546Sopenharmony_ci   msm_ring->u.nr_reloc_bos = msm_ring->u.max_reloc_bos = 0;
696bf215546Sopenharmony_ci
697bf215546Sopenharmony_ci   msm_ring->u.ring_set =
698bf215546Sopenharmony_ci      _mesa_set_create(NULL, _mesa_hash_pointer, _mesa_key_pointer_equal);
699bf215546Sopenharmony_ci
700bf215546Sopenharmony_ci   return msm_ringbuffer_init(msm_ring, size, _FD_RINGBUFFER_OBJECT);
701bf215546Sopenharmony_ci}
702