diff options
author | Christian König <deathsimple@vodafone.de> | 2012-07-09 05:52:44 -0400 |
---|---|---|
committer | Christian König <deathsimple@vodafone.de> | 2012-07-17 04:33:15 -0400 |
commit | 55d7c22192becd0ec827a6901899ff56fa985658 (patch) | |
tree | 2876d95b10e9bac71ef168dd998537c731d3222f /drivers/gpu/drm/radeon/radeon_ring.c | |
parent | 45df68035c4964d42ea3850980708ce8674f75b3 (diff) |
drm/radeon: implement ring saving on reset v4
Try to save whatever is on the rings when
we encounter an lockup.
v2: Fix spelling error. Free saved ring data if reset fails.
Add documentation for the new functions.
v3: Some more spelling fixes
v4: It doesn't make sense to save anything if all fences
are signaled
Signed-off-by: Christian König <deathsimple@vodafone.de>
Reviewed-by: Michel Dänzer <michel.daenzer@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm/radeon/radeon_ring.c')
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_ring.c | 82 |
1 files changed, 82 insertions, 0 deletions
diff --git a/drivers/gpu/drm/radeon/radeon_ring.c b/drivers/gpu/drm/radeon/radeon_ring.c index ce8eb9d5af5d..75cbe4641138 100644 --- a/drivers/gpu/drm/radeon/radeon_ring.c +++ b/drivers/gpu/drm/radeon/radeon_ring.c | |||
@@ -362,6 +362,88 @@ bool radeon_ring_test_lockup(struct radeon_device *rdev, struct radeon_ring *rin | |||
362 | return false; | 362 | return false; |
363 | } | 363 | } |
364 | 364 | ||
365 | /** | ||
366 | * radeon_ring_backup - Back up the content of a ring | ||
367 | * | ||
368 | * @rdev: radeon_device pointer | ||
369 | * @ring: the ring we want to back up | ||
370 | * | ||
371 | * Saves all unprocessed commits from a ring, returns the number of dwords saved. | ||
372 | */ | ||
373 | unsigned radeon_ring_backup(struct radeon_device *rdev, struct radeon_ring *ring, | ||
374 | uint32_t **data) | ||
375 | { | ||
376 | unsigned size, ptr, i; | ||
377 | int ridx = radeon_ring_index(rdev, ring); | ||
378 | |||
379 | /* just in case lock the ring */ | ||
380 | mutex_lock(&rdev->ring_lock); | ||
381 | *data = NULL; | ||
382 | |||
383 | if (ring->ring_obj == NULL || !ring->rptr_save_reg) { | ||
384 | mutex_unlock(&rdev->ring_lock); | ||
385 | return 0; | ||
386 | } | ||
387 | |||
388 | /* it doesn't make sense to save anything if all fences are signaled */ | ||
389 | if (!radeon_fence_count_emitted(rdev, ridx)) { | ||
390 | mutex_unlock(&rdev->ring_lock); | ||
391 | return 0; | ||
392 | } | ||
393 | |||
394 | /* calculate the number of dw on the ring */ | ||
395 | ptr = RREG32(ring->rptr_save_reg); | ||
396 | size = ring->wptr + (ring->ring_size / 4); | ||
397 | size -= ptr; | ||
398 | size &= ring->ptr_mask; | ||
399 | if (size == 0) { | ||
400 | mutex_unlock(&rdev->ring_lock); | ||
401 | return 0; | ||
402 | } | ||
403 | |||
404 | /* and then save the content of the ring */ | ||
405 | *data = kmalloc(size * 4, GFP_KERNEL); | ||
406 | for (i = 0; i < size; ++i) { | ||
407 | (*data)[i] = ring->ring[ptr++]; | ||
408 | ptr &= ring->ptr_mask; | ||
409 | } | ||
410 | |||
411 | mutex_unlock(&rdev->ring_lock); | ||
412 | return size; | ||
413 | } | ||
414 | |||
415 | /** | ||
416 | * radeon_ring_restore - append saved commands to the ring again | ||
417 | * | ||
418 | * @rdev: radeon_device pointer | ||
419 | * @ring: ring to append commands to | ||
420 | * @size: number of dwords we want to write | ||
421 | * @data: saved commands | ||
422 | * | ||
423 | * Allocates space on the ring and restore the previously saved commands. | ||
424 | */ | ||
425 | int radeon_ring_restore(struct radeon_device *rdev, struct radeon_ring *ring, | ||
426 | unsigned size, uint32_t *data) | ||
427 | { | ||
428 | int i, r; | ||
429 | |||
430 | if (!size || !data) | ||
431 | return 0; | ||
432 | |||
433 | /* restore the saved ring content */ | ||
434 | r = radeon_ring_lock(rdev, ring, size); | ||
435 | if (r) | ||
436 | return r; | ||
437 | |||
438 | for (i = 0; i < size; ++i) { | ||
439 | radeon_ring_write(ring, data[i]); | ||
440 | } | ||
441 | |||
442 | radeon_ring_unlock_commit(rdev, ring); | ||
443 | kfree(data); | ||
444 | return 0; | ||
445 | } | ||
446 | |||
365 | int radeon_ring_init(struct radeon_device *rdev, struct radeon_ring *ring, unsigned ring_size, | 447 | int radeon_ring_init(struct radeon_device *rdev, struct radeon_ring *ring, unsigned ring_size, |
366 | unsigned rptr_offs, unsigned rptr_reg, unsigned wptr_reg, | 448 | unsigned rptr_offs, unsigned rptr_reg, unsigned wptr_reg, |
367 | u32 ptr_reg_shift, u32 ptr_reg_mask, u32 nop) | 449 | u32 ptr_reg_shift, u32 ptr_reg_mask, u32 nop) |