diff options
author | Nicolai Hähnle <Nicolai.Haehnle@amd.com> | 2015-12-02 11:35:12 -0500 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2015-12-02 15:04:04 -0500 |
commit | 07df04dfcfe51a45239d056d43cbc09702262c82 (patch) | |
tree | cd4cd9b9a9d38c1dd16ea31b11a4e87766b641b9 | |
parent | e2f784fa8a3b1fbf6999ba44f7327bd9d29f2c5b (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.c | 5 |
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 | */ |
289 | static bool amd_sched_entity_in(struct amd_sched_job *sched_job) | 289 | static 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 | /** |