[PATCH 15/16] drm/radeon: implement ring commit tracking

Christian König deathsimple at vodafone.de
Mon Jul 9 03:42:02 PDT 2012


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

diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index fef4257..9c11be8 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -637,6 +637,9 @@ struct radeon_ring {
 	u32			ptr_reg_shift;
 	u32			ptr_reg_mask;
 	u32			nop;
+	unsigned		*track_back;
+	unsigned		track_ptr;
+	unsigned		track_mask;
 };
 
 /*
diff --git a/drivers/gpu/drm/radeon/radeon_ring.c b/drivers/gpu/drm/radeon/radeon_ring.c
index d9b2e45..994c98c 100644
--- a/drivers/gpu/drm/radeon/radeon_ring.c
+++ b/drivers/gpu/drm/radeon/radeon_ring.c
@@ -276,6 +276,8 @@ void radeon_ring_commit(struct radeon_device *rdev, struct radeon_ring *ring)
 	DRM_MEMORYBARRIER();
 	WREG32(ring->wptr_reg, (ring->wptr << ring->ptr_reg_shift) & ring->ptr_reg_mask);
 	(void)RREG32(ring->wptr_reg);
+	ring->track_back[ring->track_ptr++] = ring->wptr_old;
+	ring->track_ptr &= ring->track_mask;
 }
 
 void radeon_ring_unlock_commit(struct radeon_device *rdev, struct radeon_ring *ring)
@@ -362,6 +364,27 @@ bool radeon_ring_test_lockup(struct radeon_device *rdev, struct radeon_ring *rin
 	return false;
 }
 
+static unsigned radeon_ring_first_valid_commit(struct radeon_ring *ring)
+{
+	unsigned i, c, result = ring->track_ptr;
+	i = ring->track_ptr - 1;
+	while (i != ring->track_ptr) {
+		i &= ring->track_mask;
+		c = ring->track_back[i];
+
+		if (ring->wptr >= ring->rptr) {
+			if (c < ring->rptr || c >= ring->wptr)
+				break;
+		} else {
+			if (c < ring->rptr && c >= ring->wptr)
+				break;
+		}
+
+		result = i--;
+	}
+	return result;
+}
+
 int radeon_ring_init(struct radeon_device *rdev, struct radeon_ring *ring,
 		     unsigned ring_size, unsigned align,
 		     unsigned rptr_offs, unsigned rptr_reg, unsigned wptr_reg,
@@ -403,6 +426,10 @@ int radeon_ring_init(struct radeon_device *rdev, struct radeon_ring *ring,
 			dev_err(rdev->dev, "(%d) ring map failed\n", r);
 			return r;
 		}
+		ring->track_back = kmalloc(ring_size / align, GFP_KERNEL);
+		memset(ring->track_back, 0, ring_size / align);
+		ring->track_ptr = 0;
+		ring->track_mask = ((ring->ring_size / 4) / align) - 1;
 	}
 	ring->ptr_mask = (ring->ring_size / 4) - 1;
 	ring->ring_free_dw = ring->ring_size / 4;
@@ -422,6 +449,7 @@ void radeon_ring_fini(struct radeon_device *rdev, struct radeon_ring *ring)
 	ring->ready = false;
 	ring->ring = NULL;
 	ring->ring_obj = NULL;
+	kfree(ring->track_back);
 	mutex_unlock(&rdev->ring_lock);
 
 	if (ring_obj) {
@@ -447,7 +475,7 @@ 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];
-	unsigned count, i, j;
+	unsigned count, i, j, commit;
 
 	radeon_ring_free_size(rdev, ring);
 	count = (ring->ring_size / 4) - ring->ring_free_dw;
@@ -457,9 +485,16 @@ static int radeon_debugfs_ring_info(struct seq_file *m, void *data)
 	seq_printf(m, "driver's copy of the rptr: 0x%08x\n", ring->rptr);
 	seq_printf(m, "%u free dwords in ring\n", ring->ring_free_dw);
 	seq_printf(m, "%u dwords in ring\n", count);
+	commit = radeon_ring_first_valid_commit(ring);
 	i = ring->rptr;
 	for (j = 0; j <= count; j++) {
-		seq_printf(m, "r[%04d]=0x%08x\n", i, ring->ring[i]);
+		seq_printf(m, "r[%04x]=0x%08x", i, ring->ring[i]);
+		if (commit != ring->track_ptr && ring->track_back[commit] == i) {
+			seq_printf(m, " <-");
+			++commit;
+			commit &= ring->track_mask;
+		}
+		seq_printf(m, "\n");
 		i = (i + 1) & ring->ptr_mask;
 	}
 	return 0;
-- 
1.7.9.5



More information about the dri-devel mailing list