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 #ifndef FREEDRENO_RINGBUFFER_H_
10*61046927SAndroid Build Coastguard Worker #define FREEDRENO_RINGBUFFER_H_
11*61046927SAndroid Build Coastguard Worker
12*61046927SAndroid Build Coastguard Worker #include <stdio.h>
13*61046927SAndroid Build Coastguard Worker #include "util/u_atomic.h"
14*61046927SAndroid Build Coastguard Worker #include "util/u_debug.h"
15*61046927SAndroid Build Coastguard Worker
16*61046927SAndroid Build Coastguard Worker #include "adreno_common.xml.h"
17*61046927SAndroid Build Coastguard Worker #include "adreno_pm4.xml.h"
18*61046927SAndroid Build Coastguard Worker #include "freedreno_drmif.h"
19*61046927SAndroid Build Coastguard Worker #include "freedreno_pm4.h"
20*61046927SAndroid Build Coastguard Worker
21*61046927SAndroid Build Coastguard Worker #ifdef __cplusplus
22*61046927SAndroid Build Coastguard Worker extern "C" {
23*61046927SAndroid Build Coastguard Worker #endif
24*61046927SAndroid Build Coastguard Worker
25*61046927SAndroid Build Coastguard Worker struct fd_submit;
26*61046927SAndroid Build Coastguard Worker struct fd_ringbuffer;
27*61046927SAndroid Build Coastguard Worker
28*61046927SAndroid Build Coastguard Worker enum fd_ringbuffer_flags {
29*61046927SAndroid Build Coastguard Worker
30*61046927SAndroid Build Coastguard Worker /* Primary ringbuffer for a submit, ie. an IB1 level rb
31*61046927SAndroid Build Coastguard Worker * which kernel must setup RB->IB1 CP_INDIRECT_BRANCH
32*61046927SAndroid Build Coastguard Worker * packets.
33*61046927SAndroid Build Coastguard Worker */
34*61046927SAndroid Build Coastguard Worker FD_RINGBUFFER_PRIMARY = 0x1,
35*61046927SAndroid Build Coastguard Worker
36*61046927SAndroid Build Coastguard Worker /* Hint that the stateobj will be used for streaming state
37*61046927SAndroid Build Coastguard Worker * that is used once or a few times and then discarded.
38*61046927SAndroid Build Coastguard Worker *
39*61046927SAndroid Build Coastguard Worker * For sub-allocation, non streaming stateobj's should be
40*61046927SAndroid Build Coastguard Worker * sub-allocated from a page size buffer, so one long lived
41*61046927SAndroid Build Coastguard Worker * state obj doesn't prevent other pages from being freed.
42*61046927SAndroid Build Coastguard Worker * (Ie. it would be no worse than allocating a page sized
43*61046927SAndroid Build Coastguard Worker * bo for each small non-streaming stateobj).
44*61046927SAndroid Build Coastguard Worker *
45*61046927SAndroid Build Coastguard Worker * But streaming stateobj's could be sub-allocated from a
46*61046927SAndroid Build Coastguard Worker * larger buffer to reduce the alloc/del overhead.
47*61046927SAndroid Build Coastguard Worker */
48*61046927SAndroid Build Coastguard Worker FD_RINGBUFFER_STREAMING = 0x2,
49*61046927SAndroid Build Coastguard Worker
50*61046927SAndroid Build Coastguard Worker /* Indicates that "growable" cmdstream can be used,
51*61046927SAndroid Build Coastguard Worker * consisting of multiple physical cmdstream buffers
52*61046927SAndroid Build Coastguard Worker */
53*61046927SAndroid Build Coastguard Worker FD_RINGBUFFER_GROWABLE = 0x4,
54*61046927SAndroid Build Coastguard Worker
55*61046927SAndroid Build Coastguard Worker /* Internal use only: */
56*61046927SAndroid Build Coastguard Worker _FD_RINGBUFFER_OBJECT = 0x8,
57*61046927SAndroid Build Coastguard Worker };
58*61046927SAndroid Build Coastguard Worker
59*61046927SAndroid Build Coastguard Worker /* A submit object manages/tracks all the state buildup for a "submit"
60*61046927SAndroid Build Coastguard Worker * ioctl to the kernel. Additionally, with the exception of long-lived
61*61046927SAndroid Build Coastguard Worker * non-STREAMING stateobj rb's, rb's are allocated from the submit.
62*61046927SAndroid Build Coastguard Worker */
63*61046927SAndroid Build Coastguard Worker struct fd_submit *fd_submit_new(struct fd_pipe *pipe);
64*61046927SAndroid Build Coastguard Worker
65*61046927SAndroid Build Coastguard Worker /* NOTE: all ringbuffer's create from the submit should be unref'd
66*61046927SAndroid Build Coastguard Worker * before destroying the submit.
67*61046927SAndroid Build Coastguard Worker */
68*61046927SAndroid Build Coastguard Worker void fd_submit_del(struct fd_submit *submit);
69*61046927SAndroid Build Coastguard Worker
70*61046927SAndroid Build Coastguard Worker struct fd_submit * fd_submit_ref(struct fd_submit *submit);
71*61046927SAndroid Build Coastguard Worker
72*61046927SAndroid Build Coastguard Worker /* Allocate a new rb from the submit. */
73*61046927SAndroid Build Coastguard Worker struct fd_ringbuffer *fd_submit_new_ringbuffer(struct fd_submit *submit,
74*61046927SAndroid Build Coastguard Worker uint32_t size,
75*61046927SAndroid Build Coastguard Worker enum fd_ringbuffer_flags flags);
76*61046927SAndroid Build Coastguard Worker
77*61046927SAndroid Build Coastguard Worker /* in_fence_fd: -1 for no in-fence, else fence fd
78*61046927SAndroid Build Coastguard Worker * if use_fence_fd is true the output fence will be dma_fence fd backed
79*61046927SAndroid Build Coastguard Worker */
80*61046927SAndroid Build Coastguard Worker struct fd_fence *fd_submit_flush(struct fd_submit *submit, int in_fence_fd,
81*61046927SAndroid Build Coastguard Worker bool use_fence_fd);
82*61046927SAndroid Build Coastguard Worker
83*61046927SAndroid Build Coastguard Worker struct fd_ringbuffer;
84*61046927SAndroid Build Coastguard Worker struct fd_reloc;
85*61046927SAndroid Build Coastguard Worker
86*61046927SAndroid Build Coastguard Worker struct fd_ringbuffer_funcs {
87*61046927SAndroid Build Coastguard Worker void (*grow)(struct fd_ringbuffer *ring, uint32_t size);
88*61046927SAndroid Build Coastguard Worker
89*61046927SAndroid Build Coastguard Worker /**
90*61046927SAndroid Build Coastguard Worker * Alternative to emit_reloc for the softpin case, where we only need
91*61046927SAndroid Build Coastguard Worker * to track that the bo is used (and not track all the extra info that
92*61046927SAndroid Build Coastguard Worker * the kernel would need to do a legacy reloc.
93*61046927SAndroid Build Coastguard Worker */
94*61046927SAndroid Build Coastguard Worker void (*emit_bo)(struct fd_ringbuffer *ring, struct fd_bo *bo);
95*61046927SAndroid Build Coastguard Worker void (*assert_attached)(struct fd_ringbuffer *ring, struct fd_bo *bo);
96*61046927SAndroid Build Coastguard Worker
97*61046927SAndroid Build Coastguard Worker void (*emit_reloc)(struct fd_ringbuffer *ring, const struct fd_reloc *reloc);
98*61046927SAndroid Build Coastguard Worker uint32_t (*emit_reloc_ring)(struct fd_ringbuffer *ring,
99*61046927SAndroid Build Coastguard Worker struct fd_ringbuffer *target, uint32_t cmd_idx);
100*61046927SAndroid Build Coastguard Worker uint32_t (*cmd_count)(struct fd_ringbuffer *ring);
101*61046927SAndroid Build Coastguard Worker bool (*check_size)(struct fd_ringbuffer *ring);
102*61046927SAndroid Build Coastguard Worker void (*destroy)(struct fd_ringbuffer *ring);
103*61046927SAndroid Build Coastguard Worker };
104*61046927SAndroid Build Coastguard Worker
105*61046927SAndroid Build Coastguard Worker /* the ringbuffer object is not opaque so that OUT_RING() type stuff
106*61046927SAndroid Build Coastguard Worker * can be inlined. Note that users should not make assumptions about
107*61046927SAndroid Build Coastguard Worker * the size of this struct.
108*61046927SAndroid Build Coastguard Worker */
109*61046927SAndroid Build Coastguard Worker struct fd_ringbuffer {
110*61046927SAndroid Build Coastguard Worker uint32_t *cur, *end, *start;
111*61046927SAndroid Build Coastguard Worker const struct fd_ringbuffer_funcs *funcs;
112*61046927SAndroid Build Coastguard Worker
113*61046927SAndroid Build Coastguard Worker // size or end coudl probably go away
114*61046927SAndroid Build Coastguard Worker int size;
115*61046927SAndroid Build Coastguard Worker int32_t refcnt;
116*61046927SAndroid Build Coastguard Worker enum fd_ringbuffer_flags flags;
117*61046927SAndroid Build Coastguard Worker };
118*61046927SAndroid Build Coastguard Worker
119*61046927SAndroid Build Coastguard Worker /* Allocate a new long-lived state object, not associated with
120*61046927SAndroid Build Coastguard Worker * a submit:
121*61046927SAndroid Build Coastguard Worker */
122*61046927SAndroid Build Coastguard Worker struct fd_ringbuffer *fd_ringbuffer_new_object(struct fd_pipe *pipe,
123*61046927SAndroid Build Coastguard Worker uint32_t size);
124*61046927SAndroid Build Coastguard Worker
125*61046927SAndroid Build Coastguard Worker /*
126*61046927SAndroid Build Coastguard Worker * Helpers for ref/unref with some extra debugging.. unref() returns true if
127*61046927SAndroid Build Coastguard Worker * the object is still live
128*61046927SAndroid Build Coastguard Worker */
129*61046927SAndroid Build Coastguard Worker
130*61046927SAndroid Build Coastguard Worker static inline void
ref(int32_t * ref)131*61046927SAndroid Build Coastguard Worker ref(int32_t *ref)
132*61046927SAndroid Build Coastguard Worker {
133*61046927SAndroid Build Coastguard Worker ASSERTED int32_t count = p_atomic_inc_return(ref);
134*61046927SAndroid Build Coastguard Worker /* We should never see a refcnt transition 0->1, this is a sign of a
135*61046927SAndroid Build Coastguard Worker * zombie coming back from the dead!
136*61046927SAndroid Build Coastguard Worker */
137*61046927SAndroid Build Coastguard Worker assert(count != 1);
138*61046927SAndroid Build Coastguard Worker }
139*61046927SAndroid Build Coastguard Worker
140*61046927SAndroid Build Coastguard Worker static inline bool
unref(int32_t * ref)141*61046927SAndroid Build Coastguard Worker unref(int32_t *ref)
142*61046927SAndroid Build Coastguard Worker {
143*61046927SAndroid Build Coastguard Worker int32_t count = p_atomic_dec_return(ref);
144*61046927SAndroid Build Coastguard Worker assert(count != -1);
145*61046927SAndroid Build Coastguard Worker return count == 0;
146*61046927SAndroid Build Coastguard Worker }
147*61046927SAndroid Build Coastguard Worker
148*61046927SAndroid Build Coastguard Worker static inline void
fd_ringbuffer_del(struct fd_ringbuffer * ring)149*61046927SAndroid Build Coastguard Worker fd_ringbuffer_del(struct fd_ringbuffer *ring)
150*61046927SAndroid Build Coastguard Worker {
151*61046927SAndroid Build Coastguard Worker if (--ring->refcnt > 0)
152*61046927SAndroid Build Coastguard Worker return;
153*61046927SAndroid Build Coastguard Worker
154*61046927SAndroid Build Coastguard Worker ring->funcs->destroy(ring);
155*61046927SAndroid Build Coastguard Worker }
156*61046927SAndroid Build Coastguard Worker
157*61046927SAndroid Build Coastguard Worker static inline struct fd_ringbuffer *
fd_ringbuffer_ref(struct fd_ringbuffer * ring)158*61046927SAndroid Build Coastguard Worker fd_ringbuffer_ref(struct fd_ringbuffer *ring)
159*61046927SAndroid Build Coastguard Worker {
160*61046927SAndroid Build Coastguard Worker ring->refcnt++;
161*61046927SAndroid Build Coastguard Worker return ring;
162*61046927SAndroid Build Coastguard Worker }
163*61046927SAndroid Build Coastguard Worker
164*61046927SAndroid Build Coastguard Worker static inline void
fd_ringbuffer_grow(struct fd_ringbuffer * ring,uint32_t ndwords)165*61046927SAndroid Build Coastguard Worker fd_ringbuffer_grow(struct fd_ringbuffer *ring, uint32_t ndwords)
166*61046927SAndroid Build Coastguard Worker {
167*61046927SAndroid Build Coastguard Worker assert(ring->funcs->grow); /* unsupported on kgsl */
168*61046927SAndroid Build Coastguard Worker
169*61046927SAndroid Build Coastguard Worker ring->funcs->grow(ring, ring->size);
170*61046927SAndroid Build Coastguard Worker }
171*61046927SAndroid Build Coastguard Worker
172*61046927SAndroid Build Coastguard Worker static inline bool
fd_ringbuffer_check_size(struct fd_ringbuffer * ring)173*61046927SAndroid Build Coastguard Worker fd_ringbuffer_check_size(struct fd_ringbuffer *ring)
174*61046927SAndroid Build Coastguard Worker {
175*61046927SAndroid Build Coastguard Worker return ring->funcs->check_size(ring);
176*61046927SAndroid Build Coastguard Worker }
177*61046927SAndroid Build Coastguard Worker
178*61046927SAndroid Build Coastguard Worker static inline void
fd_ringbuffer_emit(struct fd_ringbuffer * ring,uint32_t data)179*61046927SAndroid Build Coastguard Worker fd_ringbuffer_emit(struct fd_ringbuffer *ring, uint32_t data)
180*61046927SAndroid Build Coastguard Worker {
181*61046927SAndroid Build Coastguard Worker (*ring->cur++) = data;
182*61046927SAndroid Build Coastguard Worker }
183*61046927SAndroid Build Coastguard Worker
184*61046927SAndroid Build Coastguard Worker struct fd_reloc {
185*61046927SAndroid Build Coastguard Worker struct fd_bo *bo;
186*61046927SAndroid Build Coastguard Worker uint64_t iova;
187*61046927SAndroid Build Coastguard Worker uint64_t orval;
188*61046927SAndroid Build Coastguard Worker #define FD_RELOC_READ 0x0001
189*61046927SAndroid Build Coastguard Worker #define FD_RELOC_WRITE 0x0002
190*61046927SAndroid Build Coastguard Worker #define FD_RELOC_DUMP 0x0004
191*61046927SAndroid Build Coastguard Worker uint32_t offset;
192*61046927SAndroid Build Coastguard Worker int32_t shift;
193*61046927SAndroid Build Coastguard Worker };
194*61046927SAndroid Build Coastguard Worker
195*61046927SAndroid Build Coastguard Worker /* We always mark BOs for write, instead of tracking it across reloc
196*61046927SAndroid Build Coastguard Worker * sources in userspace. On the kernel side, this means we track a single
197*61046927SAndroid Build Coastguard Worker * excl fence in the BO instead of a set of read fences, which is cheaper.
198*61046927SAndroid Build Coastguard Worker * The downside is that a dmabuf-shared device won't be able to read in
199*61046927SAndroid Build Coastguard Worker * parallel with a read-only access by freedreno, but most other drivers
200*61046927SAndroid Build Coastguard Worker * have decided that that usecase isn't important enough to do this
201*61046927SAndroid Build Coastguard Worker * tracking, as well.
202*61046927SAndroid Build Coastguard Worker */
203*61046927SAndroid Build Coastguard Worker #define FD_RELOC_FLAGS_INIT (FD_RELOC_READ | FD_RELOC_WRITE)
204*61046927SAndroid Build Coastguard Worker
205*61046927SAndroid Build Coastguard Worker /* NOTE: relocs are 2 dwords on a5xx+ */
206*61046927SAndroid Build Coastguard Worker
207*61046927SAndroid Build Coastguard Worker static inline void
fd_ringbuffer_attach_bo(struct fd_ringbuffer * ring,struct fd_bo * bo)208*61046927SAndroid Build Coastguard Worker fd_ringbuffer_attach_bo(struct fd_ringbuffer *ring, struct fd_bo *bo)
209*61046927SAndroid Build Coastguard Worker {
210*61046927SAndroid Build Coastguard Worker ring->funcs->emit_bo(ring, bo);
211*61046927SAndroid Build Coastguard Worker }
212*61046927SAndroid Build Coastguard Worker
213*61046927SAndroid Build Coastguard Worker static inline void
fd_ringbuffer_assert_attached(struct fd_ringbuffer * ring,struct fd_bo * bo)214*61046927SAndroid Build Coastguard Worker fd_ringbuffer_assert_attached(struct fd_ringbuffer *ring, struct fd_bo *bo)
215*61046927SAndroid Build Coastguard Worker {
216*61046927SAndroid Build Coastguard Worker #ifndef NDEBUG
217*61046927SAndroid Build Coastguard Worker ring->funcs->assert_attached(ring, bo);
218*61046927SAndroid Build Coastguard Worker #endif
219*61046927SAndroid Build Coastguard Worker }
220*61046927SAndroid Build Coastguard Worker
221*61046927SAndroid Build Coastguard Worker static inline void
fd_ringbuffer_reloc(struct fd_ringbuffer * ring,const struct fd_reloc * reloc)222*61046927SAndroid Build Coastguard Worker fd_ringbuffer_reloc(struct fd_ringbuffer *ring, const struct fd_reloc *reloc)
223*61046927SAndroid Build Coastguard Worker {
224*61046927SAndroid Build Coastguard Worker ring->funcs->emit_reloc(ring, reloc);
225*61046927SAndroid Build Coastguard Worker }
226*61046927SAndroid Build Coastguard Worker
227*61046927SAndroid Build Coastguard Worker static inline uint32_t
fd_ringbuffer_cmd_count(struct fd_ringbuffer * ring)228*61046927SAndroid Build Coastguard Worker fd_ringbuffer_cmd_count(struct fd_ringbuffer *ring)
229*61046927SAndroid Build Coastguard Worker {
230*61046927SAndroid Build Coastguard Worker if (!ring->funcs->cmd_count)
231*61046927SAndroid Build Coastguard Worker return 1;
232*61046927SAndroid Build Coastguard Worker return ring->funcs->cmd_count(ring);
233*61046927SAndroid Build Coastguard Worker }
234*61046927SAndroid Build Coastguard Worker
235*61046927SAndroid Build Coastguard Worker static inline uint32_t
fd_ringbuffer_emit_reloc_ring_full(struct fd_ringbuffer * ring,struct fd_ringbuffer * target,uint32_t cmd_idx)236*61046927SAndroid Build Coastguard Worker fd_ringbuffer_emit_reloc_ring_full(struct fd_ringbuffer *ring,
237*61046927SAndroid Build Coastguard Worker struct fd_ringbuffer *target,
238*61046927SAndroid Build Coastguard Worker uint32_t cmd_idx)
239*61046927SAndroid Build Coastguard Worker {
240*61046927SAndroid Build Coastguard Worker return ring->funcs->emit_reloc_ring(ring, target, cmd_idx);
241*61046927SAndroid Build Coastguard Worker }
242*61046927SAndroid Build Coastguard Worker
243*61046927SAndroid Build Coastguard Worker static inline uint32_t
offset_bytes(void * end,void * start)244*61046927SAndroid Build Coastguard Worker offset_bytes(void *end, void *start)
245*61046927SAndroid Build Coastguard Worker {
246*61046927SAndroid Build Coastguard Worker return ((char *)end) - ((char *)start);
247*61046927SAndroid Build Coastguard Worker }
248*61046927SAndroid Build Coastguard Worker
249*61046927SAndroid Build Coastguard Worker static inline uint32_t
fd_ringbuffer_size(struct fd_ringbuffer * ring)250*61046927SAndroid Build Coastguard Worker fd_ringbuffer_size(struct fd_ringbuffer *ring)
251*61046927SAndroid Build Coastguard Worker {
252*61046927SAndroid Build Coastguard Worker /* only really needed for stateobj ringbuffers, and won't really
253*61046927SAndroid Build Coastguard Worker * do what you expect for growable rb's.. so lets just restrict
254*61046927SAndroid Build Coastguard Worker * this to stateobj's for now:
255*61046927SAndroid Build Coastguard Worker */
256*61046927SAndroid Build Coastguard Worker assert(!(ring->flags & FD_RINGBUFFER_GROWABLE));
257*61046927SAndroid Build Coastguard Worker return offset_bytes(ring->cur, ring->start);
258*61046927SAndroid Build Coastguard Worker }
259*61046927SAndroid Build Coastguard Worker
260*61046927SAndroid Build Coastguard Worker static inline bool
fd_ringbuffer_empty(struct fd_ringbuffer * ring)261*61046927SAndroid Build Coastguard Worker fd_ringbuffer_empty(struct fd_ringbuffer *ring)
262*61046927SAndroid Build Coastguard Worker {
263*61046927SAndroid Build Coastguard Worker return (fd_ringbuffer_cmd_count(ring) == 1) &&
264*61046927SAndroid Build Coastguard Worker (offset_bytes(ring->cur, ring->start) == 0);
265*61046927SAndroid Build Coastguard Worker }
266*61046927SAndroid Build Coastguard Worker
267*61046927SAndroid Build Coastguard Worker #define LOG_DWORDS 0
268*61046927SAndroid Build Coastguard Worker
269*61046927SAndroid Build Coastguard Worker static inline void
OUT_RING(struct fd_ringbuffer * ring,uint32_t data)270*61046927SAndroid Build Coastguard Worker OUT_RING(struct fd_ringbuffer *ring, uint32_t data)
271*61046927SAndroid Build Coastguard Worker {
272*61046927SAndroid Build Coastguard Worker if (LOG_DWORDS) {
273*61046927SAndroid Build Coastguard Worker fprintf(stderr, "ring[%p]: OUT_RING %04x: %08x", ring,
274*61046927SAndroid Build Coastguard Worker (uint32_t)(ring->cur - ring->start), data);
275*61046927SAndroid Build Coastguard Worker }
276*61046927SAndroid Build Coastguard Worker fd_ringbuffer_emit(ring, data);
277*61046927SAndroid Build Coastguard Worker }
278*61046927SAndroid Build Coastguard Worker
279*61046927SAndroid Build Coastguard Worker static inline uint64_t
__reloc_iova(struct fd_bo * bo,uint32_t offset,uint64_t orval,int32_t shift)280*61046927SAndroid Build Coastguard Worker __reloc_iova(struct fd_bo *bo, uint32_t offset, uint64_t orval, int32_t shift)
281*61046927SAndroid Build Coastguard Worker {
282*61046927SAndroid Build Coastguard Worker uint64_t iova = fd_bo_get_iova(bo) + offset;
283*61046927SAndroid Build Coastguard Worker
284*61046927SAndroid Build Coastguard Worker if (shift < 0)
285*61046927SAndroid Build Coastguard Worker iova >>= -shift;
286*61046927SAndroid Build Coastguard Worker else
287*61046927SAndroid Build Coastguard Worker iova <<= shift;
288*61046927SAndroid Build Coastguard Worker
289*61046927SAndroid Build Coastguard Worker iova |= orval;
290*61046927SAndroid Build Coastguard Worker
291*61046927SAndroid Build Coastguard Worker return iova;
292*61046927SAndroid Build Coastguard Worker }
293*61046927SAndroid Build Coastguard Worker
294*61046927SAndroid Build Coastguard Worker /*
295*61046927SAndroid Build Coastguard Worker * NOTE: OUT_RELOC() is 2 dwords (64b) on a5xx+
296*61046927SAndroid Build Coastguard Worker */
297*61046927SAndroid Build Coastguard Worker static inline void
OUT_RELOC(struct fd_ringbuffer * ring,struct fd_bo * bo,uint32_t offset,uint64_t orval,int32_t shift)298*61046927SAndroid Build Coastguard Worker OUT_RELOC(struct fd_ringbuffer *ring, struct fd_bo *bo, uint32_t offset,
299*61046927SAndroid Build Coastguard Worker uint64_t orval, int32_t shift)
300*61046927SAndroid Build Coastguard Worker {
301*61046927SAndroid Build Coastguard Worker if (LOG_DWORDS) {
302*61046927SAndroid Build Coastguard Worker fprintf(stderr, "ring[%p]: OUT_RELOC %04x: %p+%u << %d", ring,
303*61046927SAndroid Build Coastguard Worker (uint32_t)(ring->cur - ring->start), bo, offset, shift);
304*61046927SAndroid Build Coastguard Worker }
305*61046927SAndroid Build Coastguard Worker assert(offset < fd_bo_size(bo));
306*61046927SAndroid Build Coastguard Worker
307*61046927SAndroid Build Coastguard Worker uint64_t iova = __reloc_iova(bo, offset, orval, shift);
308*61046927SAndroid Build Coastguard Worker
309*61046927SAndroid Build Coastguard Worker #if FD_BO_NO_HARDPIN
310*61046927SAndroid Build Coastguard Worker uint64_t *cur = (uint64_t *)ring->cur;
311*61046927SAndroid Build Coastguard Worker *cur = iova;
312*61046927SAndroid Build Coastguard Worker ring->cur += 2;
313*61046927SAndroid Build Coastguard Worker fd_ringbuffer_assert_attached(ring, bo);
314*61046927SAndroid Build Coastguard Worker #else
315*61046927SAndroid Build Coastguard Worker struct fd_reloc reloc = {
316*61046927SAndroid Build Coastguard Worker .bo = bo,
317*61046927SAndroid Build Coastguard Worker .iova = iova,
318*61046927SAndroid Build Coastguard Worker .orval = orval,
319*61046927SAndroid Build Coastguard Worker .offset = offset,
320*61046927SAndroid Build Coastguard Worker .shift = shift,
321*61046927SAndroid Build Coastguard Worker };
322*61046927SAndroid Build Coastguard Worker
323*61046927SAndroid Build Coastguard Worker fd_ringbuffer_reloc(ring, &reloc);
324*61046927SAndroid Build Coastguard Worker #endif
325*61046927SAndroid Build Coastguard Worker }
326*61046927SAndroid Build Coastguard Worker
327*61046927SAndroid Build Coastguard Worker static inline void
OUT_RB(struct fd_ringbuffer * ring,struct fd_ringbuffer * target)328*61046927SAndroid Build Coastguard Worker OUT_RB(struct fd_ringbuffer *ring, struct fd_ringbuffer *target)
329*61046927SAndroid Build Coastguard Worker {
330*61046927SAndroid Build Coastguard Worker fd_ringbuffer_emit_reloc_ring_full(ring, target, 0);
331*61046927SAndroid Build Coastguard Worker }
332*61046927SAndroid Build Coastguard Worker
333*61046927SAndroid Build Coastguard Worker static inline void
BEGIN_RING(struct fd_ringbuffer * ring,uint32_t ndwords)334*61046927SAndroid Build Coastguard Worker BEGIN_RING(struct fd_ringbuffer *ring, uint32_t ndwords)
335*61046927SAndroid Build Coastguard Worker {
336*61046927SAndroid Build Coastguard Worker if (unlikely(ring->cur + ndwords > ring->end))
337*61046927SAndroid Build Coastguard Worker fd_ringbuffer_grow(ring, ndwords);
338*61046927SAndroid Build Coastguard Worker }
339*61046927SAndroid Build Coastguard Worker
340*61046927SAndroid Build Coastguard Worker static inline void
OUT_PKT0(struct fd_ringbuffer * ring,uint16_t regindx,uint16_t cnt)341*61046927SAndroid Build Coastguard Worker OUT_PKT0(struct fd_ringbuffer *ring, uint16_t regindx, uint16_t cnt)
342*61046927SAndroid Build Coastguard Worker {
343*61046927SAndroid Build Coastguard Worker BEGIN_RING(ring, cnt + 1);
344*61046927SAndroid Build Coastguard Worker OUT_RING(ring, pm4_pkt0_hdr(regindx, cnt));
345*61046927SAndroid Build Coastguard Worker }
346*61046927SAndroid Build Coastguard Worker
347*61046927SAndroid Build Coastguard Worker static inline void
OUT_PKT2(struct fd_ringbuffer * ring)348*61046927SAndroid Build Coastguard Worker OUT_PKT2(struct fd_ringbuffer *ring)
349*61046927SAndroid Build Coastguard Worker {
350*61046927SAndroid Build Coastguard Worker BEGIN_RING(ring, 1);
351*61046927SAndroid Build Coastguard Worker OUT_RING(ring, CP_TYPE2_PKT);
352*61046927SAndroid Build Coastguard Worker }
353*61046927SAndroid Build Coastguard Worker
354*61046927SAndroid Build Coastguard Worker static inline void
OUT_PKT3(struct fd_ringbuffer * ring,uint8_t opcode,uint16_t cnt)355*61046927SAndroid Build Coastguard Worker OUT_PKT3(struct fd_ringbuffer *ring, uint8_t opcode, uint16_t cnt)
356*61046927SAndroid Build Coastguard Worker {
357*61046927SAndroid Build Coastguard Worker BEGIN_RING(ring, cnt + 1);
358*61046927SAndroid Build Coastguard Worker OUT_RING(ring, CP_TYPE3_PKT | ((cnt - 1) << 16) | ((opcode & 0xFF) << 8));
359*61046927SAndroid Build Coastguard Worker }
360*61046927SAndroid Build Coastguard Worker
361*61046927SAndroid Build Coastguard Worker /*
362*61046927SAndroid Build Coastguard Worker * Starting with a5xx, pkt4/pkt7 are used instead of pkt0/pkt3
363*61046927SAndroid Build Coastguard Worker */
364*61046927SAndroid Build Coastguard Worker
365*61046927SAndroid Build Coastguard Worker static inline void
OUT_PKT4(struct fd_ringbuffer * ring,uint16_t regindx,uint16_t cnt)366*61046927SAndroid Build Coastguard Worker OUT_PKT4(struct fd_ringbuffer *ring, uint16_t regindx, uint16_t cnt)
367*61046927SAndroid Build Coastguard Worker {
368*61046927SAndroid Build Coastguard Worker BEGIN_RING(ring, cnt + 1);
369*61046927SAndroid Build Coastguard Worker OUT_RING(ring, pm4_pkt4_hdr((uint16_t)regindx, (uint16_t)cnt));
370*61046927SAndroid Build Coastguard Worker }
371*61046927SAndroid Build Coastguard Worker
372*61046927SAndroid Build Coastguard Worker static inline void
OUT_PKT7(struct fd_ringbuffer * ring,uint32_t opcode,uint32_t cnt)373*61046927SAndroid Build Coastguard Worker OUT_PKT7(struct fd_ringbuffer *ring, uint32_t opcode, uint32_t cnt)
374*61046927SAndroid Build Coastguard Worker {
375*61046927SAndroid Build Coastguard Worker BEGIN_RING(ring, cnt + 1);
376*61046927SAndroid Build Coastguard Worker OUT_RING(ring, pm4_pkt7_hdr((uint8_t)opcode, (uint16_t)cnt));
377*61046927SAndroid Build Coastguard Worker }
378*61046927SAndroid Build Coastguard Worker
379*61046927SAndroid Build Coastguard Worker static inline void
OUT_WFI(struct fd_ringbuffer * ring)380*61046927SAndroid Build Coastguard Worker OUT_WFI(struct fd_ringbuffer *ring)
381*61046927SAndroid Build Coastguard Worker {
382*61046927SAndroid Build Coastguard Worker OUT_PKT3(ring, CP_WAIT_FOR_IDLE, 1);
383*61046927SAndroid Build Coastguard Worker OUT_RING(ring, 0x00000000);
384*61046927SAndroid Build Coastguard Worker }
385*61046927SAndroid Build Coastguard Worker
386*61046927SAndroid Build Coastguard Worker static inline void
OUT_WFI5(struct fd_ringbuffer * ring)387*61046927SAndroid Build Coastguard Worker OUT_WFI5(struct fd_ringbuffer *ring)
388*61046927SAndroid Build Coastguard Worker {
389*61046927SAndroid Build Coastguard Worker OUT_PKT7(ring, CP_WAIT_FOR_IDLE, 0);
390*61046927SAndroid Build Coastguard Worker }
391*61046927SAndroid Build Coastguard Worker
392*61046927SAndroid Build Coastguard Worker #ifdef __cplusplus
393*61046927SAndroid Build Coastguard Worker } /* end of extern "C" */
394*61046927SAndroid Build Coastguard Worker #endif
395*61046927SAndroid Build Coastguard Worker
396*61046927SAndroid Build Coastguard Worker #endif /* FREEDRENO_RINGBUFFER_H_ */
397