Commit 1decbf6b authored by Bas Nieuwenhuizen's avatar Bas Nieuwenhuizen Committed by Alex Deucher

drm/sched: Fix entities with 0 rqs.

Some blocks in amdgpu can have 0 rqs.

Job creation already fails with -ENOENT when entity->rq is NULL,
so jobs cannot be pushed. Without a rq there is no scheduler to
pop jobs, and rq selection already does the right thing with a
list of length 0.

So the operations we need to fix are:
  - Creation, do not set rq to rq_list[0] if the list can have length 0.
  - Do not flush any jobs when there is no rq.
  - On entity destruction handle the rq = NULL case.
  - on set_priority, do not try to change the rq if it is NULL.
Signed-off-by: default avatarBas Nieuwenhuizen <bas@basnieuwenhuizen.nl>
Reviewed-by: default avatarChristian König <christian.koenig@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 7a5e0d9a
...@@ -52,12 +52,12 @@ int drm_sched_entity_init(struct drm_sched_entity *entity, ...@@ -52,12 +52,12 @@ int drm_sched_entity_init(struct drm_sched_entity *entity,
{ {
int i; int i;
if (!(entity && rq_list && num_rq_list > 0 && rq_list[0])) if (!(entity && rq_list && (num_rq_list == 0 || rq_list[0])))
return -EINVAL; return -EINVAL;
memset(entity, 0, sizeof(struct drm_sched_entity)); memset(entity, 0, sizeof(struct drm_sched_entity));
INIT_LIST_HEAD(&entity->list); INIT_LIST_HEAD(&entity->list);
entity->rq = rq_list[0]; entity->rq = NULL;
entity->guilty = guilty; entity->guilty = guilty;
entity->num_rq_list = num_rq_list; entity->num_rq_list = num_rq_list;
entity->rq_list = kcalloc(num_rq_list, sizeof(struct drm_sched_rq *), entity->rq_list = kcalloc(num_rq_list, sizeof(struct drm_sched_rq *),
...@@ -67,6 +67,10 @@ int drm_sched_entity_init(struct drm_sched_entity *entity, ...@@ -67,6 +67,10 @@ int drm_sched_entity_init(struct drm_sched_entity *entity,
for (i = 0; i < num_rq_list; ++i) for (i = 0; i < num_rq_list; ++i)
entity->rq_list[i] = rq_list[i]; entity->rq_list[i] = rq_list[i];
if (num_rq_list)
entity->rq = rq_list[0];
entity->last_scheduled = NULL; entity->last_scheduled = NULL;
spin_lock_init(&entity->rq_lock); spin_lock_init(&entity->rq_lock);
...@@ -165,6 +169,9 @@ long drm_sched_entity_flush(struct drm_sched_entity *entity, long timeout) ...@@ -165,6 +169,9 @@ long drm_sched_entity_flush(struct drm_sched_entity *entity, long timeout)
struct task_struct *last_user; struct task_struct *last_user;
long ret = timeout; long ret = timeout;
if (!entity->rq)
return 0;
sched = entity->rq->sched; sched = entity->rq->sched;
/** /**
* The client will not queue more IBs during this fini, consume existing * The client will not queue more IBs during this fini, consume existing
...@@ -264,20 +271,24 @@ static void drm_sched_entity_kill_jobs(struct drm_sched_entity *entity) ...@@ -264,20 +271,24 @@ static void drm_sched_entity_kill_jobs(struct drm_sched_entity *entity)
*/ */
void drm_sched_entity_fini(struct drm_sched_entity *entity) void drm_sched_entity_fini(struct drm_sched_entity *entity)
{ {
struct drm_gpu_scheduler *sched; struct drm_gpu_scheduler *sched = NULL;
if (entity->rq) {
sched = entity->rq->sched; sched = entity->rq->sched;
drm_sched_rq_remove_entity(entity->rq, entity); drm_sched_rq_remove_entity(entity->rq, entity);
}
/* Consumption of existing IBs wasn't completed. Forcefully /* Consumption of existing IBs wasn't completed. Forcefully
* remove them here. * remove them here.
*/ */
if (spsc_queue_peek(&entity->job_queue)) { if (spsc_queue_peek(&entity->job_queue)) {
if (sched) {
/* Park the kernel for a moment to make sure it isn't processing /* Park the kernel for a moment to make sure it isn't processing
* our enity. * our enity.
*/ */
kthread_park(sched->thread); kthread_park(sched->thread);
kthread_unpark(sched->thread); kthread_unpark(sched->thread);
}
if (entity->dependency) { if (entity->dependency) {
dma_fence_remove_callback(entity->dependency, dma_fence_remove_callback(entity->dependency,
&entity->cb); &entity->cb);
...@@ -362,9 +373,11 @@ void drm_sched_entity_set_priority(struct drm_sched_entity *entity, ...@@ -362,9 +373,11 @@ void drm_sched_entity_set_priority(struct drm_sched_entity *entity,
for (i = 0; i < entity->num_rq_list; ++i) for (i = 0; i < entity->num_rq_list; ++i)
drm_sched_entity_set_rq_priority(&entity->rq_list[i], priority); drm_sched_entity_set_rq_priority(&entity->rq_list[i], priority);
if (entity->rq) {
drm_sched_rq_remove_entity(entity->rq, entity); drm_sched_rq_remove_entity(entity->rq, entity);
drm_sched_entity_set_rq_priority(&entity->rq, priority); drm_sched_entity_set_rq_priority(&entity->rq, priority);
drm_sched_rq_add_entity(entity->rq, entity); drm_sched_rq_add_entity(entity->rq, entity);
}
spin_unlock(&entity->rq_lock); spin_unlock(&entity->rq_lock);
} }
......
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