Skip to content

Commit

Permalink
drm/amdgpu: Move old fence waiting before reservation lock is aquired v2
Browse files Browse the repository at this point in the history
Helps avoiding deadlock during GPU reset.
Added mutex to amdgpu_ctx to preserve order of fences on a ring.

v2:
Put waiting logic in a function in a seperate function in amdgpu_ctx.c

Signed-off-by: Andrey Grodzovsky <andrey.grodzovsky@amd.com>
Reviewed-by: Christian König <christian.koenig@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
  • Loading branch information
Andrey Grodzovsky authored and Alex Deucher committed Oct 19, 2017
1 parent ad864d2 commit 0ae9444
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 10 deletions.
4 changes: 4 additions & 0 deletions drivers/gpu/drm/amd/amdgpu/amdgpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -738,6 +738,7 @@ struct amdgpu_ctx {
bool preamble_presented;
enum amd_sched_priority init_priority;
enum amd_sched_priority override_priority;
struct mutex lock;
};

struct amdgpu_ctx_mgr {
Expand All @@ -760,9 +761,12 @@ void amdgpu_ctx_priority_override(struct amdgpu_ctx *ctx,
int amdgpu_ctx_ioctl(struct drm_device *dev, void *data,
struct drm_file *filp);

int amdgpu_ctx_wait_prev_fence(struct amdgpu_ctx *ctx, unsigned ring_id);

void amdgpu_ctx_mgr_init(struct amdgpu_ctx_mgr *mgr);
void amdgpu_ctx_mgr_fini(struct amdgpu_ctx_mgr *mgr);


/*
* file private structure
*/
Expand Down
10 changes: 6 additions & 4 deletions drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,8 @@ static int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p, void *data)
goto free_chunk;
}

mutex_lock(&p->ctx->lock);

/* get chunks */
chunk_array_user = u64_to_user_ptr(cs->in.chunks);
if (copy_from_user(chunk_array, chunk_array_user,
Expand Down Expand Up @@ -737,8 +739,10 @@ static void amdgpu_cs_parser_fini(struct amdgpu_cs_parser *parser, int error,

dma_fence_put(parser->fence);

if (parser->ctx)
if (parser->ctx) {
mutex_unlock(&parser->ctx->lock);
amdgpu_ctx_put(parser->ctx);
}
if (parser->bo_list)
amdgpu_bo_list_put(parser->bo_list);

Expand Down Expand Up @@ -895,9 +899,7 @@ static int amdgpu_cs_ib_vm_chunk(struct amdgpu_device *adev,
r = amdgpu_ring_parse_cs(ring, p, j);
if (r)
return r;

}

j++;
}

Expand Down Expand Up @@ -985,7 +987,7 @@ static int amdgpu_cs_ib_fill(struct amdgpu_device *adev,
parser->job->ring->funcs->type == AMDGPU_RING_TYPE_VCE))
return -EINVAL;

return 0;
return amdgpu_ctx_wait_prev_fence(parser->ctx, parser->job->ring->idx);
}

static int amdgpu_cs_process_fence_dep(struct amdgpu_cs_parser *p,
Expand Down
30 changes: 24 additions & 6 deletions drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ static int amdgpu_ctx_init(struct amdgpu_device *adev,
if (!ctx->fences)
return -ENOMEM;

mutex_init(&ctx->lock);

for (i = 0; i < AMDGPU_MAX_RINGS; ++i) {
ctx->rings[i].sequence = 1;
ctx->rings[i].fences = &ctx->fences[amdgpu_sched_jobs * i];
Expand Down Expand Up @@ -126,6 +128,8 @@ static void amdgpu_ctx_fini(struct amdgpu_ctx *ctx)
&ctx->rings[i].entity);

amdgpu_queue_mgr_fini(adev, &ctx->queue_mgr);

mutex_destroy(&ctx->lock);
}

static int amdgpu_ctx_alloc(struct amdgpu_device *adev,
Expand Down Expand Up @@ -296,12 +300,8 @@ int amdgpu_ctx_add_fence(struct amdgpu_ctx *ctx, struct amdgpu_ring *ring,

idx = seq & (amdgpu_sched_jobs - 1);
other = cring->fences[idx];
if (other) {
signed long r;
r = dma_fence_wait_timeout(other, true, MAX_SCHEDULE_TIMEOUT);
if (r < 0)
return r;
}
if (other)
BUG_ON(!dma_fence_is_signaled(other));

dma_fence_get(fence);

Expand Down Expand Up @@ -372,6 +372,24 @@ void amdgpu_ctx_priority_override(struct amdgpu_ctx *ctx,
}
}

int amdgpu_ctx_wait_prev_fence(struct amdgpu_ctx *ctx, unsigned ring_id)
{
struct amdgpu_ctx_ring *cring = &ctx->rings[ring_id];
unsigned idx = cring->sequence & (amdgpu_sched_jobs - 1);
struct dma_fence *other = cring->fences[idx];

if (other) {
signed long r;
r = dma_fence_wait_timeout(other, false, MAX_SCHEDULE_TIMEOUT);
if (r < 0) {
DRM_ERROR("Error (%ld) waiting for fence!\n", r);
return r;
}
}

return 0;
}

void amdgpu_ctx_mgr_init(struct amdgpu_ctx_mgr *mgr)
{
mutex_init(&mgr->lock);
Expand Down

0 comments on commit 0ae9444

Please sign in to comment.