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/evergreen.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/evergreen.c')
-rw-r--r-- | drivers/gpu/drm/radeon/evergreen.c | 21 |
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 | ||
470 | void evergreen_hpd_fini(struct radeon_device *rdev) | 465 | void 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: |