Commit 049fc527 authored by Chunming Zhou's avatar Chunming Zhou Committed by Alex Deucher

drm/amdgpu: dispatch jobs in cs

BO validation is moved to scheduler except usrptr which must be validated
in user process
Signed-off-by: default avatarChunming Zhou <david1.zhou@amd.com>
Acked-by: default avatarChristian K?nig <christian.koenig@amd.com>
Reviewed-by: default avatarJammy Zhou <Jammy.Zhou@amd.com>
parent 372bc1e1
...@@ -1243,6 +1243,7 @@ struct amdgpu_cs_parser { ...@@ -1243,6 +1243,7 @@ struct amdgpu_cs_parser {
struct work_struct job_work; struct work_struct job_work;
int (*prepare_job)(struct amdgpu_cs_parser *sched_job); int (*prepare_job)(struct amdgpu_cs_parser *sched_job);
int (*run_job)(struct amdgpu_cs_parser *sched_job); int (*run_job)(struct amdgpu_cs_parser *sched_job);
int (*free_job)(struct amdgpu_cs_parser *sched_job);
}; };
static inline u32 amdgpu_get_ib_value(struct amdgpu_cs_parser *p, uint32_t ib_idx, int idx) static inline u32 amdgpu_get_ib_value(struct amdgpu_cs_parser *p, uint32_t ib_idx, int idx)
......
...@@ -41,6 +41,11 @@ struct amdgpu_cs_buckets { ...@@ -41,6 +41,11 @@ struct amdgpu_cs_buckets {
struct list_head bucket[AMDGPU_CS_NUM_BUCKETS]; struct list_head bucket[AMDGPU_CS_NUM_BUCKETS];
}; };
static void amdgpu_cs_parser_fini(struct amdgpu_cs_parser *parser,
int error, bool backoff);
static void amdgpu_cs_parser_fini_early(struct amdgpu_cs_parser *parser, int error, bool backoff);
static void amdgpu_cs_parser_fini_late(struct amdgpu_cs_parser *parser);
static void amdgpu_cs_buckets_init(struct amdgpu_cs_buckets *b) static void amdgpu_cs_buckets_init(struct amdgpu_cs_buckets *b)
{ {
unsigned i; unsigned i;
...@@ -126,12 +131,52 @@ int amdgpu_cs_get_ring(struct amdgpu_device *adev, u32 ip_type, ...@@ -126,12 +131,52 @@ int amdgpu_cs_get_ring(struct amdgpu_device *adev, u32 ip_type,
return 0; return 0;
} }
static void amdgpu_job_work_func(struct work_struct *work)
{
struct amdgpu_cs_parser *sched_job =
container_of(work, struct amdgpu_cs_parser,
job_work);
mutex_lock(&sched_job->job_lock);
sched_job->free_job(sched_job);
mutex_unlock(&sched_job->job_lock);
/* after processing job, free memory */
kfree(sched_job);
}
struct amdgpu_cs_parser *amdgpu_cs_parser_create(struct amdgpu_device *adev,
struct drm_file *filp,
struct amdgpu_ctx *ctx,
struct amdgpu_ib *ibs,
uint32_t num_ibs)
{
struct amdgpu_cs_parser *parser;
int i;
parser = kzalloc(sizeof(struct amdgpu_cs_parser), GFP_KERNEL);
if (!parser)
return NULL;
parser->adev = adev;
parser->filp = filp;
parser->ctx = ctx;
parser->ibs = ibs;
parser->num_ibs = num_ibs;
if (amdgpu_enable_scheduler) {
mutex_init(&parser->job_lock);
INIT_WORK(&parser->job_work, amdgpu_job_work_func);
}
for (i = 0; i < num_ibs; i++)
ibs[i].ctx = ctx;
return parser;
}
int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p, void *data) int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p, void *data)
{ {
union drm_amdgpu_cs *cs = data; union drm_amdgpu_cs *cs = data;
uint64_t *chunk_array_user; uint64_t *chunk_array_user;
uint64_t *chunk_array = NULL; uint64_t *chunk_array = NULL;
struct amdgpu_fpriv *fpriv = p->filp->driver_priv; struct amdgpu_fpriv *fpriv = p->filp->driver_priv;
struct amdgpu_bo_list *bo_list = NULL;
unsigned size, i; unsigned size, i;
int r = 0; int r = 0;
...@@ -143,7 +188,17 @@ int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p, void *data) ...@@ -143,7 +188,17 @@ int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p, void *data)
r = -EINVAL; r = -EINVAL;
goto out; goto out;
} }
p->bo_list = amdgpu_bo_list_get(fpriv, cs->in.bo_list_handle); bo_list = amdgpu_bo_list_get(fpriv, cs->in.bo_list_handle);
if (bo_list && !bo_list->has_userptr) {
p->bo_list = kzalloc(sizeof(struct amdgpu_bo_list), GFP_KERNEL);
if (!p->bo_list)
return -ENOMEM;
amdgpu_bo_list_copy(p->adev, p->bo_list, bo_list);
amdgpu_bo_list_put(bo_list);
} else if (bo_list && bo_list->has_userptr)
p->bo_list = bo_list;
else
p->bo_list = NULL;
/* get chunks */ /* get chunks */
INIT_LIST_HEAD(&p->validated); INIT_LIST_HEAD(&p->validated);
...@@ -424,8 +479,26 @@ static int cmp_size_smaller_first(void *priv, struct list_head *a, ...@@ -424,8 +479,26 @@ static int cmp_size_smaller_first(void *priv, struct list_head *a,
**/ **/
static void amdgpu_cs_parser_fini(struct amdgpu_cs_parser *parser, int error, bool backoff) static void amdgpu_cs_parser_fini(struct amdgpu_cs_parser *parser, int error, bool backoff)
{ {
unsigned i; amdgpu_cs_parser_fini_early(parser, error, backoff);
amdgpu_cs_parser_fini_late(parser);
}
static int amdgpu_cs_parser_run_job(
struct amdgpu_cs_parser *sched_job)
{
amdgpu_cs_parser_fini_early(sched_job, 0, true);
return 0;
}
static int amdgpu_cs_parser_free_job(
struct amdgpu_cs_parser *sched_job)
{
amdgpu_cs_parser_fini_late(sched_job);
return 0;
}
static void amdgpu_cs_parser_fini_early(struct amdgpu_cs_parser *parser, int error, bool backoff)
{
if (!error) { if (!error) {
/* Sort the buffer list from the smallest to largest buffer, /* Sort the buffer list from the smallest to largest buffer,
* which affects the order of buffers in the LRU list. * which affects the order of buffers in the LRU list.
...@@ -446,11 +519,19 @@ static void amdgpu_cs_parser_fini(struct amdgpu_cs_parser *parser, int error, bo ...@@ -446,11 +519,19 @@ static void amdgpu_cs_parser_fini(struct amdgpu_cs_parser *parser, int error, bo
ttm_eu_backoff_reservation(&parser->ticket, ttm_eu_backoff_reservation(&parser->ticket,
&parser->validated); &parser->validated);
} }
}
static void amdgpu_cs_parser_fini_late(struct amdgpu_cs_parser *parser)
{
unsigned i;
if (parser->ctx) if (parser->ctx)
amdgpu_ctx_put(parser->ctx); amdgpu_ctx_put(parser->ctx);
if (parser->bo_list) if (parser->bo_list) {
amdgpu_bo_list_put(parser->bo_list); if (!parser->bo_list->has_userptr)
amdgpu_bo_list_free(parser->bo_list);
else
amdgpu_bo_list_put(parser->bo_list);
}
drm_free_large(parser->vm_bos); drm_free_large(parser->vm_bos);
for (i = 0; i < parser->nchunks; i++) for (i = 0; i < parser->nchunks; i++)
drm_free_large(parser->chunks[i].kdata); drm_free_large(parser->chunks[i].kdata);
...@@ -461,6 +542,9 @@ static void amdgpu_cs_parser_fini(struct amdgpu_cs_parser *parser, int error, bo ...@@ -461,6 +542,9 @@ static void amdgpu_cs_parser_fini(struct amdgpu_cs_parser *parser, int error, bo
kfree(parser->ibs); kfree(parser->ibs);
if (parser->uf.bo) if (parser->uf.bo)
drm_gem_object_unreference_unlocked(&parser->uf.bo->gem_base); drm_gem_object_unreference_unlocked(&parser->uf.bo->gem_base);
if (!amdgpu_enable_scheduler)
kfree(parser);
} }
static int amdgpu_bo_vm_update_pte(struct amdgpu_cs_parser *p, static int amdgpu_bo_vm_update_pte(struct amdgpu_cs_parser *p,
...@@ -533,9 +617,9 @@ static int amdgpu_cs_ib_vm_chunk(struct amdgpu_device *adev, ...@@ -533,9 +617,9 @@ static int amdgpu_cs_ib_vm_chunk(struct amdgpu_device *adev,
goto out; goto out;
} }
amdgpu_cs_sync_rings(parser); amdgpu_cs_sync_rings(parser);
if (!amdgpu_enable_scheduler)
r = amdgpu_ib_schedule(adev, parser->num_ibs, parser->ibs, r = amdgpu_ib_schedule(adev, parser->num_ibs, parser->ibs,
parser->filp); parser->filp);
out: out:
mutex_unlock(&vm->mutex); mutex_unlock(&vm->mutex);
...@@ -731,35 +815,16 @@ static int amdgpu_cs_dependencies(struct amdgpu_device *adev, ...@@ -731,35 +815,16 @@ static int amdgpu_cs_dependencies(struct amdgpu_device *adev,
return 0; return 0;
} }
int amdgpu_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) static int amdgpu_cs_parser_prepare_job(struct amdgpu_cs_parser *sched_job)
{ {
struct amdgpu_device *adev = dev->dev_private; int r, i;
union drm_amdgpu_cs *cs = data; struct amdgpu_cs_parser *parser = sched_job;
struct amdgpu_cs_parser parser; struct amdgpu_device *adev = sched_job->adev;
int r, i; bool reserved_buffers = false;
bool reserved_buffers = false;
r = amdgpu_cs_parser_relocs(parser);
down_read(&adev->exclusive_lock); if (r) {
if (!adev->accel_working) { if (r != -ERESTARTSYS) {
up_read(&adev->exclusive_lock);
return -EBUSY;
}
/* initialize parser */
memset(&parser, 0, sizeof(struct amdgpu_cs_parser));
parser.filp = filp;
parser.adev = adev;
r = amdgpu_cs_parser_init(&parser, data);
if (r) {
DRM_ERROR("Failed to initialize parser !\n");
amdgpu_cs_parser_fini(&parser, r, false);
up_read(&adev->exclusive_lock);
r = amdgpu_cs_handle_lockup(adev, r);
return r;
}
r = amdgpu_cs_parser_relocs(&parser);
if (r) {
if (r != -ERESTARTSYS) {
if (r == -ENOMEM) if (r == -ENOMEM)
DRM_ERROR("Not enough memory for command submission!\n"); DRM_ERROR("Not enough memory for command submission!\n");
else else
...@@ -769,33 +834,104 @@ int amdgpu_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) ...@@ -769,33 +834,104 @@ int amdgpu_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
if (!r) { if (!r) {
reserved_buffers = true; reserved_buffers = true;
r = amdgpu_cs_ib_fill(adev, &parser); r = amdgpu_cs_ib_fill(adev, parser);
} }
if (!r) { if (!r) {
r = amdgpu_cs_dependencies(adev, &parser); r = amdgpu_cs_dependencies(adev, parser);
if (r) if (r)
DRM_ERROR("Failed in the dependencies handling %d!\n", r); DRM_ERROR("Failed in the dependencies handling %d!\n", r);
} }
if (r) {
amdgpu_cs_parser_fini(parser, r, reserved_buffers);
return r;
}
for (i = 0; i < parser->num_ibs; i++)
trace_amdgpu_cs(parser, i);
r = amdgpu_cs_ib_vm_chunk(adev, parser);
return r;
}
static struct amdgpu_ring *amdgpu_cs_parser_get_ring(
struct amdgpu_device *adev,
struct amdgpu_cs_parser *parser)
{
int i, r;
struct amdgpu_cs_chunk *chunk;
struct drm_amdgpu_cs_chunk_ib *chunk_ib;
struct amdgpu_ring *ring;
for (i = 0; i < parser->nchunks; i++) {
chunk = &parser->chunks[i];
chunk_ib = (struct drm_amdgpu_cs_chunk_ib *)chunk->kdata;
if (chunk->chunk_id != AMDGPU_CHUNK_ID_IB)
continue;
r = amdgpu_cs_get_ring(adev, chunk_ib->ip_type,
chunk_ib->ip_instance, chunk_ib->ring,
&ring);
if (r)
return NULL;
break;
}
return ring;
}
int amdgpu_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
{
struct amdgpu_device *adev = dev->dev_private;
union drm_amdgpu_cs *cs = data;
struct amdgpu_cs_parser *parser;
int r;
down_read(&adev->exclusive_lock);
if (!adev->accel_working) {
up_read(&adev->exclusive_lock);
return -EBUSY;
}
parser = amdgpu_cs_parser_create(adev, filp, NULL, NULL, 0);
if (!parser)
return -ENOMEM;
r = amdgpu_cs_parser_init(parser, data);
if (r) { if (r) {
amdgpu_cs_parser_fini(&parser, r, reserved_buffers); DRM_ERROR("Failed to initialize parser !\n");
amdgpu_cs_parser_fini(parser, r, false);
up_read(&adev->exclusive_lock); up_read(&adev->exclusive_lock);
r = amdgpu_cs_handle_lockup(adev, r); r = amdgpu_cs_handle_lockup(adev, r);
return r; return r;
} }
for (i = 0; i < parser.num_ibs; i++) if (amdgpu_enable_scheduler && parser->num_ibs) {
trace_amdgpu_cs(&parser, i); struct amdgpu_ring * ring =
amdgpu_cs_parser_get_ring(adev, parser);
r = amdgpu_cs_ib_vm_chunk(adev, &parser); parser->uf.sequence = atomic64_inc_return(
if (r) { &parser->ctx->rings[ring->idx].c_entity.last_queued_v_seq);
goto out; if ((parser->bo_list && parser->bo_list->has_userptr)) {
r = amdgpu_cs_parser_prepare_job(parser);
if (r)
goto out;
} else
parser->prepare_job = amdgpu_cs_parser_prepare_job;
parser->run_job = amdgpu_cs_parser_run_job;
parser->free_job = amdgpu_cs_parser_free_job;
amd_sched_push_job(ring->scheduler,
&parser->ctx->rings[ring->idx].c_entity,
parser);
cs->out.handle = parser->uf.sequence;
up_read(&adev->exclusive_lock);
return 0;
} }
r = amdgpu_cs_parser_prepare_job(parser);
if (r)
goto out;
cs->out.handle = parser.ibs[parser.num_ibs - 1].sequence; cs->out.handle = parser->ibs[parser->num_ibs - 1].sequence;
out: out:
amdgpu_cs_parser_fini(&parser, r, true); amdgpu_cs_parser_fini(parser, r, true);
up_read(&adev->exclusive_lock); up_read(&adev->exclusive_lock);
r = amdgpu_cs_handle_lockup(adev, r); r = amdgpu_cs_handle_lockup(adev, r);
return r; return r;
...@@ -829,18 +965,24 @@ int amdgpu_cs_wait_ioctl(struct drm_device *dev, void *data, ...@@ -829,18 +965,24 @@ int amdgpu_cs_wait_ioctl(struct drm_device *dev, void *data,
ctx = amdgpu_ctx_get(filp->driver_priv, wait->in.ctx_id); ctx = amdgpu_ctx_get(filp->driver_priv, wait->in.ctx_id);
if (ctx == NULL) if (ctx == NULL)
return -EINVAL; return -EINVAL;
if (amdgpu_enable_scheduler) {
fence = amdgpu_ctx_get_fence(ctx, ring, wait->in.handle); r = amd_sched_wait_ts(&ctx->rings[ring->idx].c_entity,
if (IS_ERR(fence)) wait->in.handle, true, timeout);
r = PTR_ERR(fence); if (r)
return r;
else if (fence) {
r = fence_wait_timeout(fence, true, timeout);
fence_put(fence);
} else
r = 1; r = 1;
} else {
fence = amdgpu_ctx_get_fence(ctx, ring, wait->in.handle);
if (IS_ERR(fence))
r = PTR_ERR(fence);
else if (fence) {
r = fence_wait_timeout(fence, true, timeout);
fence_put(fence);
} else
r = 1;
}
amdgpu_ctx_put(ctx); amdgpu_ctx_put(ctx);
if (r < 0) if (r < 0)
return r; return r;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment