aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/radeon/radeon_ring.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/radeon/radeon_ring.c')
-rw-r--r--drivers/gpu/drm/radeon/radeon_ring.c82
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 */
373unsigned 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 */
425int 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
365int radeon_ring_init(struct radeon_device *rdev, struct radeon_ring *ring, unsigned ring_size, 447int 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)