>From 6de625e9c52ce4c8d8833de8f49cb97882c3c9d1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Michel=20D=C3=A4nzer?= <michel.daenzer@amd.com>
Date: Tue, 17 Jun 2014 16:33:16 +0900
Subject: [PATCH 1/3] drm/radeon: Only enable and handle pageflip interrupts
 when needed
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Prevents radeon_crtc_handle_flip() from running before
radeon_flip_work_func(), resulting in a kernel panic due to the BUG_ON()
in drm_vblank_put().

Signed-off-by: Michel D��nzer <michel.daenzer@amd.com>
---
 drivers/gpu/drm/radeon/cik.c       | 18 ++++++++++--------
 drivers/gpu/drm/radeon/evergreen.c | 18 ++++++++++--------
 drivers/gpu/drm/radeon/r600.c      | 12 ++++++++----
 drivers/gpu/drm/radeon/si.c        | 18 ++++++++++--------
 4 files changed, 38 insertions(+), 28 deletions(-)

diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c
index aea1478..228ccad 100644
--- a/drivers/gpu/drm/radeon/cik.c
+++ b/drivers/gpu/drm/radeon/cik.c
@@ -7136,21 +7136,21 @@ int cik_irq_set(struct radeon_device *rdev)
 
 	if (rdev->num_crtc >= 2) {
 		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET,
-		       GRPH_PFLIP_INT_MASK);
+		       atomic_read(&rdev->irq.pflip[0]) ? GRPH_PFLIP_INT_MASK : 0);
 		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET,
-		       GRPH_PFLIP_INT_MASK);
+		       atomic_read(&rdev->irq.pflip[1]) ? GRPH_PFLIP_INT_MASK : 0);
 	}
 	if (rdev->num_crtc >= 4) {
 		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET,
-		       GRPH_PFLIP_INT_MASK);
+		       atomic_read(&rdev->irq.pflip[2]) ? GRPH_PFLIP_INT_MASK : 0);
 		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET,
-		       GRPH_PFLIP_INT_MASK);
+		       atomic_read(&rdev->irq.pflip[3]) ? GRPH_PFLIP_INT_MASK : 0);
 	}
 	if (rdev->num_crtc >= 6) {
 		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET,
-		       GRPH_PFLIP_INT_MASK);
+		       atomic_read(&rdev->irq.pflip[4]) ? GRPH_PFLIP_INT_MASK : 0);
 		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET,
-		       GRPH_PFLIP_INT_MASK);
+		       atomic_read(&rdev->irq.pflip[5]) ? GRPH_PFLIP_INT_MASK : 0);
 	}
 
 	WREG32(DC_HPD1_INT_CONTROL, hpd1);
@@ -7602,8 +7602,10 @@ restart_ih:
 		case 14: /* D4 page flip */
 		case 16: /* D5 page flip */
 		case 18: /* D6 page flip */
-			DRM_DEBUG("IH: D%d flip\n", ((src_id - 8) >> 1) + 1);
-			radeon_crtc_handle_flip(rdev, (src_id - 8) >> 1);
+			src_id = (src_id - 8) >> 1;
+			DRM_DEBUG("IH: D%d flip\n", src_id + 1);
+			if (atomic_read(&rdev->irq.pflip[src_id]))
+				radeon_crtc_handle_flip(rdev, src_id);
 			break;
 		case 42: /* HPD hotplug */
 			switch (src_data) {
diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c
index 653eff8..0fa0d19 100644
--- a/drivers/gpu/drm/radeon/evergreen.c
+++ b/drivers/gpu/drm/radeon/evergreen.c
@@ -4538,20 +4538,20 @@ int evergreen_irq_set(struct radeon_device *rdev)
 	}
 
 	WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET,
-	       GRPH_PFLIP_INT_MASK);
+	       atomic_read(&rdev->irq.pflip[0]) ? GRPH_PFLIP_INT_MASK : 0);
 	WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET,
-	       GRPH_PFLIP_INT_MASK);
+	       atomic_read(&rdev->irq.pflip[1]) ? GRPH_PFLIP_INT_MASK : 0);
 	if (rdev->num_crtc >= 4) {
 		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET,
-		       GRPH_PFLIP_INT_MASK);
+		       atomic_read(&rdev->irq.pflip[2]) ? GRPH_PFLIP_INT_MASK : 0);
 		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET,
-		       GRPH_PFLIP_INT_MASK);
+		       atomic_read(&rdev->irq.pflip[3]) ? GRPH_PFLIP_INT_MASK : 0);
 	}
 	if (rdev->num_crtc >= 6) {
 		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET,
-		       GRPH_PFLIP_INT_MASK);
+		       atomic_read(&rdev->irq.pflip[4]) ? GRPH_PFLIP_INT_MASK : 0);
 		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET,
-		       GRPH_PFLIP_INT_MASK);
+		       atomic_read(&rdev->irq.pflip[5]) ? GRPH_PFLIP_INT_MASK : 0);
 	}
 
 	WREG32(DC_HPD1_INT_CONTROL, hpd1);
@@ -4946,8 +4946,10 @@ restart_ih:
 		case 14: /* D4 page flip */
 		case 16: /* D5 page flip */
 		case 18: /* D6 page flip */
-			DRM_DEBUG("IH: D%d flip\n", ((src_id - 8) >> 1) + 1);
-			radeon_crtc_handle_flip(rdev, (src_id - 8) >> 1);
+			src_id = (src_id - 8) >> 1;
+			DRM_DEBUG("IH: D%d flip\n", src_id + 1);
+			if (atomic_read(&rdev->irq.pflip[src_id]))
+				radeon_crtc_handle_flip(rdev, src_id);
 			break;
 		case 42: /* HPD hotplug */
 			switch (src_data) {
diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c
index c758812..8fa171c 100644
--- a/drivers/gpu/drm/radeon/r600.c
+++ b/drivers/gpu/drm/radeon/r600.c
@@ -3614,8 +3614,10 @@ int r600_irq_set(struct radeon_device *rdev)
 	WREG32(CP_INT_CNTL, cp_int_cntl);
 	WREG32(DMA_CNTL, dma_cntl);
 	WREG32(DxMODE_INT_MASK, mode_int);
-	WREG32(D1GRPH_INTERRUPT_CONTROL, DxGRPH_PFLIP_INT_MASK);
-	WREG32(D2GRPH_INTERRUPT_CONTROL, DxGRPH_PFLIP_INT_MASK);
+	WREG32(D1GRPH_INTERRUPT_CONTROL,
+	       atomic_read(&rdev->irq.pflip[0]) ? DxGRPH_PFLIP_INT_MASK : 0);
+	WREG32(D2GRPH_INTERRUPT_CONTROL,
+	       atomic_read(&rdev->irq.pflip[1]) ? DxGRPH_PFLIP_INT_MASK : 0);
 	WREG32(GRBM_INT_CNTL, grbm_int_cntl);
 	if (ASIC_IS_DCE3(rdev)) {
 		WREG32(DC_HPD1_INT_CONTROL, hpd1);
@@ -3920,11 +3922,13 @@ restart_ih:
 			break;
 		case 9: /* D1 pflip */
 			DRM_DEBUG("IH: D1 flip\n");
-			radeon_crtc_handle_flip(rdev, 0);
+			if (atomic_read(&rdev->irq.pflip[0]))
+				radeon_crtc_handle_flip(rdev, 0);
 			break;
 		case 11: /* D2 pflip */
 			DRM_DEBUG("IH: D2 flip\n");
-			radeon_crtc_handle_flip(rdev, 1);
+			if (atomic_read(&rdev->irq.pflip[1]))
+				radeon_crtc_handle_flip(rdev, 1);
 			break;
 		case 19: /* HPD/DAC hotplug */
 			switch (src_data) {
diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c
index c128bde..5d37ea5 100644
--- a/drivers/gpu/drm/radeon/si.c
+++ b/drivers/gpu/drm/radeon/si.c
@@ -5919,21 +5919,21 @@ int si_irq_set(struct radeon_device *rdev)
 
 	if (rdev->num_crtc >= 2) {
 		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET,
-		       GRPH_PFLIP_INT_MASK);
+		       atomic_read(&rdev->irq.pflip[0]) ? GRPH_PFLIP_INT_MASK : 0);
 		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET,
-		       GRPH_PFLIP_INT_MASK);
+		       atomic_read(&rdev->irq.pflip[1]) ? GRPH_PFLIP_INT_MASK : 0);
 	}
 	if (rdev->num_crtc >= 4) {
 		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET,
-		       GRPH_PFLIP_INT_MASK);
+		       atomic_read(&rdev->irq.pflip[2]) ? GRPH_PFLIP_INT_MASK : 0);
 		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET,
-		       GRPH_PFLIP_INT_MASK);
+		       atomic_read(&rdev->irq.pflip[3]) ? GRPH_PFLIP_INT_MASK : 0);
 	}
 	if (rdev->num_crtc >= 6) {
 		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET,
-		       GRPH_PFLIP_INT_MASK);
+		       atomic_read(&rdev->irq.pflip[4]) ? GRPH_PFLIP_INT_MASK : 0);
 		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET,
-		       GRPH_PFLIP_INT_MASK);
+		       atomic_read(&rdev->irq.pflip[5]) ? GRPH_PFLIP_INT_MASK : 0);
 	}
 
 	if (!ASIC_IS_NODCE(rdev)) {
@@ -6303,8 +6303,10 @@ restart_ih:
 		case 14: /* D4 page flip */
 		case 16: /* D5 page flip */
 		case 18: /* D6 page flip */
-			DRM_DEBUG("IH: D%d flip\n", ((src_id - 8) >> 1) + 1);
-			radeon_crtc_handle_flip(rdev, (src_id - 8) >> 1);
+			src_id = (src_id - 8) >> 1;
+			DRM_DEBUG("IH: D%d flip\n", src_id + 1);
+			if (atomic_read(&rdev->irq.pflip[src_id]))
+				radeon_crtc_handle_flip(rdev, src_id);
 			break;
 		case 42: /* HPD hotplug */
 			switch (src_data) {
-- 
2.0.0

