aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/radeon/r600.c
diff options
context:
space:
mode:
authorChristian Koenig <christian.koenig@amd.com>2012-05-16 15:45:24 -0400
committerChristian König <deathsimple@vodafone.de>2012-06-21 03:38:48 -0400
commitc20dc3698dc7ecf053e2bf77299ae5982c0c2c45 (patch)
treee150268483bee4137d9c22e3121171b23a53be76 /drivers/gpu/drm/radeon/r600.c
parent6823d74003abedd688a3f535aefe6ce0e06444fd (diff)
drm/radeon: fix & improve ih ring handling v3
The spinlock was actually there to protect the rptr, but rptr was read outside of the locked area. Also we don't really need a spinlock here, an atomic should to quite fine since we only need to prevent it from being reentrant. v2: Keep the spinlock.... v3: Back to an atomic again after finding & fixing the real bug. Signed-off-by: Christian Koenig <christian.koenig@amd.com>
Diffstat (limited to 'drivers/gpu/drm/radeon/r600.c')
-rw-r--r--drivers/gpu/drm/radeon/r600.c29
1 files changed, 13 insertions, 16 deletions
diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c
index aced97bb79e0..b487c69a486d 100644
--- a/drivers/gpu/drm/radeon/r600.c
+++ b/drivers/gpu/drm/radeon/r600.c
@@ -2858,7 +2858,6 @@ void r600_disable_interrupts(struct radeon_device *rdev)
2858 WREG32(IH_RB_RPTR, 0); 2858 WREG32(IH_RB_RPTR, 0);
2859 WREG32(IH_RB_WPTR, 0); 2859 WREG32(IH_RB_WPTR, 0);
2860 rdev->ih.enabled = false; 2860 rdev->ih.enabled = false;
2861 rdev->ih.wptr = 0;
2862 rdev->ih.rptr = 0; 2861 rdev->ih.rptr = 0;
2863} 2862}
2864 2863
@@ -3310,7 +3309,6 @@ int r600_irq_process(struct radeon_device *rdev)
3310 u32 rptr; 3309 u32 rptr;
3311 u32 src_id, src_data; 3310 u32 src_id, src_data;
3312 u32 ring_index; 3311 u32 ring_index;
3313 unsigned long flags;
3314 bool queue_hotplug = false; 3312 bool queue_hotplug = false;
3315 bool queue_hdmi = false; 3313 bool queue_hdmi = false;
3316 3314
@@ -3322,24 +3320,21 @@ int r600_irq_process(struct radeon_device *rdev)
3322 RREG32(IH_RB_WPTR); 3320 RREG32(IH_RB_WPTR);
3323 3321
3324 wptr = r600_get_ih_wptr(rdev); 3322 wptr = r600_get_ih_wptr(rdev);
3325 rptr = rdev->ih.rptr;
3326 DRM_DEBUG("r600_irq_process start: rptr %d, wptr %d\n", rptr, wptr);
3327
3328 spin_lock_irqsave(&rdev->ih.lock, flags);
3329 3323
3330 if (rptr == wptr) { 3324restart_ih:
3331 spin_unlock_irqrestore(&rdev->ih.lock, flags); 3325 /* is somebody else already processing irqs? */
3326 if (atomic_xchg(&rdev->ih.lock, 1))
3332 return IRQ_NONE; 3327 return IRQ_NONE;
3333 }
3334 3328
3335restart_ih: 3329 rptr = rdev->ih.rptr;
3330 DRM_DEBUG("r600_irq_process start: rptr %d, wptr %d\n", rptr, wptr);
3331
3336 /* Order reading of wptr vs. reading of IH ring data */ 3332 /* Order reading of wptr vs. reading of IH ring data */
3337 rmb(); 3333 rmb();
3338 3334
3339 /* display interrupts */ 3335 /* display interrupts */
3340 r600_irq_ack(rdev); 3336 r600_irq_ack(rdev);
3341 3337
3342 rdev->ih.wptr = wptr;
3343 while (rptr != wptr) { 3338 while (rptr != wptr) {
3344 /* wptr/rptr are in bytes! */ 3339 /* wptr/rptr are in bytes! */
3345 ring_index = rptr / 4; 3340 ring_index = rptr / 4;
@@ -3493,17 +3488,19 @@ restart_ih:
3493 rptr += 16; 3488 rptr += 16;
3494 rptr &= rdev->ih.ptr_mask; 3489 rptr &= rdev->ih.ptr_mask;
3495 } 3490 }
3496 /* make sure wptr hasn't changed while processing */
3497 wptr = r600_get_ih_wptr(rdev);
3498 if (wptr != rdev->ih.wptr)
3499 goto restart_ih;
3500 if (queue_hotplug) 3491 if (queue_hotplug)
3501 schedule_work(&rdev->hotplug_work); 3492 schedule_work(&rdev->hotplug_work);
3502 if (queue_hdmi) 3493 if (queue_hdmi)
3503 schedule_work(&rdev->audio_work); 3494 schedule_work(&rdev->audio_work);
3504 rdev->ih.rptr = rptr; 3495 rdev->ih.rptr = rptr;
3505 WREG32(IH_RB_RPTR, rdev->ih.rptr); 3496 WREG32(IH_RB_RPTR, rdev->ih.rptr);
3506 spin_unlock_irqrestore(&rdev->ih.lock, flags); 3497 atomic_set(&rdev->ih.lock, 0);
3498
3499 /* make sure wptr hasn't changed while processing */
3500 wptr = r600_get_ih_wptr(rdev);
3501 if (wptr != rptr)
3502 goto restart_ih;
3503
3507 return IRQ_HANDLED; 3504 return IRQ_HANDLED;
3508} 3505}
3509 3506