aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNicolai Hähnle <Nicolai.Haehnle@amd.com>2015-12-02 11:35:12 -0500
committerAlex Deucher <alexander.deucher@amd.com>2015-12-02 15:04:04 -0500
commit07df04dfcfe51a45239d056d43cbc09702262c82 (patch)
treecd4cd9b9a9d38c1dd16ea31b11a4e87766b641b9
parente2f784fa8a3b1fbf6999ba44f7327bd9d29f2c5b (diff)
drm/amdgpu: fix race condition in amd_sched_entity_push_job
As soon as we leave the spinlock after the job has been added to the job queue, we can no longer rely on the job's data to be available. I have seen a null-pointer dereference due to sched == NULL in amd_sched_wakeup via amd_sched_entity_push_job and amd_sched_ib_submit_kernel_helper. Since the latter initializes sched_job->sched with the address of the ring scheduler, which is guaranteed to be non-NULL, this race appears to be a likely culprit. Signed-off-by: Nicolai Hähnle <nicolai.haehnle@amd.com> Bugzilla: https://bugs.freedesktop.org/attachment.cgi?bugid=93079 Reviewed-by: Christian König <christian.koenig@amd.com>
-rw-r--r--drivers/gpu/drm/amd/scheduler/gpu_scheduler.c5
1 files changed, 3 insertions, 2 deletions
diff --git a/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c b/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c
index 651129f2ec1d..3a4820e863ec 100644
--- a/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c
+++ b/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c
@@ -288,6 +288,7 @@ amd_sched_entity_pop_job(struct amd_sched_entity *entity)
288 */ 288 */
289static bool amd_sched_entity_in(struct amd_sched_job *sched_job) 289static bool amd_sched_entity_in(struct amd_sched_job *sched_job)
290{ 290{
291 struct amd_gpu_scheduler *sched = sched_job->sched;
291 struct amd_sched_entity *entity = sched_job->s_entity; 292 struct amd_sched_entity *entity = sched_job->s_entity;
292 bool added, first = false; 293 bool added, first = false;
293 294
@@ -302,7 +303,7 @@ static bool amd_sched_entity_in(struct amd_sched_job *sched_job)
302 303
303 /* first job wakes up scheduler */ 304 /* first job wakes up scheduler */
304 if (first) 305 if (first)
305 amd_sched_wakeup(sched_job->sched); 306 amd_sched_wakeup(sched);
306 307
307 return added; 308 return added;
308} 309}
@@ -318,9 +319,9 @@ void amd_sched_entity_push_job(struct amd_sched_job *sched_job)
318{ 319{
319 struct amd_sched_entity *entity = sched_job->s_entity; 320 struct amd_sched_entity *entity = sched_job->s_entity;
320 321
322 trace_amd_sched_job(sched_job);
321 wait_event(entity->sched->job_scheduled, 323 wait_event(entity->sched->job_scheduled,
322 amd_sched_entity_in(sched_job)); 324 amd_sched_entity_in(sched_job));
323 trace_amd_sched_job(sched_job);
324} 325}
325 326
326/** 327/**