[PATCH 06/10] drm/radeon: fix ih ring handling v2

Christian König deathsimple at vodafone.de
Thu May 31 13:16:02 PDT 2012


From: Christian Koenig <christian.koenig at amd.com>

The spinlock was actually there to protect the
rptr, but rptr was read outside of the locked area.

v2: Keep the spinlock, looks like there is still something
    in the ih that doesn't like irqs enabled.

Signed-off-by: Christian Koenig <christian.koenig at amd.com>
---
 drivers/gpu/drm/radeon/evergreen.c |    5 ++---
 drivers/gpu/drm/radeon/r600.c      |    7 ++-----
 drivers/gpu/drm/radeon/radeon.h    |    1 -
 drivers/gpu/drm/radeon/si.c        |    6 ++----
 4 files changed, 6 insertions(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c
index dd3cea4..e4c3321 100644
--- a/drivers/gpu/drm/radeon/evergreen.c
+++ b/drivers/gpu/drm/radeon/evergreen.c
@@ -2950,11 +2950,11 @@ int evergreen_irq_process(struct radeon_device *rdev)
 	if (!rdev->ih.enabled || rdev->shutdown)
 		return IRQ_NONE;
 
+	spin_lock_irqsave(&rdev->ih.lock, flags);
 	wptr = evergreen_get_ih_wptr(rdev);
 	rptr = rdev->ih.rptr;
 	DRM_DEBUG("r600_irq_process start: rptr %d, wptr %d\n", rptr, wptr);
 
-	spin_lock_irqsave(&rdev->ih.lock, flags);
 	if (rptr == wptr) {
 		spin_unlock_irqrestore(&rdev->ih.lock, flags);
 		return IRQ_NONE;
@@ -2966,7 +2966,6 @@ restart_ih:
 	/* display interrupts */
 	evergreen_irq_ack(rdev);
 
-	rdev->ih.wptr = wptr;
 	while (rptr != wptr) {
 		/* wptr/rptr are in bytes! */
 		ring_index = rptr / 4;
@@ -3267,7 +3266,7 @@ restart_ih:
 	}
 	/* make sure wptr hasn't changed while processing */
 	wptr = evergreen_get_ih_wptr(rdev);
-	if (wptr != rdev->ih.wptr)
+	if (wptr != rptr)
 		goto restart_ih;
 	if (queue_hotplug)
 		schedule_work(&rdev->hotplug_work);
diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c
index a8d8c44..e1861ac 100644
--- a/drivers/gpu/drm/radeon/r600.c
+++ b/drivers/gpu/drm/radeon/r600.c
@@ -2921,7 +2921,6 @@ void r600_disable_interrupts(struct radeon_device *rdev)
 	WREG32(IH_RB_RPTR, 0);
 	WREG32(IH_RB_WPTR, 0);
 	rdev->ih.enabled = false;
-	rdev->ih.wptr = 0;
 	rdev->ih.rptr = 0;
 }
 
@@ -3384,12 +3383,11 @@ int r600_irq_process(struct radeon_device *rdev)
 	if (!rdev->msi_enabled)
 		RREG32(IH_RB_WPTR);
 
+	spin_lock_irqsave(&rdev->ih.lock, flags);
 	wptr = r600_get_ih_wptr(rdev);
 	rptr = rdev->ih.rptr;
 	DRM_DEBUG("r600_irq_process start: rptr %d, wptr %d\n", rptr, wptr);
 
-	spin_lock_irqsave(&rdev->ih.lock, flags);
-
 	if (rptr == wptr) {
 		spin_unlock_irqrestore(&rdev->ih.lock, flags);
 		return IRQ_NONE;
@@ -3402,7 +3400,6 @@ restart_ih:
 	/* display interrupts */
 	r600_irq_ack(rdev);
 
-	rdev->ih.wptr = wptr;
 	while (rptr != wptr) {
 		/* wptr/rptr are in bytes! */
 		ring_index = rptr / 4;
@@ -3558,7 +3555,7 @@ restart_ih:
 	}
 	/* make sure wptr hasn't changed while processing */
 	wptr = r600_get_ih_wptr(rdev);
-	if (wptr != rdev->ih.wptr)
+	if (wptr != rptr)
 		goto restart_ih;
 	if (queue_hotplug)
 		schedule_work(&rdev->hotplug_work);
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index 618df9a..378d43b 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -733,7 +733,6 @@ struct r600_ih {
 	struct radeon_bo	*ring_obj;
 	volatile uint32_t	*ring;
 	unsigned		rptr;
-	unsigned		wptr;
 	unsigned		ring_size;
 	uint64_t		gpu_addr;
 	uint32_t		ptr_mask;
diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c
index 5ca8ef5..93da01c 100644
--- a/drivers/gpu/drm/radeon/si.c
+++ b/drivers/gpu/drm/radeon/si.c
@@ -3095,7 +3095,6 @@ static void si_disable_interrupts(struct radeon_device *rdev)
 	WREG32(IH_RB_RPTR, 0);
 	WREG32(IH_RB_WPTR, 0);
 	rdev->ih.enabled = false;
-	rdev->ih.wptr = 0;
 	rdev->ih.rptr = 0;
 }
 
@@ -3518,11 +3517,11 @@ int si_irq_process(struct radeon_device *rdev)
 	if (!rdev->ih.enabled || rdev->shutdown)
 		return IRQ_NONE;
 
+	spin_lock_irqsave(&rdev->ih.lock, flags);
 	wptr = si_get_ih_wptr(rdev);
 	rptr = rdev->ih.rptr;
 	DRM_DEBUG("si_irq_process start: rptr %d, wptr %d\n", rptr, wptr);
 
-	spin_lock_irqsave(&rdev->ih.lock, flags);
 	if (rptr == wptr) {
 		spin_unlock_irqrestore(&rdev->ih.lock, flags);
 		return IRQ_NONE;
@@ -3534,7 +3533,6 @@ restart_ih:
 	/* display interrupts */
 	si_irq_ack(rdev);
 
-	rdev->ih.wptr = wptr;
 	while (rptr != wptr) {
 		/* wptr/rptr are in bytes! */
 		ring_index = rptr / 4;
@@ -3787,7 +3785,7 @@ restart_ih:
 	}
 	/* make sure wptr hasn't changed while processing */
 	wptr = si_get_ih_wptr(rdev);
-	if (wptr != rdev->ih.wptr)
+	if (wptr != rptr)
 		goto restart_ih;
 	if (queue_hotplug)
 		schedule_work(&rdev->hotplug_work);
-- 
1.7.9.5



More information about the dri-devel mailing list