Skip to content

Commit

Permalink
drm/etnaviv: move PMRs to submit object
Browse files Browse the repository at this point in the history
To make them available to the event worker even after the actual
command stream execution has finished.

Signed-off-by: Lucas Stach <[email protected]>
  • Loading branch information
lynxeye-dev committed Jan 2, 2018
1 parent e0329e6 commit ef146c0
Show file tree
Hide file tree
Showing 6 changed files with 44 additions and 49 deletions.
14 changes: 1 addition & 13 deletions drivers/gpu/drm/etnaviv/etnaviv_cmdbuf.c
Original file line number Diff line number Diff line change
Expand Up @@ -88,10 +88,9 @@ void etnaviv_cmdbuf_suballoc_destroy(struct etnaviv_cmdbuf_suballoc *suballoc)

struct etnaviv_cmdbuf *
etnaviv_cmdbuf_new(struct etnaviv_cmdbuf_suballoc *suballoc, u32 size,
size_t nr_bos, size_t nr_pmrs)
size_t nr_bos)
{
struct etnaviv_cmdbuf *cmdbuf;
struct etnaviv_perfmon_request *pmrs;
size_t sz = size_vstruct(nr_bos, sizeof(cmdbuf->bo_map[0]),
sizeof(*cmdbuf));
int granule_offs, order, ret;
Expand All @@ -100,12 +99,6 @@ etnaviv_cmdbuf_new(struct etnaviv_cmdbuf_suballoc *suballoc, u32 size,
if (!cmdbuf)
return NULL;

sz = sizeof(*pmrs) * nr_pmrs;
pmrs = kzalloc(sz, GFP_KERNEL);
if (!pmrs)
goto out_free_cmdbuf;

cmdbuf->pmrs = pmrs;
cmdbuf->suballoc = suballoc;
cmdbuf->size = size;

Expand All @@ -132,10 +125,6 @@ etnaviv_cmdbuf_new(struct etnaviv_cmdbuf_suballoc *suballoc, u32 size,
cmdbuf->vaddr = suballoc->vaddr + cmdbuf->suballoc_offset;

return cmdbuf;

out_free_cmdbuf:
kfree(cmdbuf);
return NULL;
}

void etnaviv_cmdbuf_free(struct etnaviv_cmdbuf *cmdbuf)
Expand All @@ -151,7 +140,6 @@ void etnaviv_cmdbuf_free(struct etnaviv_cmdbuf *cmdbuf)
suballoc->free_space = 1;
mutex_unlock(&suballoc->lock);
wake_up_all(&suballoc->free_event);
kfree(cmdbuf->pmrs);
kfree(cmdbuf);
}

Expand Down
5 changes: 1 addition & 4 deletions drivers/gpu/drm/etnaviv/etnaviv_cmdbuf.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,6 @@ struct etnaviv_cmdbuf {
u32 exec_state;
/* per GPU in-flight list */
struct list_head node;
/* perfmon requests */
unsigned int nr_pmrs;
struct etnaviv_perfmon_request *pmrs;
/* BOs attached to this command buffer */
unsigned int nr_bos;
struct etnaviv_vram_mapping *bo_map[0];
Expand All @@ -53,7 +50,7 @@ void etnaviv_cmdbuf_suballoc_destroy(struct etnaviv_cmdbuf_suballoc *suballoc);

struct etnaviv_cmdbuf *
etnaviv_cmdbuf_new(struct etnaviv_cmdbuf_suballoc *suballoc, u32 size,
size_t nr_bos, size_t nr_pmrs);
size_t nr_bos);
void etnaviv_cmdbuf_free(struct etnaviv_cmdbuf *cmdbuf);

u32 etnaviv_cmdbuf_get_va(struct etnaviv_cmdbuf *buf);
Expand Down
5 changes: 3 additions & 2 deletions drivers/gpu/drm/etnaviv/etnaviv_gem.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,14 +97,15 @@ struct etnaviv_gem_submit_bo {

/* Created per submit-ioctl, to track bo's and cmdstream bufs, etc,
* associated with the cmdstream submission for synchronization (and
* make it easier to unwind when things go wrong, etc). This only
* lasts for the duration of the submit-ioctl.
* make it easier to unwind when things go wrong, etc).
*/
struct etnaviv_gem_submit {
struct kref refcount;
struct etnaviv_gpu *gpu;
struct dma_fence *out_fence, *in_fence;
u32 flags;
unsigned int nr_pmrs;
struct etnaviv_perfmon_request *pmrs;
unsigned int nr_bos;
struct etnaviv_gem_submit_bo bos[0];
/* No new members here, the previous one is variable-length! */
Expand Down
40 changes: 23 additions & 17 deletions drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,23 @@
#define BO_PINNED 0x2000

static struct etnaviv_gem_submit *submit_create(struct drm_device *dev,
struct etnaviv_gpu *gpu, size_t nr)
struct etnaviv_gpu *gpu, size_t nr_bos, size_t nr_pmrs)
{
struct etnaviv_gem_submit *submit;
size_t sz = size_vstruct(nr, sizeof(submit->bos[0]), sizeof(*submit));
size_t sz = size_vstruct(nr_bos, sizeof(submit->bos[0]), sizeof(*submit));

submit = kzalloc(sz, GFP_KERNEL);
if (!submit)
return NULL;

submit->pmrs = kcalloc(nr_pmrs, sizeof(struct etnaviv_perfmon_request),
GFP_KERNEL);
if (!submit->pmrs) {
kfree(submit);
return NULL;
}
submit->nr_pmrs = nr_pmrs;

submit->gpu = gpu;
kref_init(&submit->refcount);

Expand Down Expand Up @@ -295,13 +303,11 @@ static int submit_reloc(struct etnaviv_gem_submit *submit, void *stream,
}

static int submit_perfmon_validate(struct etnaviv_gem_submit *submit,
struct etnaviv_cmdbuf *cmdbuf,
const struct drm_etnaviv_gem_submit_pmr *pmrs,
u32 nr_pms)
u32 exec_state, const struct drm_etnaviv_gem_submit_pmr *pmrs)
{
u32 i;

for (i = 0; i < nr_pms; i++) {
for (i = 0; i < submit->nr_pmrs; i++) {
const struct drm_etnaviv_gem_submit_pmr *r = pmrs + i;
struct etnaviv_gem_submit_bo *bo;
int ret;
Expand All @@ -326,17 +332,17 @@ static int submit_perfmon_validate(struct etnaviv_gem_submit *submit,
return -EINVAL;
}

if (etnaviv_pm_req_validate(r, cmdbuf->exec_state)) {
if (etnaviv_pm_req_validate(r, exec_state)) {
DRM_ERROR("perfmon request: domain or signal not valid");
return -EINVAL;
}

cmdbuf->pmrs[i].flags = r->flags;
cmdbuf->pmrs[i].domain = r->domain;
cmdbuf->pmrs[i].signal = r->signal;
cmdbuf->pmrs[i].sequence = r->sequence;
cmdbuf->pmrs[i].offset = r->read_offset;
cmdbuf->pmrs[i].bo_vma = etnaviv_gem_vmap(&bo->obj->base);
submit->pmrs[i].flags = r->flags;
submit->pmrs[i].domain = r->domain;
submit->pmrs[i].signal = r->signal;
submit->pmrs[i].sequence = r->sequence;
submit->pmrs[i].offset = r->read_offset;
submit->pmrs[i].bo_vma = etnaviv_gem_vmap(&bo->obj->base);
}

return 0;
Expand Down Expand Up @@ -367,6 +373,7 @@ static void submit_cleanup(struct kref *kref)
dma_fence_put(submit->in_fence);
if (submit->out_fence)
dma_fence_put(submit->out_fence);
kfree(submit->pmrs);
kfree(submit);
}

Expand Down Expand Up @@ -427,7 +434,7 @@ int etnaviv_ioctl_gem_submit(struct drm_device *dev, void *data,
stream = kvmalloc_array(1, args->stream_size, GFP_KERNEL);
cmdbuf = etnaviv_cmdbuf_new(gpu->cmdbuf_suballoc,
ALIGN(args->stream_size, 8) + 8,
args->nr_bos, args->nr_pmrs);
args->nr_bos);
if (!bos || !relocs || !pmrs || !stream || !cmdbuf) {
ret = -ENOMEM;
goto err_submit_cmds;
Expand Down Expand Up @@ -456,7 +463,6 @@ int etnaviv_ioctl_gem_submit(struct drm_device *dev, void *data,
ret = -EFAULT;
goto err_submit_cmds;
}
cmdbuf->nr_pmrs = args->nr_pmrs;

ret = copy_from_user(stream, u64_to_user_ptr(args->stream),
args->stream_size);
Expand All @@ -475,7 +481,7 @@ int etnaviv_ioctl_gem_submit(struct drm_device *dev, void *data,

ww_acquire_init(&ticket, &reservation_ww_class);

submit = submit_create(dev, gpu, args->nr_bos);
submit = submit_create(dev, gpu, args->nr_bos, args->nr_pmrs);
if (!submit) {
ret = -ENOMEM;
goto err_submit_ww_acquire;
Expand Down Expand Up @@ -518,7 +524,7 @@ int etnaviv_ioctl_gem_submit(struct drm_device *dev, void *data,
if (ret)
goto err_submit_objects;

ret = submit_perfmon_validate(submit, cmdbuf, pmrs, args->nr_pmrs);
ret = submit_perfmon_validate(submit, args->exec_state, pmrs);
if (ret)
goto err_submit_objects;

Expand Down
27 changes: 15 additions & 12 deletions drivers/gpu/drm/etnaviv/etnaviv_gpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -717,7 +717,7 @@ int etnaviv_gpu_init(struct etnaviv_gpu *gpu)
}

/* Create buffer: */
gpu->buffer = etnaviv_cmdbuf_new(gpu->cmdbuf_suballoc, PAGE_SIZE, 0, 0);
gpu->buffer = etnaviv_cmdbuf_new(gpu->cmdbuf_suballoc, PAGE_SIZE, 0);
if (!gpu->buffer) {
ret = -ENOMEM;
dev_err(gpu->dev, "could not create command buffer\n");
Expand Down Expand Up @@ -1317,11 +1317,11 @@ void etnaviv_gpu_pm_put(struct etnaviv_gpu *gpu)
static void sync_point_perfmon_sample(struct etnaviv_gpu *gpu,
struct etnaviv_event *event, unsigned int flags)
{
const struct etnaviv_cmdbuf *cmdbuf = event->cmdbuf;
const struct etnaviv_gem_submit *submit = event->submit;
unsigned int i;

for (i = 0; i < cmdbuf->nr_pmrs; i++) {
const struct etnaviv_perfmon_request *pmr = cmdbuf->pmrs + i;
for (i = 0; i < submit->nr_pmrs; i++) {
const struct etnaviv_perfmon_request *pmr = submit->pmrs + i;

if (pmr->flags == flags)
etnaviv_perfmon_process(gpu, pmr);
Expand Down Expand Up @@ -1349,14 +1349,14 @@ static void sync_point_perfmon_sample_pre(struct etnaviv_gpu *gpu,
static void sync_point_perfmon_sample_post(struct etnaviv_gpu *gpu,
struct etnaviv_event *event)
{
const struct etnaviv_cmdbuf *cmdbuf = event->cmdbuf;
const struct etnaviv_gem_submit *submit = event->submit;
unsigned int i;
u32 val;

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;
for (i = 0; i < submit->nr_pmrs; i++) {
const struct etnaviv_perfmon_request *pmr = submit->pmrs + i;

*pmr->bo_vma = pmr->sequence;
}
Expand Down Expand Up @@ -1392,7 +1392,7 @@ int etnaviv_gpu_submit(struct etnaviv_gpu *gpu,
* - a sync point to re-configure gpu, process ETNA_PM_PROCESS_POST requests
* and update the sequence number for userspace.
*/
if (cmdbuf->nr_pmrs)
if (submit->nr_pmrs)
nr_events = 3;

ret = event_alloc(gpu, nr_events, event);
Expand All @@ -1416,17 +1416,19 @@ int etnaviv_gpu_submit(struct etnaviv_gpu *gpu,
submit->out_fence = dma_fence_get(fence);
gpu->active_fence = submit->out_fence->seqno;

if (cmdbuf->nr_pmrs) {
if (submit->nr_pmrs) {
gpu->event[event[1]].sync_point = &sync_point_perfmon_sample_pre;
gpu->event[event[1]].cmdbuf = cmdbuf;
kref_get(&submit->refcount);
gpu->event[event[1]].submit = submit;
etnaviv_sync_point_queue(gpu, event[1]);
}

etnaviv_buffer_queue(gpu, event[0], cmdbuf);

if (cmdbuf->nr_pmrs) {
if (submit->nr_pmrs) {
gpu->event[event[2]].sync_point = &sync_point_perfmon_sample_post;
gpu->event[event[2]].cmdbuf = cmdbuf;
kref_get(&submit->refcount);
gpu->event[event[2]].submit = submit;
etnaviv_sync_point_queue(gpu, event[2]);
}

Expand Down Expand Up @@ -1465,6 +1467,7 @@ static void sync_point_worker(struct work_struct *work)
u32 addr = gpu_read(gpu, VIVS_FE_DMA_ADDRESS);

event->sync_point(gpu, event);
etnaviv_submit_put(event->submit);
event_free(gpu, gpu->sync_point_event);

/* restart FE last to avoid GPU and IRQ racing against this worker */
Expand Down
2 changes: 1 addition & 1 deletion drivers/gpu/drm/etnaviv/etnaviv_gpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ struct etnaviv_chip_identity {

struct etnaviv_event {
struct dma_fence *fence;
struct etnaviv_cmdbuf *cmdbuf;
struct etnaviv_gem_submit *submit;

void (*sync_point)(struct etnaviv_gpu *gpu, struct etnaviv_event *event);
};
Expand Down

0 comments on commit ef146c0

Please sign in to comment.