aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/radeon/r600.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/r600.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/r600.c')
-rw-r--r--drivers/gpu/drm/radeon/r600.c38
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
782void r600_hpd_fini(struct radeon_device *rdev) 774void 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: