diff options
author | Nicolai Hähnle <nicolai.haehnle@amd.com> | 2016-02-05 10:59:43 -0500 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2016-02-10 14:07:31 -0500 |
commit | a8d81b36267366603771431747438d18f32ae2d5 (patch) | |
tree | fb6460edb485890a55b6a101751812abcfb0b7c1 /drivers/gpu/drm/amd/amdgpu/amdgpu_sa.c | |
parent | ca19852884c8937eed89560f924f5a34cfcc22af (diff) |
drm/amdgpu: hold reference to fences in amdgpu_sa_bo_new (v2)
An arbitrary amount of time can pass between spin_unlock and
fence_wait_any_timeout, so we need to ensure that nobody frees the
fences from under us.
A stress test (rapidly starting and killing hundreds of glxgears
instances) ran into a deadlock in fence_wait_any_timeout after
about an hour, and this race condition appears to be a plausible
cause.
v2: agd: rebase on upstream
Signed-off-by: Nicolai Hähnle <nicolai.haehnle@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Reviewed-by: Christian König <christian.koenig@amd.com>
Cc: stable@vger.kernel.org
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_sa.c')
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_sa.c | 5 |
1 files changed, 4 insertions, 1 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_sa.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_sa.c index 8b88edb0434b..ca72a2e487b9 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_sa.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_sa.c | |||
@@ -354,12 +354,15 @@ int amdgpu_sa_bo_new(struct amdgpu_sa_manager *sa_manager, | |||
354 | 354 | ||
355 | for (i = 0, count = 0; i < AMDGPU_MAX_RINGS; ++i) | 355 | for (i = 0, count = 0; i < AMDGPU_MAX_RINGS; ++i) |
356 | if (fences[i]) | 356 | if (fences[i]) |
357 | fences[count++] = fences[i]; | 357 | fences[count++] = fence_get(fences[i]); |
358 | 358 | ||
359 | if (count) { | 359 | if (count) { |
360 | spin_unlock(&sa_manager->wq.lock); | 360 | spin_unlock(&sa_manager->wq.lock); |
361 | t = fence_wait_any_timeout(fences, count, false, | 361 | t = fence_wait_any_timeout(fences, count, false, |
362 | MAX_SCHEDULE_TIMEOUT); | 362 | MAX_SCHEDULE_TIMEOUT); |
363 | for (i = 0; i < count; ++i) | ||
364 | fence_put(fences[i]); | ||
365 | |||
363 | r = (t > 0) ? 0 : t; | 366 | r = (t > 0) ? 0 : t; |
364 | spin_lock(&sa_manager->wq.lock); | 367 | spin_lock(&sa_manager->wq.lock); |
365 | } else { | 368 | } else { |