Skip to content

Commit

Permalink
drm/etnaviv: move dependency handling to scheduler
Browse files Browse the repository at this point in the history
Move the fence dependency handling to the scheduler where it belongs.
Jobs with unsignaled dependencies just get to sit in the scheduler queue
without holding any locks.

Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
  • Loading branch information
Lucas Stach committed Feb 12, 2018
1 parent e93b6de commit 683da22
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 68 deletions.
3 changes: 3 additions & 0 deletions drivers/gpu/drm/etnaviv/etnaviv_gem.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,9 @@ struct etnaviv_gem_submit_bo {
u32 flags;
struct etnaviv_gem_object *obj;
struct etnaviv_vram_mapping *mapping;
struct dma_fence *excl;
unsigned int nr_shared;
struct dma_fence **shared;
};

/* Created per submit-ioctl, to track bo's and cmdstream bufs, etc,
Expand Down
38 changes: 21 additions & 17 deletions drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c
Original file line number Diff line number Diff line change
Expand Up @@ -170,29 +170,33 @@ static int submit_lock_objects(struct etnaviv_gem_submit *submit,
return ret;
}

static int submit_fence_sync(const struct etnaviv_gem_submit *submit)
static int submit_fence_sync(struct etnaviv_gem_submit *submit)
{
unsigned int context = submit->gpu->fence_context;
int i, ret = 0;

for (i = 0; i < submit->nr_bos; i++) {
struct etnaviv_gem_object *etnaviv_obj = submit->bos[i].obj;
bool write = submit->bos[i].flags & ETNA_SUBMIT_BO_WRITE;
bool explicit = !!(submit->flags & ETNA_SUBMIT_NO_IMPLICIT);
struct etnaviv_gem_submit_bo *bo = &submit->bos[i];
struct reservation_object *robj = bo->obj->resv;

ret = etnaviv_gpu_fence_sync_obj(etnaviv_obj, context, write,
explicit);
if (ret)
break;
}
if (!(bo->flags & ETNA_SUBMIT_BO_WRITE)) {
ret = reservation_object_reserve_shared(robj);
if (ret)
return ret;
}

if (submit->flags & ETNA_SUBMIT_NO_IMPLICIT)
continue;

if (bo->flags & ETNA_SUBMIT_BO_WRITE) {
ret = reservation_object_get_fences_rcu(robj, &bo->excl,
&bo->nr_shared,
&bo->shared);
if (ret)
return ret;
} else {
bo->excl = reservation_object_get_excl_rcu(robj);
}

if (submit->flags & ETNA_SUBMIT_FENCE_FD_IN) {
/*
* Wait if the fence is from a foreign context, or if the fence
* array contains any fence from a foreign context.
*/
if (!dma_fence_match_context(submit->in_fence, context))
ret = dma_fence_wait(submit->in_fence, true);
}

return ret;
Expand Down
48 changes: 0 additions & 48 deletions drivers/gpu/drm/etnaviv/etnaviv_gpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -1084,54 +1084,6 @@ static struct dma_fence *etnaviv_gpu_fence_alloc(struct etnaviv_gpu *gpu)
return &f->base;
}

int etnaviv_gpu_fence_sync_obj(struct etnaviv_gem_object *etnaviv_obj,
unsigned int context, bool exclusive, bool explicit)
{
struct reservation_object *robj = etnaviv_obj->resv;
struct reservation_object_list *fobj;
struct dma_fence *fence;
int i, ret;

if (!exclusive) {
ret = reservation_object_reserve_shared(robj);
if (ret)
return ret;
}

if (explicit)
return 0;

/*
* If we have any shared fences, then the exclusive fence
* should be ignored as it will already have been signalled.
*/
fobj = reservation_object_get_list(robj);
if (!fobj || fobj->shared_count == 0) {
/* Wait on any existing exclusive fence which isn't our own */
fence = reservation_object_get_excl(robj);
if (fence && fence->context != context) {
ret = dma_fence_wait(fence, true);
if (ret)
return ret;
}
}

if (!exclusive || !fobj)
return 0;

for (i = 0; i < fobj->shared_count; i++) {
fence = rcu_dereference_protected(fobj->shared[i],
reservation_object_held(robj));
if (fence->context != context) {
ret = dma_fence_wait(fence, true);
if (ret)
return ret;
}
}

return 0;
}

/*
* event management:
*/
Expand Down
3 changes: 0 additions & 3 deletions drivers/gpu/drm/etnaviv/etnaviv_gpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -188,9 +188,6 @@ int etnaviv_gpu_init(struct etnaviv_gpu *gpu);
int etnaviv_gpu_debugfs(struct etnaviv_gpu *gpu, struct seq_file *m);
#endif

int etnaviv_gpu_fence_sync_obj(struct etnaviv_gem_object *etnaviv_obj,
unsigned int context, bool exclusive, bool implicit);

void etnaviv_gpu_retire(struct etnaviv_gpu *gpu);
int etnaviv_gpu_wait_fence_interruptible(struct etnaviv_gpu *gpu,
u32 fence, struct timespec *timeout);
Expand Down
45 changes: 45 additions & 0 deletions drivers/gpu/drm/etnaviv/etnaviv_sched.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,51 @@ struct etnaviv_gem_submit *to_etnaviv_submit(struct drm_sched_job *sched_job)
struct dma_fence *etnaviv_sched_dependency(struct drm_sched_job *sched_job,
struct drm_sched_entity *entity)
{
struct etnaviv_gem_submit *submit = to_etnaviv_submit(sched_job);
struct dma_fence *fence;
int i;

if (unlikely(submit->in_fence)) {
fence = submit->in_fence;
submit->in_fence = NULL;

if (!dma_fence_is_signaled(fence))
return fence;

dma_fence_put(fence);
}

for (i = 0; i < submit->nr_bos; i++) {
struct etnaviv_gem_submit_bo *bo = &submit->bos[i];
int j;

if (bo->excl) {
fence = bo->excl;
bo->excl = NULL;

if (!dma_fence_is_signaled(fence))
return fence;

dma_fence_put(fence);
}

for (j = 0; j < bo->nr_shared; j++) {
if (!bo->shared[j])
continue;

fence = bo->shared[j];
bo->shared[j] = NULL;

if (!dma_fence_is_signaled(fence))
return fence;

dma_fence_put(fence);
}
kfree(bo->shared);
bo->nr_shared = 0;
bo->shared = NULL;
}

return NULL;
}

Expand Down

0 comments on commit 683da22

Please sign in to comment.