aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRob Clark2016-06-03 14:41:20 -0500
committerRob Clark2016-07-20 18:42:21 -0500
commitdd1f372001d4e6de648fa33b6b74d89aaa24cf75 (patch)
tree33e08717fa9f430a83b76f9e00364a1d9745c882 /freedreno
parent0d6152913098d739be07f9085cdf44c9cc68d096 (diff)
downloadexternal-libgbm-dd1f372001d4e6de648fa33b6b74d89aaa24cf75.tar.gz
external-libgbm-dd1f372001d4e6de648fa33b6b74d89aaa24cf75.tar.xz
external-libgbm-dd1f372001d4e6de648fa33b6b74d89aaa24cf75.zip
freedreno/msm: split out cmd buffer tracking from ring
First step towards supporting a single logical ringbuffer mapping to multiple physical cmd buffers, which will enable dynamically growing ringbuffers. Signed-off-by: Rob Clark <robclark@freedesktop.org>
Diffstat (limited to 'freedreno')
-rw-r--r--freedreno/msm/msm_ringbuffer.c128
1 files changed, 83 insertions, 45 deletions
diff --git a/freedreno/msm/msm_ringbuffer.c b/freedreno/msm/msm_ringbuffer.c
index 4b46c202..7eebac18 100644
--- a/freedreno/msm/msm_ringbuffer.c
+++ b/freedreno/msm/msm_ringbuffer.c
@@ -36,11 +36,26 @@
36#include "freedreno_ringbuffer.h" 36#include "freedreno_ringbuffer.h"
37#include "msm_priv.h" 37#include "msm_priv.h"
38 38
39/* represents a single cmd buffer in the submit ioctl. Each cmd buffer has
40 * a backing bo, and a reloc table.
41 */
42struct msm_cmd {
43 struct fd_ringbuffer *ring;
44 struct fd_bo *ring_bo;
45
46 /* reloc's table: */
47 struct drm_msm_gem_submit_reloc *relocs;
48 uint32_t nr_relocs, max_relocs;
49};
50
39struct msm_ringbuffer { 51struct msm_ringbuffer {
40 struct fd_ringbuffer base; 52 struct fd_ringbuffer base;
41 struct fd_bo *ring_bo;
42 53
43 /* submit ioctl related tables: */ 54 /* submit ioctl related tables:
55 * Note that bos and cmds are tracked by the parent ringbuffer, since
56 * that is global to the submit ioctl call. The reloc's table is tracked
57 * per cmd-buffer.
58 */
44 struct { 59 struct {
45 /* bo's table: */ 60 /* bo's table: */
46 struct drm_msm_gem_submit_bo *bos; 61 struct drm_msm_gem_submit_bo *bos;
@@ -49,19 +64,19 @@ struct msm_ringbuffer {
49 /* cmd's table: */ 64 /* cmd's table: */
50 struct drm_msm_gem_submit_cmd *cmds; 65 struct drm_msm_gem_submit_cmd *cmds;
51 uint32_t nr_cmds, max_cmds; 66 uint32_t nr_cmds, max_cmds;
52
53 /* reloc's table: */
54 struct drm_msm_gem_submit_reloc *relocs;
55 uint32_t nr_relocs, max_relocs;
56 } submit; 67 } submit;
57 68
58 /* should have matching entries in submit.bos: */ 69 /* should have matching entries in submit.bos: */
70 /* Note, only in parent ringbuffer */
59 struct fd_bo **bos; 71 struct fd_bo **bos;
60 uint32_t nr_bos, max_bos; 72 uint32_t nr_bos, max_bos;
61 73
62 /* should have matching entries in submit.cmds: */ 74 /* should have matching entries in submit.cmds: */
63 struct fd_ringbuffer **rings; 75 struct msm_cmd **cmds;
64 uint32_t nr_rings, max_rings; 76 uint32_t nr_cmds, max_cmds;
77
78 /* current cmd-buffer: */
79 struct msm_cmd *cmd;
65}; 80};
66 81
67static pthread_mutex_t idx_lock = PTHREAD_MUTEX_INITIALIZER; 82static pthread_mutex_t idx_lock = PTHREAD_MUTEX_INITIALIZER;
@@ -99,6 +114,33 @@ static struct fd_bo * ring_bo_new(struct fd_device *dev, uint32_t size)
99 return bo; 114 return bo;
100} 115}
101 116
117static void ring_cmd_del(struct msm_cmd *cmd)
118{
119 if (cmd->ring_bo)
120 ring_bo_del(cmd->ring->pipe->dev, cmd->ring_bo);
121 free(cmd->relocs);
122 free(cmd);
123}
124
125static struct msm_cmd * ring_cmd_new(struct fd_ringbuffer *ring, uint32_t size)
126{
127 struct msm_cmd *cmd = calloc(1, sizeof(*cmd));
128
129 if (!cmd)
130 return NULL;
131
132 cmd->ring = ring;
133 cmd->ring_bo = ring_bo_new(ring->pipe->dev, size);
134 if (!cmd->ring_bo)
135 goto fail;
136
137 return cmd;
138
139fail:
140 ring_cmd_del(cmd);
141 return NULL;
142}
143
102static void *grow(void *ptr, uint32_t nr, uint32_t *max, uint32_t sz) 144static void *grow(void *ptr, uint32_t nr, uint32_t *max, uint32_t sz)
103{ 145{
104 if ((nr + 1) > *max) { 146 if ((nr + 1) > *max) {
@@ -179,8 +221,7 @@ static int check_cmd_bo(struct fd_ringbuffer *ring,
179/* Ensure that submit has corresponding entry in cmds table for the 221/* Ensure that submit has corresponding entry in cmds table for the
180 * target cmdstream buffer: 222 * target cmdstream buffer:
181 */ 223 */
182static void get_cmd(struct fd_ringbuffer *ring, 224static void get_cmd(struct fd_ringbuffer *ring, struct msm_cmd *target_cmd,
183 struct fd_ringbuffer *target_ring, struct fd_bo *target_bo,
184 uint32_t submit_offset, uint32_t size, uint32_t type) 225 uint32_t submit_offset, uint32_t size, uint32_t type)
185{ 226{
186 struct msm_ringbuffer *msm_ring = to_msm_ringbuffer(ring); 227 struct msm_ringbuffer *msm_ring = to_msm_ringbuffer(ring);
@@ -193,17 +234,17 @@ static void get_cmd(struct fd_ringbuffer *ring,
193 if ((cmd->submit_offset == submit_offset) && 234 if ((cmd->submit_offset == submit_offset) &&
194 (cmd->size == size) && 235 (cmd->size == size) &&
195 (cmd->type == type) && 236 (cmd->type == type) &&
196 check_cmd_bo(ring, cmd, target_bo)) 237 check_cmd_bo(ring, cmd, target_cmd->ring_bo))
197 return; 238 return;
198 } 239 }
199 240
200 /* create cmd buf if not: */ 241 /* create cmd buf if not: */
201 i = APPEND(&msm_ring->submit, cmds); 242 i = APPEND(&msm_ring->submit, cmds);
202 APPEND(msm_ring, rings); 243 APPEND(msm_ring, cmds);
203 msm_ring->rings[i] = target_ring; 244 msm_ring->cmds[i] = target_cmd;
204 cmd = &msm_ring->submit.cmds[i]; 245 cmd = &msm_ring->submit.cmds[i];
205 cmd->type = type; 246 cmd->type = type;
206 cmd->submit_idx = bo2idx(ring, target_bo, FD_RELOC_READ); 247 cmd->submit_idx = bo2idx(ring, target_cmd->ring_bo, FD_RELOC_READ);
207 cmd->submit_offset = submit_offset; 248 cmd->submit_offset = submit_offset;
208 cmd->size = size; 249 cmd->size = size;
209 cmd->pad = 0; 250 cmd->pad = 0;
@@ -212,17 +253,17 @@ static void get_cmd(struct fd_ringbuffer *ring,
212static void * msm_ringbuffer_hostptr(struct fd_ringbuffer *ring) 253static void * msm_ringbuffer_hostptr(struct fd_ringbuffer *ring)
213{ 254{
214 struct msm_ringbuffer *msm_ring = to_msm_ringbuffer(ring); 255 struct msm_ringbuffer *msm_ring = to_msm_ringbuffer(ring);
215 return fd_bo_map(msm_ring->ring_bo); 256 return fd_bo_map(msm_ring->cmd->ring_bo);
216} 257}
217 258
218static uint32_t find_next_reloc_idx(struct msm_ringbuffer *msm_ring, 259static uint32_t find_next_reloc_idx(struct msm_cmd *msm_cmd,
219 uint32_t start, uint32_t offset) 260 uint32_t start, uint32_t offset)
220{ 261{
221 uint32_t i; 262 uint32_t i;
222 263
223 /* a binary search would be more clever.. */ 264 /* a binary search would be more clever.. */
224 for (i = start; i < msm_ring->submit.nr_relocs; i++) { 265 for (i = start; i < msm_cmd->nr_relocs; i++) {
225 struct drm_msm_gem_submit_reloc *reloc = &msm_ring->submit.relocs[i]; 266 struct drm_msm_gem_submit_reloc *reloc = &msm_cmd->relocs[i];
226 if (reloc->submit_offset >= offset) 267 if (reloc->submit_offset >= offset)
227 return i; 268 return i;
228 } 269 }
@@ -243,21 +284,20 @@ static void flush_reset(struct fd_ringbuffer *ring)
243 284
244 /* for each of the cmd buffers, clear their reloc's: */ 285 /* for each of the cmd buffers, clear their reloc's: */
245 for (i = 0; i < msm_ring->submit.nr_cmds; i++) { 286 for (i = 0; i < msm_ring->submit.nr_cmds; i++) {
246 struct msm_ringbuffer *target_ring = to_msm_ringbuffer(msm_ring->rings[i]); 287 struct msm_cmd *target_cmd = msm_ring->cmds[i];
247 target_ring->submit.nr_relocs = 0; 288 target_cmd->nr_relocs = 0;
248 } 289 }
249 290
250 msm_ring->submit.nr_relocs = 0; 291 msm_ring->cmd->nr_relocs = 0;
251 msm_ring->submit.nr_cmds = 0; 292 msm_ring->submit.nr_cmds = 0;
252 msm_ring->submit.nr_bos = 0; 293 msm_ring->submit.nr_bos = 0;
253 msm_ring->nr_rings = 0; 294 msm_ring->nr_cmds = 0;
254 msm_ring->nr_bos = 0; 295 msm_ring->nr_bos = 0;
255} 296}
256 297
257static int msm_ringbuffer_flush(struct fd_ringbuffer *ring, uint32_t *last_start) 298static int msm_ringbuffer_flush(struct fd_ringbuffer *ring, uint32_t *last_start)
258{ 299{
259 struct msm_ringbuffer *msm_ring = to_msm_ringbuffer(ring); 300 struct msm_ringbuffer *msm_ring = to_msm_ringbuffer(ring);
260 struct fd_bo *ring_bo = msm_ring->ring_bo;
261 struct drm_msm_gem_submit req = { 301 struct drm_msm_gem_submit req = {
262 .pipe = to_msm_pipe(ring->pipe)->pipe, 302 .pipe = to_msm_pipe(ring->pipe)->pipe,
263 }; 303 };
@@ -267,7 +307,7 @@ static int msm_ringbuffer_flush(struct fd_ringbuffer *ring, uint32_t *last_start
267 submit_offset = offset_bytes(last_start, ring->start); 307 submit_offset = offset_bytes(last_start, ring->start);
268 size = offset_bytes(ring->cur, last_start); 308 size = offset_bytes(ring->cur, last_start);
269 309
270 get_cmd(ring, ring, ring_bo, submit_offset, size, MSM_SUBMIT_CMD_BUF); 310 get_cmd(ring, msm_ring->cmd, submit_offset, size, MSM_SUBMIT_CMD_BUF);
271 311
272 /* needs to be after get_cmd() as that could create bos/cmds table: */ 312 /* needs to be after get_cmd() as that could create bos/cmds table: */
273 req.bos = VOID2U64(msm_ring->submit.bos), 313 req.bos = VOID2U64(msm_ring->submit.bos),
@@ -278,10 +318,10 @@ static int msm_ringbuffer_flush(struct fd_ringbuffer *ring, uint32_t *last_start
278 /* for each of the cmd's fix up their reloc's: */ 318 /* for each of the cmd's fix up their reloc's: */
279 for (i = 0; i < msm_ring->submit.nr_cmds; i++) { 319 for (i = 0; i < msm_ring->submit.nr_cmds; i++) {
280 struct drm_msm_gem_submit_cmd *cmd = &msm_ring->submit.cmds[i]; 320 struct drm_msm_gem_submit_cmd *cmd = &msm_ring->submit.cmds[i];
281 struct msm_ringbuffer *target_ring = to_msm_ringbuffer(msm_ring->rings[i]); 321 struct msm_cmd *msm_cmd = msm_ring->cmds[i];
282 uint32_t a = find_next_reloc_idx(target_ring, 0, cmd->submit_offset); 322 uint32_t a = find_next_reloc_idx(msm_cmd, 0, cmd->submit_offset);
283 uint32_t b = find_next_reloc_idx(target_ring, a, cmd->submit_offset + cmd->size); 323 uint32_t b = find_next_reloc_idx(msm_cmd, a, cmd->submit_offset + cmd->size);
284 cmd->relocs = VOID2U64(&target_ring->submit.relocs[a]); 324 cmd->relocs = VOID2U64(&msm_cmd->relocs[a]);
285 cmd->nr_relocs = (b > a) ? b - a : 0; 325 cmd->nr_relocs = (b > a) ? b - a : 0;
286 } 326 }
287 327
@@ -308,12 +348,11 @@ static int msm_ringbuffer_flush(struct fd_ringbuffer *ring, uint32_t *last_start
308 r->reloc_idx, r->reloc_offset); 348 r->reloc_idx, r->reloc_offset);
309 } 349 }
310 } 350 }
311 } else { 351 } else if (!ret) {
312 /* update timestamp on all rings associated with submit: */ 352 /* update timestamp on all rings associated with submit: */
313 for (i = 0; i < msm_ring->submit.nr_cmds; i++) { 353 for (i = 0; i < msm_ring->submit.nr_cmds; i++) {
314 struct fd_ringbuffer *target_ring = msm_ring->rings[i]; 354 struct msm_cmd *msm_cmd = msm_ring->cmds[i];
315 if (!ret) 355 msm_cmd->ring->last_timestamp = req.fence;
316 target_ring->last_timestamp = req.fence;
317 } 356 }
318 } 357 }
319 358
@@ -334,10 +373,10 @@ static void msm_ringbuffer_emit_reloc(struct fd_ringbuffer *ring,
334 struct fd_ringbuffer *parent = ring->parent ? ring->parent : ring; 373 struct fd_ringbuffer *parent = ring->parent ? ring->parent : ring;
335 struct msm_bo *msm_bo = to_msm_bo(r->bo); 374 struct msm_bo *msm_bo = to_msm_bo(r->bo);
336 struct drm_msm_gem_submit_reloc *reloc; 375 struct drm_msm_gem_submit_reloc *reloc;
337 uint32_t idx = APPEND(&msm_ring->submit, relocs); 376 uint32_t idx = APPEND(msm_ring->cmd, relocs);
338 uint32_t addr; 377 uint32_t addr;
339 378
340 reloc = &msm_ring->submit.relocs[idx]; 379 reloc = &msm_ring->cmd->relocs[idx];
341 380
342 reloc->reloc_idx = bo2idx(parent, r->bo, r->flags); 381 reloc->reloc_idx = bo2idx(parent, r->bo, r->flags);
343 reloc->reloc_offset = r->offset; 382 reloc->reloc_offset = r->offset;
@@ -357,13 +396,12 @@ static void msm_ringbuffer_emit_reloc_ring(struct fd_ringbuffer *ring,
357 struct fd_ringbuffer *target, 396 struct fd_ringbuffer *target,
358 uint32_t submit_offset, uint32_t size) 397 uint32_t submit_offset, uint32_t size)
359{ 398{
360 struct fd_bo *target_bo = to_msm_ringbuffer(target)->ring_bo; 399 struct msm_cmd *cmd = to_msm_ringbuffer(target)->cmd;
361 400
362 get_cmd(ring, target, target_bo, submit_offset, size, 401 get_cmd(ring, cmd, submit_offset, size, MSM_SUBMIT_CMD_IB_TARGET_BUF);
363 MSM_SUBMIT_CMD_IB_TARGET_BUF);
364 402
365 msm_ringbuffer_emit_reloc(ring, &(struct fd_reloc){ 403 msm_ringbuffer_emit_reloc(ring, &(struct fd_reloc){
366 .bo = target_bo, 404 .bo = cmd->ring_bo,
367 .flags = FD_RELOC_READ, 405 .flags = FD_RELOC_READ,
368 .offset = submit_offset, 406 .offset = submit_offset,
369 }); 407 });
@@ -372,13 +410,12 @@ static void msm_ringbuffer_emit_reloc_ring(struct fd_ringbuffer *ring,
372static void msm_ringbuffer_destroy(struct fd_ringbuffer *ring) 410static void msm_ringbuffer_destroy(struct fd_ringbuffer *ring)
373{ 411{
374 struct msm_ringbuffer *msm_ring = to_msm_ringbuffer(ring); 412 struct msm_ringbuffer *msm_ring = to_msm_ringbuffer(ring);
375 if (msm_ring->ring_bo) 413 if (msm_ring->cmd)
376 ring_bo_del(ring->pipe->dev, msm_ring->ring_bo); 414 ring_cmd_del(msm_ring->cmd);
377 free(msm_ring->submit.relocs);
378 free(msm_ring->submit.cmds); 415 free(msm_ring->submit.cmds);
379 free(msm_ring->submit.bos); 416 free(msm_ring->submit.bos);
380 free(msm_ring->bos); 417 free(msm_ring->bos);
381 free(msm_ring->rings); 418 free(msm_ring->cmds);
382 free(msm_ring); 419 free(msm_ring);
383} 420}
384 421
@@ -405,10 +442,11 @@ drm_private struct fd_ringbuffer * msm_ringbuffer_new(struct fd_pipe *pipe,
405 442
406 ring = &msm_ring->base; 443 ring = &msm_ring->base;
407 ring->funcs = &funcs; 444 ring->funcs = &funcs;
445 ring->pipe = pipe; /* needed in ring_cmd_new() */
408 446
409 msm_ring->ring_bo = ring_bo_new(pipe->dev, size); 447 msm_ring->cmd = ring_cmd_new(ring, size);
410 if (!msm_ring->ring_bo) { 448 if (!msm_ring->cmd) {
411 ERROR_MSG("ringbuffer allocation failed"); 449 ERROR_MSG("command buffer allocation failed");
412 goto fail; 450 goto fail;
413 } 451 }
414 452