aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/radeon/radeon_kms.c
diff options
context:
space:
mode:
authorChristian Koenig <christian.koenig@amd.com>2012-05-16 19:33:30 -0400
committerChristian König <deathsimple@vodafone.de>2012-06-21 03:38:50 -0400
commitfb98257a9d9d2089972b18079d5bdd4412e107e2 (patch)
tree72f6115ccae023c1e6122bdd82cf310c8014de23 /drivers/gpu/drm/radeon/radeon_kms.c
parentc20dc3698dc7ecf053e2bf77299ae5982c0c2c45 (diff)
drm/radeon: apply Murphy's law to the kms irq code v3
1. It is really dangerous to have more than one spinlock protecting the same information. 2. radeon_irq_set sometimes wasn't called with lock protection, so it can happen that more than one CPU would tamper with the irq regs at the same time. 3. The pm.gui_idle variable was assuming that the 3D engine wasn't becoming idle between testing the register and setting the variable. So just remove it and test the register directly. v2: Also handle the hpd irq code the same way. v3: Rename hpd parameter for clarification. Signed-off-by: Christian Koenig <christian.koenig@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm/radeon/radeon_kms.c')
-rw-r--r--drivers/gpu/drm/radeon/radeon_kms.c12
1 files changed, 9 insertions, 3 deletions
diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c
index 5c58d7d90cb2..18b81d63ee7b 100644
--- a/drivers/gpu/drm/radeon/radeon_kms.c
+++ b/drivers/gpu/drm/radeon/radeon_kms.c
@@ -382,29 +382,35 @@ u32 radeon_get_vblank_counter_kms(struct drm_device *dev, int crtc)
382int radeon_enable_vblank_kms(struct drm_device *dev, int crtc) 382int radeon_enable_vblank_kms(struct drm_device *dev, int crtc)
383{ 383{
384 struct radeon_device *rdev = dev->dev_private; 384 struct radeon_device *rdev = dev->dev_private;
385 unsigned long irqflags;
386 int r;
385 387
386 if (crtc < 0 || crtc >= rdev->num_crtc) { 388 if (crtc < 0 || crtc >= rdev->num_crtc) {
387 DRM_ERROR("Invalid crtc %d\n", crtc); 389 DRM_ERROR("Invalid crtc %d\n", crtc);
388 return -EINVAL; 390 return -EINVAL;
389 } 391 }
390 392
393 spin_lock_irqsave(&rdev->irq.lock, irqflags);
391 rdev->irq.crtc_vblank_int[crtc] = true; 394 rdev->irq.crtc_vblank_int[crtc] = true;
392 395 r = radeon_irq_set(rdev);
393 return radeon_irq_set(rdev); 396 spin_unlock_irqrestore(&rdev->irq.lock, irqflags);
397 return r;
394} 398}
395 399
396void radeon_disable_vblank_kms(struct drm_device *dev, int crtc) 400void radeon_disable_vblank_kms(struct drm_device *dev, int crtc)
397{ 401{
398 struct radeon_device *rdev = dev->dev_private; 402 struct radeon_device *rdev = dev->dev_private;
403 unsigned long irqflags;
399 404
400 if (crtc < 0 || crtc >= rdev->num_crtc) { 405 if (crtc < 0 || crtc >= rdev->num_crtc) {
401 DRM_ERROR("Invalid crtc %d\n", crtc); 406 DRM_ERROR("Invalid crtc %d\n", crtc);
402 return; 407 return;
403 } 408 }
404 409
410 spin_lock_irqsave(&rdev->irq.lock, irqflags);
405 rdev->irq.crtc_vblank_int[crtc] = false; 411 rdev->irq.crtc_vblank_int[crtc] = false;
406
407 radeon_irq_set(rdev); 412 radeon_irq_set(rdev);
413 spin_unlock_irqrestore(&rdev->irq.lock, irqflags);
408} 414}
409 415
410int radeon_get_vblank_timestamp_kms(struct drm_device *dev, int crtc, 416int radeon_get_vblank_timestamp_kms(struct drm_device *dev, int crtc,