aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/radeon/evergreen.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/evergreen.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/evergreen.c')
-rw-r--r--drivers/gpu/drm/radeon/evergreen.c21
1 files changed, 6 insertions, 15 deletions
diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c
index 765bd1f2e1ce..bdc1f30d7474 100644
--- a/drivers/gpu/drm/radeon/evergreen.c
+++ b/drivers/gpu/drm/radeon/evergreen.c
@@ -428,6 +428,7 @@ void evergreen_hpd_init(struct radeon_device *rdev)
428{ 428{
429 struct drm_device *dev = rdev->ddev; 429 struct drm_device *dev = rdev->ddev;
430 struct drm_connector *connector; 430 struct drm_connector *connector;
431 unsigned enabled = 0;
431 u32 tmp = DC_HPDx_CONNECTION_TIMER(0x9c4) | 432 u32 tmp = DC_HPDx_CONNECTION_TIMER(0x9c4) |
432 DC_HPDx_RX_INT_TIMER(0xfa) | DC_HPDx_EN; 433 DC_HPDx_RX_INT_TIMER(0xfa) | DC_HPDx_EN;
433 434
@@ -436,73 +437,64 @@ void evergreen_hpd_init(struct radeon_device *rdev)
436 switch (radeon_connector->hpd.hpd) { 437 switch (radeon_connector->hpd.hpd) {
437 case RADEON_HPD_1: 438 case RADEON_HPD_1:
438 WREG32(DC_HPD1_CONTROL, tmp); 439 WREG32(DC_HPD1_CONTROL, tmp);
439 rdev->irq.hpd[0] = true;
440 break; 440 break;
441 case RADEON_HPD_2: 441 case RADEON_HPD_2:
442 WREG32(DC_HPD2_CONTROL, tmp); 442 WREG32(DC_HPD2_CONTROL, tmp);
443 rdev->irq.hpd[1] = true;
444 break; 443 break;
445 case RADEON_HPD_3: 444 case RADEON_HPD_3:
446 WREG32(DC_HPD3_CONTROL, tmp); 445 WREG32(DC_HPD3_CONTROL, tmp);
447 rdev->irq.hpd[2] = true;
448 break; 446 break;
449 case RADEON_HPD_4: 447 case RADEON_HPD_4:
450 WREG32(DC_HPD4_CONTROL, tmp); 448 WREG32(DC_HPD4_CONTROL, tmp);
451 rdev->irq.hpd[3] = true;
452 break; 449 break;
453 case RADEON_HPD_5: 450 case RADEON_HPD_5:
454 WREG32(DC_HPD5_CONTROL, tmp); 451 WREG32(DC_HPD5_CONTROL, tmp);
455 rdev->irq.hpd[4] = true;
456 break; 452 break;
457 case RADEON_HPD_6: 453 case RADEON_HPD_6:
458 WREG32(DC_HPD6_CONTROL, tmp); 454 WREG32(DC_HPD6_CONTROL, tmp);
459 rdev->irq.hpd[5] = true;
460 break; 455 break;
461 default: 456 default:
462 break; 457 break;
463 } 458 }
464 radeon_hpd_set_polarity(rdev, radeon_connector->hpd.hpd); 459 radeon_hpd_set_polarity(rdev, radeon_connector->hpd.hpd);
460 enabled |= 1 << radeon_connector->hpd.hpd;
465 } 461 }
466 if (rdev->irq.installed) 462 radeon_irq_kms_enable_hpd(rdev, enabled);
467 evergreen_irq_set(rdev);
468} 463}
469 464
470void evergreen_hpd_fini(struct radeon_device *rdev) 465void evergreen_hpd_fini(struct radeon_device *rdev)
471{ 466{
472 struct drm_device *dev = rdev->ddev; 467 struct drm_device *dev = rdev->ddev;
473 struct drm_connector *connector; 468 struct drm_connector *connector;
469 unsigned disabled = 0;
474 470
475 list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 471 list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
476 struct radeon_connector *radeon_connector = to_radeon_connector(connector); 472 struct radeon_connector *radeon_connector = to_radeon_connector(connector);
477 switch (radeon_connector->hpd.hpd) { 473 switch (radeon_connector->hpd.hpd) {
478 case RADEON_HPD_1: 474 case RADEON_HPD_1:
479 WREG32(DC_HPD1_CONTROL, 0); 475 WREG32(DC_HPD1_CONTROL, 0);
480 rdev->irq.hpd[0] = false;
481 break; 476 break;
482 case RADEON_HPD_2: 477 case RADEON_HPD_2:
483 WREG32(DC_HPD2_CONTROL, 0); 478 WREG32(DC_HPD2_CONTROL, 0);
484 rdev->irq.hpd[1] = false;
485 break; 479 break;
486 case RADEON_HPD_3: 480 case RADEON_HPD_3:
487 WREG32(DC_HPD3_CONTROL, 0); 481 WREG32(DC_HPD3_CONTROL, 0);
488 rdev->irq.hpd[2] = false;
489 break; 482 break;
490 case RADEON_HPD_4: 483 case RADEON_HPD_4:
491 WREG32(DC_HPD4_CONTROL, 0); 484 WREG32(DC_HPD4_CONTROL, 0);
492 rdev->irq.hpd[3] = false;
493 break; 485 break;
494 case RADEON_HPD_5: 486 case RADEON_HPD_5:
495 WREG32(DC_HPD5_CONTROL, 0); 487 WREG32(DC_HPD5_CONTROL, 0);
496 rdev->irq.hpd[4] = false;
497 break; 488 break;
498 case RADEON_HPD_6: 489 case RADEON_HPD_6:
499 WREG32(DC_HPD6_CONTROL, 0); 490 WREG32(DC_HPD6_CONTROL, 0);
500 rdev->irq.hpd[5] = false;
501 break; 491 break;
502 default: 492 default:
503 break; 493 break;
504 } 494 }
495 disabled |= 1 << radeon_connector->hpd.hpd;
505 } 496 }
497 radeon_irq_kms_disable_hpd(rdev, disabled);
506} 498}
507 499
508/* watermark setup */ 500/* watermark setup */
@@ -2984,7 +2976,6 @@ restart_ih:
2984 break; 2976 break;
2985 case 233: /* GUI IDLE */ 2977 case 233: /* GUI IDLE */
2986 DRM_DEBUG("IH: GUI idle\n"); 2978 DRM_DEBUG("IH: GUI idle\n");
2987 rdev->pm.gui_idle = true;
2988 wake_up(&rdev->irq.idle_queue); 2979 wake_up(&rdev->irq.idle_queue);
2989 break; 2980 break;
2990 default: 2981 default: