From: Christian Koenig <christian.koe...@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

Reply via email to