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 | |
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')
-rw-r--r-- | drivers/gpu/drm/radeon/evergreen.c | 21 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/r100.c | 29 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/r600.c | 38 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/r600_hdmi.c | 6 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon.h | 35 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_irq_kms.c | 96 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_kms.c | 12 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_pm.c | 12 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/rs600.c | 13 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/si.c | 1 |
10 files changed, 144 insertions, 119 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: |
diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index 415b7d8fbba2..e8fe4ae3bc23 100644 --- a/drivers/gpu/drm/radeon/r100.c +++ b/drivers/gpu/drm/radeon/r100.c | |||
@@ -567,43 +567,27 @@ void r100_hpd_init(struct radeon_device *rdev) | |||
567 | { | 567 | { |
568 | struct drm_device *dev = rdev->ddev; | 568 | struct drm_device *dev = rdev->ddev; |
569 | struct drm_connector *connector; | 569 | struct drm_connector *connector; |
570 | unsigned enable = 0; | ||
570 | 571 | ||
571 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { | 572 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
572 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); | 573 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
573 | switch (radeon_connector->hpd.hpd) { | 574 | enable |= 1 << radeon_connector->hpd.hpd; |
574 | case RADEON_HPD_1: | ||
575 | rdev->irq.hpd[0] = true; | ||
576 | break; | ||
577 | case RADEON_HPD_2: | ||
578 | rdev->irq.hpd[1] = true; | ||
579 | break; | ||
580 | default: | ||
581 | break; | ||
582 | } | ||
583 | radeon_hpd_set_polarity(rdev, radeon_connector->hpd.hpd); | 575 | radeon_hpd_set_polarity(rdev, radeon_connector->hpd.hpd); |
584 | } | 576 | } |
585 | if (rdev->irq.installed) | 577 | radeon_irq_kms_enable_hpd(rdev, enable); |
586 | r100_irq_set(rdev); | ||
587 | } | 578 | } |
588 | 579 | ||
589 | void r100_hpd_fini(struct radeon_device *rdev) | 580 | void r100_hpd_fini(struct radeon_device *rdev) |
590 | { | 581 | { |
591 | struct drm_device *dev = rdev->ddev; | 582 | struct drm_device *dev = rdev->ddev; |
592 | struct drm_connector *connector; | 583 | struct drm_connector *connector; |
584 | unsigned disable = 0; | ||
593 | 585 | ||
594 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { | 586 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
595 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); | 587 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
596 | switch (radeon_connector->hpd.hpd) { | 588 | disable |= 1 << radeon_connector->hpd.hpd; |
597 | case RADEON_HPD_1: | ||
598 | rdev->irq.hpd[0] = false; | ||
599 | break; | ||
600 | case RADEON_HPD_2: | ||
601 | rdev->irq.hpd[1] = false; | ||
602 | break; | ||
603 | default: | ||
604 | break; | ||
605 | } | ||
606 | } | 589 | } |
590 | radeon_irq_kms_disable_hpd(rdev, disable); | ||
607 | } | 591 | } |
608 | 592 | ||
609 | /* | 593 | /* |
@@ -782,7 +766,6 @@ int r100_irq_process(struct radeon_device *rdev) | |||
782 | /* gui idle interrupt */ | 766 | /* gui idle interrupt */ |
783 | if (status & RADEON_GUI_IDLE_STAT) { | 767 | if (status & RADEON_GUI_IDLE_STAT) { |
784 | rdev->irq.gui_idle_acked = true; | 768 | rdev->irq.gui_idle_acked = true; |
785 | rdev->pm.gui_idle = true; | ||
786 | wake_up(&rdev->irq.idle_queue); | 769 | wake_up(&rdev->irq.idle_queue); |
787 | } | 770 | } |
788 | /* Vertical blank interrupts */ | 771 | /* Vertical blank interrupts */ |
diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index b487c69a486d..9cd77286542c 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c | |||
@@ -709,6 +709,7 @@ void r600_hpd_init(struct radeon_device *rdev) | |||
709 | { | 709 | { |
710 | struct drm_device *dev = rdev->ddev; | 710 | struct drm_device *dev = rdev->ddev; |
711 | struct drm_connector *connector; | 711 | struct drm_connector *connector; |
712 | unsigned enable = 0; | ||
712 | 713 | ||
713 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { | 714 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
714 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); | 715 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
@@ -729,28 +730,22 @@ void r600_hpd_init(struct radeon_device *rdev) | |||
729 | switch (radeon_connector->hpd.hpd) { | 730 | switch (radeon_connector->hpd.hpd) { |
730 | case RADEON_HPD_1: | 731 | case RADEON_HPD_1: |
731 | WREG32(DC_HPD1_CONTROL, tmp); | 732 | WREG32(DC_HPD1_CONTROL, tmp); |
732 | rdev->irq.hpd[0] = true; | ||
733 | break; | 733 | break; |
734 | case RADEON_HPD_2: | 734 | case RADEON_HPD_2: |
735 | WREG32(DC_HPD2_CONTROL, tmp); | 735 | WREG32(DC_HPD2_CONTROL, tmp); |
736 | rdev->irq.hpd[1] = true; | ||
737 | break; | 736 | break; |
738 | case RADEON_HPD_3: | 737 | case RADEON_HPD_3: |
739 | WREG32(DC_HPD3_CONTROL, tmp); | 738 | WREG32(DC_HPD3_CONTROL, tmp); |
740 | rdev->irq.hpd[2] = true; | ||
741 | break; | 739 | break; |
742 | case RADEON_HPD_4: | 740 | case RADEON_HPD_4: |
743 | WREG32(DC_HPD4_CONTROL, tmp); | 741 | WREG32(DC_HPD4_CONTROL, tmp); |
744 | rdev->irq.hpd[3] = true; | ||
745 | break; | 742 | break; |
746 | /* DCE 3.2 */ | 743 | /* DCE 3.2 */ |
747 | case RADEON_HPD_5: | 744 | case RADEON_HPD_5: |
748 | WREG32(DC_HPD5_CONTROL, tmp); | 745 | WREG32(DC_HPD5_CONTROL, tmp); |
749 | rdev->irq.hpd[4] = true; | ||
750 | break; | 746 | break; |
751 | case RADEON_HPD_6: | 747 | case RADEON_HPD_6: |
752 | WREG32(DC_HPD6_CONTROL, tmp); | 748 | WREG32(DC_HPD6_CONTROL, tmp); |
753 | rdev->irq.hpd[5] = true; | ||
754 | break; | 749 | break; |
755 | default: | 750 | default: |
756 | break; | 751 | break; |
@@ -759,85 +754,73 @@ void r600_hpd_init(struct radeon_device *rdev) | |||
759 | switch (radeon_connector->hpd.hpd) { | 754 | switch (radeon_connector->hpd.hpd) { |
760 | case RADEON_HPD_1: | 755 | case RADEON_HPD_1: |
761 | WREG32(DC_HOT_PLUG_DETECT1_CONTROL, DC_HOT_PLUG_DETECTx_EN); | 756 | WREG32(DC_HOT_PLUG_DETECT1_CONTROL, DC_HOT_PLUG_DETECTx_EN); |
762 | rdev->irq.hpd[0] = true; | ||
763 | break; | 757 | break; |
764 | case RADEON_HPD_2: | 758 | case RADEON_HPD_2: |
765 | WREG32(DC_HOT_PLUG_DETECT2_CONTROL, DC_HOT_PLUG_DETECTx_EN); | 759 | WREG32(DC_HOT_PLUG_DETECT2_CONTROL, DC_HOT_PLUG_DETECTx_EN); |
766 | rdev->irq.hpd[1] = true; | ||
767 | break; | 760 | break; |
768 | case RADEON_HPD_3: | 761 | case RADEON_HPD_3: |
769 | WREG32(DC_HOT_PLUG_DETECT3_CONTROL, DC_HOT_PLUG_DETECTx_EN); | 762 | WREG32(DC_HOT_PLUG_DETECT3_CONTROL, DC_HOT_PLUG_DETECTx_EN); |
770 | rdev->irq.hpd[2] = true; | ||
771 | break; | 763 | break; |
772 | default: | 764 | default: |
773 | break; | 765 | break; |
774 | } | 766 | } |
775 | } | 767 | } |
768 | enable |= 1 << radeon_connector->hpd.hpd; | ||
776 | radeon_hpd_set_polarity(rdev, radeon_connector->hpd.hpd); | 769 | radeon_hpd_set_polarity(rdev, radeon_connector->hpd.hpd); |
777 | } | 770 | } |
778 | if (rdev->irq.installed) | 771 | radeon_irq_kms_enable_hpd(rdev, enable); |
779 | r600_irq_set(rdev); | ||
780 | } | 772 | } |
781 | 773 | ||
782 | void r600_hpd_fini(struct radeon_device *rdev) | 774 | void r600_hpd_fini(struct radeon_device *rdev) |
783 | { | 775 | { |
784 | struct drm_device *dev = rdev->ddev; | 776 | struct drm_device *dev = rdev->ddev; |
785 | struct drm_connector *connector; | 777 | struct drm_connector *connector; |
778 | unsigned disable = 0; | ||
786 | 779 | ||
787 | if (ASIC_IS_DCE3(rdev)) { | 780 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
788 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { | 781 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
789 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); | 782 | if (ASIC_IS_DCE3(rdev)) { |
790 | switch (radeon_connector->hpd.hpd) { | 783 | switch (radeon_connector->hpd.hpd) { |
791 | case RADEON_HPD_1: | 784 | case RADEON_HPD_1: |
792 | WREG32(DC_HPD1_CONTROL, 0); | 785 | WREG32(DC_HPD1_CONTROL, 0); |
793 | rdev->irq.hpd[0] = false; | ||
794 | break; | 786 | break; |
795 | case RADEON_HPD_2: | 787 | case RADEON_HPD_2: |
796 | WREG32(DC_HPD2_CONTROL, 0); | 788 | WREG32(DC_HPD2_CONTROL, 0); |
797 | rdev->irq.hpd[1] = false; | ||
798 | break; | 789 | break; |
799 | case RADEON_HPD_3: | 790 | case RADEON_HPD_3: |
800 | WREG32(DC_HPD3_CONTROL, 0); | 791 | WREG32(DC_HPD3_CONTROL, 0); |
801 | rdev->irq.hpd[2] = false; | ||
802 | break; | 792 | break; |
803 | case RADEON_HPD_4: | 793 | case RADEON_HPD_4: |
804 | WREG32(DC_HPD4_CONTROL, 0); | 794 | WREG32(DC_HPD4_CONTROL, 0); |
805 | rdev->irq.hpd[3] = false; | ||
806 | break; | 795 | break; |
807 | /* DCE 3.2 */ | 796 | /* DCE 3.2 */ |
808 | case RADEON_HPD_5: | 797 | case RADEON_HPD_5: |
809 | WREG32(DC_HPD5_CONTROL, 0); | 798 | WREG32(DC_HPD5_CONTROL, 0); |
810 | rdev->irq.hpd[4] = false; | ||
811 | break; | 799 | break; |
812 | case RADEON_HPD_6: | 800 | case RADEON_HPD_6: |
813 | WREG32(DC_HPD6_CONTROL, 0); | 801 | WREG32(DC_HPD6_CONTROL, 0); |
814 | rdev->irq.hpd[5] = false; | ||
815 | break; | 802 | break; |
816 | default: | 803 | default: |
817 | break; | 804 | break; |
818 | } | 805 | } |
819 | } | 806 | } else { |
820 | } else { | ||
821 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { | ||
822 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); | ||
823 | switch (radeon_connector->hpd.hpd) { | 807 | switch (radeon_connector->hpd.hpd) { |
824 | case RADEON_HPD_1: | 808 | case RADEON_HPD_1: |
825 | WREG32(DC_HOT_PLUG_DETECT1_CONTROL, 0); | 809 | WREG32(DC_HOT_PLUG_DETECT1_CONTROL, 0); |
826 | rdev->irq.hpd[0] = false; | ||
827 | break; | 810 | break; |
828 | case RADEON_HPD_2: | 811 | case RADEON_HPD_2: |
829 | WREG32(DC_HOT_PLUG_DETECT2_CONTROL, 0); | 812 | WREG32(DC_HOT_PLUG_DETECT2_CONTROL, 0); |
830 | rdev->irq.hpd[1] = false; | ||
831 | break; | 813 | break; |
832 | case RADEON_HPD_3: | 814 | case RADEON_HPD_3: |
833 | WREG32(DC_HOT_PLUG_DETECT3_CONTROL, 0); | 815 | WREG32(DC_HOT_PLUG_DETECT3_CONTROL, 0); |
834 | rdev->irq.hpd[2] = false; | ||
835 | break; | 816 | break; |
836 | default: | 817 | default: |
837 | break; | 818 | break; |
838 | } | 819 | } |
839 | } | 820 | } |
821 | disable |= 1 << radeon_connector->hpd.hpd; | ||
840 | } | 822 | } |
823 | radeon_irq_kms_disable_hpd(rdev, disable); | ||
841 | } | 824 | } |
842 | 825 | ||
843 | /* | 826 | /* |
@@ -3476,7 +3459,6 @@ restart_ih: | |||
3476 | break; | 3459 | break; |
3477 | case 233: /* GUI IDLE */ | 3460 | case 233: /* GUI IDLE */ |
3478 | DRM_DEBUG("IH: GUI idle\n"); | 3461 | DRM_DEBUG("IH: GUI idle\n"); |
3479 | rdev->pm.gui_idle = true; | ||
3480 | wake_up(&rdev->irq.idle_queue); | 3462 | wake_up(&rdev->irq.idle_queue); |
3481 | break; | 3463 | break; |
3482 | default: | 3464 | default: |
diff --git a/drivers/gpu/drm/radeon/r600_hdmi.c b/drivers/gpu/drm/radeon/r600_hdmi.c index 82a0a4c919c0..e3558c3ef24a 100644 --- a/drivers/gpu/drm/radeon/r600_hdmi.c +++ b/drivers/gpu/drm/radeon/r600_hdmi.c | |||
@@ -519,8 +519,7 @@ void r600_hdmi_enable(struct drm_encoder *encoder) | |||
519 | 519 | ||
520 | if (rdev->irq.installed) { | 520 | if (rdev->irq.installed) { |
521 | /* if irq is available use it */ | 521 | /* if irq is available use it */ |
522 | rdev->irq.afmt[dig->afmt->id] = true; | 522 | radeon_irq_kms_enable_afmt(rdev, dig->afmt->id); |
523 | radeon_irq_set(rdev); | ||
524 | } | 523 | } |
525 | 524 | ||
526 | dig->afmt->enabled = true; | 525 | dig->afmt->enabled = true; |
@@ -556,8 +555,7 @@ void r600_hdmi_disable(struct drm_encoder *encoder) | |||
556 | offset, radeon_encoder->encoder_id); | 555 | offset, radeon_encoder->encoder_id); |
557 | 556 | ||
558 | /* disable irq */ | 557 | /* disable irq */ |
559 | rdev->irq.afmt[dig->afmt->id] = false; | 558 | radeon_irq_kms_disable_afmt(rdev, dig->afmt->id); |
560 | radeon_irq_set(rdev); | ||
561 | 559 | ||
562 | /* Older chipsets not handled by AtomBIOS */ | 560 | /* Older chipsets not handled by AtomBIOS */ |
563 | if (rdev->family >= CHIP_R600 && !ASIC_IS_DCE3(rdev)) { | 561 | if (rdev->family >= CHIP_R600 && !ASIC_IS_DCE3(rdev)) { |
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 5ddf895a5926..353a1830514a 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h | |||
@@ -615,21 +615,20 @@ union radeon_irq_stat_regs { | |||
615 | #define RADEON_MAX_AFMT_BLOCKS 6 | 615 | #define RADEON_MAX_AFMT_BLOCKS 6 |
616 | 616 | ||
617 | struct radeon_irq { | 617 | struct radeon_irq { |
618 | bool installed; | 618 | bool installed; |
619 | bool sw_int[RADEON_NUM_RINGS]; | 619 | spinlock_t lock; |
620 | bool crtc_vblank_int[RADEON_MAX_CRTCS]; | 620 | bool sw_int[RADEON_NUM_RINGS]; |
621 | bool pflip[RADEON_MAX_CRTCS]; | 621 | int sw_refcount[RADEON_NUM_RINGS]; |
622 | wait_queue_head_t vblank_queue; | 622 | bool crtc_vblank_int[RADEON_MAX_CRTCS]; |
623 | bool hpd[RADEON_MAX_HPD_PINS]; | 623 | bool pflip[RADEON_MAX_CRTCS]; |
624 | bool gui_idle; | 624 | int pflip_refcount[RADEON_MAX_CRTCS]; |
625 | bool gui_idle_acked; | 625 | wait_queue_head_t vblank_queue; |
626 | wait_queue_head_t idle_queue; | 626 | bool hpd[RADEON_MAX_HPD_PINS]; |
627 | bool afmt[RADEON_MAX_AFMT_BLOCKS]; | 627 | bool gui_idle; |
628 | spinlock_t sw_lock; | 628 | bool gui_idle_acked; |
629 | int sw_refcount[RADEON_NUM_RINGS]; | 629 | wait_queue_head_t idle_queue; |
630 | union radeon_irq_stat_regs stat_regs; | 630 | bool afmt[RADEON_MAX_AFMT_BLOCKS]; |
631 | spinlock_t pflip_lock[RADEON_MAX_CRTCS]; | 631 | union radeon_irq_stat_regs stat_regs; |
632 | int pflip_refcount[RADEON_MAX_CRTCS]; | ||
633 | }; | 632 | }; |
634 | 633 | ||
635 | int radeon_irq_kms_init(struct radeon_device *rdev); | 634 | int radeon_irq_kms_init(struct radeon_device *rdev); |
@@ -638,6 +637,11 @@ void radeon_irq_kms_sw_irq_get(struct radeon_device *rdev, int ring); | |||
638 | void radeon_irq_kms_sw_irq_put(struct radeon_device *rdev, int ring); | 637 | void radeon_irq_kms_sw_irq_put(struct radeon_device *rdev, int ring); |
639 | void radeon_irq_kms_pflip_irq_get(struct radeon_device *rdev, int crtc); | 638 | void radeon_irq_kms_pflip_irq_get(struct radeon_device *rdev, int crtc); |
640 | void radeon_irq_kms_pflip_irq_put(struct radeon_device *rdev, int crtc); | 639 | void radeon_irq_kms_pflip_irq_put(struct radeon_device *rdev, int crtc); |
640 | void radeon_irq_kms_enable_afmt(struct radeon_device *rdev, int block); | ||
641 | void radeon_irq_kms_disable_afmt(struct radeon_device *rdev, int block); | ||
642 | void radeon_irq_kms_enable_hpd(struct radeon_device *rdev, unsigned hpd_mask); | ||
643 | void radeon_irq_kms_disable_hpd(struct radeon_device *rdev, unsigned hpd_mask); | ||
644 | int radeon_irq_kms_wait_gui_idle(struct radeon_device *rdev); | ||
641 | 645 | ||
642 | /* | 646 | /* |
643 | * CP & rings. | 647 | * CP & rings. |
@@ -1062,7 +1066,6 @@ struct radeon_pm { | |||
1062 | int active_crtc_count; | 1066 | int active_crtc_count; |
1063 | int req_vblank; | 1067 | int req_vblank; |
1064 | bool vblank_sync; | 1068 | bool vblank_sync; |
1065 | bool gui_idle; | ||
1066 | fixed20_12 max_bandwidth; | 1069 | fixed20_12 max_bandwidth; |
1067 | fixed20_12 igp_sideport_mclk; | 1070 | fixed20_12 igp_sideport_mclk; |
1068 | fixed20_12 igp_system_mclk; | 1071 | fixed20_12 igp_system_mclk; |
diff --git a/drivers/gpu/drm/radeon/radeon_irq_kms.c b/drivers/gpu/drm/radeon/radeon_irq_kms.c index 5df58d1aba06..c5eb7a1461cf 100644 --- a/drivers/gpu/drm/radeon/radeon_irq_kms.c +++ b/drivers/gpu/drm/radeon/radeon_irq_kms.c | |||
@@ -32,6 +32,8 @@ | |||
32 | #include "radeon.h" | 32 | #include "radeon.h" |
33 | #include "atom.h" | 33 | #include "atom.h" |
34 | 34 | ||
35 | #define RADEON_WAIT_IDLE_TIMEOUT 200 | ||
36 | |||
35 | irqreturn_t radeon_driver_irq_handler_kms(DRM_IRQ_ARGS) | 37 | irqreturn_t radeon_driver_irq_handler_kms(DRM_IRQ_ARGS) |
36 | { | 38 | { |
37 | struct drm_device *dev = (struct drm_device *) arg; | 39 | struct drm_device *dev = (struct drm_device *) arg; |
@@ -62,8 +64,10 @@ static void radeon_hotplug_work_func(struct work_struct *work) | |||
62 | void radeon_driver_irq_preinstall_kms(struct drm_device *dev) | 64 | void radeon_driver_irq_preinstall_kms(struct drm_device *dev) |
63 | { | 65 | { |
64 | struct radeon_device *rdev = dev->dev_private; | 66 | struct radeon_device *rdev = dev->dev_private; |
67 | unsigned long irqflags; | ||
65 | unsigned i; | 68 | unsigned i; |
66 | 69 | ||
70 | spin_lock_irqsave(&rdev->irq.lock, irqflags); | ||
67 | /* Disable *all* interrupts */ | 71 | /* Disable *all* interrupts */ |
68 | for (i = 0; i < RADEON_NUM_RINGS; i++) | 72 | for (i = 0; i < RADEON_NUM_RINGS; i++) |
69 | rdev->irq.sw_int[i] = false; | 73 | rdev->irq.sw_int[i] = false; |
@@ -76,6 +80,7 @@ void radeon_driver_irq_preinstall_kms(struct drm_device *dev) | |||
76 | rdev->irq.afmt[i] = false; | 80 | rdev->irq.afmt[i] = false; |
77 | } | 81 | } |
78 | radeon_irq_set(rdev); | 82 | radeon_irq_set(rdev); |
83 | spin_unlock_irqrestore(&rdev->irq.lock, irqflags); | ||
79 | /* Clear bits */ | 84 | /* Clear bits */ |
80 | radeon_irq_process(rdev); | 85 | radeon_irq_process(rdev); |
81 | } | 86 | } |
@@ -83,23 +88,28 @@ void radeon_driver_irq_preinstall_kms(struct drm_device *dev) | |||
83 | int radeon_driver_irq_postinstall_kms(struct drm_device *dev) | 88 | int radeon_driver_irq_postinstall_kms(struct drm_device *dev) |
84 | { | 89 | { |
85 | struct radeon_device *rdev = dev->dev_private; | 90 | struct radeon_device *rdev = dev->dev_private; |
91 | unsigned long irqflags; | ||
86 | unsigned i; | 92 | unsigned i; |
87 | 93 | ||
88 | dev->max_vblank_count = 0x001fffff; | 94 | dev->max_vblank_count = 0x001fffff; |
95 | spin_lock_irqsave(&rdev->irq.lock, irqflags); | ||
89 | for (i = 0; i < RADEON_NUM_RINGS; i++) | 96 | for (i = 0; i < RADEON_NUM_RINGS; i++) |
90 | rdev->irq.sw_int[i] = true; | 97 | rdev->irq.sw_int[i] = true; |
91 | radeon_irq_set(rdev); | 98 | radeon_irq_set(rdev); |
99 | spin_unlock_irqrestore(&rdev->irq.lock, irqflags); | ||
92 | return 0; | 100 | return 0; |
93 | } | 101 | } |
94 | 102 | ||
95 | void radeon_driver_irq_uninstall_kms(struct drm_device *dev) | 103 | void radeon_driver_irq_uninstall_kms(struct drm_device *dev) |
96 | { | 104 | { |
97 | struct radeon_device *rdev = dev->dev_private; | 105 | struct radeon_device *rdev = dev->dev_private; |
106 | unsigned long irqflags; | ||
98 | unsigned i; | 107 | unsigned i; |
99 | 108 | ||
100 | if (rdev == NULL) { | 109 | if (rdev == NULL) { |
101 | return; | 110 | return; |
102 | } | 111 | } |
112 | spin_lock_irqsave(&rdev->irq.lock, irqflags); | ||
103 | /* Disable *all* interrupts */ | 113 | /* Disable *all* interrupts */ |
104 | for (i = 0; i < RADEON_NUM_RINGS; i++) | 114 | for (i = 0; i < RADEON_NUM_RINGS; i++) |
105 | rdev->irq.sw_int[i] = false; | 115 | rdev->irq.sw_int[i] = false; |
@@ -112,6 +122,7 @@ void radeon_driver_irq_uninstall_kms(struct drm_device *dev) | |||
112 | rdev->irq.afmt[i] = false; | 122 | rdev->irq.afmt[i] = false; |
113 | } | 123 | } |
114 | radeon_irq_set(rdev); | 124 | radeon_irq_set(rdev); |
125 | spin_unlock_irqrestore(&rdev->irq.lock, irqflags); | ||
115 | } | 126 | } |
116 | 127 | ||
117 | static bool radeon_msi_ok(struct radeon_device *rdev) | 128 | static bool radeon_msi_ok(struct radeon_device *rdev) |
@@ -168,15 +179,12 @@ static bool radeon_msi_ok(struct radeon_device *rdev) | |||
168 | 179 | ||
169 | int radeon_irq_kms_init(struct radeon_device *rdev) | 180 | int radeon_irq_kms_init(struct radeon_device *rdev) |
170 | { | 181 | { |
171 | int i; | ||
172 | int r = 0; | 182 | int r = 0; |
173 | 183 | ||
174 | INIT_WORK(&rdev->hotplug_work, radeon_hotplug_work_func); | 184 | INIT_WORK(&rdev->hotplug_work, radeon_hotplug_work_func); |
175 | INIT_WORK(&rdev->audio_work, r600_audio_update_hdmi); | 185 | INIT_WORK(&rdev->audio_work, r600_audio_update_hdmi); |
176 | 186 | ||
177 | spin_lock_init(&rdev->irq.sw_lock); | 187 | spin_lock_init(&rdev->irq.lock); |
178 | for (i = 0; i < rdev->num_crtc; i++) | ||
179 | spin_lock_init(&rdev->irq.pflip_lock[i]); | ||
180 | r = drm_vblank_init(rdev->ddev, rdev->num_crtc); | 188 | r = drm_vblank_init(rdev->ddev, rdev->num_crtc); |
181 | if (r) { | 189 | if (r) { |
182 | return r; | 190 | return r; |
@@ -217,25 +225,25 @@ void radeon_irq_kms_sw_irq_get(struct radeon_device *rdev, int ring) | |||
217 | { | 225 | { |
218 | unsigned long irqflags; | 226 | unsigned long irqflags; |
219 | 227 | ||
220 | spin_lock_irqsave(&rdev->irq.sw_lock, irqflags); | 228 | spin_lock_irqsave(&rdev->irq.lock, irqflags); |
221 | if (rdev->ddev->irq_enabled && (++rdev->irq.sw_refcount[ring] == 1)) { | 229 | if (rdev->ddev->irq_enabled && (++rdev->irq.sw_refcount[ring] == 1)) { |
222 | rdev->irq.sw_int[ring] = true; | 230 | rdev->irq.sw_int[ring] = true; |
223 | radeon_irq_set(rdev); | 231 | radeon_irq_set(rdev); |
224 | } | 232 | } |
225 | spin_unlock_irqrestore(&rdev->irq.sw_lock, irqflags); | 233 | spin_unlock_irqrestore(&rdev->irq.lock, irqflags); |
226 | } | 234 | } |
227 | 235 | ||
228 | void radeon_irq_kms_sw_irq_put(struct radeon_device *rdev, int ring) | 236 | void radeon_irq_kms_sw_irq_put(struct radeon_device *rdev, int ring) |
229 | { | 237 | { |
230 | unsigned long irqflags; | 238 | unsigned long irqflags; |
231 | 239 | ||
232 | spin_lock_irqsave(&rdev->irq.sw_lock, irqflags); | 240 | spin_lock_irqsave(&rdev->irq.lock, irqflags); |
233 | BUG_ON(rdev->ddev->irq_enabled && rdev->irq.sw_refcount[ring] <= 0); | 241 | BUG_ON(rdev->ddev->irq_enabled && rdev->irq.sw_refcount[ring] <= 0); |
234 | if (rdev->ddev->irq_enabled && (--rdev->irq.sw_refcount[ring] == 0)) { | 242 | if (rdev->ddev->irq_enabled && (--rdev->irq.sw_refcount[ring] == 0)) { |
235 | rdev->irq.sw_int[ring] = false; | 243 | rdev->irq.sw_int[ring] = false; |
236 | radeon_irq_set(rdev); | 244 | radeon_irq_set(rdev); |
237 | } | 245 | } |
238 | spin_unlock_irqrestore(&rdev->irq.sw_lock, irqflags); | 246 | spin_unlock_irqrestore(&rdev->irq.lock, irqflags); |
239 | } | 247 | } |
240 | 248 | ||
241 | void radeon_irq_kms_pflip_irq_get(struct radeon_device *rdev, int crtc) | 249 | void radeon_irq_kms_pflip_irq_get(struct radeon_device *rdev, int crtc) |
@@ -245,12 +253,12 @@ void radeon_irq_kms_pflip_irq_get(struct radeon_device *rdev, int crtc) | |||
245 | if (crtc < 0 || crtc >= rdev->num_crtc) | 253 | if (crtc < 0 || crtc >= rdev->num_crtc) |
246 | return; | 254 | return; |
247 | 255 | ||
248 | spin_lock_irqsave(&rdev->irq.pflip_lock[crtc], irqflags); | 256 | spin_lock_irqsave(&rdev->irq.lock, irqflags); |
249 | if (rdev->ddev->irq_enabled && (++rdev->irq.pflip_refcount[crtc] == 1)) { | 257 | if (rdev->ddev->irq_enabled && (++rdev->irq.pflip_refcount[crtc] == 1)) { |
250 | rdev->irq.pflip[crtc] = true; | 258 | rdev->irq.pflip[crtc] = true; |
251 | radeon_irq_set(rdev); | 259 | radeon_irq_set(rdev); |
252 | } | 260 | } |
253 | spin_unlock_irqrestore(&rdev->irq.pflip_lock[crtc], irqflags); | 261 | spin_unlock_irqrestore(&rdev->irq.lock, irqflags); |
254 | } | 262 | } |
255 | 263 | ||
256 | void radeon_irq_kms_pflip_irq_put(struct radeon_device *rdev, int crtc) | 264 | void radeon_irq_kms_pflip_irq_put(struct radeon_device *rdev, int crtc) |
@@ -260,12 +268,76 @@ void radeon_irq_kms_pflip_irq_put(struct radeon_device *rdev, int crtc) | |||
260 | if (crtc < 0 || crtc >= rdev->num_crtc) | 268 | if (crtc < 0 || crtc >= rdev->num_crtc) |
261 | return; | 269 | return; |
262 | 270 | ||
263 | spin_lock_irqsave(&rdev->irq.pflip_lock[crtc], irqflags); | 271 | spin_lock_irqsave(&rdev->irq.lock, irqflags); |
264 | BUG_ON(rdev->ddev->irq_enabled && rdev->irq.pflip_refcount[crtc] <= 0); | 272 | BUG_ON(rdev->ddev->irq_enabled && rdev->irq.pflip_refcount[crtc] <= 0); |
265 | if (rdev->ddev->irq_enabled && (--rdev->irq.pflip_refcount[crtc] == 0)) { | 273 | if (rdev->ddev->irq_enabled && (--rdev->irq.pflip_refcount[crtc] == 0)) { |
266 | rdev->irq.pflip[crtc] = false; | 274 | rdev->irq.pflip[crtc] = false; |
267 | radeon_irq_set(rdev); | 275 | radeon_irq_set(rdev); |
268 | } | 276 | } |
269 | spin_unlock_irqrestore(&rdev->irq.pflip_lock[crtc], irqflags); | 277 | spin_unlock_irqrestore(&rdev->irq.lock, irqflags); |
270 | } | 278 | } |
271 | 279 | ||
280 | void radeon_irq_kms_enable_afmt(struct radeon_device *rdev, int block) | ||
281 | { | ||
282 | unsigned long irqflags; | ||
283 | |||
284 | spin_lock_irqsave(&rdev->irq.lock, irqflags); | ||
285 | rdev->irq.afmt[block] = true; | ||
286 | radeon_irq_set(rdev); | ||
287 | spin_unlock_irqrestore(&rdev->irq.lock, irqflags); | ||
288 | |||
289 | } | ||
290 | |||
291 | void radeon_irq_kms_disable_afmt(struct radeon_device *rdev, int block) | ||
292 | { | ||
293 | unsigned long irqflags; | ||
294 | |||
295 | spin_lock_irqsave(&rdev->irq.lock, irqflags); | ||
296 | rdev->irq.afmt[block] = false; | ||
297 | radeon_irq_set(rdev); | ||
298 | spin_unlock_irqrestore(&rdev->irq.lock, irqflags); | ||
299 | } | ||
300 | |||
301 | void radeon_irq_kms_enable_hpd(struct radeon_device *rdev, unsigned hpd_mask) | ||
302 | { | ||
303 | unsigned long irqflags; | ||
304 | int i; | ||
305 | |||
306 | spin_lock_irqsave(&rdev->irq.lock, irqflags); | ||
307 | for (i = 0; i < RADEON_MAX_HPD_PINS; ++i) | ||
308 | rdev->irq.hpd[i] |= !!(hpd_mask & (1 << i)); | ||
309 | radeon_irq_set(rdev); | ||
310 | spin_unlock_irqrestore(&rdev->irq.lock, irqflags); | ||
311 | } | ||
312 | |||
313 | void radeon_irq_kms_disable_hpd(struct radeon_device *rdev, unsigned hpd_mask) | ||
314 | { | ||
315 | unsigned long irqflags; | ||
316 | int i; | ||
317 | |||
318 | spin_lock_irqsave(&rdev->irq.lock, irqflags); | ||
319 | for (i = 0; i < RADEON_MAX_HPD_PINS; ++i) | ||
320 | rdev->irq.hpd[i] &= !(hpd_mask & (1 << i)); | ||
321 | radeon_irq_set(rdev); | ||
322 | spin_unlock_irqrestore(&rdev->irq.lock, irqflags); | ||
323 | } | ||
324 | |||
325 | int radeon_irq_kms_wait_gui_idle(struct radeon_device *rdev) | ||
326 | { | ||
327 | unsigned long irqflags; | ||
328 | int r; | ||
329 | |||
330 | spin_lock_irqsave(&rdev->irq.lock, irqflags); | ||
331 | rdev->irq.gui_idle = true; | ||
332 | radeon_irq_set(rdev); | ||
333 | spin_unlock_irqrestore(&rdev->irq.lock, irqflags); | ||
334 | |||
335 | r = wait_event_timeout(rdev->irq.idle_queue, radeon_gui_idle(rdev), | ||
336 | msecs_to_jiffies(RADEON_WAIT_IDLE_TIMEOUT)); | ||
337 | |||
338 | spin_lock_irqsave(&rdev->irq.lock, irqflags); | ||
339 | rdev->irq.gui_idle = false; | ||
340 | radeon_irq_set(rdev); | ||
341 | spin_unlock_irqrestore(&rdev->irq.lock, irqflags); | ||
342 | return r; | ||
343 | } | ||
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, |
diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c index 9dc0b54fe3e3..7ae606600107 100644 --- a/drivers/gpu/drm/radeon/radeon_pm.c +++ b/drivers/gpu/drm/radeon/radeon_pm.c | |||
@@ -34,7 +34,6 @@ | |||
34 | #define RADEON_IDLE_LOOP_MS 100 | 34 | #define RADEON_IDLE_LOOP_MS 100 |
35 | #define RADEON_RECLOCK_DELAY_MS 200 | 35 | #define RADEON_RECLOCK_DELAY_MS 200 |
36 | #define RADEON_WAIT_VBLANK_TIMEOUT 200 | 36 | #define RADEON_WAIT_VBLANK_TIMEOUT 200 |
37 | #define RADEON_WAIT_IDLE_TIMEOUT 200 | ||
38 | 37 | ||
39 | static const char *radeon_pm_state_type_name[5] = { | 38 | static const char *radeon_pm_state_type_name[5] = { |
40 | "Default", | 39 | "Default", |
@@ -257,15 +256,8 @@ static void radeon_pm_set_clocks(struct radeon_device *rdev) | |||
257 | /* gui idle int has issues on older chips it seems */ | 256 | /* gui idle int has issues on older chips it seems */ |
258 | if (rdev->family >= CHIP_R600) { | 257 | if (rdev->family >= CHIP_R600) { |
259 | if (rdev->irq.installed) { | 258 | if (rdev->irq.installed) { |
260 | /* wait for GPU idle */ | 259 | /* wait for GPU to become idle */ |
261 | rdev->pm.gui_idle = false; | 260 | radeon_irq_kms_wait_gui_idle(rdev); |
262 | rdev->irq.gui_idle = true; | ||
263 | radeon_irq_set(rdev); | ||
264 | wait_event_interruptible_timeout( | ||
265 | rdev->irq.idle_queue, rdev->pm.gui_idle, | ||
266 | msecs_to_jiffies(RADEON_WAIT_IDLE_TIMEOUT)); | ||
267 | rdev->irq.gui_idle = false; | ||
268 | radeon_irq_set(rdev); | ||
269 | } | 261 | } |
270 | } else { | 262 | } else { |
271 | struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; | 263 | struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; |
diff --git a/drivers/gpu/drm/radeon/rs600.c b/drivers/gpu/drm/radeon/rs600.c index e95c5e61d4e2..f9aee25023cc 100644 --- a/drivers/gpu/drm/radeon/rs600.c +++ b/drivers/gpu/drm/radeon/rs600.c | |||
@@ -294,6 +294,7 @@ void rs600_hpd_init(struct radeon_device *rdev) | |||
294 | { | 294 | { |
295 | struct drm_device *dev = rdev->ddev; | 295 | struct drm_device *dev = rdev->ddev; |
296 | struct drm_connector *connector; | 296 | struct drm_connector *connector; |
297 | unsigned enable = 0; | ||
297 | 298 | ||
298 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { | 299 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
299 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); | 300 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
@@ -301,26 +302,25 @@ void rs600_hpd_init(struct radeon_device *rdev) | |||
301 | case RADEON_HPD_1: | 302 | case RADEON_HPD_1: |
302 | WREG32(R_007D00_DC_HOT_PLUG_DETECT1_CONTROL, | 303 | WREG32(R_007D00_DC_HOT_PLUG_DETECT1_CONTROL, |
303 | S_007D00_DC_HOT_PLUG_DETECT1_EN(1)); | 304 | S_007D00_DC_HOT_PLUG_DETECT1_EN(1)); |
304 | rdev->irq.hpd[0] = true; | ||
305 | break; | 305 | break; |
306 | case RADEON_HPD_2: | 306 | case RADEON_HPD_2: |
307 | WREG32(R_007D10_DC_HOT_PLUG_DETECT2_CONTROL, | 307 | WREG32(R_007D10_DC_HOT_PLUG_DETECT2_CONTROL, |
308 | S_007D10_DC_HOT_PLUG_DETECT2_EN(1)); | 308 | S_007D10_DC_HOT_PLUG_DETECT2_EN(1)); |
309 | rdev->irq.hpd[1] = true; | ||
310 | break; | 309 | break; |
311 | default: | 310 | default: |
312 | break; | 311 | break; |
313 | } | 312 | } |
313 | enable |= 1 << radeon_connector->hpd.hpd; | ||
314 | radeon_hpd_set_polarity(rdev, radeon_connector->hpd.hpd); | 314 | radeon_hpd_set_polarity(rdev, radeon_connector->hpd.hpd); |
315 | } | 315 | } |
316 | if (rdev->irq.installed) | 316 | radeon_irq_kms_enable_hpd(rdev, enable); |
317 | rs600_irq_set(rdev); | ||
318 | } | 317 | } |
319 | 318 | ||
320 | void rs600_hpd_fini(struct radeon_device *rdev) | 319 | void rs600_hpd_fini(struct radeon_device *rdev) |
321 | { | 320 | { |
322 | struct drm_device *dev = rdev->ddev; | 321 | struct drm_device *dev = rdev->ddev; |
323 | struct drm_connector *connector; | 322 | struct drm_connector *connector; |
323 | unsigned disable = 0; | ||
324 | 324 | ||
325 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { | 325 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
326 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); | 326 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
@@ -328,17 +328,17 @@ void rs600_hpd_fini(struct radeon_device *rdev) | |||
328 | case RADEON_HPD_1: | 328 | case RADEON_HPD_1: |
329 | WREG32(R_007D00_DC_HOT_PLUG_DETECT1_CONTROL, | 329 | WREG32(R_007D00_DC_HOT_PLUG_DETECT1_CONTROL, |
330 | S_007D00_DC_HOT_PLUG_DETECT1_EN(0)); | 330 | S_007D00_DC_HOT_PLUG_DETECT1_EN(0)); |
331 | rdev->irq.hpd[0] = false; | ||
332 | break; | 331 | break; |
333 | case RADEON_HPD_2: | 332 | case RADEON_HPD_2: |
334 | WREG32(R_007D10_DC_HOT_PLUG_DETECT2_CONTROL, | 333 | WREG32(R_007D10_DC_HOT_PLUG_DETECT2_CONTROL, |
335 | S_007D10_DC_HOT_PLUG_DETECT2_EN(0)); | 334 | S_007D10_DC_HOT_PLUG_DETECT2_EN(0)); |
336 | rdev->irq.hpd[1] = false; | ||
337 | break; | 335 | break; |
338 | default: | 336 | default: |
339 | break; | 337 | break; |
340 | } | 338 | } |
339 | disable |= 1 << radeon_connector->hpd.hpd; | ||
341 | } | 340 | } |
341 | radeon_irq_kms_disable_hpd(rdev, disable); | ||
342 | } | 342 | } |
343 | 343 | ||
344 | int rs600_asic_reset(struct radeon_device *rdev) | 344 | int rs600_asic_reset(struct radeon_device *rdev) |
@@ -686,7 +686,6 @@ int rs600_irq_process(struct radeon_device *rdev) | |||
686 | /* GUI idle */ | 686 | /* GUI idle */ |
687 | if (G_000040_GUI_IDLE(status)) { | 687 | if (G_000040_GUI_IDLE(status)) { |
688 | rdev->irq.gui_idle_acked = true; | 688 | rdev->irq.gui_idle_acked = true; |
689 | rdev->pm.gui_idle = true; | ||
690 | wake_up(&rdev->irq.idle_queue); | 689 | wake_up(&rdev->irq.idle_queue); |
691 | } | 690 | } |
692 | /* Vertical blank interrupts */ | 691 | /* Vertical blank interrupts */ |
diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index ecef972050d1..a65045bccaf6 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c | |||
@@ -3617,7 +3617,6 @@ restart_ih: | |||
3617 | break; | 3617 | break; |
3618 | case 233: /* GUI IDLE */ | 3618 | case 233: /* GUI IDLE */ |
3619 | DRM_DEBUG("IH: GUI idle\n"); | 3619 | DRM_DEBUG("IH: GUI idle\n"); |
3620 | rdev->pm.gui_idle = true; | ||
3621 | wake_up(&rdev->irq.idle_queue); | 3620 | wake_up(&rdev->irq.idle_queue); |
3622 | break; | 3621 | break; |
3623 | default: | 3622 | default: |