[PATCH 24/26] drm/radeon: extend ring debugfs files with fence info

Christian König deathsimple at vodafone.de
Wed Apr 25 05:46:41 PDT 2012


That should aid in debugging multi ring lockups.

Signed-off-by: Christian König <deathsimple at vodafone.de>
---
 drivers/gpu/drm/radeon/radeon.h       |    1 +
 drivers/gpu/drm/radeon/radeon_fence.c |    1 +
 drivers/gpu/drm/radeon/radeon_ring.c  |   43 ++++++++++++++++++++++++++++++++-
 3 files changed, 44 insertions(+), 1 deletions(-)

diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index b2d72e2..21b9a75 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -233,6 +233,7 @@ struct radeon_fence {
 	bool				signaled;
 	/* RB, DMA, etc. */
 	int				ring;
+	unsigned			emitted_at;
 	struct radeon_semaphore		*semaphore;
 	struct radeon_ib		*ib;
 };
diff --git a/drivers/gpu/drm/radeon/radeon_fence.c b/drivers/gpu/drm/radeon/radeon_fence.c
index 09e13e3..f8bdef5 100644
--- a/drivers/gpu/drm/radeon/radeon_fence.c
+++ b/drivers/gpu/drm/radeon/radeon_fence.c
@@ -71,6 +71,7 @@ int radeon_fence_emit(struct radeon_device *rdev, struct radeon_fence *fence)
 		return 0;
 	}
 	fence->seq = atomic_add_return(1, &rdev->fence_drv[fence->ring].seq);
+	fence->emitted_at = rdev->ring[fence->ring].wptr;
 	radeon_fence_ring_emit(rdev, fence->ring, fence);
 	trace_radeon_fence_emit(rdev->ddev, fence->seq);
 	fence->emitted = true;
diff --git a/drivers/gpu/drm/radeon/radeon_ring.c b/drivers/gpu/drm/radeon/radeon_ring.c
index 4d1987d..992a615 100644
--- a/drivers/gpu/drm/radeon/radeon_ring.c
+++ b/drivers/gpu/drm/radeon/radeon_ring.c
@@ -485,8 +485,12 @@ static int radeon_debugfs_ring_info(struct seq_file *m, void *data)
 	struct radeon_device *rdev = dev->dev_private;
 	int ridx = *(int*)node->info_ent->data;
 	struct radeon_ring *ring = &rdev->ring[ridx];
+	struct radeon_fence *fence = NULL;
 	unsigned count, i, j;
+	unsigned long flags;
 
+	mutex_lock(&ring->mutex);
+	read_lock_irqsave(&rdev->fence_lock, flags);
 	radeon_ring_free_size(rdev, ring);
 	count = (ring->ring_size / 4) - ring->ring_free_dw;
 	seq_printf(m, "wptr(0x%04x): 0x%08x\n", ring->wptr_reg, RREG32(ring->wptr_reg));
@@ -496,10 +500,47 @@ static int radeon_debugfs_ring_info(struct seq_file *m, void *data)
 	seq_printf(m, "%u free dwords in ring\n", ring->ring_free_dw);
 	seq_printf(m, "%u dwords in ring\n", count);
 	i = ring->rptr;
+	if (!list_empty(&rdev->fence_drv[ridx].emitted)) {
+		fence = list_first_entry(&rdev->fence_drv[ridx].emitted, 
+					 struct radeon_fence, list);
+
+		if (fence->emitted_at < ring->rptr && (
+		    ring->wptr >= ring->rptr || fence->emitted_at > ring->wptr)) {
+
+			/* if first emitted fence is before current
+			   read pointer, then print that content also */
+			count = (fence->emitted_at + (ring->ring_size / 4));
+			count -= ring->wptr;
+			count &= ring->ptr_mask;
+			count = (ring->ring_size / 4) - count;
+			i = fence->emitted_at;
+		}
+	} else {
+		fence = NULL;
+	}
 	for (j = 0; j <= count; j++) {
-		seq_printf(m, "r[%04d]=0x%08x\n", i, ring->ring[i]);
+		seq_printf(m, "r[%04d]=0x%08x", i, ring->ring[i]);
+		if (i == ring->rptr) {
+			seq_printf(m, " <- RPTR ");
+		}
+		if (fence && fence->emitted_at == i) {
+			seq_printf(m, " <- seq 0x%08x", fence->seq);
+			if (fence->semaphore) {
+				seq_printf(m, " sem @ 0x%09Lx ",
+					   (long long)fence->semaphore->gpu_addr);
+			}
+			if (fence->list.next != &rdev->fence_drv[ridx].emitted) {
+				fence = list_entry(fence->list.next,
+						   struct radeon_fence, list);
+			} else {
+				fence = NULL;
+			}
+		}
+		seq_printf(m, "\n");
 		i = (i + 1) & ring->ptr_mask;
 	}
+	read_unlock_irqrestore(&rdev->fence_lock, flags);
+	mutex_unlock(&ring->mutex);
 	return 0;
 }
 
-- 
1.7.5.4



More information about the dri-devel mailing list