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/r600.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/r600.c')
-rw-r--r-- | drivers/gpu/drm/radeon/r600.c | 38 |
1 files changed, 10 insertions, 28 deletions
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: |