diff options
Diffstat (limited to 'freedreno')
-rw-r--r-- | freedreno/freedreno_priv.h | 6 | ||||
-rw-r--r-- | freedreno/freedreno_ringbuffer.c | 32 | ||||
-rw-r--r-- | freedreno/freedreno_ringbuffer.h | 2 | ||||
-rw-r--r-- | freedreno/kgsl/kgsl_ringbuffer.c | 7 | ||||
-rw-r--r-- | freedreno/msm/msm_ringbuffer.c | 155 |
5 files changed, 166 insertions, 36 deletions
diff --git a/freedreno/freedreno_priv.h b/freedreno/freedreno_priv.h index 9737b322..cdfdbe8d 100644 --- a/freedreno/freedreno_priv.h +++ b/freedreno/freedreno_priv.h | |||
@@ -134,12 +134,14 @@ struct fd_ringmarker { | |||
134 | struct fd_ringbuffer_funcs { | 134 | struct fd_ringbuffer_funcs { |
135 | void * (*hostptr)(struct fd_ringbuffer *ring); | 135 | void * (*hostptr)(struct fd_ringbuffer *ring); |
136 | int (*flush)(struct fd_ringbuffer *ring, uint32_t *last_start); | 136 | int (*flush)(struct fd_ringbuffer *ring, uint32_t *last_start); |
137 | void (*grow)(struct fd_ringbuffer *ring, uint32_t size); | ||
137 | void (*reset)(struct fd_ringbuffer *ring); | 138 | void (*reset)(struct fd_ringbuffer *ring); |
138 | void (*emit_reloc)(struct fd_ringbuffer *ring, | 139 | void (*emit_reloc)(struct fd_ringbuffer *ring, |
139 | const struct fd_reloc *reloc); | 140 | const struct fd_reloc *reloc); |
140 | void (*emit_reloc_ring)(struct fd_ringbuffer *ring, | 141 | uint32_t (*emit_reloc_ring)(struct fd_ringbuffer *ring, |
141 | struct fd_ringbuffer *target, | 142 | struct fd_ringbuffer *target, uint32_t cmd_idx, |
142 | uint32_t submit_offset, uint32_t size); | 143 | uint32_t submit_offset, uint32_t size); |
144 | uint32_t (*cmd_count)(struct fd_ringbuffer *ring); | ||
143 | void (*destroy)(struct fd_ringbuffer *ring); | 145 | void (*destroy)(struct fd_ringbuffer *ring); |
144 | }; | 146 | }; |
145 | 147 | ||
diff --git a/freedreno/freedreno_ringbuffer.c b/freedreno/freedreno_ringbuffer.c index 34a06d83..22dafb39 100644 --- a/freedreno/freedreno_ringbuffer.c +++ b/freedreno/freedreno_ringbuffer.c | |||
@@ -45,10 +45,9 @@ fd_ringbuffer_new(struct fd_pipe *pipe, uint32_t size) | |||
45 | if (!ring) | 45 | if (!ring) |
46 | return NULL; | 46 | return NULL; |
47 | 47 | ||
48 | ring->size = size; | ||
49 | ring->pipe = pipe; | 48 | ring->pipe = pipe; |
50 | ring->start = ring->funcs->hostptr(ring); | 49 | ring->start = ring->funcs->hostptr(ring); |
51 | ring->end = &(ring->start[size/4]); | 50 | ring->end = &(ring->start[ring->size/4]); |
52 | 51 | ||
53 | ring->cur = ring->last_start = ring->start; | 52 | ring->cur = ring->last_start = ring->start; |
54 | 53 | ||
@@ -87,6 +86,22 @@ int fd_ringbuffer_flush(struct fd_ringbuffer *ring) | |||
87 | return ring->funcs->flush(ring, ring->last_start); | 86 | return ring->funcs->flush(ring, ring->last_start); |
88 | } | 87 | } |
89 | 88 | ||
89 | void fd_ringbuffer_grow(struct fd_ringbuffer *ring, uint32_t ndwords) | ||
90 | { | ||
91 | assert(ring->funcs->grow); /* unsupported on kgsl */ | ||
92 | |||
93 | /* there is an upper bound on IB size, which appears to be 0x100000 */ | ||
94 | if (ring->size < 0x100000) | ||
95 | ring->size *= 2; | ||
96 | |||
97 | ring->funcs->grow(ring, ring->size); | ||
98 | |||
99 | ring->start = ring->funcs->hostptr(ring); | ||
100 | ring->end = &(ring->start[ring->size/4]); | ||
101 | |||
102 | ring->cur = ring->last_start = ring->start; | ||
103 | } | ||
104 | |||
90 | uint32_t fd_ringbuffer_timestamp(struct fd_ringbuffer *ring) | 105 | uint32_t fd_ringbuffer_timestamp(struct fd_ringbuffer *ring) |
91 | { | 106 | { |
92 | return ring->last_timestamp; | 107 | return ring->last_timestamp; |
@@ -108,7 +123,14 @@ void fd_ringbuffer_emit_reloc_ring(struct fd_ringbuffer *ring, | |||
108 | submit_offset = offset_bytes(target->cur, target->ring->start); | 123 | submit_offset = offset_bytes(target->cur, target->ring->start); |
109 | size = offset_bytes(end->cur, target->cur); | 124 | size = offset_bytes(end->cur, target->cur); |
110 | 125 | ||
111 | ring->funcs->emit_reloc_ring(ring, target->ring, submit_offset, size); | 126 | ring->funcs->emit_reloc_ring(ring, target->ring, 0, submit_offset, size); |
127 | } | ||
128 | |||
129 | uint32_t fd_ringbuffer_cmd_count(struct fd_ringbuffer *ring) | ||
130 | { | ||
131 | if (!ring->funcs->cmd_count) | ||
132 | return 1; | ||
133 | return ring->funcs->cmd_count(ring); | ||
112 | } | 134 | } |
113 | 135 | ||
114 | uint32_t | 136 | uint32_t |
@@ -116,9 +138,7 @@ fd_ringbuffer_emit_reloc_ring_full(struct fd_ringbuffer *ring, | |||
116 | struct fd_ringbuffer *target, uint32_t cmd_idx) | 138 | struct fd_ringbuffer *target, uint32_t cmd_idx) |
117 | { | 139 | { |
118 | uint32_t size = offset_bytes(target->cur, target->start); | 140 | uint32_t size = offset_bytes(target->cur, target->start); |
119 | assert(cmd_idx == 0); | 141 | return ring->funcs->emit_reloc_ring(ring, target, cmd_idx, 0, size); |
120 | ring->funcs->emit_reloc_ring(ring, target, 0, size); | ||
121 | return size; | ||
122 | } | 142 | } |
123 | 143 | ||
124 | struct fd_ringmarker * fd_ringmarker_new(struct fd_ringbuffer *ring) | 144 | struct fd_ringmarker * fd_ringmarker_new(struct fd_ringbuffer *ring) |
diff --git a/freedreno/freedreno_ringbuffer.h b/freedreno/freedreno_ringbuffer.h index 643f50b7..8899b5de 100644 --- a/freedreno/freedreno_ringbuffer.h +++ b/freedreno/freedreno_ringbuffer.h | |||
@@ -56,6 +56,7 @@ void fd_ringbuffer_set_parent(struct fd_ringbuffer *ring, | |||
56 | struct fd_ringbuffer *parent); | 56 | struct fd_ringbuffer *parent); |
57 | void fd_ringbuffer_reset(struct fd_ringbuffer *ring); | 57 | void fd_ringbuffer_reset(struct fd_ringbuffer *ring); |
58 | int fd_ringbuffer_flush(struct fd_ringbuffer *ring); | 58 | int fd_ringbuffer_flush(struct fd_ringbuffer *ring); |
59 | void fd_ringbuffer_grow(struct fd_ringbuffer *ring, uint32_t ndwords); | ||
59 | uint32_t fd_ringbuffer_timestamp(struct fd_ringbuffer *ring); | 60 | uint32_t fd_ringbuffer_timestamp(struct fd_ringbuffer *ring); |
60 | 61 | ||
61 | static inline void fd_ringbuffer_emit(struct fd_ringbuffer *ring, | 62 | static inline void fd_ringbuffer_emit(struct fd_ringbuffer *ring, |
@@ -77,6 +78,7 @@ struct fd_reloc { | |||
77 | void fd_ringbuffer_reloc(struct fd_ringbuffer *ring, const struct fd_reloc *reloc); | 78 | void fd_ringbuffer_reloc(struct fd_ringbuffer *ring, const struct fd_reloc *reloc); |
78 | will_be_deprecated void fd_ringbuffer_emit_reloc_ring(struct fd_ringbuffer *ring, | 79 | will_be_deprecated void fd_ringbuffer_emit_reloc_ring(struct fd_ringbuffer *ring, |
79 | struct fd_ringmarker *target, struct fd_ringmarker *end); | 80 | struct fd_ringmarker *target, struct fd_ringmarker *end); |
81 | uint32_t fd_ringbuffer_cmd_count(struct fd_ringbuffer *ring); | ||
80 | uint32_t fd_ringbuffer_emit_reloc_ring_full(struct fd_ringbuffer *ring, | 82 | uint32_t fd_ringbuffer_emit_reloc_ring_full(struct fd_ringbuffer *ring, |
81 | struct fd_ringbuffer *target, uint32_t cmd_idx); | 83 | struct fd_ringbuffer *target, uint32_t cmd_idx); |
82 | 84 | ||
diff --git a/freedreno/kgsl/kgsl_ringbuffer.c b/freedreno/kgsl/kgsl_ringbuffer.c index a0bc9d07..7b3298ab 100644 --- a/freedreno/kgsl/kgsl_ringbuffer.c +++ b/freedreno/kgsl/kgsl_ringbuffer.c | |||
@@ -173,12 +173,14 @@ static void kgsl_ringbuffer_emit_reloc(struct fd_ringbuffer *ring, | |||
173 | kgsl_pipe_add_submit(to_kgsl_pipe(ring->pipe), kgsl_bo); | 173 | kgsl_pipe_add_submit(to_kgsl_pipe(ring->pipe), kgsl_bo); |
174 | } | 174 | } |
175 | 175 | ||
176 | static void kgsl_ringbuffer_emit_reloc_ring(struct fd_ringbuffer *ring, | 176 | static uint32_t kgsl_ringbuffer_emit_reloc_ring(struct fd_ringbuffer *ring, |
177 | struct fd_ringbuffer *target, | 177 | struct fd_ringbuffer *target, uint32_t cmd_idx, |
178 | uint32_t submit_offset, uint32_t size) | 178 | uint32_t submit_offset, uint32_t size) |
179 | { | 179 | { |
180 | struct kgsl_ringbuffer *target_ring = to_kgsl_ringbuffer(target); | 180 | struct kgsl_ringbuffer *target_ring = to_kgsl_ringbuffer(target); |
181 | assert(cmd_idx == 0); | ||
181 | (*ring->cur++) = target_ring->bo->gpuaddr + submit_offset; | 182 | (*ring->cur++) = target_ring->bo->gpuaddr + submit_offset; |
183 | return size; | ||
182 | } | 184 | } |
183 | 185 | ||
184 | static void kgsl_ringbuffer_destroy(struct fd_ringbuffer *ring) | 186 | static void kgsl_ringbuffer_destroy(struct fd_ringbuffer *ring) |
@@ -213,6 +215,7 @@ drm_private struct fd_ringbuffer * kgsl_ringbuffer_new(struct fd_pipe *pipe, | |||
213 | 215 | ||
214 | ring = &kgsl_ring->base; | 216 | ring = &kgsl_ring->base; |
215 | ring->funcs = &funcs; | 217 | ring->funcs = &funcs; |
218 | ring->size = size; | ||
216 | 219 | ||
217 | kgsl_ring->bo = kgsl_rb_bo_new(to_kgsl_pipe(pipe), size); | 220 | kgsl_ring->bo = kgsl_rb_bo_new(to_kgsl_pipe(pipe), size); |
218 | if (!kgsl_ring->bo) { | 221 | if (!kgsl_ring->bo) { |
diff --git a/freedreno/msm/msm_ringbuffer.c b/freedreno/msm/msm_ringbuffer.c index 301ac66f..86fc83e0 100644 --- a/freedreno/msm/msm_ringbuffer.c +++ b/freedreno/msm/msm_ringbuffer.c | |||
@@ -40,12 +40,16 @@ | |||
40 | * a backing bo, and a reloc table. | 40 | * a backing bo, and a reloc table. |
41 | */ | 41 | */ |
42 | struct msm_cmd { | 42 | struct msm_cmd { |
43 | struct list_head list; | ||
44 | |||
43 | struct fd_ringbuffer *ring; | 45 | struct fd_ringbuffer *ring; |
44 | struct fd_bo *ring_bo; | 46 | struct fd_bo *ring_bo; |
45 | 47 | ||
46 | /* reloc's table: */ | 48 | /* reloc's table: */ |
47 | struct drm_msm_gem_submit_reloc *relocs; | 49 | struct drm_msm_gem_submit_reloc *relocs; |
48 | uint32_t nr_relocs, max_relocs; | 50 | uint32_t nr_relocs, max_relocs; |
51 | |||
52 | uint32_t size; | ||
49 | }; | 53 | }; |
50 | 54 | ||
51 | struct msm_ringbuffer { | 55 | struct msm_ringbuffer { |
@@ -75,10 +79,28 @@ struct msm_ringbuffer { | |||
75 | struct msm_cmd **cmds; | 79 | struct msm_cmd **cmds; |
76 | uint32_t nr_cmds, max_cmds; | 80 | uint32_t nr_cmds, max_cmds; |
77 | 81 | ||
78 | /* current cmd-buffer: */ | 82 | /* List of physical cmdstream buffers (msm_cmd) assocated with this |
79 | struct msm_cmd *cmd; | 83 | * logical fd_ringbuffer. |
84 | * | ||
85 | * Note that this is different from msm_ringbuffer::cmds (which | ||
86 | * shadows msm_ringbuffer::submit::cmds for tracking submit ioctl | ||
87 | * related stuff, and *only* is tracked in the parent ringbuffer. | ||
88 | * And only has "completed" cmd buffers (ie. we already know the | ||
89 | * size) added via get_cmd(). | ||
90 | */ | ||
91 | struct list_head cmd_list; | ||
92 | |||
93 | int is_growable; | ||
94 | unsigned cmd_count; | ||
80 | }; | 95 | }; |
81 | 96 | ||
97 | static inline struct msm_ringbuffer * to_msm_ringbuffer(struct fd_ringbuffer *x) | ||
98 | { | ||
99 | return (struct msm_ringbuffer *)x; | ||
100 | } | ||
101 | |||
102 | #define INIT_SIZE 0x1000 | ||
103 | |||
82 | static pthread_mutex_t idx_lock = PTHREAD_MUTEX_INITIALIZER; | 104 | static pthread_mutex_t idx_lock = PTHREAD_MUTEX_INITIALIZER; |
83 | drm_private extern pthread_mutex_t table_lock; | 105 | drm_private extern pthread_mutex_t table_lock; |
84 | 106 | ||
@@ -118,12 +140,15 @@ static void ring_cmd_del(struct msm_cmd *cmd) | |||
118 | { | 140 | { |
119 | if (cmd->ring_bo) | 141 | if (cmd->ring_bo) |
120 | ring_bo_del(cmd->ring->pipe->dev, cmd->ring_bo); | 142 | ring_bo_del(cmd->ring->pipe->dev, cmd->ring_bo); |
143 | list_del(&cmd->list); | ||
144 | to_msm_ringbuffer(cmd->ring)->cmd_count--; | ||
121 | free(cmd->relocs); | 145 | free(cmd->relocs); |
122 | free(cmd); | 146 | free(cmd); |
123 | } | 147 | } |
124 | 148 | ||
125 | static struct msm_cmd * ring_cmd_new(struct fd_ringbuffer *ring, uint32_t size) | 149 | static struct msm_cmd * ring_cmd_new(struct fd_ringbuffer *ring, uint32_t size) |
126 | { | 150 | { |
151 | struct msm_ringbuffer *msm_ring = to_msm_ringbuffer(ring); | ||
127 | struct msm_cmd *cmd = calloc(1, sizeof(*cmd)); | 152 | struct msm_cmd *cmd = calloc(1, sizeof(*cmd)); |
128 | 153 | ||
129 | if (!cmd) | 154 | if (!cmd) |
@@ -134,6 +159,9 @@ static struct msm_cmd * ring_cmd_new(struct fd_ringbuffer *ring, uint32_t size) | |||
134 | if (!cmd->ring_bo) | 159 | if (!cmd->ring_bo) |
135 | goto fail; | 160 | goto fail; |
136 | 161 | ||
162 | list_addtail(&cmd->list, &msm_ring->cmd_list); | ||
163 | msm_ring->cmd_count++; | ||
164 | |||
137 | return cmd; | 165 | return cmd; |
138 | 166 | ||
139 | fail: | 167 | fail: |
@@ -158,9 +186,11 @@ static void *grow(void *ptr, uint32_t nr, uint32_t *max, uint32_t sz) | |||
158 | (x)->nr_ ## name ++; \ | 186 | (x)->nr_ ## name ++; \ |
159 | }) | 187 | }) |
160 | 188 | ||
161 | static inline struct msm_ringbuffer * to_msm_ringbuffer(struct fd_ringbuffer *x) | 189 | static struct msm_cmd *current_cmd(struct fd_ringbuffer *ring) |
162 | { | 190 | { |
163 | return (struct msm_ringbuffer *)x; | 191 | struct msm_ringbuffer *msm_ring = to_msm_ringbuffer(ring); |
192 | assert(!LIST_IS_EMPTY(&msm_ring->cmd_list)); | ||
193 | return LIST_LAST_ENTRY(&msm_ring->cmd_list, struct msm_cmd, list); | ||
164 | } | 194 | } |
165 | 195 | ||
166 | static uint32_t append_bo(struct fd_ringbuffer *ring, struct fd_bo *bo) | 196 | static uint32_t append_bo(struct fd_ringbuffer *ring, struct fd_bo *bo) |
@@ -248,12 +278,13 @@ static void get_cmd(struct fd_ringbuffer *ring, struct msm_cmd *target_cmd, | |||
248 | cmd->submit_offset = submit_offset; | 278 | cmd->submit_offset = submit_offset; |
249 | cmd->size = size; | 279 | cmd->size = size; |
250 | cmd->pad = 0; | 280 | cmd->pad = 0; |
281 | |||
282 | target_cmd->size = size; | ||
251 | } | 283 | } |
252 | 284 | ||
253 | static void * msm_ringbuffer_hostptr(struct fd_ringbuffer *ring) | 285 | static void * msm_ringbuffer_hostptr(struct fd_ringbuffer *ring) |
254 | { | 286 | { |
255 | struct msm_ringbuffer *msm_ring = to_msm_ringbuffer(ring); | 287 | return fd_bo_map(current_cmd(ring)->ring_bo); |
256 | return fd_bo_map(msm_ring->cmd->ring_bo); | ||
257 | } | 288 | } |
258 | 289 | ||
259 | static uint32_t find_next_reloc_idx(struct msm_cmd *msm_cmd, | 290 | static uint32_t find_next_reloc_idx(struct msm_cmd *msm_cmd, |
@@ -271,6 +302,15 @@ static uint32_t find_next_reloc_idx(struct msm_cmd *msm_cmd, | |||
271 | return i; | 302 | return i; |
272 | } | 303 | } |
273 | 304 | ||
305 | static void delete_cmds(struct msm_ringbuffer *msm_ring) | ||
306 | { | ||
307 | struct msm_cmd *cmd, *tmp; | ||
308 | |||
309 | LIST_FOR_EACH_ENTRY_SAFE(cmd, tmp, &msm_ring->cmd_list, list) { | ||
310 | ring_cmd_del(cmd); | ||
311 | } | ||
312 | } | ||
313 | |||
274 | static void flush_reset(struct fd_ringbuffer *ring) | 314 | static void flush_reset(struct fd_ringbuffer *ring) |
275 | { | 315 | { |
276 | struct msm_ringbuffer *msm_ring = to_msm_ringbuffer(ring); | 316 | struct msm_ringbuffer *msm_ring = to_msm_ringbuffer(ring); |
@@ -288,11 +328,36 @@ static void flush_reset(struct fd_ringbuffer *ring) | |||
288 | target_cmd->nr_relocs = 0; | 328 | target_cmd->nr_relocs = 0; |
289 | } | 329 | } |
290 | 330 | ||
291 | msm_ring->cmd->nr_relocs = 0; | ||
292 | msm_ring->submit.nr_cmds = 0; | 331 | msm_ring->submit.nr_cmds = 0; |
293 | msm_ring->submit.nr_bos = 0; | 332 | msm_ring->submit.nr_bos = 0; |
294 | msm_ring->nr_cmds = 0; | 333 | msm_ring->nr_cmds = 0; |
295 | msm_ring->nr_bos = 0; | 334 | msm_ring->nr_bos = 0; |
335 | |||
336 | if (msm_ring->is_growable) { | ||
337 | delete_cmds(msm_ring); | ||
338 | } else { | ||
339 | /* in old mode, just reset the # of relocs: */ | ||
340 | current_cmd(ring)->nr_relocs = 0; | ||
341 | } | ||
342 | } | ||
343 | |||
344 | static void finalize_current_cmd(struct fd_ringbuffer *ring, uint32_t *last_start) | ||
345 | { | ||
346 | uint32_t submit_offset, size, type; | ||
347 | struct fd_ringbuffer *parent; | ||
348 | |||
349 | if (ring->parent) { | ||
350 | parent = ring->parent; | ||
351 | type = MSM_SUBMIT_CMD_IB_TARGET_BUF; | ||
352 | } else { | ||
353 | parent = ring; | ||
354 | type = MSM_SUBMIT_CMD_BUF; | ||
355 | } | ||
356 | |||
357 | submit_offset = offset_bytes(last_start, ring->start); | ||
358 | size = offset_bytes(ring->cur, last_start); | ||
359 | |||
360 | get_cmd(parent, current_cmd(ring), submit_offset, size, type); | ||
296 | } | 361 | } |
297 | 362 | ||
298 | static void dump_submit(struct msm_ringbuffer *msm_ring) | 363 | static void dump_submit(struct msm_ringbuffer *msm_ring) |
@@ -323,13 +388,10 @@ static int msm_ringbuffer_flush(struct fd_ringbuffer *ring, uint32_t *last_start | |||
323 | struct drm_msm_gem_submit req = { | 388 | struct drm_msm_gem_submit req = { |
324 | .pipe = to_msm_pipe(ring->pipe)->pipe, | 389 | .pipe = to_msm_pipe(ring->pipe)->pipe, |
325 | }; | 390 | }; |
326 | uint32_t i, submit_offset, size; | 391 | uint32_t i; |
327 | int ret; | 392 | int ret; |
328 | 393 | ||
329 | submit_offset = offset_bytes(last_start, ring->start); | 394 | finalize_current_cmd(ring, last_start); |
330 | size = offset_bytes(ring->cur, last_start); | ||
331 | |||
332 | get_cmd(ring, msm_ring->cmd, submit_offset, size, MSM_SUBMIT_CMD_BUF); | ||
333 | 395 | ||
334 | /* needs to be after get_cmd() as that could create bos/cmds table: */ | 396 | /* needs to be after get_cmd() as that could create bos/cmds table: */ |
335 | req.bos = VOID2U64(msm_ring->submit.bos), | 397 | req.bos = VOID2U64(msm_ring->submit.bos), |
@@ -367,6 +429,13 @@ static int msm_ringbuffer_flush(struct fd_ringbuffer *ring, uint32_t *last_start | |||
367 | return ret; | 429 | return ret; |
368 | } | 430 | } |
369 | 431 | ||
432 | static void msm_ringbuffer_grow(struct fd_ringbuffer *ring, uint32_t size) | ||
433 | { | ||
434 | assert(to_msm_ringbuffer(ring)->is_growable); | ||
435 | finalize_current_cmd(ring, ring->last_start); | ||
436 | ring_cmd_new(ring, size); | ||
437 | } | ||
438 | |||
370 | static void msm_ringbuffer_reset(struct fd_ringbuffer *ring) | 439 | static void msm_ringbuffer_reset(struct fd_ringbuffer *ring) |
371 | { | 440 | { |
372 | flush_reset(ring); | 441 | flush_reset(ring); |
@@ -375,14 +444,14 @@ static void msm_ringbuffer_reset(struct fd_ringbuffer *ring) | |||
375 | static void msm_ringbuffer_emit_reloc(struct fd_ringbuffer *ring, | 444 | static void msm_ringbuffer_emit_reloc(struct fd_ringbuffer *ring, |
376 | const struct fd_reloc *r) | 445 | const struct fd_reloc *r) |
377 | { | 446 | { |
378 | struct msm_ringbuffer *msm_ring = to_msm_ringbuffer(ring); | ||
379 | struct fd_ringbuffer *parent = ring->parent ? ring->parent : ring; | 447 | struct fd_ringbuffer *parent = ring->parent ? ring->parent : ring; |
380 | struct msm_bo *msm_bo = to_msm_bo(r->bo); | 448 | struct msm_bo *msm_bo = to_msm_bo(r->bo); |
381 | struct drm_msm_gem_submit_reloc *reloc; | 449 | struct drm_msm_gem_submit_reloc *reloc; |
382 | uint32_t idx = APPEND(msm_ring->cmd, relocs); | 450 | struct msm_cmd *cmd = current_cmd(ring); |
451 | uint32_t idx = APPEND(cmd, relocs); | ||
383 | uint32_t addr; | 452 | uint32_t addr; |
384 | 453 | ||
385 | reloc = &msm_ring->cmd->relocs[idx]; | 454 | reloc = &cmd->relocs[idx]; |
386 | 455 | ||
387 | reloc->reloc_idx = bo2idx(parent, r->bo, r->flags); | 456 | reloc->reloc_idx = bo2idx(parent, r->bo, r->flags); |
388 | reloc->reloc_offset = r->offset; | 457 | reloc->reloc_offset = r->offset; |
@@ -398,26 +467,53 @@ static void msm_ringbuffer_emit_reloc(struct fd_ringbuffer *ring, | |||
398 | (*ring->cur++) = addr | r->or; | 467 | (*ring->cur++) = addr | r->or; |
399 | } | 468 | } |
400 | 469 | ||
401 | static void msm_ringbuffer_emit_reloc_ring(struct fd_ringbuffer *ring, | 470 | static uint32_t msm_ringbuffer_emit_reloc_ring(struct fd_ringbuffer *ring, |
402 | struct fd_ringbuffer *target, | 471 | struct fd_ringbuffer *target, uint32_t cmd_idx, |
403 | uint32_t submit_offset, uint32_t size) | 472 | uint32_t submit_offset, uint32_t size) |
404 | { | 473 | { |
405 | struct msm_cmd *cmd = to_msm_ringbuffer(target)->cmd; | 474 | struct msm_cmd *cmd = NULL; |
475 | uint32_t idx = 0; | ||
476 | |||
477 | LIST_FOR_EACH_ENTRY(cmd, &to_msm_ringbuffer(target)->cmd_list, list) { | ||
478 | if (idx == cmd_idx) | ||
479 | break; | ||
480 | idx++; | ||
481 | } | ||
406 | 482 | ||
407 | get_cmd(ring, cmd, submit_offset, size, MSM_SUBMIT_CMD_IB_TARGET_BUF); | 483 | assert(cmd && (idx == cmd_idx)); |
484 | |||
485 | if (idx < (to_msm_ringbuffer(target)->cmd_count - 1)) { | ||
486 | /* All but the last cmd buffer is fully "baked" (ie. already has | ||
487 | * done get_cmd() to add it to the cmds table). But in this case, | ||
488 | * the size we get is invalid (since it is calculated from the | ||
489 | * last cmd buffer): | ||
490 | */ | ||
491 | size = cmd->size; | ||
492 | } else { | ||
493 | get_cmd(ring, cmd, submit_offset, size, MSM_SUBMIT_CMD_IB_TARGET_BUF); | ||
494 | } | ||
408 | 495 | ||
409 | msm_ringbuffer_emit_reloc(ring, &(struct fd_reloc){ | 496 | msm_ringbuffer_emit_reloc(ring, &(struct fd_reloc){ |
410 | .bo = cmd->ring_bo, | 497 | .bo = cmd->ring_bo, |
411 | .flags = FD_RELOC_READ, | 498 | .flags = FD_RELOC_READ, |
412 | .offset = submit_offset, | 499 | .offset = submit_offset, |
413 | }); | 500 | }); |
501 | |||
502 | return size; | ||
503 | } | ||
504 | |||
505 | static uint32_t msm_ringbuffer_cmd_count(struct fd_ringbuffer *ring) | ||
506 | { | ||
507 | return to_msm_ringbuffer(ring)->cmd_count; | ||
414 | } | 508 | } |
415 | 509 | ||
416 | static void msm_ringbuffer_destroy(struct fd_ringbuffer *ring) | 510 | static void msm_ringbuffer_destroy(struct fd_ringbuffer *ring) |
417 | { | 511 | { |
418 | struct msm_ringbuffer *msm_ring = to_msm_ringbuffer(ring); | 512 | struct msm_ringbuffer *msm_ring = to_msm_ringbuffer(ring); |
419 | if (msm_ring->cmd) | 513 | |
420 | ring_cmd_del(msm_ring->cmd); | 514 | flush_reset(ring); |
515 | delete_cmds(msm_ring); | ||
516 | |||
421 | free(msm_ring->submit.cmds); | 517 | free(msm_ring->submit.cmds); |
422 | free(msm_ring->submit.bos); | 518 | free(msm_ring->submit.bos); |
423 | free(msm_ring->bos); | 519 | free(msm_ring->bos); |
@@ -428,9 +524,11 @@ static void msm_ringbuffer_destroy(struct fd_ringbuffer *ring) | |||
428 | static const struct fd_ringbuffer_funcs funcs = { | 524 | static const struct fd_ringbuffer_funcs funcs = { |
429 | .hostptr = msm_ringbuffer_hostptr, | 525 | .hostptr = msm_ringbuffer_hostptr, |
430 | .flush = msm_ringbuffer_flush, | 526 | .flush = msm_ringbuffer_flush, |
527 | .grow = msm_ringbuffer_grow, | ||
431 | .reset = msm_ringbuffer_reset, | 528 | .reset = msm_ringbuffer_reset, |
432 | .emit_reloc = msm_ringbuffer_emit_reloc, | 529 | .emit_reloc = msm_ringbuffer_emit_reloc, |
433 | .emit_reloc_ring = msm_ringbuffer_emit_reloc_ring, | 530 | .emit_reloc_ring = msm_ringbuffer_emit_reloc_ring, |
531 | .cmd_count = msm_ringbuffer_cmd_count, | ||
434 | .destroy = msm_ringbuffer_destroy, | 532 | .destroy = msm_ringbuffer_destroy, |
435 | }; | 533 | }; |
436 | 534 | ||
@@ -446,15 +544,20 @@ drm_private struct fd_ringbuffer * msm_ringbuffer_new(struct fd_pipe *pipe, | |||
446 | goto fail; | 544 | goto fail; |
447 | } | 545 | } |
448 | 546 | ||
547 | if (size == 0) { | ||
548 | assert(pipe->dev->version >= FD_VERSION_UNLIMITED_CMDS); | ||
549 | size = INIT_SIZE; | ||
550 | msm_ring->is_growable = TRUE; | ||
551 | } | ||
552 | |||
553 | list_inithead(&msm_ring->cmd_list); | ||
554 | |||
449 | ring = &msm_ring->base; | 555 | ring = &msm_ring->base; |
450 | ring->funcs = &funcs; | 556 | ring->funcs = &funcs; |
557 | ring->size = size; | ||
451 | ring->pipe = pipe; /* needed in ring_cmd_new() */ | 558 | ring->pipe = pipe; /* needed in ring_cmd_new() */ |
452 | 559 | ||
453 | msm_ring->cmd = ring_cmd_new(ring, size); | 560 | ring_cmd_new(ring, size); |
454 | if (!msm_ring->cmd) { | ||
455 | ERROR_MSG("command buffer allocation failed"); | ||
456 | goto fail; | ||
457 | } | ||
458 | 561 | ||
459 | return ring; | 562 | return ring; |
460 | fail: | 563 | fail: |