[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