Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/etnaviv: use 'sync points' for performance monitor requests

With 'sync points' we can sample the reqeustes perform signals
before and/or after the submited command buffer.

Changes v2 -> v3:
- fixed indentation and init nr_events to 1

Changes v4 -> v5:
- simplify logic around fence handling.

Signed-off-by: Christian Gmeiner <christian.gmeiner@gmail.com>
Signed-off-by: Lucas Stach <l.stach@pengutronix.de>

authored by

Christian Gmeiner and committed by
Lucas Stach
68dc0b29 547d340d

+70 -6
+69 -6
drivers/gpu/drm/etnaviv/etnaviv_gpu.c
··· 1329 1329 pm_runtime_put_autosuspend(gpu->dev); 1330 1330 } 1331 1331 1332 + static void sync_point_perfmon_sample(struct etnaviv_gpu *gpu, 1333 + struct etnaviv_event *event, unsigned int flags) 1334 + { 1335 + const struct etnaviv_cmdbuf *cmdbuf = event->cmdbuf; 1336 + unsigned int i; 1337 + 1338 + for (i = 0; i < cmdbuf->nr_pmrs; i++) { 1339 + const struct etnaviv_perfmon_request *pmr = cmdbuf->pmrs + i; 1340 + 1341 + if (pmr->flags == flags) 1342 + etnaviv_perfmon_process(gpu, pmr); 1343 + } 1344 + } 1345 + 1346 + static void sync_point_perfmon_sample_pre(struct etnaviv_gpu *gpu, 1347 + struct etnaviv_event *event) 1348 + { 1349 + sync_point_perfmon_sample(gpu, event, ETNA_PM_PROCESS_PRE); 1350 + } 1351 + 1352 + static void sync_point_perfmon_sample_post(struct etnaviv_gpu *gpu, 1353 + struct etnaviv_event *event) 1354 + { 1355 + const struct etnaviv_cmdbuf *cmdbuf = event->cmdbuf; 1356 + unsigned int i; 1357 + 1358 + sync_point_perfmon_sample(gpu, event, ETNA_PM_PROCESS_POST); 1359 + 1360 + for (i = 0; i < cmdbuf->nr_pmrs; i++) { 1361 + const struct etnaviv_perfmon_request *pmr = cmdbuf->pmrs + i; 1362 + 1363 + *pmr->bo_vma = pmr->sequence; 1364 + } 1365 + } 1366 + 1367 + 1332 1368 /* add bo's to gpu's ring, and kick gpu: */ 1333 1369 int etnaviv_gpu_submit(struct etnaviv_gpu *gpu, 1334 1370 struct etnaviv_gem_submit *submit, struct etnaviv_cmdbuf *cmdbuf) 1335 1371 { 1336 1372 struct dma_fence *fence; 1337 - unsigned int event, i; 1373 + unsigned int i, nr_events = 1, event[3]; 1338 1374 int ret; 1339 1375 1340 1376 ret = etnaviv_gpu_pm_get_sync(gpu); ··· 1386 1350 * 1387 1351 */ 1388 1352 1389 - ret = event_alloc(gpu, 1, &event); 1353 + /* 1354 + * if there are performance monitor requests we need to have 1355 + * - a sync point to re-configure gpu and process ETNA_PM_PROCESS_PRE 1356 + * requests. 1357 + * - a sync point to re-configure gpu, process ETNA_PM_PROCESS_POST requests 1358 + * and update the sequence number for userspace. 1359 + */ 1360 + if (cmdbuf->nr_pmrs) 1361 + nr_events = 3; 1362 + 1363 + ret = event_alloc(gpu, nr_events, event); 1390 1364 if (ret) { 1391 - DRM_ERROR("no free event\n"); 1365 + DRM_ERROR("no free events\n"); 1392 1366 goto out_pm_put; 1393 1367 } 1394 1368 ··· 1406 1360 1407 1361 fence = etnaviv_gpu_fence_alloc(gpu); 1408 1362 if (!fence) { 1409 - event_free(gpu, event); 1363 + for (i = 0; i < nr_events; i++) 1364 + event_free(gpu, event[i]); 1365 + 1410 1366 ret = -ENOMEM; 1411 1367 goto out_unlock; 1412 1368 } 1413 1369 1414 - gpu->event[event].fence = fence; 1370 + gpu->event[event[0]].fence = fence; 1415 1371 submit->fence = dma_fence_get(fence); 1416 1372 gpu->active_fence = submit->fence->seqno; 1417 1373 ··· 1423 1375 gpu->lastctx = cmdbuf->ctx; 1424 1376 } 1425 1377 1426 - etnaviv_buffer_queue(gpu, event, cmdbuf); 1378 + if (cmdbuf->nr_pmrs) { 1379 + gpu->event[event[1]].sync_point = &sync_point_perfmon_sample_pre; 1380 + gpu->event[event[1]].cmdbuf = cmdbuf; 1381 + etnaviv_sync_point_queue(gpu, event[1]); 1382 + } 1383 + 1384 + etnaviv_buffer_queue(gpu, event[0], cmdbuf); 1385 + 1386 + if (cmdbuf->nr_pmrs) { 1387 + gpu->event[event[2]].sync_point = &sync_point_perfmon_sample_post; 1388 + gpu->event[event[2]].cmdbuf = cmdbuf; 1389 + etnaviv_sync_point_queue(gpu, event[2]); 1390 + } 1427 1391 1428 1392 cmdbuf->fence = fence; 1429 1393 list_add_tail(&cmdbuf->node, &gpu->active_cmd_list); ··· 1541 1481 } 1542 1482 1543 1483 fence = gpu->event[event].fence; 1484 + if (!fence) 1485 + continue; 1486 + 1544 1487 gpu->event[event].fence = NULL; 1545 1488 dma_fence_signal(fence); 1546 1489
+1
drivers/gpu/drm/etnaviv/etnaviv_gpu.h
··· 89 89 90 90 struct etnaviv_event { 91 91 struct dma_fence *fence; 92 + struct etnaviv_cmdbuf *cmdbuf; 92 93 93 94 void (*sync_point)(struct etnaviv_gpu *gpu, struct etnaviv_event *event); 94 95 };