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>
This commit is contained in:
Christian Gmeiner 2017-09-24 15:15:30 +02:00 committed by Lucas Stach
parent 547d340d3f
commit 68dc0b295d
2 changed files with 70 additions and 6 deletions

View File

@ -1329,12 +1329,48 @@ void etnaviv_gpu_pm_put(struct etnaviv_gpu *gpu)
pm_runtime_put_autosuspend(gpu->dev);
}
static void sync_point_perfmon_sample(struct etnaviv_gpu *gpu,
struct etnaviv_event *event, unsigned int flags)
{
const struct etnaviv_cmdbuf *cmdbuf = event->cmdbuf;
unsigned int i;
for (i = 0; i < cmdbuf->nr_pmrs; i++) {
const struct etnaviv_perfmon_request *pmr = cmdbuf->pmrs + i;
if (pmr->flags == flags)
etnaviv_perfmon_process(gpu, pmr);
}
}
static void sync_point_perfmon_sample_pre(struct etnaviv_gpu *gpu,
struct etnaviv_event *event)
{
sync_point_perfmon_sample(gpu, event, ETNA_PM_PROCESS_PRE);
}
static void sync_point_perfmon_sample_post(struct etnaviv_gpu *gpu,
struct etnaviv_event *event)
{
const struct etnaviv_cmdbuf *cmdbuf = event->cmdbuf;
unsigned int i;
sync_point_perfmon_sample(gpu, event, ETNA_PM_PROCESS_POST);
for (i = 0; i < cmdbuf->nr_pmrs; i++) {
const struct etnaviv_perfmon_request *pmr = cmdbuf->pmrs + i;
*pmr->bo_vma = pmr->sequence;
}
}
/* add bo's to gpu's ring, and kick gpu: */
int etnaviv_gpu_submit(struct etnaviv_gpu *gpu,
struct etnaviv_gem_submit *submit, struct etnaviv_cmdbuf *cmdbuf)
{
struct dma_fence *fence;
unsigned int event, i;
unsigned int i, nr_events = 1, event[3];
int ret;
ret = etnaviv_gpu_pm_get_sync(gpu);
@ -1350,9 +1386,19 @@ int etnaviv_gpu_submit(struct etnaviv_gpu *gpu,
*
*/
ret = event_alloc(gpu, 1, &event);
/*
* if there are performance monitor requests we need to have
* - a sync point to re-configure gpu and process ETNA_PM_PROCESS_PRE
* requests.
* - a sync point to re-configure gpu, process ETNA_PM_PROCESS_POST requests
* and update the sequence number for userspace.
*/
if (cmdbuf->nr_pmrs)
nr_events = 3;
ret = event_alloc(gpu, nr_events, event);
if (ret) {
DRM_ERROR("no free event\n");
DRM_ERROR("no free events\n");
goto out_pm_put;
}
@ -1360,12 +1406,14 @@ int etnaviv_gpu_submit(struct etnaviv_gpu *gpu,
fence = etnaviv_gpu_fence_alloc(gpu);
if (!fence) {
event_free(gpu, event);
for (i = 0; i < nr_events; i++)
event_free(gpu, event[i]);
ret = -ENOMEM;
goto out_unlock;
}
gpu->event[event].fence = fence;
gpu->event[event[0]].fence = fence;
submit->fence = dma_fence_get(fence);
gpu->active_fence = submit->fence->seqno;
@ -1375,7 +1423,19 @@ int etnaviv_gpu_submit(struct etnaviv_gpu *gpu,
gpu->lastctx = cmdbuf->ctx;
}
etnaviv_buffer_queue(gpu, event, cmdbuf);
if (cmdbuf->nr_pmrs) {
gpu->event[event[1]].sync_point = &sync_point_perfmon_sample_pre;
gpu->event[event[1]].cmdbuf = cmdbuf;
etnaviv_sync_point_queue(gpu, event[1]);
}
etnaviv_buffer_queue(gpu, event[0], cmdbuf);
if (cmdbuf->nr_pmrs) {
gpu->event[event[2]].sync_point = &sync_point_perfmon_sample_post;
gpu->event[event[2]].cmdbuf = cmdbuf;
etnaviv_sync_point_queue(gpu, event[2]);
}
cmdbuf->fence = fence;
list_add_tail(&cmdbuf->node, &gpu->active_cmd_list);
@ -1481,6 +1541,9 @@ static irqreturn_t irq_handler(int irq, void *data)
}
fence = gpu->event[event].fence;
if (!fence)
continue;
gpu->event[event].fence = NULL;
dma_fence_signal(fence);

View File

@ -89,6 +89,7 @@ struct etnaviv_chip_identity {
struct etnaviv_event {
struct dma_fence *fence;
struct etnaviv_cmdbuf *cmdbuf;
void (*sync_point)(struct etnaviv_gpu *gpu, struct etnaviv_event *event);
};