aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm
diff options
context:
space:
mode:
authorChristian König <deathsimple@vodafone.de>2012-05-09 09:34:48 -0400
committerDave Airlie <airlied@redhat.com>2012-05-09 12:22:20 -0400
commit8a47cc9ec1249eefd600adb273148c62879a560d (patch)
tree70cda5e8f7830a508431b1a87c472978c927150b /drivers/gpu/drm
parent3b7a2b24ea2b703b3af595d0d4ee233ab0b36377 (diff)
drm/radeon: rework locking ring emission mutex in fence deadlock detection v2
Some callers illegal called fence_wait_next/empty while holding the ring emission mutex. So don't relock the mutex in that cases, and move the actual locking into the fence code. v2: Don't try to unlock the mutex if it isn't locked. Signed-off-by: Christian König <deathsimple@vodafone.de> Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu/drm')
-rw-r--r--drivers/gpu/drm/radeon/radeon.h4
-rw-r--r--drivers/gpu/drm/radeon/radeon_device.c5
-rw-r--r--drivers/gpu/drm/radeon/radeon_fence.c43
-rw-r--r--drivers/gpu/drm/radeon/radeon_pm.c8
-rw-r--r--drivers/gpu/drm/radeon/radeon_ring.c6
5 files changed, 37 insertions, 29 deletions
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index 7c8711793421..701094b05f47 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -284,8 +284,8 @@ int radeon_fence_emit(struct radeon_device *rdev, struct radeon_fence *fence);
284void radeon_fence_process(struct radeon_device *rdev, int ring); 284void radeon_fence_process(struct radeon_device *rdev, int ring);
285bool radeon_fence_signaled(struct radeon_fence *fence); 285bool radeon_fence_signaled(struct radeon_fence *fence);
286int radeon_fence_wait(struct radeon_fence *fence, bool interruptible); 286int radeon_fence_wait(struct radeon_fence *fence, bool interruptible);
287int radeon_fence_wait_next(struct radeon_device *rdev, int ring); 287int radeon_fence_wait_next_locked(struct radeon_device *rdev, int ring);
288int radeon_fence_wait_empty(struct radeon_device *rdev, int ring); 288int radeon_fence_wait_empty_locked(struct radeon_device *rdev, int ring);
289struct radeon_fence *radeon_fence_ref(struct radeon_fence *fence); 289struct radeon_fence *radeon_fence_ref(struct radeon_fence *fence);
290void radeon_fence_unref(struct radeon_fence **fence); 290void radeon_fence_unref(struct radeon_fence **fence);
291unsigned radeon_fence_count_emitted(struct radeon_device *rdev, int ring); 291unsigned radeon_fence_count_emitted(struct radeon_device *rdev, int ring);
diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c
index 0e7b72a0ed35..b827b2e578f3 100644
--- a/drivers/gpu/drm/radeon/radeon_device.c
+++ b/drivers/gpu/drm/radeon/radeon_device.c
@@ -912,9 +912,12 @@ int radeon_suspend_kms(struct drm_device *dev, pm_message_t state)
912 } 912 }
913 /* evict vram memory */ 913 /* evict vram memory */
914 radeon_bo_evict_vram(rdev); 914 radeon_bo_evict_vram(rdev);
915
916 mutex_lock(&rdev->ring_lock);
915 /* wait for gpu to finish processing current batch */ 917 /* wait for gpu to finish processing current batch */
916 for (i = 0; i < RADEON_NUM_RINGS; i++) 918 for (i = 0; i < RADEON_NUM_RINGS; i++)
917 radeon_fence_wait_empty(rdev, i); 919 radeon_fence_wait_empty_locked(rdev, i);
920 mutex_unlock(&rdev->ring_lock);
918 921
919 radeon_save_bios_scratch_regs(rdev); 922 radeon_save_bios_scratch_regs(rdev);
920 923
diff --git a/drivers/gpu/drm/radeon/radeon_fence.c b/drivers/gpu/drm/radeon/radeon_fence.c
index ed202255ac76..098d1faed1a6 100644
--- a/drivers/gpu/drm/radeon/radeon_fence.c
+++ b/drivers/gpu/drm/radeon/radeon_fence.c
@@ -194,7 +194,7 @@ bool radeon_fence_signaled(struct radeon_fence *fence)
194} 194}
195 195
196static int radeon_fence_wait_seq(struct radeon_device *rdev, u64 target_seq, 196static int radeon_fence_wait_seq(struct radeon_device *rdev, u64 target_seq,
197 unsigned ring, bool intr) 197 unsigned ring, bool intr, bool lock_ring)
198{ 198{
199 unsigned long timeout, last_activity; 199 unsigned long timeout, last_activity;
200 uint64_t seq; 200 uint64_t seq;
@@ -249,8 +249,16 @@ static int radeon_fence_wait_seq(struct radeon_device *rdev, u64 target_seq,
249 if (seq != atomic64_read(&rdev->fence_drv[ring].last_seq)) { 249 if (seq != atomic64_read(&rdev->fence_drv[ring].last_seq)) {
250 continue; 250 continue;
251 } 251 }
252
253 if (lock_ring) {
254 mutex_lock(&rdev->ring_lock);
255 }
256
252 /* test if somebody else has already decided that this is a lockup */ 257 /* test if somebody else has already decided that this is a lockup */
253 if (last_activity != rdev->fence_drv[ring].last_activity) { 258 if (last_activity != rdev->fence_drv[ring].last_activity) {
259 if (lock_ring) {
260 mutex_unlock(&rdev->ring_lock);
261 }
254 continue; 262 continue;
255 } 263 }
256 264
@@ -264,15 +272,17 @@ static int radeon_fence_wait_seq(struct radeon_device *rdev, u64 target_seq,
264 rdev->fence_drv[i].last_activity = jiffies; 272 rdev->fence_drv[i].last_activity = jiffies;
265 } 273 }
266 274
267 /* change last activity so nobody else think there is a lockup */
268 for (i = 0; i < RADEON_NUM_RINGS; ++i) {
269 rdev->fence_drv[i].last_activity = jiffies;
270 }
271
272 /* mark the ring as not ready any more */ 275 /* mark the ring as not ready any more */
273 rdev->ring[ring].ready = false; 276 rdev->ring[ring].ready = false;
277 if (lock_ring) {
278 mutex_unlock(&rdev->ring_lock);
279 }
274 return -EDEADLK; 280 return -EDEADLK;
275 } 281 }
282
283 if (lock_ring) {
284 mutex_unlock(&rdev->ring_lock);
285 }
276 } 286 }
277 } 287 }
278 return 0; 288 return 0;
@@ -287,7 +297,8 @@ int radeon_fence_wait(struct radeon_fence *fence, bool intr)
287 return -EINVAL; 297 return -EINVAL;
288 } 298 }
289 299
290 r = radeon_fence_wait_seq(fence->rdev, fence->seq, fence->ring, intr); 300 r = radeon_fence_wait_seq(fence->rdev, fence->seq,
301 fence->ring, intr, true);
291 if (r) { 302 if (r) {
292 return r; 303 return r;
293 } 304 }
@@ -295,7 +306,7 @@ int radeon_fence_wait(struct radeon_fence *fence, bool intr)
295 return 0; 306 return 0;
296} 307}
297 308
298int radeon_fence_wait_next(struct radeon_device *rdev, int ring) 309int radeon_fence_wait_next_locked(struct radeon_device *rdev, int ring)
299{ 310{
300 uint64_t seq; 311 uint64_t seq;
301 312
@@ -305,20 +316,22 @@ int radeon_fence_wait_next(struct radeon_device *rdev, int ring)
305 */ 316 */
306 seq = atomic64_read(&rdev->fence_drv[ring].last_seq) + 1ULL; 317 seq = atomic64_read(&rdev->fence_drv[ring].last_seq) + 1ULL;
307 if (seq >= rdev->fence_drv[ring].seq) { 318 if (seq >= rdev->fence_drv[ring].seq) {
308 /* nothing to wait for, last_seq is already the last emited fence */ 319 /* nothing to wait for, last_seq is
309 return 0; 320 already the last emited fence */
321 return -ENOENT;
310 } 322 }
311 return radeon_fence_wait_seq(rdev, seq, ring, false); 323 return radeon_fence_wait_seq(rdev, seq, ring, false, false);
312} 324}
313 325
314int radeon_fence_wait_empty(struct radeon_device *rdev, int ring) 326int radeon_fence_wait_empty_locked(struct radeon_device *rdev, int ring)
315{ 327{
316 /* We are not protected by ring lock when reading current seq 328 /* We are not protected by ring lock when reading current seq
317 * but it's ok as wait empty is call from place where no more 329 * but it's ok as wait empty is call from place where no more
318 * activity can be scheduled so there won't be concurrent access 330 * activity can be scheduled so there won't be concurrent access
319 * to seq value. 331 * to seq value.
320 */ 332 */
321 return radeon_fence_wait_seq(rdev, rdev->fence_drv[ring].seq, ring, false); 333 return radeon_fence_wait_seq(rdev, rdev->fence_drv[ring].seq,
334 ring, false, false);
322} 335}
323 336
324struct radeon_fence *radeon_fence_ref(struct radeon_fence *fence) 337struct radeon_fence *radeon_fence_ref(struct radeon_fence *fence)
@@ -410,14 +423,16 @@ void radeon_fence_driver_fini(struct radeon_device *rdev)
410{ 423{
411 int ring; 424 int ring;
412 425
426 mutex_lock(&rdev->ring_lock);
413 for (ring = 0; ring < RADEON_NUM_RINGS; ring++) { 427 for (ring = 0; ring < RADEON_NUM_RINGS; ring++) {
414 if (!rdev->fence_drv[ring].initialized) 428 if (!rdev->fence_drv[ring].initialized)
415 continue; 429 continue;
416 radeon_fence_wait_empty(rdev, ring); 430 radeon_fence_wait_empty_locked(rdev, ring);
417 wake_up_all(&rdev->fence_drv[ring].queue); 431 wake_up_all(&rdev->fence_drv[ring].queue);
418 radeon_scratch_free(rdev, rdev->fence_drv[ring].scratch_reg); 432 radeon_scratch_free(rdev, rdev->fence_drv[ring].scratch_reg);
419 rdev->fence_drv[ring].initialized = false; 433 rdev->fence_drv[ring].initialized = false;
420 } 434 }
435 mutex_unlock(&rdev->ring_lock);
421} 436}
422 437
423 438
diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c
index 7c3874589e3b..08825548ee69 100644
--- a/drivers/gpu/drm/radeon/radeon_pm.c
+++ b/drivers/gpu/drm/radeon/radeon_pm.c
@@ -270,13 +270,7 @@ static void radeon_pm_set_clocks(struct radeon_device *rdev)
270 } else { 270 } else {
271 struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; 271 struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX];
272 if (ring->ready) { 272 if (ring->ready) {
273 struct radeon_fence *fence; 273 radeon_fence_wait_empty_locked(rdev, RADEON_RING_TYPE_GFX_INDEX);
274 radeon_ring_alloc(rdev, ring, 64);
275 radeon_fence_create(rdev, &fence, radeon_ring_index(rdev, ring));
276 radeon_fence_emit(rdev, fence);
277 radeon_ring_commit(rdev, ring);
278 radeon_fence_wait(fence, false);
279 radeon_fence_unref(&fence);
280 } 274 }
281 } 275 }
282 radeon_unmap_vram_bos(rdev); 276 radeon_unmap_vram_bos(rdev);
diff --git a/drivers/gpu/drm/radeon/radeon_ring.c b/drivers/gpu/drm/radeon/radeon_ring.c
index 4ae222bb3ec5..2fdc8c35f87c 100644
--- a/drivers/gpu/drm/radeon/radeon_ring.c
+++ b/drivers/gpu/drm/radeon/radeon_ring.c
@@ -347,9 +347,7 @@ int radeon_ring_alloc(struct radeon_device *rdev, struct radeon_ring *ring, unsi
347 if (ndw < ring->ring_free_dw) { 347 if (ndw < ring->ring_free_dw) {
348 break; 348 break;
349 } 349 }
350 mutex_unlock(&rdev->ring_lock); 350 r = radeon_fence_wait_next_locked(rdev, radeon_ring_index(rdev, ring));
351 r = radeon_fence_wait_next(rdev, radeon_ring_index(rdev, ring));
352 mutex_lock(&rdev->ring_lock);
353 if (r) 351 if (r)
354 return r; 352 return r;
355 } 353 }
@@ -408,7 +406,6 @@ void radeon_ring_force_activity(struct radeon_device *rdev, struct radeon_ring *
408{ 406{
409 int r; 407 int r;
410 408
411 mutex_lock(&rdev->ring_lock);
412 radeon_ring_free_size(rdev, ring); 409 radeon_ring_free_size(rdev, ring);
413 if (ring->rptr == ring->wptr) { 410 if (ring->rptr == ring->wptr) {
414 r = radeon_ring_alloc(rdev, ring, 1); 411 r = radeon_ring_alloc(rdev, ring, 1);
@@ -417,7 +414,6 @@ void radeon_ring_force_activity(struct radeon_device *rdev, struct radeon_ring *
417 radeon_ring_commit(rdev, ring); 414 radeon_ring_commit(rdev, ring);
418 } 415 }
419 } 416 }
420 mutex_unlock(&rdev->ring_lock);
421} 417}
422 418
423void radeon_ring_lockup_update(struct radeon_ring *ring) 419void radeon_ring_lockup_update(struct radeon_ring *ring)