diff options
author | Christian Koenig <christian.koenig@amd.com> | 2012-05-16 19:33:30 -0400 |
---|---|---|
committer | Christian König <deathsimple@vodafone.de> | 2012-06-21 03:38:50 -0400 |
commit | fb98257a9d9d2089972b18079d5bdd4412e107e2 (patch) | |
tree | 72f6115ccae023c1e6122bdd82cf310c8014de23 /drivers/gpu/drm/radeon/radeon_kms.c | |
parent | c20dc3698dc7ecf053e2bf77299ae5982c0c2c45 (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.c | 12 |
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) | |||
382 | int radeon_enable_vblank_kms(struct drm_device *dev, int crtc) | 382 | int 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 | ||
396 | void radeon_disable_vblank_kms(struct drm_device *dev, int crtc) | 400 | void 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 | ||
410 | int radeon_get_vblank_timestamp_kms(struct drm_device *dev, int crtc, | 416 | int radeon_get_vblank_timestamp_kms(struct drm_device *dev, int crtc, |