All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/2] drm/radeon: Only enable and handle pageflip interrupts when needed
@ 2014-06-26  9:29 Michel Dänzer
  2014-06-26  9:29 ` [PATCH 2/2] drm/radeon: Track the status of a page flip more explicitly Michel Dänzer
  2014-06-26 10:39 ` [PATCH 1/2] drm/radeon: Only enable and handle pageflip interrupts when needed Christian König
  0 siblings, 2 replies; 34+ messages in thread
From: Michel Dänzer @ 2014-06-26  9:29 UTC (permalink / raw)
  To: dri-devel

From: Michel Dänzer <michel.daenzer@amd.com>

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().

Tested-by: Dieter Nützel <Dieter@nuetzel-hh.de>
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 0f4b38f..7f522a4 100644
--- a/drivers/gpu/drm/radeon/cik.c
+++ b/drivers/gpu/drm/radeon/cik.c
@@ -7145,21 +7145,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);
@@ -7611,8 +7611,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 0443183..fa6e320 100644
--- a/drivers/gpu/drm/radeon/evergreen.c
+++ b/drivers/gpu/drm/radeon/evergreen.c
@@ -4542,20 +4542,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);
@@ -4950,8 +4950,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 ae54f76..2f9a2af 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

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH 2/2] drm/radeon: Track the status of a page flip more explicitly
  2014-06-26  9:29 [PATCH 1/2] drm/radeon: Only enable and handle pageflip interrupts when needed Michel Dänzer
@ 2014-06-26  9:29 ` Michel Dänzer
  2014-06-30  9:12   ` [PATCH v2] " Michel Dänzer
  2014-06-26 10:39 ` [PATCH 1/2] drm/radeon: Only enable and handle pageflip interrupts when needed Christian König
  1 sibling, 1 reply; 34+ messages in thread
From: Michel Dänzer @ 2014-06-26  9:29 UTC (permalink / raw)
  To: dri-devel

From: Michel Dänzer <michel.daenzer@amd.com>

This is another line of defence against the panic fixed by the previous
change, and should make the life cycle of a page flip clearer.

Tested-by: Dieter Nützel <Dieter@nuetzel-hh.de>
Signed-off-by: Michel Dänzer <michel.daenzer@amd.com>
---
 drivers/gpu/drm/radeon/radeon_display.c | 19 ++++++++++++++-----
 drivers/gpu/drm/radeon/radeon_mode.h    |  7 +++++++
 2 files changed, 21 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c
index 8b575a4..65882cd 100644
--- a/drivers/gpu/drm/radeon/radeon_display.c
+++ b/drivers/gpu/drm/radeon/radeon_display.c
@@ -284,7 +284,6 @@ static void radeon_unpin_work_func(struct work_struct *__work)
 void radeon_crtc_handle_vblank(struct radeon_device *rdev, int crtc_id)
 {
 	struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];
-	struct radeon_flip_work *work;
 	unsigned long flags;
 	u32 update_pending;
 	int vpos, hpos;
@@ -294,8 +293,11 @@ void radeon_crtc_handle_vblank(struct radeon_device *rdev, int crtc_id)
 		return;
 
 	spin_lock_irqsave(&rdev->ddev->event_lock, flags);
-	work = radeon_crtc->flip_work;
-	if (work == NULL) {
+	if (radeon_crtc->flip_status != RADEON_FLIP_SUBMITTED) {
+		DRM_DEBUG_DRIVER("radeon_crtc->flip_status = %d != "
+				 "RADEON_FLIP_SUBMITTED(%d)\n",
+				 radeon_crtc->flip_status,
+				 RADEON_FLIP_SUBMITTED);
 		spin_unlock_irqrestore(&rdev->ddev->event_lock, flags);
 		return;
 	}
@@ -343,12 +345,17 @@ void radeon_crtc_handle_flip(struct radeon_device *rdev, int crtc_id)
 
 	spin_lock_irqsave(&rdev->ddev->event_lock, flags);
 	work = radeon_crtc->flip_work;
-	if (work == NULL) {
+	if (radeon_crtc->flip_status != RADEON_FLIP_SUBMITTED) {
+		DRM_DEBUG_DRIVER("radeon_crtc->flip_status = %d != "
+				 "RADEON_FLIP_SUBMITTED(%d)\n",
+				 radeon_crtc->flip_status,
+				 RADEON_FLIP_SUBMITTED);
 		spin_unlock_irqrestore(&rdev->ddev->event_lock, flags);
 		return;
 	}
 
 	/* Pageflip completed. Clean up. */
+	radeon_crtc->flip_status = RADEON_FLIP_NONE;
 	radeon_crtc->flip_work = NULL;
 
 	/* wakeup userspace */
@@ -475,6 +482,7 @@ static void radeon_flip_work_func(struct work_struct *__work)
 	/* do the flip (mmio) */
 	radeon_page_flip(rdev, radeon_crtc->crtc_id, base);
 
+	radeon_crtc->flip_status = RADEON_FLIP_SUBMITTED;
 	spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
 	up_read(&rdev->exclusive_lock);
 
@@ -543,7 +551,7 @@ static int radeon_crtc_page_flip(struct drm_crtc *crtc,
 	/* We borrow the event spin lock for protecting flip_work */
 	spin_lock_irqsave(&crtc->dev->event_lock, flags);
 
-	if (radeon_crtc->flip_work) {
+	if (radeon_crtc->flip_status != RADEON_FLIP_NONE) {
 		DRM_DEBUG_DRIVER("flip queue: crtc already busy\n");
 		spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
 		drm_gem_object_unreference_unlocked(&work->old_rbo->gem_base);
@@ -551,6 +559,7 @@ static int radeon_crtc_page_flip(struct drm_crtc *crtc,
 		kfree(work);
 		return -EBUSY;
 	}
+	radeon_crtc->flip_status = RADEON_FLIP_PENDING;
 	radeon_crtc->flip_work = work;
 
 	/* update crtc fb */
diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h
index b59096f..ed6b6e0 100644
--- a/drivers/gpu/drm/radeon/radeon_mode.h
+++ b/drivers/gpu/drm/radeon/radeon_mode.h
@@ -301,6 +301,12 @@ struct radeon_atom_ss {
 	uint16_t amount;
 };
 
+enum radeon_flip_status {
+	RADEON_FLIP_NONE,
+	RADEON_FLIP_PENDING,
+	RADEON_FLIP_SUBMITTED
+};
+
 struct radeon_crtc {
 	struct drm_crtc base;
 	int crtc_id;
@@ -326,6 +332,7 @@ struct radeon_crtc {
 	/* page flipping */
 	struct workqueue_struct *flip_queue;
 	struct radeon_flip_work *flip_work;
+	enum radeon_flip_status flip_status;
 	/* pll sharing */
 	struct radeon_atom_ss ss;
 	bool ss_enabled;
-- 
2.0.0

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 34+ messages in thread

* Re: [PATCH 1/2] drm/radeon: Only enable and handle pageflip interrupts when needed
  2014-06-26  9:29 [PATCH 1/2] drm/radeon: Only enable and handle pageflip interrupts when needed Michel Dänzer
  2014-06-26  9:29 ` [PATCH 2/2] drm/radeon: Track the status of a page flip more explicitly Michel Dänzer
@ 2014-06-26 10:39 ` Christian König
  2014-06-26 11:51   ` Dieter Nützel
                     ` (2 more replies)
  1 sibling, 3 replies; 34+ messages in thread
From: Christian König @ 2014-06-26 10:39 UTC (permalink / raw)
  To: Michel Dänzer, dri-devel

Am 26.06.2014 11:29, schrieb Michel Dänzer:
> From: Michel Dänzer <michel.daenzer@amd.com>
>
> 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().
>
> Tested-by: Dieter Nützel <Dieter@nuetzel-hh.de>
> Signed-off-by: Michel Dänzer <michel.daenzer@amd.com>

Does patch #2 alone fixes the problem as well?

I would rather want to avoid turning the pflip interrupt on and off.

Christian.

> ---
>   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 0f4b38f..7f522a4 100644
> --- a/drivers/gpu/drm/radeon/cik.c
> +++ b/drivers/gpu/drm/radeon/cik.c
> @@ -7145,21 +7145,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);
> @@ -7611,8 +7611,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 0443183..fa6e320 100644
> --- a/drivers/gpu/drm/radeon/evergreen.c
> +++ b/drivers/gpu/drm/radeon/evergreen.c
> @@ -4542,20 +4542,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);
> @@ -4950,8 +4950,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 ae54f76..2f9a2af 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) {

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH 1/2] drm/radeon: Only enable and handle pageflip interrupts when needed
  2014-06-26 10:39 ` [PATCH 1/2] drm/radeon: Only enable and handle pageflip interrupts when needed Christian König
@ 2014-06-26 11:51   ` Dieter Nützel
  2014-06-27  0:53   ` Dieter Nützel
  2014-06-27  2:58   ` Michel Dänzer
  2 siblings, 0 replies; 34+ messages in thread
From: Dieter Nützel @ 2014-06-26 11:51 UTC (permalink / raw)
  To: Christian König; +Cc: Michel Dänzer, dri-devel

Am 26.06.2014 12:39, schrieb Christian König:
> Am 26.06.2014 11:29, schrieb Michel Dänzer:
>> From: Michel Dänzer <michel.daenzer@amd.com>
>> 
>> 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().
>> 
>> Tested-by: Dieter Nützel <Dieter@nuetzel-hh.de>
>> Signed-off-by: Michel Dänzer <michel.daenzer@amd.com>
> 
> Does patch #2 alone fixes the problem as well?
> 
> I would rather want to avoid turning the pflip interrupt on and off.
> 
> Christian.

Christian,

I'll try for you after the doctor (my wife and I are sick over the last 
several weeks(!) ;-() and before 'Fußball' ;-)))
--- That's why I'm on the 'hobel' that much and not in our forest, 
etc...
But our two children are OK...

All the above is my 'new/second' life...
...before that I've studied computer science with medicine as second 
part and had a deeper look into medical imagery.

Cheers,
    Dieter

>> ---
>>   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 0f4b38f..7f522a4 100644
>> --- a/drivers/gpu/drm/radeon/cik.c
>> +++ b/drivers/gpu/drm/radeon/cik.c
>> @@ -7145,21 +7145,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);
>> @@ -7611,8 +7611,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 0443183..fa6e320 100644
>> --- a/drivers/gpu/drm/radeon/evergreen.c
>> +++ b/drivers/gpu/drm/radeon/evergreen.c
>> @@ -4542,20 +4542,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);
>> @@ -4950,8 +4950,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 ae54f76..2f9a2af 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) {
> 
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH 1/2] drm/radeon: Only enable and handle pageflip interrupts when needed
  2014-06-26 10:39 ` [PATCH 1/2] drm/radeon: Only enable and handle pageflip interrupts when needed Christian König
  2014-06-26 11:51   ` Dieter Nützel
@ 2014-06-27  0:53   ` Dieter Nützel
  2014-06-27  1:03     ` Michel Dänzer
  2014-06-27  2:58   ` Michel Dänzer
  2 siblings, 1 reply; 34+ messages in thread
From: Dieter Nützel @ 2014-06-27  0:53 UTC (permalink / raw)
  To: Christian König; +Cc: Michel Dänzer, dri-devel

[-- Attachment #1: Type: text/plain, Size: 10175 bytes --]

Am 26.06.2014 12:39, schrieb Christian König:
> Am 26.06.2014 11:29, schrieb Michel Dänzer:
>> From: Michel Dänzer <michel.daenzer@amd.com>
>> 
>> 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().
>> 
>> Tested-by: Dieter Nützel <Dieter@nuetzel-hh.de>
>> Signed-off-by: Michel Dänzer <michel.daenzer@amd.com>
> 
> Does patch #2 alone fixes the problem as well?

With #2 alone I get this during boot up (before plymouth):

[   11.942342] [drm] fb depth is 24
[   11.942344] [drm]    pitch is 7680
[   11.942739] fbcon: radeondrmfb (fb0) is primary device
[   11.943090] [drm:radeon_crtc_handle_flip] *ERROR* 
radeon_crtc->flip_status = 0 != RADEON_FLIP_SUBMITTED(2)
[   11.943912] Console: switching to colour frame buffer device 240x67
[   11.995623] radeon 0000:01:00.0: fb0: radeondrmfb frame buffer device
[   11.995628] radeon 0000:01:00.0: registered panic notifier
[   11.998112] [drm] Initialized radeon 2.39.0 20080528 for 0000:01:00.0 
on minor 0
[   15.259867] [drm:radeon_crtc_handle_flip] *ERROR* 
radeon_crtc->flip_status = 0 != RADEON_FLIP_SUBMITTED(2)

And during X / KDE start, again:

[   30.960442] [drm:radeon_crtc_handle_flip] *ERROR* 
radeon_crtc->flip_status = 0 != RADEON_FLIP_SUBMITTED(2)
[   31.343925] [drm:radeon_crtc_handle_flip] *ERROR* 
radeon_crtc->flip_status = 0 != RADEON_FLIP_SUBMITTED(2)
[   37.687138] [drm:radeon_crtc_handle_flip] *ERROR* 
radeon_crtc->flip_status = 0 != RADEON_FLIP_SUBMITTED(2)
[  187.005621] [drm:radeon_crtc_handle_flip] *ERROR* 
radeon_crtc->flip_status = 0 != RADEON_FLIP_SUBMITTED(2)

Much more in dmesg.
(See dmesg-3.16-rc2-Michel-2.xz)

But with Michel's #1+2 and 3 I got this in Xorg.0.log:
(See Xorg.0.log.old.xz)

(EE) [mi] EQ overflowing.  Additional events will be discarded until 
existing events are processed.
(EE)
(EE) Backtrace:

> I would rather want to avoid turning the pflip interrupt on and off.

I'm under the impression, that #2 alone is more responsive, but.

Sorry, after Fußball ;-)

Dieter

>> ---
>>   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 0f4b38f..7f522a4 100644
>> --- a/drivers/gpu/drm/radeon/cik.c
>> +++ b/drivers/gpu/drm/radeon/cik.c
>> @@ -7145,21 +7145,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);
>> @@ -7611,8 +7611,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 0443183..fa6e320 100644
>> --- a/drivers/gpu/drm/radeon/evergreen.c
>> +++ b/drivers/gpu/drm/radeon/evergreen.c
>> @@ -4542,20 +4542,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);
>> @@ -4950,8 +4950,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 ae54f76..2f9a2af 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) {
> 
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel

[-- Attachment #2: dmesg-3.16-rc2-Michel-2.xz --]
[-- Type: application/x-xz, Size: 14348 bytes --]

[-- Attachment #3: Xorg.0.log.old.xz --]
[-- Type: application/x-xz, Size: 9500 bytes --]

[-- Attachment #4: Type: text/plain, Size: 159 bytes --]

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH 1/2] drm/radeon: Only enable and handle pageflip interrupts when needed
  2014-06-27  0:53   ` Dieter Nützel
@ 2014-06-27  1:03     ` Michel Dänzer
  2014-06-27  1:08       ` Dieter Nützel
  2014-06-27  2:06       ` Dieter Nützel
  0 siblings, 2 replies; 34+ messages in thread
From: Michel Dänzer @ 2014-06-27  1:03 UTC (permalink / raw)
  To: Dieter Nützel, Christian König; +Cc: dri-devel

On 27.06.2014 09:53, Dieter Nützel wrote:
> Am 26.06.2014 12:39, schrieb Christian König:
>> Am 26.06.2014 11:29, schrieb Michel Dänzer:
>>> From: Michel Dänzer <michel.daenzer@amd.com>
>>>
>>> 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().
>>>
>>> Tested-by: Dieter Nützel <Dieter@nuetzel-hh.de>
>>> Signed-off-by: Michel Dänzer <michel.daenzer@amd.com>
>>
>> Does patch #2 alone fixes the problem as well?
> 
> With #2 alone I get this during boot up (before plymouth):

[...]

> [   15.259867] [drm:radeon_crtc_handle_flip] *ERROR*
> radeon_crtc->flip_status = 0 != RADEON_FLIP_SUBMITTED(2)

That's the original patch I sent to you along with two others for
testing. The patch I submitted in this series has these messages
downgraded to debugging messages, as they just show the patch preventing
bad stuff from happening as designed.

The question is, can you reproduce the panic or the 'impossible msc'
lines in the Xorg log with only patch #2?


> But with Michel's #1+2 and 3 I got this in Xorg.0.log:
> (See Xorg.0.log.old.xz)
> 
> (EE) [mi] EQ overflowing.  Additional events will be discarded until
> existing events are processed.

That may not be directly related to the page flipping issues.


-- 
Earthling Michel Dänzer            |                  http://www.amd.com
Libre software enthusiast          |                Mesa and X developer

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH 1/2] drm/radeon: Only enable and handle pageflip interrupts when needed
  2014-06-27  1:03     ` Michel Dänzer
@ 2014-06-27  1:08       ` Dieter Nützel
  2014-06-27  2:06       ` Dieter Nützel
  1 sibling, 0 replies; 34+ messages in thread
From: Dieter Nützel @ 2014-06-27  1:08 UTC (permalink / raw)
  To: Michel Dänzer; +Cc: dri-devel

Am 27.06.2014 03:03, schrieb Michel Dänzer:
> On 27.06.2014 09:53, Dieter Nützel wrote:
>> Am 26.06.2014 12:39, schrieb Christian König:
>>> Am 26.06.2014 11:29, schrieb Michel Dänzer:
>>>> From: Michel Dänzer <michel.daenzer@amd.com>
>>>> 
>>>> 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().
>>>> 
>>>> Tested-by: Dieter Nützel <Dieter@nuetzel-hh.de>
>>>> Signed-off-by: Michel Dänzer <michel.daenzer@amd.com>
>>> 
>>> Does patch #2 alone fixes the problem as well?
>> 
>> With #2 alone I get this during boot up (before plymouth):
> 
> [...]
> 
>> [   15.259867] [drm:radeon_crtc_handle_flip] *ERROR*
>> radeon_crtc->flip_status = 0 != RADEON_FLIP_SUBMITTED(2)
> 
> That's the original patch I sent to you along with two others for
> testing. The patch I submitted in this series has these messages
> downgraded to debugging messages, as they just show the patch 
> preventing
> bad stuff from happening as designed.
> 
> The question is, can you reproduce the panic or the 'impossible msc'
> lines in the Xorg log with only patch #2?

Oh, shit sorry.
I'll redo in a minute before I went to bed!

-Dieter

>> But with Michel's #1+2 and 3 I got this in Xorg.0.log:
>> (See Xorg.0.log.old.xz)
>> 
>> (EE) [mi] EQ overflowing.  Additional events will be discarded until
>> existing events are processed.
> 
> That may not be directly related to the page flipping issues.
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH 1/2] drm/radeon: Only enable and handle pageflip interrupts when needed
  2014-06-27  1:03     ` Michel Dänzer
  2014-06-27  1:08       ` Dieter Nützel
@ 2014-06-27  2:06       ` Dieter Nützel
  2014-06-27  3:03         ` Michel Dänzer
  1 sibling, 1 reply; 34+ messages in thread
From: Dieter Nützel @ 2014-06-27  2:06 UTC (permalink / raw)
  To: Michel Dänzer; +Cc: dri-devel

Am 27.06.2014 03:03, schrieb Michel Dänzer:
> On 27.06.2014 09:53, Dieter Nützel wrote:
>> Am 26.06.2014 12:39, schrieb Christian König:
>>> Am 26.06.2014 11:29, schrieb Michel Dänzer:
>>>> From: Michel Dänzer <michel.daenzer@amd.com>
>>>> 
>>>> 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().
>>>> 
>>>> Tested-by: Dieter Nützel <Dieter@nuetzel-hh.de>
>>>> Signed-off-by: Michel Dänzer <michel.daenzer@amd.com>
>>> 
>>> Does patch #2 alone fixes the problem as well?
>> 
>> With #2 alone I get this during boot up (before plymouth):
> 
> [...]
> 
>> [   15.259867] [drm:radeon_crtc_handle_flip] *ERROR*
>> radeon_crtc->flip_status = 0 != RADEON_FLIP_SUBMITTED(2)
> 
> That's the original patch I sent to you along with two others for
> testing. The patch I submitted in this series has these messages
> downgraded to debugging messages, as they just show the patch 
> preventing
> bad stuff from happening as designed.
> 
> The question is, can you reproduce the panic or the 'impossible msc'
> lines in the Xorg log with only patch #2?

Here we go (the 'new' #2 alone):

For the panic I need more time.
But the first 'impossible msc' line arise during X start:

[    80.271] (II) RADEON(0): Modeline "1680x1050"x0.0  119.00  1680 1728 
1760 1840  1050 1053 1059 1080 +hsync -vsync (64.7 kHz e)
[    80.271] (II) RADEON(0): Modeline "1920x1080"x60.0  172.80  1920 
2040 2248 2576  1080 1081 1084 1118 -hsync +vsync (67.1 kHz e)
[   100.246] (WW) RADEON(0): radeon_dri2_flip_event_handler: Pageflip 
completion event has impossible msc 5302 < target_msc 5303

Some arise with KWin cube effects.

[  1059.124] (WW) RADEON(0): radeon_dri2_flip_event_handler: Pageflip 
completion event has impossible msc 62948 < target_msc 62949
[  1067.223] (WW) RADEON(0): radeon_dri2_flip_event_handler: Pageflip 
completion event has impossible msc 63435 < target_msc 63436
[  1081.458] (WW) RADEON(0): radeon_dri2_flip_event_handler: Pageflip 
completion event has impossible msc 64290 < target_msc 64291
[  1233.165] (WW) RADEON(0): radeon_dri2_flip_event_handler: Pageflip 
completion event has impossible msc 73416 < target_msc 73417
[  1233.515] (WW) RADEON(0): radeon_dri2_flip_event_handler: Pageflip 
completion event has impossible msc 73437 < target_msc 73438
[  1234.330] (WW) RADEON(0): radeon_dri2_flip_event_handler: Pageflip 
completion event has impossible msc 73486 < target_msc 73487
[  1235.079] (WW) RADEON(0): radeon_dri2_flip_event_handler: Pageflip 
completion event has impossible msc 73531 < target_msc 73532

Sleep well!

-Dieter

>> But with Michel's #1+2 and 3 I got this in Xorg.0.log:
>> (See Xorg.0.log.old.xz)
>> 
>> (EE) [mi] EQ overflowing.  Additional events will be discarded until
>> existing events are processed.
> 
> That may not be directly related to the page flipping issues.
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH 1/2] drm/radeon: Only enable and handle pageflip interrupts when needed
  2014-06-26 10:39 ` [PATCH 1/2] drm/radeon: Only enable and handle pageflip interrupts when needed Christian König
  2014-06-26 11:51   ` Dieter Nützel
  2014-06-27  0:53   ` Dieter Nützel
@ 2014-06-27  2:58   ` Michel Dänzer
  2014-06-27  8:18     ` Christian König
  2 siblings, 1 reply; 34+ messages in thread
From: Michel Dänzer @ 2014-06-27  2:58 UTC (permalink / raw)
  To: Christian König; +Cc: dri-devel

On 26.06.2014 19:39, Christian König wrote:
> Am 26.06.2014 11:29, schrieb Michel Dänzer:
>> From: Michel Dänzer <michel.daenzer@amd.com>
>>
>> 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().
>>
>> Tested-by: Dieter Nützel <Dieter@nuetzel-hh.de>
>> Signed-off-by: Michel Dänzer <michel.daenzer@amd.com>
> 
> Does patch #2 alone fixes the problem as well?

It should avoid the panic as well.


> I would rather want to avoid turning the pflip interrupt on and off.

What's the problem with that? It's not like we're saving any register
writes by not doing it.

The diagnostic messages Dieter was getting with only patch #2 show that
the pflip interrupt often triggers unnecessarily, potentially wasting
power by waking up the CPU from a power saving state pointlessly.


-- 
Earthling Michel Dänzer            |                  http://www.amd.com
Libre software enthusiast          |                Mesa and X developer
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH 1/2] drm/radeon: Only enable and handle pageflip interrupts when needed
  2014-06-27  2:06       ` Dieter Nützel
@ 2014-06-27  3:03         ` Michel Dänzer
  2014-06-27  3:17           ` Michel Dänzer
  0 siblings, 1 reply; 34+ messages in thread
From: Michel Dänzer @ 2014-06-27  3:03 UTC (permalink / raw)
  To: Dieter Nützel; +Cc: dri-devel

On 27.06.2014 11:06, Dieter Nützel wrote:
> Am 27.06.2014 03:03, schrieb Michel Dänzer:
>> 
>> The question is, can you reproduce the panic or the 'impossible msc'
>> lines in the Xorg log with only patch #2?
> 
> Here we go (the 'new' #2 alone):
> 
> For the panic I need more time.
> But the first 'impossible msc' line arise during X start:
> 
> [    80.271] (II) RADEON(0): Modeline "1680x1050"x0.0  119.00  1680 1728
> 1760 1840  1050 1053 1059 1080 +hsync -vsync (64.7 kHz e)
> [    80.271] (II) RADEON(0): Modeline "1920x1080"x60.0  172.80  1920
> 2040 2248 2576  1080 1081 1084 1118 -hsync +vsync (67.1 kHz e)
> [   100.246] (WW) RADEON(0): radeon_dri2_flip_event_handler: Pageflip
> completion event has impossible msc 5302 < target_msc 5303
> 
> Some arise with KWin cube effects.

Once you've confirmed patch #2 alone avoids the panic, can you try if
adding patch #1 again avoids the 'impossible msc' lines as well?


-- 
Earthling Michel Dänzer            |                  http://www.amd.com
Libre software enthusiast          |                Mesa and X developer
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH 1/2] drm/radeon: Only enable and handle pageflip interrupts when needed
  2014-06-27  3:03         ` Michel Dänzer
@ 2014-06-27  3:17           ` Michel Dänzer
  0 siblings, 0 replies; 34+ messages in thread
From: Michel Dänzer @ 2014-06-27  3:17 UTC (permalink / raw)
  To: Dieter Nützel; +Cc: dri-devel

On 27.06.2014 12:03, Michel Dänzer wrote:
> On 27.06.2014 11:06, Dieter Nützel wrote:
>> Am 27.06.2014 03:03, schrieb Michel Dänzer:
>>>
>>> The question is, can you reproduce the panic or the 'impossible msc'
>>> lines in the Xorg log with only patch #2?
>>
>> Here we go (the 'new' #2 alone):
>>
>> For the panic I need more time.
>> But the first 'impossible msc' line arise during X start:
>>
>> [    80.271] (II) RADEON(0): Modeline "1680x1050"x0.0  119.00  1680 1728
>> 1760 1840  1050 1053 1059 1080 +hsync -vsync (64.7 kHz e)
>> [    80.271] (II) RADEON(0): Modeline "1920x1080"x60.0  172.80  1920
>> 2040 2248 2576  1080 1081 1084 1118 -hsync +vsync (67.1 kHz e)
>> [   100.246] (WW) RADEON(0): radeon_dri2_flip_event_handler: Pageflip
>> completion event has impossible msc 5302 < target_msc 5303
>>
>> Some arise with KWin cube effects.
> 
> Once you've confirmed patch #2 alone avoids the panic, can you try if
> adding patch #1 again avoids the 'impossible msc' lines as well?

Never mind, I was able to reproduce them with both patches.


-- 
Earthling Michel Dänzer            |                  http://www.amd.com
Libre software enthusiast          |                Mesa and X developer
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH 1/2] drm/radeon: Only enable and handle pageflip interrupts when needed
  2014-06-27  2:58   ` Michel Dänzer
@ 2014-06-27  8:18     ` Christian König
  2014-06-27  9:44       ` Michel Dänzer
  0 siblings, 1 reply; 34+ messages in thread
From: Christian König @ 2014-06-27  8:18 UTC (permalink / raw)
  To: Michel Dänzer; +Cc: dri-devel

Am 27.06.2014 04:58, schrieb Michel Dänzer:
> On 26.06.2014 19:39, Christian König wrote:
>> Am 26.06.2014 11:29, schrieb Michel Dänzer:
>>> From: Michel Dänzer <michel.daenzer@amd.com>
>>>
>>> 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().
>>>
>>> Tested-by: Dieter Nützel <Dieter@nuetzel-hh.de>
>>> Signed-off-by: Michel Dänzer <michel.daenzer@amd.com>
>> Does patch #2 alone fixes the problem as well?
> It should avoid the panic as well.
>
>
>> I would rather want to avoid turning the pflip interrupt on and off.
> What's the problem with that? It's not like we're saving any register
> writes by not doing it.

We don't? As far as I can see we reprogram all interrupt registers if 
any of the interrupts changed, this has already lead to quite some 
additional overhead in the fence waiting code.

>
> The diagnostic messages Dieter was getting with only patch #2 show that
> the pflip interrupt often triggers unnecessarily, potentially wasting
> power by waking up the CPU from a power saving state pointlessly.
That's a really good point, but my question would rather be why does the 
pflip interrupt fires if there isn't any pflip?

Turning the vblank and other interrupts off makes sense because they 
fire anyway, but pflip should only fire if we really made a request for 
it to do so.

Regards,
Christian.
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH 1/2] drm/radeon: Only enable and handle pageflip interrupts when needed
  2014-06-27  8:18     ` Christian König
@ 2014-06-27  9:44       ` Michel Dänzer
  2014-06-27 10:47         ` Christian König
  0 siblings, 1 reply; 34+ messages in thread
From: Michel Dänzer @ 2014-06-27  9:44 UTC (permalink / raw)
  To: Christian König; +Cc: dri-devel

On 27.06.2014 17:18, Christian König wrote:
> Am 27.06.2014 04:58, schrieb Michel Dänzer:
>> On 26.06.2014 19:39, Christian König wrote:
>>> Am 26.06.2014 11:29, schrieb Michel Dänzer:
>>>> From: Michel Dänzer <michel.daenzer@amd.com>
>>>> 
>>>> 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().
>>>> 
>>>> Tested-by: Dieter Nützel <Dieter@nuetzel-hh.de> Signed-off-by:
>>>> Michel Dänzer <michel.daenzer@amd.com>
>>> Does patch #2 alone fixes the problem as well?
>> It should avoid the panic as well.
>> 
>> 
>>> I would rather want to avoid turning the pflip interrupt on and
>>> off.
>> What's the problem with that? It's not like we're saving any
>> register writes by not doing it.
> 
> We don't? As far as I can see we reprogram all interrupt registers
> if any of the interrupts changed,

Maybe I'm missing something, but: radeon_irq_kms_pflip_irq_get/put()
call radeon_irq_set() every time, as there can only be one active page
flip per CRTC. And radeon_irq_set() always writes the same registers,
only the bits it writes to them change depending on which interrupts the
driver is currently interested in.

> this has already lead to quite some additional overhead in the fence
> waiting code.

radeon_irq_set() should probably be split up to reduce the overhead.


>> The diagnostic messages Dieter was getting with only patch #2 show
>> that the pflip interrupt often triggers unnecessarily, potentially
>> wasting power by waking up the CPU from a power saving state
>> pointlessly.
> That's a really good point, but my question would rather be why does
> the pflip interrupt fires if there isn't any pflip?

There is a page flip, but it already completes in the vertical blank
interrupt handler in a lot of (most?) cases.

Which brings me back to the question: Do we really need the pflip
interrupt yet? [0] Since flips are no longer programmed to the hardware
in the vertical blank handler but in a work queue, is there actually
still any problem with handling the flip completion in the vertical
blank interrupt handler?

FWIW, by disabling the radeon_crtc_handle_flip() call from the pflip
interrupt handler, I no longer seem to be able to reproduce the
'impossible msc' lines in the Xorg log file.

[0] Of course the pflip interrupt will be needed for asynchronous flips,
but that doesn't mean we have to use it for all flips?


-- 
Earthling Michel Dänzer            |                  http://www.amd.com
Libre software enthusiast          |                Mesa and X developer
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH 1/2] drm/radeon: Only enable and handle pageflip interrupts when needed
  2014-06-27  9:44       ` Michel Dänzer
@ 2014-06-27 10:47         ` Christian König
  2014-06-30  9:34           ` Michel Dänzer
  0 siblings, 1 reply; 34+ messages in thread
From: Christian König @ 2014-06-27 10:47 UTC (permalink / raw)
  To: Michel Dänzer; +Cc: dri-devel

Am 27.06.2014 11:44, schrieb Michel Dänzer:
> On 27.06.2014 17:18, Christian König wrote:
>> Am 27.06.2014 04:58, schrieb Michel Dänzer:
>>> On 26.06.2014 19:39, Christian König wrote:
>>>> Am 26.06.2014 11:29, schrieb Michel Dänzer:
>>>>> From: Michel Dänzer <michel.daenzer@amd.com>
>>>>>
>>>>> 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().
>>>>>
>>>>> Tested-by: Dieter Nützel <Dieter@nuetzel-hh.de> Signed-off-by:
>>>>> Michel Dänzer <michel.daenzer@amd.com>
>>>> Does patch #2 alone fixes the problem as well?
>>> It should avoid the panic as well.
>>>
>>>
>>>> I would rather want to avoid turning the pflip interrupt on and
>>>> off.
>>> What's the problem with that? It's not like we're saving any
>>> register writes by not doing it.
>> We don't? As far as I can see we reprogram all interrupt registers
>> if any of the interrupts changed,
> Maybe I'm missing something, but: radeon_irq_kms_pflip_irq_get/put()
> call radeon_irq_set() every time, as there can only be one active page
> flip per CRTC. And radeon_irq_set() always writes the same registers,
> only the bits it writes to them change depending on which interrupts the
> driver is currently interested in.

We first turn on the vblank interrupt which results in a 
radeon_irq_set() and then turn on the pflip, which results in another 
radeon_irq_set() .

>
>> this has already lead to quite some additional overhead in the fence
>> waiting code.
> radeon_irq_set() should probably be split up to reduce the overhead.

Yeah, agree totally but didn't had time for this yet (it has a rather 
low priority). Might be a good task for someone to get his hands dirty 
on the kernel code for the first time as well.

I think turning interrupts on and off at each fence wait is the reason 
why inlining r100_mm_rreg and r100_mm_wreg again turned out to improve 
performance for some people quite a bit.

>>> The diagnostic messages Dieter was getting with only patch #2 show
>>> that the pflip interrupt often triggers unnecessarily, potentially
>>> wasting power by waking up the CPU from a power saving state
>>> pointlessly.
>> That's a really good point, but my question would rather be why does
>> the pflip interrupt fires if there isn't any pflip?
> There is a page flip, but it already completes in the vertical blank
> interrupt handler in a lot of (most?) cases.

The issue is still that as far as I understand it when the vblank 
interrupt fires the flip is actually not completed yet.

So we only don't see the pending bit high any more because of the 
minimal time between vblank fires and we check the bit.

The delay between vblank start and the flip being executed seemed to be 
depending on the pixel clock (which makes sense because the CRTC is 
driven by it), so when it might work ok for a 50Hz mode we can still run 
into problems with 24Hz modes.

> Which brings me back to the question: Do we really need the pflip
> interrupt yet? [0] Since flips are no longer programmed to the hardware
> in the vertical blank handler but in a work queue, is there actually
> still any problem with handling the flip completion in the vertical
> blank interrupt handler?

Good question, essentially we need to test with a TV capable of the 24Hz 
modes. I don't have the necessary hardware here and last time was only 
able to test this by torturing my poor HP monitor with a 24Hz modeline 
it actually couldn't handle.

> FWIW, by disabling the radeon_crtc_handle_flip() call from the pflip
> interrupt handler, I no longer seem to be able to reproduce the
> 'impossible msc' lines in the Xorg log file.

Good to know, that narrows down the scenario how this problem is triggered.

> [0] Of course the pflip interrupt will be needed for asynchronous flips,
> but that doesn't mean we have to use it for all flips?
It seemed to be the right thing for the job, but at this time I planned 
to use it exclusively and stop bothering with the vblank interrupt at all.

But then Alex noted that the pflip interrupt might be unreliable on 
older system and so I wanted to use the exiting vblank handling as 
backup. Now I'm not sure any more what's the best approach here.

Regards,
Christian.
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 34+ messages in thread

* [PATCH v2] drm/radeon: Track the status of a page flip more explicitly
  2014-06-26  9:29 ` [PATCH 2/2] drm/radeon: Track the status of a page flip more explicitly Michel Dänzer
@ 2014-06-30  9:12   ` Michel Dänzer
  2014-06-30  9:14     ` Christian König
  2014-07-01 16:23     ` Alex Deucher
  0 siblings, 2 replies; 34+ messages in thread
From: Michel Dänzer @ 2014-06-30  9:12 UTC (permalink / raw)
  To: dri-devel

From: Michel Dänzer <michel.daenzer@amd.com>

This prevents a panic: radeon_crtc_handle_page_flip() could run before
radeon_flip_work_func(), triggering the BUG_ON() in drm_vblank_put().

Tested-by: Dieter Nützel <Dieter@nuetzel-hh.de>
Signed-off-by: Michel Dänzer <michel.daenzer@amd.com>
---

v2: Update log message

 drivers/gpu/drm/radeon/radeon_display.c | 19 ++++++++++++++-----
 drivers/gpu/drm/radeon/radeon_mode.h    |  7 +++++++
 2 files changed, 21 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c
index 8b575a4..65882cd 100644
--- a/drivers/gpu/drm/radeon/radeon_display.c
+++ b/drivers/gpu/drm/radeon/radeon_display.c
@@ -284,7 +284,6 @@ static void radeon_unpin_work_func(struct work_struct *__work)
 void radeon_crtc_handle_vblank(struct radeon_device *rdev, int crtc_id)
 {
 	struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];
-	struct radeon_flip_work *work;
 	unsigned long flags;
 	u32 update_pending;
 	int vpos, hpos;
@@ -294,8 +293,11 @@ void radeon_crtc_handle_vblank(struct radeon_device *rdev, int crtc_id)
 		return;
 
 	spin_lock_irqsave(&rdev->ddev->event_lock, flags);
-	work = radeon_crtc->flip_work;
-	if (work == NULL) {
+	if (radeon_crtc->flip_status != RADEON_FLIP_SUBMITTED) {
+		DRM_DEBUG_DRIVER("radeon_crtc->flip_status = %d != "
+				 "RADEON_FLIP_SUBMITTED(%d)\n",
+				 radeon_crtc->flip_status,
+				 RADEON_FLIP_SUBMITTED);
 		spin_unlock_irqrestore(&rdev->ddev->event_lock, flags);
 		return;
 	}
@@ -343,12 +345,17 @@ void radeon_crtc_handle_flip(struct radeon_device *rdev, int crtc_id)
 
 	spin_lock_irqsave(&rdev->ddev->event_lock, flags);
 	work = radeon_crtc->flip_work;
-	if (work == NULL) {
+	if (radeon_crtc->flip_status != RADEON_FLIP_SUBMITTED) {
+		DRM_DEBUG_DRIVER("radeon_crtc->flip_status = %d != "
+				 "RADEON_FLIP_SUBMITTED(%d)\n",
+				 radeon_crtc->flip_status,
+				 RADEON_FLIP_SUBMITTED);
 		spin_unlock_irqrestore(&rdev->ddev->event_lock, flags);
 		return;
 	}
 
 	/* Pageflip completed. Clean up. */
+	radeon_crtc->flip_status = RADEON_FLIP_NONE;
 	radeon_crtc->flip_work = NULL;
 
 	/* wakeup userspace */
@@ -475,6 +482,7 @@ static void radeon_flip_work_func(struct work_struct *__work)
 	/* do the flip (mmio) */
 	radeon_page_flip(rdev, radeon_crtc->crtc_id, base);
 
+	radeon_crtc->flip_status = RADEON_FLIP_SUBMITTED;
 	spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
 	up_read(&rdev->exclusive_lock);
 
@@ -543,7 +551,7 @@ static int radeon_crtc_page_flip(struct drm_crtc *crtc,
 	/* We borrow the event spin lock for protecting flip_work */
 	spin_lock_irqsave(&crtc->dev->event_lock, flags);
 
-	if (radeon_crtc->flip_work) {
+	if (radeon_crtc->flip_status != RADEON_FLIP_NONE) {
 		DRM_DEBUG_DRIVER("flip queue: crtc already busy\n");
 		spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
 		drm_gem_object_unreference_unlocked(&work->old_rbo->gem_base);
@@ -551,6 +559,7 @@ static int radeon_crtc_page_flip(struct drm_crtc *crtc,
 		kfree(work);
 		return -EBUSY;
 	}
+	radeon_crtc->flip_status = RADEON_FLIP_PENDING;
 	radeon_crtc->flip_work = work;
 
 	/* update crtc fb */
diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h
index b59096f..ed6b6e0 100644
--- a/drivers/gpu/drm/radeon/radeon_mode.h
+++ b/drivers/gpu/drm/radeon/radeon_mode.h
@@ -301,6 +301,12 @@ struct radeon_atom_ss {
 	uint16_t amount;
 };
 
+enum radeon_flip_status {
+	RADEON_FLIP_NONE,
+	RADEON_FLIP_PENDING,
+	RADEON_FLIP_SUBMITTED
+};
+
 struct radeon_crtc {
 	struct drm_crtc base;
 	int crtc_id;
@@ -326,6 +332,7 @@ struct radeon_crtc {
 	/* page flipping */
 	struct workqueue_struct *flip_queue;
 	struct radeon_flip_work *flip_work;
+	enum radeon_flip_status flip_status;
 	/* pll sharing */
 	struct radeon_atom_ss ss;
 	bool ss_enabled;
-- 
2.0.0

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 34+ messages in thread

* Re: [PATCH v2] drm/radeon: Track the status of a page flip more explicitly
  2014-06-30  9:12   ` [PATCH v2] " Michel Dänzer
@ 2014-06-30  9:14     ` Christian König
  2014-07-01 16:23     ` Alex Deucher
  1 sibling, 0 replies; 34+ messages in thread
From: Christian König @ 2014-06-30  9:14 UTC (permalink / raw)
  To: Michel Dänzer, dri-devel

Am 30.06.2014 11:12, schrieb Michel Dänzer:
> From: Michel Dänzer <michel.daenzer@amd.com>
>
> This prevents a panic: radeon_crtc_handle_page_flip() could run before
> radeon_flip_work_func(), triggering the BUG_ON() in drm_vblank_put().
>
> Tested-by: Dieter Nützel <Dieter@nuetzel-hh.de>
> Signed-off-by: Michel Dänzer <michel.daenzer@amd.com>

Reviewed-by: Christian König <christian.koenig@amd.com>

> ---
>
> v2: Update log message
>
>   drivers/gpu/drm/radeon/radeon_display.c | 19 ++++++++++++++-----
>   drivers/gpu/drm/radeon/radeon_mode.h    |  7 +++++++
>   2 files changed, 21 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c
> index 8b575a4..65882cd 100644
> --- a/drivers/gpu/drm/radeon/radeon_display.c
> +++ b/drivers/gpu/drm/radeon/radeon_display.c
> @@ -284,7 +284,6 @@ static void radeon_unpin_work_func(struct work_struct *__work)
>   void radeon_crtc_handle_vblank(struct radeon_device *rdev, int crtc_id)
>   {
>   	struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];
> -	struct radeon_flip_work *work;
>   	unsigned long flags;
>   	u32 update_pending;
>   	int vpos, hpos;
> @@ -294,8 +293,11 @@ void radeon_crtc_handle_vblank(struct radeon_device *rdev, int crtc_id)
>   		return;
>   
>   	spin_lock_irqsave(&rdev->ddev->event_lock, flags);
> -	work = radeon_crtc->flip_work;
> -	if (work == NULL) {
> +	if (radeon_crtc->flip_status != RADEON_FLIP_SUBMITTED) {
> +		DRM_DEBUG_DRIVER("radeon_crtc->flip_status = %d != "
> +				 "RADEON_FLIP_SUBMITTED(%d)\n",
> +				 radeon_crtc->flip_status,
> +				 RADEON_FLIP_SUBMITTED);
>   		spin_unlock_irqrestore(&rdev->ddev->event_lock, flags);
>   		return;
>   	}
> @@ -343,12 +345,17 @@ void radeon_crtc_handle_flip(struct radeon_device *rdev, int crtc_id)
>   
>   	spin_lock_irqsave(&rdev->ddev->event_lock, flags);
>   	work = radeon_crtc->flip_work;
> -	if (work == NULL) {
> +	if (radeon_crtc->flip_status != RADEON_FLIP_SUBMITTED) {
> +		DRM_DEBUG_DRIVER("radeon_crtc->flip_status = %d != "
> +				 "RADEON_FLIP_SUBMITTED(%d)\n",
> +				 radeon_crtc->flip_status,
> +				 RADEON_FLIP_SUBMITTED);
>   		spin_unlock_irqrestore(&rdev->ddev->event_lock, flags);
>   		return;
>   	}
>   
>   	/* Pageflip completed. Clean up. */
> +	radeon_crtc->flip_status = RADEON_FLIP_NONE;
>   	radeon_crtc->flip_work = NULL;
>   
>   	/* wakeup userspace */
> @@ -475,6 +482,7 @@ static void radeon_flip_work_func(struct work_struct *__work)
>   	/* do the flip (mmio) */
>   	radeon_page_flip(rdev, radeon_crtc->crtc_id, base);
>   
> +	radeon_crtc->flip_status = RADEON_FLIP_SUBMITTED;
>   	spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
>   	up_read(&rdev->exclusive_lock);
>   
> @@ -543,7 +551,7 @@ static int radeon_crtc_page_flip(struct drm_crtc *crtc,
>   	/* We borrow the event spin lock for protecting flip_work */
>   	spin_lock_irqsave(&crtc->dev->event_lock, flags);
>   
> -	if (radeon_crtc->flip_work) {
> +	if (radeon_crtc->flip_status != RADEON_FLIP_NONE) {
>   		DRM_DEBUG_DRIVER("flip queue: crtc already busy\n");
>   		spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
>   		drm_gem_object_unreference_unlocked(&work->old_rbo->gem_base);
> @@ -551,6 +559,7 @@ static int radeon_crtc_page_flip(struct drm_crtc *crtc,
>   		kfree(work);
>   		return -EBUSY;
>   	}
> +	radeon_crtc->flip_status = RADEON_FLIP_PENDING;
>   	radeon_crtc->flip_work = work;
>   
>   	/* update crtc fb */
> diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h
> index b59096f..ed6b6e0 100644
> --- a/drivers/gpu/drm/radeon/radeon_mode.h
> +++ b/drivers/gpu/drm/radeon/radeon_mode.h
> @@ -301,6 +301,12 @@ struct radeon_atom_ss {
>   	uint16_t amount;
>   };
>   
> +enum radeon_flip_status {
> +	RADEON_FLIP_NONE,
> +	RADEON_FLIP_PENDING,
> +	RADEON_FLIP_SUBMITTED
> +};
> +
>   struct radeon_crtc {
>   	struct drm_crtc base;
>   	int crtc_id;
> @@ -326,6 +332,7 @@ struct radeon_crtc {
>   	/* page flipping */
>   	struct workqueue_struct *flip_queue;
>   	struct radeon_flip_work *flip_work;
> +	enum radeon_flip_status flip_status;
>   	/* pll sharing */
>   	struct radeon_atom_ss ss;
>   	bool ss_enabled;

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH 1/2] drm/radeon: Only enable and handle pageflip interrupts when needed
  2014-06-27 10:47         ` Christian König
@ 2014-06-30  9:34           ` Michel Dänzer
  2014-06-30 12:31             ` Christian König
  0 siblings, 1 reply; 34+ messages in thread
From: Michel Dänzer @ 2014-06-30  9:34 UTC (permalink / raw)
  To: Christian König; +Cc: dri-devel

On 27.06.2014 19:47, Christian König wrote:
> Am 27.06.2014 11:44, schrieb Michel Dänzer:
>> On 27.06.2014 17:18, Christian König wrote:
>>> Am 27.06.2014 04:58, schrieb Michel Dänzer:
>>>> On 26.06.2014 19:39, Christian König wrote:
>>>>> Am 26.06.2014 11:29, schrieb Michel Dänzer:
>>>>>> From: Michel Dänzer <michel.daenzer@amd.com>
>>>>>>
>>>>>> 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().
>>>>>>
>>>>>> Tested-by: Dieter Nützel <Dieter@nuetzel-hh.de> Signed-off-by:
>>>>>> Michel Dänzer <michel.daenzer@amd.com>
>>>>> Does patch #2 alone fixes the problem as well?
>>>> It should avoid the panic as well.

I've sent a v2 of that patch with an updated commit log. Alex, please get
that into 3.16 ASAP to prevent people from running into the panic.


>>>>> I would rather want to avoid turning the pflip interrupt on and
>>>>> off.
>>>> What's the problem with that? It's not like we're saving any
>>>> register writes by not doing it.
>>> We don't? As far as I can see we reprogram all interrupt registers
>>> if any of the interrupts changed,
>> Maybe I'm missing something, but: radeon_irq_kms_pflip_irq_get/put()
>> call radeon_irq_set() every time, as there can only be one active page
>> flip per CRTC. And radeon_irq_set() always writes the same registers,
>> only the bits it writes to them change depending on which interrupts the
>> driver is currently interested in.
> 
> We first turn on the vblank interrupt which results in a
> radeon_irq_set() and then turn on the pflip, which results in another
> radeon_irq_set() .

The DRM core delays disabling the hardware vblank interrupt, so
radeon_irq_set() should only be called once for that.

radeon_irq_kms_pflip_irq_get/put() always call radeon_irq_set() even before
my changes.


Anyway, for the issues surrounding the pflip interrupt, I took a step back
and considered a fundamentally different approach: It occurred to me that a
lot of the issues we've been struggling with are related to programming the
flips to the hardware such that they execute during the vertical blank
period. We don't know exactly when the hardware update happens or when would
be a good time to program the flip. So why bother with that at all?

The patch below (only fleshed out for CIK) moves the programming of the
flip to the hardware back to the vertical blank interrupt handler, but
changes it to execute during the horizontal blank period. In addition to
allowing the pflip interrupt handling, radeon_crtc_handle_vblank() and
radeon_flip_pending() to be removed, this should make adding support for
asynchronous flips trivial and support for replacing pending flips much
easier. What do you think?


> The delay between vblank start and the flip being executed seemed to be
> depending on the pixel clock (which makes sense because the CRTC is
> driven by it), so when it might work ok for a 50Hz mode we can still run
> into problems with 24Hz modes.

I couldn't see any tearing with this patch at 640x480 at 60 Hz and reduced
blanking, which should have a lower pixel clock and shorter vertical blank
period than 1920x1080 at 24 Hz?


commit 7b2861589f05c5c5c752108ce105161ebc0d6bf5
Author: Michel Dänzer <michel.daenzer@amd.com>
Date:   Mon Jun 30 17:57:01 2014 +0900

    drm/radeon: Program page flips to execute in hblank instead of vblank

diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c
index e911898..2842013 100644
--- a/drivers/gpu/drm/radeon/atombios_crtc.c
+++ b/drivers/gpu/drm/radeon/atombios_crtc.c
@@ -1284,6 +1284,10 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc,
                break;
        }

+       /* Make sure updates happen at vertical blank */
+       WREG32(EVERGREEN_GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset, 0);
+       WREG32(EVERGREEN_MASTER_UPDATE_MODE + radeon_crtc->crtc_offset, 0);
+
        WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + radeon_crtc->crtc_offset,
               upper_32_bits(fb_location));
        WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + radeon_crtc->crtc_offset,
@@ -1321,15 +1325,6 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc,
        WREG32(EVERGREEN_VIEWPORT_SIZE + radeon_crtc->crtc_offset,
               (viewport_w << 16) | viewport_h);

-       /* pageflip setup */
-       /* make sure flip is at vb rather than hb */
-       tmp = RREG32(EVERGREEN_GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset);
-       tmp &= ~EVERGREEN_GRPH_SURFACE_UPDATE_H_RETRACE_EN;
-       WREG32(EVERGREEN_GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset, tmp);
-
-       /* set pageflip to happen anywhere in vblank interval */
-       WREG32(EVERGREEN_MASTER_UPDATE_MODE + radeon_crtc->crtc_offset, 0);
-
        if (!atomic && fb && fb != crtc->primary->fb) {
                radeon_fb = to_radeon_framebuffer(fb);
                rbo = gem_to_radeon_bo(radeon_fb->obj);
diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c
index 0f4b38f..d0a994c 100644
--- a/drivers/gpu/drm/radeon/cik.c
+++ b/drivers/gpu/drm/radeon/cik.c
@@ -7143,25 +7143,6 @@ int cik_irq_set(struct radeon_device *rdev)
                WREG32(LB_INTERRUPT_MASK + EVERGREEN_CRTC5_REGISTER_OFFSET, crtc6);
        }

-       if (rdev->num_crtc >= 2) {
-               WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET,
-                      GRPH_PFLIP_INT_MASK);
-               WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET,
-                      GRPH_PFLIP_INT_MASK);
-       }
-       if (rdev->num_crtc >= 4) {
-               WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET,
-                      GRPH_PFLIP_INT_MASK);
-               WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET,
-                      GRPH_PFLIP_INT_MASK);
-       }
-       if (rdev->num_crtc >= 6) {
-               WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET,
-                      GRPH_PFLIP_INT_MASK);
-               WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET,
-                      GRPH_PFLIP_INT_MASK);
-       }
-
        WREG32(DC_HPD1_INT_CONTROL, hpd1);
        WREG32(DC_HPD2_INT_CONTROL, hpd2);
        WREG32(DC_HPD3_INT_CONTROL, hpd3);
@@ -7215,12 +7196,6 @@ static inline void cik_irq_ack(struct radeon_device *rdev)
                        EVERGREEN_CRTC5_REGISTER_OFFSET);
        }

-       if (rdev->irq.stat_regs.cik.d1grph_int & GRPH_PFLIP_INT_OCCURRED)
-               WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC0_REGISTER_OFFSET,
-                      GRPH_PFLIP_INT_CLEAR);
-       if (rdev->irq.stat_regs.cik.d2grph_int & GRPH_PFLIP_INT_OCCURRED)
-               WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC1_REGISTER_OFFSET,
-                      GRPH_PFLIP_INT_CLEAR);
        if (rdev->irq.stat_regs.cik.disp_int & LB_D1_VBLANK_INTERRUPT)
                WREG32(LB_VBLANK_STATUS + EVERGREEN_CRTC0_REGISTER_OFFSET, VBLANK_ACK);
        if (rdev->irq.stat_regs.cik.disp_int & LB_D1_VLINE_INTERRUPT)
@@ -7231,12 +7206,6 @@ static inline void cik_irq_ack(struct radeon_device *rdev)
                WREG32(LB_VLINE_STATUS + EVERGREEN_CRTC1_REGISTER_OFFSET, VLINE_ACK);

        if (rdev->num_crtc >= 4) {
-               if (rdev->irq.stat_regs.cik.d3grph_int & GRPH_PFLIP_INT_OCCURRED)
-                       WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET,
-                              GRPH_PFLIP_INT_CLEAR);
-               if (rdev->irq.stat_regs.cik.d4grph_int & GRPH_PFLIP_INT_OCCURRED)
-                       WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC3_REGISTER_OFFSET,
-                              GRPH_PFLIP_INT_CLEAR);
                if (rdev->irq.stat_regs.cik.disp_int_cont2 & LB_D3_VBLANK_INTERRUPT)
                        WREG32(LB_VBLANK_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET, VBLANK_ACK);
                if (rdev->irq.stat_regs.cik.disp_int_cont2 & LB_D3_VLINE_INTERRUPT)
@@ -7248,12 +7217,6 @@ static inline void cik_irq_ack(struct radeon_device *rdev)
        }

        if (rdev->num_crtc >= 6) {
-               if (rdev->irq.stat_regs.cik.d5grph_int & GRPH_PFLIP_INT_OCCURRED)
-                       WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET,
-                              GRPH_PFLIP_INT_CLEAR);
-               if (rdev->irq.stat_regs.cik.d6grph_int & GRPH_PFLIP_INT_OCCURRED)
-                       WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET,
-                              GRPH_PFLIP_INT_CLEAR);
                if (rdev->irq.stat_regs.cik.disp_int_cont4 & LB_D5_VBLANK_INTERRUPT)
                        WREG32(LB_VBLANK_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET, VBLANK_ACK);
                if (rdev->irq.stat_regs.cik.disp_int_cont4 & LB_D5_VLINE_INTERRUPT)
@@ -7459,7 +7422,7 @@ restart_ih:
                                                wake_up(&rdev->irq.vblank_queue);
                                        }
                                        if (atomic_read(&rdev->irq.pflip[0]))
-                                               radeon_crtc_handle_vblank(rdev, 0);
+                                               radeon_crtc_handle_flip(rdev, 0);
                                        rdev->irq.stat_regs.cik.disp_int &= ~LB_D1_VBLANK_INTERRUPT;
                                        DRM_DEBUG("IH: D1 vblank\n");
                                }
@@ -7485,7 +7448,7 @@ restart_ih:
                                                wake_up(&rdev->irq.vblank_queue);
                                        }
                                        if (atomic_read(&rdev->irq.pflip[1]))
-                                               radeon_crtc_handle_vblank(rdev, 1);
+                                               radeon_crtc_handle_flip(rdev, 1);
                                        rdev->irq.stat_regs.cik.disp_int_cont &= ~LB_D2_VBLANK_INTERRUPT;
                                        DRM_DEBUG("IH: D2 vblank\n");
                                }
@@ -7511,7 +7474,7 @@ restart_ih:
                                                wake_up(&rdev->irq.vblank_queue);
                                        }
                                        if (atomic_read(&rdev->irq.pflip[2]))
-                                               radeon_crtc_handle_vblank(rdev, 2);
+                                               radeon_crtc_handle_flip(rdev, 2);
                                        rdev->irq.stat_regs.cik.disp_int_cont2 &= ~LB_D3_VBLANK_INTERRUPT;
                                        DRM_DEBUG("IH: D3 vblank\n");
                                }
@@ -7537,7 +7500,7 @@ restart_ih:
                                                wake_up(&rdev->irq.vblank_queue);
                                        }
                                        if (atomic_read(&rdev->irq.pflip[3]))
-                                               radeon_crtc_handle_vblank(rdev, 3);
+                                               radeon_crtc_handle_flip(rdev, 3);
                                        rdev->irq.stat_regs.cik.disp_int_cont3 &= ~LB_D4_VBLANK_INTERRUPT;
                                        DRM_DEBUG("IH: D4 vblank\n");
                                }
@@ -7563,7 +7526,7 @@ restart_ih:
                                                wake_up(&rdev->irq.vblank_queue);
                                        }
                                        if (atomic_read(&rdev->irq.pflip[4]))
-                                               radeon_crtc_handle_vblank(rdev, 4);
+                                               radeon_crtc_handle_flip(rdev, 4);
                                        rdev->irq.stat_regs.cik.disp_int_cont4 &= ~LB_D5_VBLANK_INTERRUPT;
                                        DRM_DEBUG("IH: D5 vblank\n");
                                }
@@ -7589,7 +7552,7 @@ restart_ih:
                                                wake_up(&rdev->irq.vblank_queue);
                                        }
                                        if (atomic_read(&rdev->irq.pflip[5]))
-                                               radeon_crtc_handle_vblank(rdev, 5);
+                                               radeon_crtc_handle_flip(rdev, 5);
                                        rdev->irq.stat_regs.cik.disp_int_cont5 &= ~LB_D6_VBLANK_INTERRUPT;
                                        DRM_DEBUG("IH: D6 vblank\n");
                                }
@@ -7605,15 +7568,6 @@ restart_ih:
                                break;
                        }
                        break;
-               case 8: /* D1 page flip */
-               case 10: /* D2 page flip */
-               case 12: /* D3 page flip */
-               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);
-                       break;
                case 42: /* HPD hotplug */
                        switch (src_data) {
                        case 0:
diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c
index 0443183..4798d61 100644
--- a/drivers/gpu/drm/radeon/evergreen.c
+++ b/drivers/gpu/drm/radeon/evergreen.c
@@ -1317,7 +1317,10 @@ void evergreen_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base)
 {
        struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];
        u32 tmp = RREG32(EVERGREEN_GRPH_UPDATE + radeon_crtc->crtc_offset);
-       int i;
+
+       /* Take surface updates at horizontal blank */
+       WREG32(EVERGREEN_GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset,
+              EVERGREEN_GRPH_SURFACE_UPDATE_H_RETRACE_EN);

        /* Lock the graphics update lock */
        tmp |= EVERGREEN_GRPH_UPDATE_LOCK;
@@ -1334,15 +1337,7 @@ void evergreen_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base)
        WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset,
               (u32)crtc_base);

-       /* Wait for update_pending to go high. */
-       for (i = 0; i < rdev->usec_timeout; i++) {
-               if (RREG32(EVERGREEN_GRPH_UPDATE + radeon_crtc->crtc_offset) & EVERGREEN_GRPH_SURFACE_UPDATE_PENDING)
-                       break;
-               udelay(1);
-       }
-       DRM_DEBUG("Update pending now high. Unlocking vupdate_lock.\n");
-
-       /* Unlock the lock, so double-buffering can take place inside vblank */
+       /* Unlock the lock, so double-buffering can take place inside hblank */
        tmp &= ~EVERGREEN_GRPH_UPDATE_LOCK;
        WREG32(EVERGREEN_GRPH_UPDATE + radeon_crtc->crtc_offset, tmp);
 }
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index 8e8ef08..c8b7f26 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -681,6 +681,7 @@ struct radeon_flip_work {
        struct work_struct              unpin_work;
        struct radeon_device            *rdev;
        int                             crtc_id;
+       uint64_t                        base;
        struct drm_framebuffer          *fb;
        struct drm_pending_vblank_event *event;
        struct radeon_bo                *old_rbo;
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c
index 65882cd..9a7554c 100644
--- a/drivers/gpu/drm/radeon/radeon_display.c
+++ b/drivers/gpu/drm/radeon/radeon_display.c
@@ -354,6 +354,9 @@ void radeon_crtc_handle_flip(struct radeon_device *rdev, int crtc_id)
                return;
        }

+       /* do the flip (mmio) */
+       radeon_page_flip(rdev, radeon_crtc->crtc_id, work->base);
+
        /* Pageflip completed. Clean up. */
        radeon_crtc->flip_status = RADEON_FLIP_NONE;
        radeon_crtc->flip_work = NULL;
@@ -479,9 +482,7 @@ static void radeon_flip_work_func(struct work_struct *__work)
        /* set the proper interrupt */
        radeon_irq_kms_pflip_irq_get(rdev, radeon_crtc->crtc_id);

-       /* do the flip (mmio) */
-       radeon_page_flip(rdev, radeon_crtc->crtc_id, base);
-
+       work->base = base;
        radeon_crtc->flip_status = RADEON_FLIP_SUBMITTED;
        spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
        up_read(&rdev->exclusive_lock);


-- 
Earthling Michel Dänzer            |                  http://www.amd.com
Libre software enthusiast          |                Mesa and X developer
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 34+ messages in thread

* Re: [PATCH 1/2] drm/radeon: Only enable and handle pageflip interrupts when needed
  2014-06-30  9:34           ` Michel Dänzer
@ 2014-06-30 12:31             ` Christian König
  2014-06-30 16:22               ` Dieter Nützel
  2014-07-01  8:14               ` [PATCH 1/2] drm/radeon: Program page flips to execute in hblank instead of vblank Michel Dänzer
  0 siblings, 2 replies; 34+ messages in thread
From: Christian König @ 2014-06-30 12:31 UTC (permalink / raw)
  To: Michel Dänzer; +Cc: dri-devel

Am 30.06.2014 11:34, schrieb Michel Dänzer:
> On 27.06.2014 19:47, Christian König wrote:
>> Am 27.06.2014 11:44, schrieb Michel Dänzer:
>>> On 27.06.2014 17:18, Christian König wrote:
>>>> Am 27.06.2014 04:58, schrieb Michel Dänzer:
>>>>> On 26.06.2014 19:39, Christian König wrote:
>>>>>> Am 26.06.2014 11:29, schrieb Michel Dänzer:
>>>>>>> From: Michel Dänzer <michel.daenzer@amd.com>
>>>>>>>
>>>>>>> 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().
>>>>>>>
>>>>>>> Tested-by: Dieter Nützel <Dieter@nuetzel-hh.de> Signed-off-by:
>>>>>>> Michel Dänzer <michel.daenzer@amd.com>
>>>>>> Does patch #2 alone fixes the problem as well?
>>>>> It should avoid the panic as well.
> I've sent a v2 of that patch with an updated commit log. Alex, please get
> that into 3.16 ASAP to prevent people from running into the panic.
>
>
>>>>>> I would rather want to avoid turning the pflip interrupt on and
>>>>>> off.
>>>>> What's the problem with that? It's not like we're saving any
>>>>> register writes by not doing it.
>>>> We don't? As far as I can see we reprogram all interrupt registers
>>>> if any of the interrupts changed,
>>> Maybe I'm missing something, but: radeon_irq_kms_pflip_irq_get/put()
>>> call radeon_irq_set() every time, as there can only be one active page
>>> flip per CRTC. And radeon_irq_set() always writes the same registers,
>>> only the bits it writes to them change depending on which interrupts the
>>> driver is currently interested in.
>> We first turn on the vblank interrupt which results in a
>> radeon_irq_set() and then turn on the pflip, which results in another
>> radeon_irq_set() .
> The DRM core delays disabling the hardware vblank interrupt, so
> radeon_irq_set() should only be called once for that.
>
> radeon_irq_kms_pflip_irq_get/put() always call radeon_irq_set() even before
> my changes.
>
>
> Anyway, for the issues surrounding the pflip interrupt, I took a step back
> and considered a fundamentally different approach: It occurred to me that a
> lot of the issues we've been struggling with are related to programming the
> flips to the hardware such that they execute during the vertical blank
> period. We don't know exactly when the hardware update happens or when would
> be a good time to program the flip. So why bother with that at all?
I've considered this as well, but at this time still hoped that we could 
completely replace the vblank interrupt with the pflip interrupt.

> The patch below (only fleshed out for CIK) moves the programming of the
> flip to the hardware back to the vertical blank interrupt handler, but
> changes it to execute during the horizontal blank period. In addition to
> allowing the pflip interrupt handling, radeon_crtc_handle_vblank() and
> radeon_flip_pending() to be removed, this should make adding support for
> asynchronous flips trivial and support for replacing pending flips much
> easier. What do you think?
It also allows us to stop fiddling with the update pending bit as well, 
e.g. no more busy waiting for it to become high in evergreen_page_flip.

And as far as I can see it still support all not so trivial use cases 
like switching to hblank if rendering isn't completed before a certain 
timeout and dynamic refresh etc...

Yeah, sounds like a really good idea to me.

>> The delay between vblank start and the flip being executed seemed to be
>> depending on the pixel clock (which makes sense because the CRTC is
>> driven by it), so when it might work ok for a 50Hz mode we can still run
>> into problems with 24Hz modes.
> I couldn't see any tearing with this patch at 640x480 at 60 Hz and reduced
> blanking, which should have a lower pixel clock and shorter vertical blank
> period than 1920x1080 at 24 Hz?

In theory that should do the trick as well. But let's just make patches 
for it and then we can make a request to the people who originally 
reported the problem to test the whole implementation.

That should give us enough confidence that it will work correctly,
Christian.

>
>
> commit 7b2861589f05c5c5c752108ce105161ebc0d6bf5
> Author: Michel Dänzer <michel.daenzer@amd.com>
> Date:   Mon Jun 30 17:57:01 2014 +0900
>
>      drm/radeon: Program page flips to execute in hblank instead of vblank
>
> diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c
> index e911898..2842013 100644
> --- a/drivers/gpu/drm/radeon/atombios_crtc.c
> +++ b/drivers/gpu/drm/radeon/atombios_crtc.c
> @@ -1284,6 +1284,10 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc,
>                  break;
>          }
>
> +       /* Make sure updates happen at vertical blank */
> +       WREG32(EVERGREEN_GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset, 0);
> +       WREG32(EVERGREEN_MASTER_UPDATE_MODE + radeon_crtc->crtc_offset, 0);
> +
>          WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + radeon_crtc->crtc_offset,
>                 upper_32_bits(fb_location));
>          WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + radeon_crtc->crtc_offset,
> @@ -1321,15 +1325,6 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc,
>          WREG32(EVERGREEN_VIEWPORT_SIZE + radeon_crtc->crtc_offset,
>                 (viewport_w << 16) | viewport_h);
>
> -       /* pageflip setup */
> -       /* make sure flip is at vb rather than hb */
> -       tmp = RREG32(EVERGREEN_GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset);
> -       tmp &= ~EVERGREEN_GRPH_SURFACE_UPDATE_H_RETRACE_EN;
> -       WREG32(EVERGREEN_GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset, tmp);
> -
> -       /* set pageflip to happen anywhere in vblank interval */
> -       WREG32(EVERGREEN_MASTER_UPDATE_MODE + radeon_crtc->crtc_offset, 0);
> -
>          if (!atomic && fb && fb != crtc->primary->fb) {
>                  radeon_fb = to_radeon_framebuffer(fb);
>                  rbo = gem_to_radeon_bo(radeon_fb->obj);
> diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c
> index 0f4b38f..d0a994c 100644
> --- a/drivers/gpu/drm/radeon/cik.c
> +++ b/drivers/gpu/drm/radeon/cik.c
> @@ -7143,25 +7143,6 @@ int cik_irq_set(struct radeon_device *rdev)
>                  WREG32(LB_INTERRUPT_MASK + EVERGREEN_CRTC5_REGISTER_OFFSET, crtc6);
>          }
>
> -       if (rdev->num_crtc >= 2) {
> -               WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET,
> -                      GRPH_PFLIP_INT_MASK);
> -               WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET,
> -                      GRPH_PFLIP_INT_MASK);
> -       }
> -       if (rdev->num_crtc >= 4) {
> -               WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET,
> -                      GRPH_PFLIP_INT_MASK);
> -               WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET,
> -                      GRPH_PFLIP_INT_MASK);
> -       }
> -       if (rdev->num_crtc >= 6) {
> -               WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET,
> -                      GRPH_PFLIP_INT_MASK);
> -               WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET,
> -                      GRPH_PFLIP_INT_MASK);
> -       }
> -
>          WREG32(DC_HPD1_INT_CONTROL, hpd1);
>          WREG32(DC_HPD2_INT_CONTROL, hpd2);
>          WREG32(DC_HPD3_INT_CONTROL, hpd3);
> @@ -7215,12 +7196,6 @@ static inline void cik_irq_ack(struct radeon_device *rdev)
>                          EVERGREEN_CRTC5_REGISTER_OFFSET);
>          }
>
> -       if (rdev->irq.stat_regs.cik.d1grph_int & GRPH_PFLIP_INT_OCCURRED)
> -               WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC0_REGISTER_OFFSET,
> -                      GRPH_PFLIP_INT_CLEAR);
> -       if (rdev->irq.stat_regs.cik.d2grph_int & GRPH_PFLIP_INT_OCCURRED)
> -               WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC1_REGISTER_OFFSET,
> -                      GRPH_PFLIP_INT_CLEAR);
>          if (rdev->irq.stat_regs.cik.disp_int & LB_D1_VBLANK_INTERRUPT)
>                  WREG32(LB_VBLANK_STATUS + EVERGREEN_CRTC0_REGISTER_OFFSET, VBLANK_ACK);
>          if (rdev->irq.stat_regs.cik.disp_int & LB_D1_VLINE_INTERRUPT)
> @@ -7231,12 +7206,6 @@ static inline void cik_irq_ack(struct radeon_device *rdev)
>                  WREG32(LB_VLINE_STATUS + EVERGREEN_CRTC1_REGISTER_OFFSET, VLINE_ACK);
>
>          if (rdev->num_crtc >= 4) {
> -               if (rdev->irq.stat_regs.cik.d3grph_int & GRPH_PFLIP_INT_OCCURRED)
> -                       WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET,
> -                              GRPH_PFLIP_INT_CLEAR);
> -               if (rdev->irq.stat_regs.cik.d4grph_int & GRPH_PFLIP_INT_OCCURRED)
> -                       WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC3_REGISTER_OFFSET,
> -                              GRPH_PFLIP_INT_CLEAR);
>                  if (rdev->irq.stat_regs.cik.disp_int_cont2 & LB_D3_VBLANK_INTERRUPT)
>                          WREG32(LB_VBLANK_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET, VBLANK_ACK);
>                  if (rdev->irq.stat_regs.cik.disp_int_cont2 & LB_D3_VLINE_INTERRUPT)
> @@ -7248,12 +7217,6 @@ static inline void cik_irq_ack(struct radeon_device *rdev)
>          }
>
>          if (rdev->num_crtc >= 6) {
> -               if (rdev->irq.stat_regs.cik.d5grph_int & GRPH_PFLIP_INT_OCCURRED)
> -                       WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET,
> -                              GRPH_PFLIP_INT_CLEAR);
> -               if (rdev->irq.stat_regs.cik.d6grph_int & GRPH_PFLIP_INT_OCCURRED)
> -                       WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET,
> -                              GRPH_PFLIP_INT_CLEAR);
>                  if (rdev->irq.stat_regs.cik.disp_int_cont4 & LB_D5_VBLANK_INTERRUPT)
>                          WREG32(LB_VBLANK_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET, VBLANK_ACK);
>                  if (rdev->irq.stat_regs.cik.disp_int_cont4 & LB_D5_VLINE_INTERRUPT)
> @@ -7459,7 +7422,7 @@ restart_ih:
>                                                  wake_up(&rdev->irq.vblank_queue);
>                                          }
>                                          if (atomic_read(&rdev->irq.pflip[0]))
> -                                               radeon_crtc_handle_vblank(rdev, 0);
> +                                               radeon_crtc_handle_flip(rdev, 0);
>                                          rdev->irq.stat_regs.cik.disp_int &= ~LB_D1_VBLANK_INTERRUPT;
>                                          DRM_DEBUG("IH: D1 vblank\n");
>                                  }
> @@ -7485,7 +7448,7 @@ restart_ih:
>                                                  wake_up(&rdev->irq.vblank_queue);
>                                          }
>                                          if (atomic_read(&rdev->irq.pflip[1]))
> -                                               radeon_crtc_handle_vblank(rdev, 1);
> +                                               radeon_crtc_handle_flip(rdev, 1);
>                                          rdev->irq.stat_regs.cik.disp_int_cont &= ~LB_D2_VBLANK_INTERRUPT;
>                                          DRM_DEBUG("IH: D2 vblank\n");
>                                  }
> @@ -7511,7 +7474,7 @@ restart_ih:
>                                                  wake_up(&rdev->irq.vblank_queue);
>                                          }
>                                          if (atomic_read(&rdev->irq.pflip[2]))
> -                                               radeon_crtc_handle_vblank(rdev, 2);
> +                                               radeon_crtc_handle_flip(rdev, 2);
>                                          rdev->irq.stat_regs.cik.disp_int_cont2 &= ~LB_D3_VBLANK_INTERRUPT;
>                                          DRM_DEBUG("IH: D3 vblank\n");
>                                  }
> @@ -7537,7 +7500,7 @@ restart_ih:
>                                                  wake_up(&rdev->irq.vblank_queue);
>                                          }
>                                          if (atomic_read(&rdev->irq.pflip[3]))
> -                                               radeon_crtc_handle_vblank(rdev, 3);
> +                                               radeon_crtc_handle_flip(rdev, 3);
>                                          rdev->irq.stat_regs.cik.disp_int_cont3 &= ~LB_D4_VBLANK_INTERRUPT;
>                                          DRM_DEBUG("IH: D4 vblank\n");
>                                  }
> @@ -7563,7 +7526,7 @@ restart_ih:
>                                                  wake_up(&rdev->irq.vblank_queue);
>                                          }
>                                          if (atomic_read(&rdev->irq.pflip[4]))
> -                                               radeon_crtc_handle_vblank(rdev, 4);
> +                                               radeon_crtc_handle_flip(rdev, 4);
>                                          rdev->irq.stat_regs.cik.disp_int_cont4 &= ~LB_D5_VBLANK_INTERRUPT;
>                                          DRM_DEBUG("IH: D5 vblank\n");
>                                  }
> @@ -7589,7 +7552,7 @@ restart_ih:
>                                                  wake_up(&rdev->irq.vblank_queue);
>                                          }
>                                          if (atomic_read(&rdev->irq.pflip[5]))
> -                                               radeon_crtc_handle_vblank(rdev, 5);
> +                                               radeon_crtc_handle_flip(rdev, 5);
>                                          rdev->irq.stat_regs.cik.disp_int_cont5 &= ~LB_D6_VBLANK_INTERRUPT;
>                                          DRM_DEBUG("IH: D6 vblank\n");
>                                  }
> @@ -7605,15 +7568,6 @@ restart_ih:
>                                  break;
>                          }
>                          break;
> -               case 8: /* D1 page flip */
> -               case 10: /* D2 page flip */
> -               case 12: /* D3 page flip */
> -               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);
> -                       break;
>                  case 42: /* HPD hotplug */
>                          switch (src_data) {
>                          case 0:
> diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c
> index 0443183..4798d61 100644
> --- a/drivers/gpu/drm/radeon/evergreen.c
> +++ b/drivers/gpu/drm/radeon/evergreen.c
> @@ -1317,7 +1317,10 @@ void evergreen_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base)
>   {
>          struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];
>          u32 tmp = RREG32(EVERGREEN_GRPH_UPDATE + radeon_crtc->crtc_offset);
> -       int i;
> +
> +       /* Take surface updates at horizontal blank */
> +       WREG32(EVERGREEN_GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset,
> +              EVERGREEN_GRPH_SURFACE_UPDATE_H_RETRACE_EN);
>
>          /* Lock the graphics update lock */
>          tmp |= EVERGREEN_GRPH_UPDATE_LOCK;
> @@ -1334,15 +1337,7 @@ void evergreen_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base)
>          WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset,
>                 (u32)crtc_base);
>
> -       /* Wait for update_pending to go high. */
> -       for (i = 0; i < rdev->usec_timeout; i++) {
> -               if (RREG32(EVERGREEN_GRPH_UPDATE + radeon_crtc->crtc_offset) & EVERGREEN_GRPH_SURFACE_UPDATE_PENDING)
> -                       break;
> -               udelay(1);
> -       }
> -       DRM_DEBUG("Update pending now high. Unlocking vupdate_lock.\n");
> -
> -       /* Unlock the lock, so double-buffering can take place inside vblank */
> +       /* Unlock the lock, so double-buffering can take place inside hblank */
>          tmp &= ~EVERGREEN_GRPH_UPDATE_LOCK;
>          WREG32(EVERGREEN_GRPH_UPDATE + radeon_crtc->crtc_offset, tmp);
>   }
> diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
> index 8e8ef08..c8b7f26 100644
> --- a/drivers/gpu/drm/radeon/radeon.h
> +++ b/drivers/gpu/drm/radeon/radeon.h
> @@ -681,6 +681,7 @@ struct radeon_flip_work {
>          struct work_struct              unpin_work;
>          struct radeon_device            *rdev;
>          int                             crtc_id;
> +       uint64_t                        base;
>          struct drm_framebuffer          *fb;
>          struct drm_pending_vblank_event *event;
>          struct radeon_bo                *old_rbo;
> diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c
> index 65882cd..9a7554c 100644
> --- a/drivers/gpu/drm/radeon/radeon_display.c
> +++ b/drivers/gpu/drm/radeon/radeon_display.c
> @@ -354,6 +354,9 @@ void radeon_crtc_handle_flip(struct radeon_device *rdev, int crtc_id)
>                  return;
>          }
>
> +       /* do the flip (mmio) */
> +       radeon_page_flip(rdev, radeon_crtc->crtc_id, work->base);
> +
>          /* Pageflip completed. Clean up. */
>          radeon_crtc->flip_status = RADEON_FLIP_NONE;
>          radeon_crtc->flip_work = NULL;
> @@ -479,9 +482,7 @@ static void radeon_flip_work_func(struct work_struct *__work)
>          /* set the proper interrupt */
>          radeon_irq_kms_pflip_irq_get(rdev, radeon_crtc->crtc_id);
>
> -       /* do the flip (mmio) */
> -       radeon_page_flip(rdev, radeon_crtc->crtc_id, base);
> -
> +       work->base = base;
>          radeon_crtc->flip_status = RADEON_FLIP_SUBMITTED;
>          spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
>          up_read(&rdev->exclusive_lock);
>
>

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH 1/2] drm/radeon: Only enable and handle pageflip interrupts when needed
  2014-06-30 12:31             ` Christian König
@ 2014-06-30 16:22               ` Dieter Nützel
  2014-07-01  8:14               ` [PATCH 1/2] drm/radeon: Program page flips to execute in hblank instead of vblank Michel Dänzer
  1 sibling, 0 replies; 34+ messages in thread
From: Dieter Nützel @ 2014-06-30 16:22 UTC (permalink / raw)
  To: Christian König; +Cc: Michel Dänzer, dri-devel

Am 30.06.2014 14:31, schrieb Christian König:
> Am 30.06.2014 11:34, schrieb Michel Dänzer:
>> On 27.06.2014 19:47, Christian König wrote:
>>> Am 27.06.2014 11:44, schrieb Michel Dänzer:
>>>> On 27.06.2014 17:18, Christian König wrote:
>>>>> Am 27.06.2014 04:58, schrieb Michel Dänzer:
>>>>>> On 26.06.2014 19:39, Christian König wrote:
>>>>>>> Am 26.06.2014 11:29, schrieb Michel Dänzer:
>>>>>>>> From: Michel Dänzer <michel.daenzer@amd.com>
>>>>>>>> 
>>>>>>>> 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().
>>>>>>>> 
>>>>>>>> Tested-by: Dieter Nützel <Dieter@nuetzel-hh.de> Signed-off-by:
>>>>>>>> Michel Dänzer <michel.daenzer@amd.com>
>>>>>>> Does patch #2 alone fixes the problem as well?
>>>>>> It should avoid the panic as well.
>> I've sent a v2 of that patch with an updated commit log. Alex, please 
>> get
>> that into 3.16 ASAP to prevent people from running into the panic.

Compiling...

>>>>>>> I would rather want to avoid turning the pflip interrupt on and
>>>>>>> off.
>>>>>> What's the problem with that? It's not like we're saving any
>>>>>> register writes by not doing it.
>>>>> We don't? As far as I can see we reprogram all interrupt registers
>>>>> if any of the interrupts changed,
>>>> Maybe I'm missing something, but: radeon_irq_kms_pflip_irq_get/put()
>>>> call radeon_irq_set() every time, as there can only be one active 
>>>> page
>>>> flip per CRTC. And radeon_irq_set() always writes the same 
>>>> registers,
>>>> only the bits it writes to them change depending on which interrupts 
>>>> the
>>>> driver is currently interested in.
>>> We first turn on the vblank interrupt which results in a
>>> radeon_irq_set() and then turn on the pflip, which results in another
>>> radeon_irq_set() .
>> The DRM core delays disabling the hardware vblank interrupt, so
>> radeon_irq_set() should only be called once for that.
>> 
>> radeon_irq_kms_pflip_irq_get/put() always call radeon_irq_set() even 
>> before
>> my changes.
>> 
>> 
>> Anyway, for the issues surrounding the pflip interrupt, I took a step 
>> back
>> and considered a fundamentally different approach: It occurred to me 
>> that a
>> lot of the issues we've been struggling with are related to 
>> programming the
>> flips to the hardware such that they execute during the vertical blank
>> period. We don't know exactly when the hardware update happens or when 
>> would
>> be a good time to program the flip. So why bother with that at all?
> I've considered this as well, but at this time still hoped that we
> could completely replace the vblank interrupt with the pflip
> interrupt.
> 
>> The patch below (only fleshed out for CIK) moves the programming of 
>> the
>> flip to the hardware back to the vertical blank interrupt handler, but
>> changes it to execute during the horizontal blank period. In addition 
>> to
>> allowing the pflip interrupt handling, radeon_crtc_handle_vblank() and
>> radeon_flip_pending() to be removed, this should make adding support 
>> for
>> asynchronous flips trivial and support for replacing pending flips 
>> much
>> easier. What do you think?
> It also allows us to stop fiddling with the update pending bit as
> well, e.g. no more busy waiting for it to become high in
> evergreen_page_flip.
> 
> And as far as I can see it still support all not so trivial use cases
> like switching to hblank if rendering isn't completed before a certain
> timeout and dynamic refresh etc...
> 
> Yeah, sounds like a really good idea to me.
> 
>>> The delay between vblank start and the flip being executed seemed to 
>>> be
>>> depending on the pixel clock (which makes sense because the CRTC is
>>> driven by it), so when it might work ok for a 50Hz mode we can still 
>>> run
>>> into problems with 24Hz modes.
>> I couldn't see any tearing with this patch at 640x480 at 60 Hz and 
>> reduced
>> blanking, which should have a lower pixel clock and shorter vertical 
>> blank
>> period than 1920x1080 at 24 Hz?
> 
> In theory that should do the trick as well. But let's just make
> patches for it and then we can make a request to the people who
> originally reported the problem to test the whole implementation.
> 
> That should give us enough confidence that it will work correctly,
> Christian.

So please flesh something out (for r600 at least) and let me try ;-)

BTW Have someone looked at this (dpm typos):
Bug 79071 - Hang with dpm radeon hd 5750, pcie 1.1 motherboard
https://bugzilla.kernel.org/show_bug.cgi?id=79071
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 34+ messages in thread

* [PATCH 1/2] drm/radeon: Program page flips to execute in hblank instead of vblank
  2014-06-30 12:31             ` Christian König
  2014-06-30 16:22               ` Dieter Nützel
@ 2014-07-01  8:14               ` Michel Dänzer
  2014-07-01  8:14                 ` [PATCH 2/2] drm/radeon: Remove radeon_kms_pflip_irq_get/put() Michel Dänzer
                                   ` (2 more replies)
  1 sibling, 3 replies; 34+ messages in thread
From: Michel Dänzer @ 2014-07-01  8:14 UTC (permalink / raw)
  To: dri-devel

From: Michel Dänzer <michel.daenzer@amd.com>

But move the programming back to the vertical blank interrupt handler.
And signal the flip as being completed immediately after programming it
to the hardware.

This way we don't have to guess whether or not the hardware will execute
the flip in a given vertical blank period, avoiding a whole lot of
trouble.

Also, not using the page flip interrupt anymore avoids problems due to
completing page flips earlier than expected by userspace.

Signed-off-by: Michel Dänzer <michel.daenzer@amd.com>
---
 drivers/gpu/drm/radeon/atombios_crtc.c  | 28 ++++-------
 drivers/gpu/drm/radeon/cik.c            | 58 +++-------------------
 drivers/gpu/drm/radeon/evergreen.c      | 86 +++++----------------------------
 drivers/gpu/drm/radeon/r100.c           | 48 +++---------------
 drivers/gpu/drm/radeon/r600.c           | 18 +------
 drivers/gpu/drm/radeon/radeon.h         |  3 +-
 drivers/gpu/drm/radeon/radeon_asic.c    | 22 ---------
 drivers/gpu/drm/radeon/radeon_asic.h    |  4 --
 drivers/gpu/drm/radeon/radeon_display.c | 51 ++-----------------
 drivers/gpu/drm/radeon/radeon_mode.h    |  1 -
 drivers/gpu/drm/radeon/rs600.c          | 28 +++--------
 drivers/gpu/drm/radeon/rv770.c          | 24 ++-------
 drivers/gpu/drm/radeon/si.c             | 52 +++-----------------
 13 files changed, 59 insertions(+), 364 deletions(-)

diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c
index e911898..65cfdbb 100644
--- a/drivers/gpu/drm/radeon/atombios_crtc.c
+++ b/drivers/gpu/drm/radeon/atombios_crtc.c
@@ -1284,6 +1284,10 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc,
 		break;
 	}
 
+	/* Make sure updates happen at vertical blank */
+	WREG32(EVERGREEN_GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset, 0);
+	WREG32(EVERGREEN_MASTER_UPDATE_MODE + radeon_crtc->crtc_offset, 0);
+
 	WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + radeon_crtc->crtc_offset,
 	       upper_32_bits(fb_location));
 	WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + radeon_crtc->crtc_offset,
@@ -1321,15 +1325,6 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc,
 	WREG32(EVERGREEN_VIEWPORT_SIZE + radeon_crtc->crtc_offset,
 	       (viewport_w << 16) | viewport_h);
 
-	/* pageflip setup */
-	/* make sure flip is at vb rather than hb */
-	tmp = RREG32(EVERGREEN_GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset);
-	tmp &= ~EVERGREEN_GRPH_SURFACE_UPDATE_H_RETRACE_EN;
-	WREG32(EVERGREEN_GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset, tmp);
-
-	/* set pageflip to happen anywhere in vblank interval */
-	WREG32(EVERGREEN_MASTER_UPDATE_MODE + radeon_crtc->crtc_offset, 0);
-
 	if (!atomic && fb && fb != crtc->primary->fb) {
 		radeon_fb = to_radeon_framebuffer(fb);
 		rbo = gem_to_radeon_bo(radeon_fb->obj);
@@ -1360,7 +1355,7 @@ static int avivo_crtc_do_set_base(struct drm_crtc *crtc,
 	uint64_t fb_location;
 	uint32_t fb_format, fb_pitch_pixels, tiling_flags;
 	u32 fb_swap = R600_D1GRPH_SWAP_ENDIAN_NONE;
-	u32 tmp, viewport_w, viewport_h;
+	u32 viewport_w, viewport_h;
 	int r;
 
 	/* no fb bound */
@@ -1451,6 +1446,10 @@ static int avivo_crtc_do_set_base(struct drm_crtc *crtc,
 	else
 		WREG32(AVIVO_D2VGA_CONTROL, 0);
 
+	/* Make sure updates happen at vertical blank */
+	WREG32(AVIVO_D1GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset, 0);
+	WREG32(AVIVO_D1MODE_MASTER_UPDATE_MODE + radeon_crtc->crtc_offset, 0);
+
 	if (rdev->family >= CHIP_RV770) {
 		if (radeon_crtc->crtc_id) {
 			WREG32(R700_D2GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, upper_32_bits(fb_location));
@@ -1490,15 +1489,6 @@ static int avivo_crtc_do_set_base(struct drm_crtc *crtc,
 	WREG32(AVIVO_D1MODE_VIEWPORT_SIZE + radeon_crtc->crtc_offset,
 	       (viewport_w << 16) | viewport_h);
 
-	/* pageflip setup */
-	/* make sure flip is at vb rather than hb */
-	tmp = RREG32(AVIVO_D1GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset);
-	tmp &= ~AVIVO_D1GRPH_SURFACE_UPDATE_H_RETRACE_EN;
-	WREG32(AVIVO_D1GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset, tmp);
-
-	/* set pageflip to happen anywhere in vblank interval */
-	WREG32(AVIVO_D1MODE_MASTER_UPDATE_MODE + radeon_crtc->crtc_offset, 0);
-
 	if (!atomic && fb && fb != crtc->primary->fb) {
 		radeon_fb = to_radeon_framebuffer(fb);
 		rbo = gem_to_radeon_bo(radeon_fb->obj);
diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c
index 0f4b38f..d0a994c 100644
--- a/drivers/gpu/drm/radeon/cik.c
+++ b/drivers/gpu/drm/radeon/cik.c
@@ -7143,25 +7143,6 @@ int cik_irq_set(struct radeon_device *rdev)
 		WREG32(LB_INTERRUPT_MASK + EVERGREEN_CRTC5_REGISTER_OFFSET, crtc6);
 	}
 
-	if (rdev->num_crtc >= 2) {
-		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET,
-		       GRPH_PFLIP_INT_MASK);
-		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET,
-		       GRPH_PFLIP_INT_MASK);
-	}
-	if (rdev->num_crtc >= 4) {
-		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET,
-		       GRPH_PFLIP_INT_MASK);
-		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET,
-		       GRPH_PFLIP_INT_MASK);
-	}
-	if (rdev->num_crtc >= 6) {
-		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET,
-		       GRPH_PFLIP_INT_MASK);
-		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET,
-		       GRPH_PFLIP_INT_MASK);
-	}
-
 	WREG32(DC_HPD1_INT_CONTROL, hpd1);
 	WREG32(DC_HPD2_INT_CONTROL, hpd2);
 	WREG32(DC_HPD3_INT_CONTROL, hpd3);
@@ -7215,12 +7196,6 @@ static inline void cik_irq_ack(struct radeon_device *rdev)
 			EVERGREEN_CRTC5_REGISTER_OFFSET);
 	}
 
-	if (rdev->irq.stat_regs.cik.d1grph_int & GRPH_PFLIP_INT_OCCURRED)
-		WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC0_REGISTER_OFFSET,
-		       GRPH_PFLIP_INT_CLEAR);
-	if (rdev->irq.stat_regs.cik.d2grph_int & GRPH_PFLIP_INT_OCCURRED)
-		WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC1_REGISTER_OFFSET,
-		       GRPH_PFLIP_INT_CLEAR);
 	if (rdev->irq.stat_regs.cik.disp_int & LB_D1_VBLANK_INTERRUPT)
 		WREG32(LB_VBLANK_STATUS + EVERGREEN_CRTC0_REGISTER_OFFSET, VBLANK_ACK);
 	if (rdev->irq.stat_regs.cik.disp_int & LB_D1_VLINE_INTERRUPT)
@@ -7231,12 +7206,6 @@ static inline void cik_irq_ack(struct radeon_device *rdev)
 		WREG32(LB_VLINE_STATUS + EVERGREEN_CRTC1_REGISTER_OFFSET, VLINE_ACK);
 
 	if (rdev->num_crtc >= 4) {
-		if (rdev->irq.stat_regs.cik.d3grph_int & GRPH_PFLIP_INT_OCCURRED)
-			WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET,
-			       GRPH_PFLIP_INT_CLEAR);
-		if (rdev->irq.stat_regs.cik.d4grph_int & GRPH_PFLIP_INT_OCCURRED)
-			WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC3_REGISTER_OFFSET,
-			       GRPH_PFLIP_INT_CLEAR);
 		if (rdev->irq.stat_regs.cik.disp_int_cont2 & LB_D3_VBLANK_INTERRUPT)
 			WREG32(LB_VBLANK_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET, VBLANK_ACK);
 		if (rdev->irq.stat_regs.cik.disp_int_cont2 & LB_D3_VLINE_INTERRUPT)
@@ -7248,12 +7217,6 @@ static inline void cik_irq_ack(struct radeon_device *rdev)
 	}
 
 	if (rdev->num_crtc >= 6) {
-		if (rdev->irq.stat_regs.cik.d5grph_int & GRPH_PFLIP_INT_OCCURRED)
-			WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET,
-			       GRPH_PFLIP_INT_CLEAR);
-		if (rdev->irq.stat_regs.cik.d6grph_int & GRPH_PFLIP_INT_OCCURRED)
-			WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET,
-			       GRPH_PFLIP_INT_CLEAR);
 		if (rdev->irq.stat_regs.cik.disp_int_cont4 & LB_D5_VBLANK_INTERRUPT)
 			WREG32(LB_VBLANK_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET, VBLANK_ACK);
 		if (rdev->irq.stat_regs.cik.disp_int_cont4 & LB_D5_VLINE_INTERRUPT)
@@ -7459,7 +7422,7 @@ restart_ih:
 						wake_up(&rdev->irq.vblank_queue);
 					}
 					if (atomic_read(&rdev->irq.pflip[0]))
-						radeon_crtc_handle_vblank(rdev, 0);
+						radeon_crtc_handle_flip(rdev, 0);
 					rdev->irq.stat_regs.cik.disp_int &= ~LB_D1_VBLANK_INTERRUPT;
 					DRM_DEBUG("IH: D1 vblank\n");
 				}
@@ -7485,7 +7448,7 @@ restart_ih:
 						wake_up(&rdev->irq.vblank_queue);
 					}
 					if (atomic_read(&rdev->irq.pflip[1]))
-						radeon_crtc_handle_vblank(rdev, 1);
+						radeon_crtc_handle_flip(rdev, 1);
 					rdev->irq.stat_regs.cik.disp_int_cont &= ~LB_D2_VBLANK_INTERRUPT;
 					DRM_DEBUG("IH: D2 vblank\n");
 				}
@@ -7511,7 +7474,7 @@ restart_ih:
 						wake_up(&rdev->irq.vblank_queue);
 					}
 					if (atomic_read(&rdev->irq.pflip[2]))
-						radeon_crtc_handle_vblank(rdev, 2);
+						radeon_crtc_handle_flip(rdev, 2);
 					rdev->irq.stat_regs.cik.disp_int_cont2 &= ~LB_D3_VBLANK_INTERRUPT;
 					DRM_DEBUG("IH: D3 vblank\n");
 				}
@@ -7537,7 +7500,7 @@ restart_ih:
 						wake_up(&rdev->irq.vblank_queue);
 					}
 					if (atomic_read(&rdev->irq.pflip[3]))
-						radeon_crtc_handle_vblank(rdev, 3);
+						radeon_crtc_handle_flip(rdev, 3);
 					rdev->irq.stat_regs.cik.disp_int_cont3 &= ~LB_D4_VBLANK_INTERRUPT;
 					DRM_DEBUG("IH: D4 vblank\n");
 				}
@@ -7563,7 +7526,7 @@ restart_ih:
 						wake_up(&rdev->irq.vblank_queue);
 					}
 					if (atomic_read(&rdev->irq.pflip[4]))
-						radeon_crtc_handle_vblank(rdev, 4);
+						radeon_crtc_handle_flip(rdev, 4);
 					rdev->irq.stat_regs.cik.disp_int_cont4 &= ~LB_D5_VBLANK_INTERRUPT;
 					DRM_DEBUG("IH: D5 vblank\n");
 				}
@@ -7589,7 +7552,7 @@ restart_ih:
 						wake_up(&rdev->irq.vblank_queue);
 					}
 					if (atomic_read(&rdev->irq.pflip[5]))
-						radeon_crtc_handle_vblank(rdev, 5);
+						radeon_crtc_handle_flip(rdev, 5);
 					rdev->irq.stat_regs.cik.disp_int_cont5 &= ~LB_D6_VBLANK_INTERRUPT;
 					DRM_DEBUG("IH: D6 vblank\n");
 				}
@@ -7605,15 +7568,6 @@ restart_ih:
 				break;
 			}
 			break;
-		case 8: /* D1 page flip */
-		case 10: /* D2 page flip */
-		case 12: /* D3 page flip */
-		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);
-			break;
 		case 42: /* HPD hotplug */
 			switch (src_data) {
 			case 0:
diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c
index 0443183..e7d685a 100644
--- a/drivers/gpu/drm/radeon/evergreen.c
+++ b/drivers/gpu/drm/radeon/evergreen.c
@@ -1308,16 +1308,15 @@ void dce4_wait_for_vblank(struct radeon_device *rdev, int crtc)
  * @crtc_base: new address of the crtc (GPU MC address)
  *
  * Does the actual pageflip (evergreen+).
- * During vblank we take the crtc lock and wait for the update_pending
- * bit to go high, when it does, we release the lock, and allow the
- * double buffered update to take place.
- * Returns the current update pending status.
  */
 void evergreen_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base)
 {
 	struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];
 	u32 tmp = RREG32(EVERGREEN_GRPH_UPDATE + radeon_crtc->crtc_offset);
-	int i;
+
+	/* Take surface updates at horizontal blank */
+	WREG32(EVERGREEN_GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset,
+	       EVERGREEN_GRPH_SURFACE_UPDATE_H_RETRACE_EN);
 
 	/* Lock the graphics update lock */
 	tmp |= EVERGREEN_GRPH_UPDATE_LOCK;
@@ -1334,36 +1333,11 @@ void evergreen_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base)
 	WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset,
 	       (u32)crtc_base);
 
-	/* Wait for update_pending to go high. */
-	for (i = 0; i < rdev->usec_timeout; i++) {
-		if (RREG32(EVERGREEN_GRPH_UPDATE + radeon_crtc->crtc_offset) & EVERGREEN_GRPH_SURFACE_UPDATE_PENDING)
-			break;
-		udelay(1);
-	}
-	DRM_DEBUG("Update pending now high. Unlocking vupdate_lock.\n");
-
-	/* Unlock the lock, so double-buffering can take place inside vblank */
+	/* Unlock the lock, so double-buffering can take place inside hblank */
 	tmp &= ~EVERGREEN_GRPH_UPDATE_LOCK;
 	WREG32(EVERGREEN_GRPH_UPDATE + radeon_crtc->crtc_offset, tmp);
 }
 
-/**
- * evergreen_page_flip_pending - check if page flip is still pending
- *
- * @rdev: radeon_device pointer
- * @crtc_id: crtc to check
- *
- * Returns the current update pending status.
- */
-bool evergreen_page_flip_pending(struct radeon_device *rdev, int crtc_id)
-{
-	struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];
-
-	/* Return current update_pending status: */
-	return !!(RREG32(EVERGREEN_GRPH_UPDATE + radeon_crtc->crtc_offset) &
-		EVERGREEN_GRPH_SURFACE_UPDATE_PENDING);
-}
-
 /* get temperature in millidegrees */
 int evergreen_get_temp(struct radeon_device *rdev)
 {
@@ -4541,23 +4515,6 @@ int evergreen_irq_set(struct radeon_device *rdev)
 		WREG32(INT_MASK + EVERGREEN_CRTC5_REGISTER_OFFSET, crtc6);
 	}
 
-	WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET,
-	       GRPH_PFLIP_INT_MASK);
-	WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET,
-	       GRPH_PFLIP_INT_MASK);
-	if (rdev->num_crtc >= 4) {
-		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET,
-		       GRPH_PFLIP_INT_MASK);
-		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET,
-		       GRPH_PFLIP_INT_MASK);
-	}
-	if (rdev->num_crtc >= 6) {
-		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET,
-		       GRPH_PFLIP_INT_MASK);
-		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET,
-		       GRPH_PFLIP_INT_MASK);
-	}
-
 	WREG32(DC_HPD1_INT_CONTROL, hpd1);
 	WREG32(DC_HPD2_INT_CONTROL, hpd2);
 	WREG32(DC_HPD3_INT_CONTROL, hpd3);
@@ -4607,10 +4564,6 @@ static void evergreen_irq_ack(struct radeon_device *rdev)
 	rdev->irq.stat_regs.evergreen.afmt_status5 = RREG32(AFMT_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET);
 	rdev->irq.stat_regs.evergreen.afmt_status6 = RREG32(AFMT_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET);
 
-	if (rdev->irq.stat_regs.evergreen.d1grph_int & GRPH_PFLIP_INT_OCCURRED)
-		WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC0_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR);
-	if (rdev->irq.stat_regs.evergreen.d2grph_int & GRPH_PFLIP_INT_OCCURRED)
-		WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC1_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR);
 	if (rdev->irq.stat_regs.evergreen.disp_int & LB_D1_VBLANK_INTERRUPT)
 		WREG32(VBLANK_STATUS + EVERGREEN_CRTC0_REGISTER_OFFSET, VBLANK_ACK);
 	if (rdev->irq.stat_regs.evergreen.disp_int & LB_D1_VLINE_INTERRUPT)
@@ -4621,10 +4574,6 @@ static void evergreen_irq_ack(struct radeon_device *rdev)
 		WREG32(VLINE_STATUS + EVERGREEN_CRTC1_REGISTER_OFFSET, VLINE_ACK);
 
 	if (rdev->num_crtc >= 4) {
-		if (rdev->irq.stat_regs.evergreen.d3grph_int & GRPH_PFLIP_INT_OCCURRED)
-			WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR);
-		if (rdev->irq.stat_regs.evergreen.d4grph_int & GRPH_PFLIP_INT_OCCURRED)
-			WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC3_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR);
 		if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & LB_D3_VBLANK_INTERRUPT)
 			WREG32(VBLANK_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET, VBLANK_ACK);
 		if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & LB_D3_VLINE_INTERRUPT)
@@ -4636,10 +4585,6 @@ static void evergreen_irq_ack(struct radeon_device *rdev)
 	}
 
 	if (rdev->num_crtc >= 6) {
-		if (rdev->irq.stat_regs.evergreen.d5grph_int & GRPH_PFLIP_INT_OCCURRED)
-			WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR);
-		if (rdev->irq.stat_regs.evergreen.d6grph_int & GRPH_PFLIP_INT_OCCURRED)
-			WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR);
 		if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & LB_D5_VBLANK_INTERRUPT)
 			WREG32(VBLANK_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET, VBLANK_ACK);
 		if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & LB_D5_VLINE_INTERRUPT)
@@ -4798,7 +4743,7 @@ restart_ih:
 						wake_up(&rdev->irq.vblank_queue);
 					}
 					if (atomic_read(&rdev->irq.pflip[0]))
-						radeon_crtc_handle_vblank(rdev, 0);
+						radeon_crtc_handle_flip(rdev, 0);
 					rdev->irq.stat_regs.evergreen.disp_int &= ~LB_D1_VBLANK_INTERRUPT;
 					DRM_DEBUG("IH: D1 vblank\n");
 				}
@@ -4824,7 +4769,7 @@ restart_ih:
 						wake_up(&rdev->irq.vblank_queue);
 					}
 					if (atomic_read(&rdev->irq.pflip[1]))
-						radeon_crtc_handle_vblank(rdev, 1);
+						radeon_crtc_handle_flip(rdev, 1);
 					rdev->irq.stat_regs.evergreen.disp_int_cont &= ~LB_D2_VBLANK_INTERRUPT;
 					DRM_DEBUG("IH: D2 vblank\n");
 				}
@@ -4850,7 +4795,7 @@ restart_ih:
 						wake_up(&rdev->irq.vblank_queue);
 					}
 					if (atomic_read(&rdev->irq.pflip[2]))
-						radeon_crtc_handle_vblank(rdev, 2);
+						radeon_crtc_handle_flip(rdev, 2);
 					rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~LB_D3_VBLANK_INTERRUPT;
 					DRM_DEBUG("IH: D3 vblank\n");
 				}
@@ -4876,7 +4821,7 @@ restart_ih:
 						wake_up(&rdev->irq.vblank_queue);
 					}
 					if (atomic_read(&rdev->irq.pflip[3]))
-						radeon_crtc_handle_vblank(rdev, 3);
+						radeon_crtc_handle_flip(rdev, 3);
 					rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~LB_D4_VBLANK_INTERRUPT;
 					DRM_DEBUG("IH: D4 vblank\n");
 				}
@@ -4902,7 +4847,7 @@ restart_ih:
 						wake_up(&rdev->irq.vblank_queue);
 					}
 					if (atomic_read(&rdev->irq.pflip[4]))
-						radeon_crtc_handle_vblank(rdev, 4);
+						radeon_crtc_handle_flip(rdev, 4);
 					rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~LB_D5_VBLANK_INTERRUPT;
 					DRM_DEBUG("IH: D5 vblank\n");
 				}
@@ -4928,7 +4873,7 @@ restart_ih:
 						wake_up(&rdev->irq.vblank_queue);
 					}
 					if (atomic_read(&rdev->irq.pflip[5]))
-						radeon_crtc_handle_vblank(rdev, 5);
+						radeon_crtc_handle_flip(rdev, 5);
 					rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~LB_D6_VBLANK_INTERRUPT;
 					DRM_DEBUG("IH: D6 vblank\n");
 				}
@@ -4944,15 +4889,6 @@ restart_ih:
 				break;
 			}
 			break;
-		case 8: /* D1 page flip */
-		case 10: /* D2 page flip */
-		case 12: /* D3 page flip */
-		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);
-			break;
 		case 42: /* HPD hotplug */
 			switch (src_data) {
 			case 0:
diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c
index ad99813..8d9f092 100644
--- a/drivers/gpu/drm/radeon/r100.c
+++ b/drivers/gpu/drm/radeon/r100.c
@@ -149,50 +149,18 @@ void r100_wait_for_vblank(struct radeon_device *rdev, int crtc)
  * @crtc_base: new address of the crtc (GPU MC address)
  *
  * Does the actual pageflip (r1xx-r4xx).
- * During vblank we take the crtc lock and wait for the update_pending
- * bit to go high, when it does, we release the lock, and allow the
- * double buffered update to take place.
  */
 void r100_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base)
 {
 	struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];
-	u32 tmp = ((u32)crtc_base) | RADEON_CRTC_OFFSET__OFFSET_LOCK;
-	int i;
-
-	/* Lock the graphics update lock */
-	/* update the scanout addresses */
-	WREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset, tmp);
+	u32 crtc_offset_cntl = RREG32(RADEON_CRTC_OFFSET_CNTL);
 
-	/* Wait for update_pending to go high. */
-	for (i = 0; i < rdev->usec_timeout; i++) {
-		if (RREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset) & RADEON_CRTC_OFFSET__GUI_TRIG_OFFSET)
-			break;
-		udelay(1);
-	}
-	DRM_DEBUG("Update pending now high. Unlocking vupdate_lock.\n");
-
-	/* Unlock the lock, so double-buffering can take place inside vblank */
-	tmp &= ~RADEON_CRTC_OFFSET__OFFSET_LOCK;
-	WREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset, tmp);
-
-}
-
-/**
- * r100_page_flip_pending - check if page flip is still pending
- *
- * @rdev: radeon_device pointer
- * @crtc_id: crtc to check
- *
- * Check if the last pagefilp is still pending (r1xx-r4xx).
- * Returns the current update pending status.
- */
-bool r100_page_flip_pending(struct radeon_device *rdev, int crtc_id)
-{
-	struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];
+	/* Take surface updates at horizontal blank */
+	WREG32(RADEON_CRTC_OFFSET_CNTL,
+	       crtc_offset_cntl | RADEON_CRTC_OFFSET_FLIP_CNTL);
 
-	/* Return current update_pending status: */
-	return !!(RREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset) &
-		RADEON_CRTC_OFFSET__GUI_TRIG_OFFSET);
+	/* Update the scanout address */
+	WREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset, crtc_base);
 }
 
 /**
@@ -779,7 +747,7 @@ int r100_irq_process(struct radeon_device *rdev)
 				wake_up(&rdev->irq.vblank_queue);
 			}
 			if (atomic_read(&rdev->irq.pflip[0]))
-				radeon_crtc_handle_vblank(rdev, 0);
+				radeon_crtc_handle_flip(rdev, 0);
 		}
 		if (status & RADEON_CRTC2_VBLANK_STAT) {
 			if (rdev->irq.crtc_vblank_int[1]) {
@@ -788,7 +756,7 @@ int r100_irq_process(struct radeon_device *rdev)
 				wake_up(&rdev->irq.vblank_queue);
 			}
 			if (atomic_read(&rdev->irq.pflip[1]))
-				radeon_crtc_handle_vblank(rdev, 1);
+				radeon_crtc_handle_flip(rdev, 1);
 		}
 		if (status & RADEON_FP_DETECT_STAT) {
 			queue_hotplug = true;
diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c
index ae54f76..8f318ec 100644
--- a/drivers/gpu/drm/radeon/r600.c
+++ b/drivers/gpu/drm/radeon/r600.c
@@ -3614,8 +3614,6 @@ 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(GRBM_INT_CNTL, grbm_int_cntl);
 	if (ASIC_IS_DCE3(rdev)) {
 		WREG32(DC_HPD1_INT_CONTROL, hpd1);
@@ -3672,10 +3670,6 @@ static void r600_irq_ack(struct radeon_device *rdev)
 	rdev->irq.stat_regs.r600.d1grph_int = RREG32(D1GRPH_INTERRUPT_STATUS);
 	rdev->irq.stat_regs.r600.d2grph_int = RREG32(D2GRPH_INTERRUPT_STATUS);
 
-	if (rdev->irq.stat_regs.r600.d1grph_int & DxGRPH_PFLIP_INT_OCCURRED)
-		WREG32(D1GRPH_INTERRUPT_STATUS, DxGRPH_PFLIP_INT_CLEAR);
-	if (rdev->irq.stat_regs.r600.d2grph_int & DxGRPH_PFLIP_INT_OCCURRED)
-		WREG32(D2GRPH_INTERRUPT_STATUS, DxGRPH_PFLIP_INT_CLEAR);
 	if (rdev->irq.stat_regs.r600.disp_int & LB_D1_VBLANK_INTERRUPT)
 		WREG32(D1MODE_VBLANK_STATUS, DxMODE_VBLANK_ACK);
 	if (rdev->irq.stat_regs.r600.disp_int & LB_D1_VLINE_INTERRUPT)
@@ -3876,7 +3870,7 @@ restart_ih:
 						wake_up(&rdev->irq.vblank_queue);
 					}
 					if (atomic_read(&rdev->irq.pflip[0]))
-						radeon_crtc_handle_vblank(rdev, 0);
+						radeon_crtc_handle_flip(rdev, 0);
 					rdev->irq.stat_regs.r600.disp_int &= ~LB_D1_VBLANK_INTERRUPT;
 					DRM_DEBUG("IH: D1 vblank\n");
 				}
@@ -3902,7 +3896,7 @@ restart_ih:
 						wake_up(&rdev->irq.vblank_queue);
 					}
 					if (atomic_read(&rdev->irq.pflip[1]))
-						radeon_crtc_handle_vblank(rdev, 1);
+						radeon_crtc_handle_flip(rdev, 1);
 					rdev->irq.stat_regs.r600.disp_int &= ~LB_D2_VBLANK_INTERRUPT;
 					DRM_DEBUG("IH: D2 vblank\n");
 				}
@@ -3918,14 +3912,6 @@ restart_ih:
 				break;
 			}
 			break;
-		case 9: /* D1 pflip */
-			DRM_DEBUG("IH: D1 flip\n");
-			radeon_crtc_handle_flip(rdev, 0);
-			break;
-		case 11: /* D2 pflip */
-			DRM_DEBUG("IH: D2 flip\n");
-			radeon_crtc_handle_flip(rdev, 1);
-			break;
 		case 19: /* HPD/DAC hotplug */
 			switch (src_data) {
 			case 0:
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index 8e8ef08..7a45c93 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -681,6 +681,7 @@ struct radeon_flip_work {
 	struct work_struct		unpin_work;
 	struct radeon_device		*rdev;
 	int				crtc_id;
+	uint64_t			base;
 	struct drm_framebuffer		*fb;
 	struct drm_pending_vblank_event *event;
 	struct radeon_bo		*old_rbo;
@@ -1884,7 +1885,6 @@ struct radeon_asic {
 	/* pageflipping */
 	struct {
 		void (*page_flip)(struct radeon_device *rdev, int crtc, u64 crtc_base);
-		bool (*page_flip_pending)(struct radeon_device *rdev, int crtc);
 	} pflip;
 };
 
@@ -2746,7 +2746,6 @@ void radeon_ring_write(struct radeon_ring *ring, uint32_t v);
 #define radeon_pm_init_profile(rdev) (rdev)->asic->pm.init_profile((rdev))
 #define radeon_pm_get_dynpm_state(rdev) (rdev)->asic->pm.get_dynpm_state((rdev))
 #define radeon_page_flip(rdev, crtc, base) (rdev)->asic->pflip.page_flip((rdev), (crtc), (base))
-#define radeon_page_flip_pending(rdev, crtc) (rdev)->asic->pflip.page_flip_pending((rdev), (crtc))
 #define radeon_wait_for_vblank(rdev, crtc) (rdev)->asic->display.wait_for_vblank((rdev), (crtc))
 #define radeon_mc_wait_for_idle(rdev) (rdev)->asic->mc_wait_for_idle((rdev))
 #define radeon_get_xclk(rdev) (rdev)->asic->get_xclk((rdev))
diff --git a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c
index 7ef3fc6..9943fb1 100644
--- a/drivers/gpu/drm/radeon/radeon_asic.c
+++ b/drivers/gpu/drm/radeon/radeon_asic.c
@@ -249,7 +249,6 @@ static struct radeon_asic r100_asic = {
 	},
 	.pflip = {
 		.page_flip = &r100_page_flip,
-		.page_flip_pending = &r100_page_flip_pending,
 	},
 };
 
@@ -315,7 +314,6 @@ static struct radeon_asic r200_asic = {
 	},
 	.pflip = {
 		.page_flip = &r100_page_flip,
-		.page_flip_pending = &r100_page_flip_pending,
 	},
 };
 
@@ -395,7 +393,6 @@ static struct radeon_asic r300_asic = {
 	},
 	.pflip = {
 		.page_flip = &r100_page_flip,
-		.page_flip_pending = &r100_page_flip_pending,
 	},
 };
 
@@ -461,7 +458,6 @@ static struct radeon_asic r300_asic_pcie = {
 	},
 	.pflip = {
 		.page_flip = &r100_page_flip,
-		.page_flip_pending = &r100_page_flip_pending,
 	},
 };
 
@@ -527,7 +523,6 @@ static struct radeon_asic r420_asic = {
 	},
 	.pflip = {
 		.page_flip = &r100_page_flip,
-		.page_flip_pending = &r100_page_flip_pending,
 	},
 };
 
@@ -593,7 +588,6 @@ static struct radeon_asic rs400_asic = {
 	},
 	.pflip = {
 		.page_flip = &r100_page_flip,
-		.page_flip_pending = &r100_page_flip_pending,
 	},
 };
 
@@ -662,7 +656,6 @@ static struct radeon_asic rs600_asic = {
 	},
 	.pflip = {
 		.page_flip = &rs600_page_flip,
-		.page_flip_pending = &rs600_page_flip_pending,
 	},
 };
 
@@ -730,7 +723,6 @@ static struct radeon_asic rs690_asic = {
 	},
 	.pflip = {
 		.page_flip = &rs600_page_flip,
-		.page_flip_pending = &rs600_page_flip_pending,
 	},
 };
 
@@ -796,7 +788,6 @@ static struct radeon_asic rv515_asic = {
 	},
 	.pflip = {
 		.page_flip = &rs600_page_flip,
-		.page_flip_pending = &rs600_page_flip_pending,
 	},
 };
 
@@ -862,7 +853,6 @@ static struct radeon_asic r520_asic = {
 	},
 	.pflip = {
 		.page_flip = &rs600_page_flip,
-		.page_flip_pending = &rs600_page_flip_pending,
 	},
 };
 
@@ -961,7 +951,6 @@ static struct radeon_asic r600_asic = {
 	},
 	.pflip = {
 		.page_flip = &rs600_page_flip,
-		.page_flip_pending = &rs600_page_flip_pending,
 	},
 };
 
@@ -1052,7 +1041,6 @@ static struct radeon_asic rv6xx_asic = {
 	},
 	.pflip = {
 		.page_flip = &rs600_page_flip,
-		.page_flip_pending = &rs600_page_flip_pending,
 	},
 };
 
@@ -1143,7 +1131,6 @@ static struct radeon_asic rs780_asic = {
 	},
 	.pflip = {
 		.page_flip = &rs600_page_flip,
-		.page_flip_pending = &rs600_page_flip_pending,
 	},
 };
 
@@ -1249,7 +1236,6 @@ static struct radeon_asic rv770_asic = {
 	},
 	.pflip = {
 		.page_flip = &rv770_page_flip,
-		.page_flip_pending = &rv770_page_flip_pending,
 	},
 };
 
@@ -1368,7 +1354,6 @@ static struct radeon_asic evergreen_asic = {
 	},
 	.pflip = {
 		.page_flip = &evergreen_page_flip,
-		.page_flip_pending = &evergreen_page_flip_pending,
 	},
 };
 
@@ -1460,7 +1445,6 @@ static struct radeon_asic sumo_asic = {
 	},
 	.pflip = {
 		.page_flip = &evergreen_page_flip,
-		.page_flip_pending = &evergreen_page_flip_pending,
 	},
 };
 
@@ -1553,7 +1537,6 @@ static struct radeon_asic btc_asic = {
 	},
 	.pflip = {
 		.page_flip = &evergreen_page_flip,
-		.page_flip_pending = &evergreen_page_flip_pending,
 	},
 };
 
@@ -1697,7 +1680,6 @@ static struct radeon_asic cayman_asic = {
 	},
 	.pflip = {
 		.page_flip = &evergreen_page_flip,
-		.page_flip_pending = &evergreen_page_flip_pending,
 	},
 };
 
@@ -1798,7 +1780,6 @@ static struct radeon_asic trinity_asic = {
 	},
 	.pflip = {
 		.page_flip = &evergreen_page_flip,
-		.page_flip_pending = &evergreen_page_flip_pending,
 	},
 };
 
@@ -1929,7 +1910,6 @@ static struct radeon_asic si_asic = {
 	},
 	.pflip = {
 		.page_flip = &evergreen_page_flip,
-		.page_flip_pending = &evergreen_page_flip_pending,
 	},
 };
 
@@ -2092,7 +2072,6 @@ static struct radeon_asic ci_asic = {
 	},
 	.pflip = {
 		.page_flip = &evergreen_page_flip,
-		.page_flip_pending = &evergreen_page_flip_pending,
 	},
 };
 
@@ -2197,7 +2176,6 @@ static struct radeon_asic kv_asic = {
 	},
 	.pflip = {
 		.page_flip = &evergreen_page_flip,
-		.page_flip_pending = &evergreen_page_flip_pending,
 	},
 };
 
diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h
index 645a3de..170a80c 100644
--- a/drivers/gpu/drm/radeon/radeon_asic.h
+++ b/drivers/gpu/drm/radeon/radeon_asic.h
@@ -137,7 +137,6 @@ extern void r100_pm_init_profile(struct radeon_device *rdev);
 extern void r100_pm_get_dynpm_state(struct radeon_device *rdev);
 extern void r100_page_flip(struct radeon_device *rdev, int crtc,
 			   u64 crtc_base);
-extern bool r100_page_flip_pending(struct radeon_device *rdev, int crtc);
 extern void r100_wait_for_vblank(struct radeon_device *rdev, int crtc);
 extern int r100_mc_wait_for_idle(struct radeon_device *rdev);
 
@@ -244,7 +243,6 @@ extern void rs600_pm_prepare(struct radeon_device *rdev);
 extern void rs600_pm_finish(struct radeon_device *rdev);
 extern void rs600_page_flip(struct radeon_device *rdev, int crtc,
 			    u64 crtc_base);
-extern bool rs600_page_flip_pending(struct radeon_device *rdev, int crtc);
 void rs600_set_safe_registers(struct radeon_device *rdev);
 extern void avivo_wait_for_vblank(struct radeon_device *rdev, int crtc);
 extern int rs600_mc_wait_for_idle(struct radeon_device *rdev);
@@ -449,7 +447,6 @@ int rv770_suspend(struct radeon_device *rdev);
 int rv770_resume(struct radeon_device *rdev);
 void rv770_pm_misc(struct radeon_device *rdev);
 void rv770_page_flip(struct radeon_device *rdev, int crtc, u64 crtc_base);
-bool rv770_page_flip_pending(struct radeon_device *rdev, int crtc);
 void r700_vram_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc);
 void r700_cp_stop(struct radeon_device *rdev);
 void r700_cp_fini(struct radeon_device *rdev);
@@ -517,7 +514,6 @@ int sumo_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk);
 int evergreen_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk);
 extern void evergreen_page_flip(struct radeon_device *rdev, int crtc,
 				u64 crtc_base);
-extern bool evergreen_page_flip_pending(struct radeon_device *rdev, int crtc);
 extern void dce4_wait_for_vblank(struct radeon_device *rdev, int crtc);
 void evergreen_disable_interrupt_state(struct radeon_device *rdev);
 int evergreen_mc_wait_for_idle(struct radeon_device *rdev);
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c
index 65882cd..e66323e 100644
--- a/drivers/gpu/drm/radeon/radeon_display.c
+++ b/drivers/gpu/drm/radeon/radeon_display.c
@@ -281,50 +281,6 @@ static void radeon_unpin_work_func(struct work_struct *__work)
 	kfree(work);
 }
 
-void radeon_crtc_handle_vblank(struct radeon_device *rdev, int crtc_id)
-{
-	struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];
-	unsigned long flags;
-	u32 update_pending;
-	int vpos, hpos;
-
-	/* can happen during initialization */
-	if (radeon_crtc == NULL)
-		return;
-
-	spin_lock_irqsave(&rdev->ddev->event_lock, flags);
-	if (radeon_crtc->flip_status != RADEON_FLIP_SUBMITTED) {
-		DRM_DEBUG_DRIVER("radeon_crtc->flip_status = %d != "
-				 "RADEON_FLIP_SUBMITTED(%d)\n",
-				 radeon_crtc->flip_status,
-				 RADEON_FLIP_SUBMITTED);
-		spin_unlock_irqrestore(&rdev->ddev->event_lock, flags);
-		return;
-	}
-
-	update_pending = radeon_page_flip_pending(rdev, crtc_id);
-
-	/* Has the pageflip already completed in crtc, or is it certain
-	 * to complete in this vblank?
-	 */
-	if (update_pending &&
-	    (DRM_SCANOUTPOS_VALID & radeon_get_crtc_scanoutpos(rdev->ddev, crtc_id, 0,
-							       &vpos, &hpos, NULL, NULL)) &&
-	    ((vpos >= (99 * rdev->mode_info.crtcs[crtc_id]->base.hwmode.crtc_vdisplay)/100) ||
-	     (vpos < 0 && !ASIC_IS_AVIVO(rdev)))) {
-		/* crtc didn't flip in this target vblank interval,
-		 * but flip is pending in crtc. Based on the current
-		 * scanout position we know that the current frame is
-		 * (nearly) complete and the flip will (likely)
-		 * complete before the start of the next frame.
-		 */
-		update_pending = 0;
-	}
-	spin_unlock_irqrestore(&rdev->ddev->event_lock, flags);
-	if (!update_pending)
-		radeon_crtc_handle_flip(rdev, crtc_id);
-}
-
 /**
  * radeon_crtc_handle_flip - page flip completed
  *
@@ -354,6 +310,9 @@ void radeon_crtc_handle_flip(struct radeon_device *rdev, int crtc_id)
 		return;
 	}
 
+	/* do the flip (mmio) */
+	radeon_page_flip(rdev, radeon_crtc->crtc_id, work->base);
+
 	/* Pageflip completed. Clean up. */
 	radeon_crtc->flip_status = RADEON_FLIP_NONE;
 	radeon_crtc->flip_work = NULL;
@@ -479,9 +438,7 @@ static void radeon_flip_work_func(struct work_struct *__work)
 	/* set the proper interrupt */
 	radeon_irq_kms_pflip_irq_get(rdev, radeon_crtc->crtc_id);
 
-	/* do the flip (mmio) */
-	radeon_page_flip(rdev, radeon_crtc->crtc_id, base);
-
+	work->base = base;
 	radeon_crtc->flip_status = RADEON_FLIP_SUBMITTED;
 	spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
 	up_read(&rdev->exclusive_lock);
diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h
index ed6b6e0..1810a12 100644
--- a/drivers/gpu/drm/radeon/radeon_mode.h
+++ b/drivers/gpu/drm/radeon/radeon_mode.h
@@ -913,7 +913,6 @@ bool radeon_fbdev_robj_is_fb(struct radeon_device *rdev, struct radeon_bo *robj)
 
 void radeon_fb_output_poll_changed(struct radeon_device *rdev);
 
-void radeon_crtc_handle_vblank(struct radeon_device *rdev, int crtc_id);
 void radeon_crtc_handle_flip(struct radeon_device *rdev, int crtc_id);
 
 int radeon_align_pitch(struct radeon_device *rdev, int width, int bpp, bool tiled);
diff --git a/drivers/gpu/drm/radeon/rs600.c b/drivers/gpu/drm/radeon/rs600.c
index 818f4eb..b5e63a7 100644
--- a/drivers/gpu/drm/radeon/rs600.c
+++ b/drivers/gpu/drm/radeon/rs600.c
@@ -113,7 +113,10 @@ void rs600_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base)
 {
 	struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];
 	u32 tmp = RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset);
-	int i;
+
+	/* Take surface updates at horizontal blank */
+	WREG32(AVIVO_D1GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset,
+	       AVIVO_D1GRPH_SURFACE_UPDATE_H_RETRACE_EN);
 
 	/* Lock the graphics update lock */
 	tmp |= AVIVO_D1GRPH_UPDATE_LOCK;
@@ -125,28 +128,11 @@ void rs600_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base)
 	WREG32(AVIVO_D1GRPH_PRIMARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset,
 	       (u32)crtc_base);
 
-	/* Wait for update_pending to go high. */
-	for (i = 0; i < rdev->usec_timeout; i++) {
-		if (RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset) & AVIVO_D1GRPH_SURFACE_UPDATE_PENDING)
-			break;
-		udelay(1);
-	}
-	DRM_DEBUG("Update pending now high. Unlocking vupdate_lock.\n");
-
-	/* Unlock the lock, so double-buffering can take place inside vblank */
+	/* Unlock the lock, so double-buffering can take place inside hblank */
 	tmp &= ~AVIVO_D1GRPH_UPDATE_LOCK;
 	WREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset, tmp);
 }
 
-bool rs600_page_flip_pending(struct radeon_device *rdev, int crtc_id)
-{
-	struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];
-
-	/* Return current update_pending status: */
-	return !!(RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset) &
-		AVIVO_D1GRPH_SURFACE_UPDATE_PENDING);
-}
-
 void avivo_program_fmt(struct drm_encoder *encoder)
 {
 	struct drm_device *dev = encoder->dev;
@@ -790,7 +776,7 @@ int rs600_irq_process(struct radeon_device *rdev)
 				wake_up(&rdev->irq.vblank_queue);
 			}
 			if (atomic_read(&rdev->irq.pflip[0]))
-				radeon_crtc_handle_vblank(rdev, 0);
+				radeon_crtc_handle_flip(rdev, 0);
 		}
 		if (G_007EDC_LB_D2_VBLANK_INTERRUPT(rdev->irq.stat_regs.r500.disp_int)) {
 			if (rdev->irq.crtc_vblank_int[1]) {
@@ -799,7 +785,7 @@ int rs600_irq_process(struct radeon_device *rdev)
 				wake_up(&rdev->irq.vblank_queue);
 			}
 			if (atomic_read(&rdev->irq.pflip[1]))
-				radeon_crtc_handle_vblank(rdev, 1);
+				radeon_crtc_handle_flip(rdev, 1);
 		}
 		if (G_007EDC_DC_HOT_PLUG_DETECT1_INTERRUPT(rdev->irq.stat_regs.r500.disp_int)) {
 			queue_hotplug = true;
diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c
index 97b7766..ef66be4 100644
--- a/drivers/gpu/drm/radeon/rv770.c
+++ b/drivers/gpu/drm/radeon/rv770.c
@@ -805,7 +805,10 @@ void rv770_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base)
 {
 	struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];
 	u32 tmp = RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset);
-	int i;
+
+	/* Take surface updates at horizontal blank */
+	WREG32(AVIVO_D1GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset,
+	       AVIVO_D1GRPH_SURFACE_UPDATE_H_RETRACE_EN);
 
 	/* Lock the graphics update lock */
 	tmp |= AVIVO_D1GRPH_UPDATE_LOCK;
@@ -824,28 +827,11 @@ void rv770_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base)
 	WREG32(D1GRPH_PRIMARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset,
 	       (u32)crtc_base);
 
-	/* Wait for update_pending to go high. */
-	for (i = 0; i < rdev->usec_timeout; i++) {
-		if (RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset) & AVIVO_D1GRPH_SURFACE_UPDATE_PENDING)
-			break;
-		udelay(1);
-	}
-	DRM_DEBUG("Update pending now high. Unlocking vupdate_lock.\n");
-
-	/* Unlock the lock, so double-buffering can take place inside vblank */
+	/* Unlock the lock, so double-buffering can take place inside hblank */
 	tmp &= ~AVIVO_D1GRPH_UPDATE_LOCK;
 	WREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset, tmp);
 }
 
-bool rv770_page_flip_pending(struct radeon_device *rdev, int crtc_id)
-{
-	struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];
-
-	/* Return current update_pending status: */
-	return !!(RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset) &
-		AVIVO_D1GRPH_SURFACE_UPDATE_PENDING);
-}
-
 /* get temperature in millidegrees */
 int rv770_get_temp(struct radeon_device *rdev)
 {
diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c
index c128bde..fee797f 100644
--- a/drivers/gpu/drm/radeon/si.c
+++ b/drivers/gpu/drm/radeon/si.c
@@ -5917,25 +5917,6 @@ int si_irq_set(struct radeon_device *rdev)
 		WREG32(INT_MASK + EVERGREEN_CRTC5_REGISTER_OFFSET, crtc6);
 	}
 
-	if (rdev->num_crtc >= 2) {
-		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET,
-		       GRPH_PFLIP_INT_MASK);
-		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET,
-		       GRPH_PFLIP_INT_MASK);
-	}
-	if (rdev->num_crtc >= 4) {
-		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET,
-		       GRPH_PFLIP_INT_MASK);
-		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET,
-		       GRPH_PFLIP_INT_MASK);
-	}
-	if (rdev->num_crtc >= 6) {
-		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET,
-		       GRPH_PFLIP_INT_MASK);
-		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET,
-		       GRPH_PFLIP_INT_MASK);
-	}
-
 	if (!ASIC_IS_NODCE(rdev)) {
 		WREG32(DC_HPD1_INT_CONTROL, hpd1);
 		WREG32(DC_HPD2_INT_CONTROL, hpd2);
@@ -5974,10 +5955,6 @@ static inline void si_irq_ack(struct radeon_device *rdev)
 		rdev->irq.stat_regs.evergreen.d6grph_int = RREG32(GRPH_INT_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET);
 	}
 
-	if (rdev->irq.stat_regs.evergreen.d1grph_int & GRPH_PFLIP_INT_OCCURRED)
-		WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC0_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR);
-	if (rdev->irq.stat_regs.evergreen.d2grph_int & GRPH_PFLIP_INT_OCCURRED)
-		WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC1_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR);
 	if (rdev->irq.stat_regs.evergreen.disp_int & LB_D1_VBLANK_INTERRUPT)
 		WREG32(VBLANK_STATUS + EVERGREEN_CRTC0_REGISTER_OFFSET, VBLANK_ACK);
 	if (rdev->irq.stat_regs.evergreen.disp_int & LB_D1_VLINE_INTERRUPT)
@@ -5988,10 +5965,6 @@ static inline void si_irq_ack(struct radeon_device *rdev)
 		WREG32(VLINE_STATUS + EVERGREEN_CRTC1_REGISTER_OFFSET, VLINE_ACK);
 
 	if (rdev->num_crtc >= 4) {
-		if (rdev->irq.stat_regs.evergreen.d3grph_int & GRPH_PFLIP_INT_OCCURRED)
-			WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR);
-		if (rdev->irq.stat_regs.evergreen.d4grph_int & GRPH_PFLIP_INT_OCCURRED)
-			WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC3_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR);
 		if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & LB_D3_VBLANK_INTERRUPT)
 			WREG32(VBLANK_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET, VBLANK_ACK);
 		if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & LB_D3_VLINE_INTERRUPT)
@@ -6003,10 +5976,6 @@ static inline void si_irq_ack(struct radeon_device *rdev)
 	}
 
 	if (rdev->num_crtc >= 6) {
-		if (rdev->irq.stat_regs.evergreen.d5grph_int & GRPH_PFLIP_INT_OCCURRED)
-			WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR);
-		if (rdev->irq.stat_regs.evergreen.d6grph_int & GRPH_PFLIP_INT_OCCURRED)
-			WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR);
 		if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & LB_D5_VBLANK_INTERRUPT)
 			WREG32(VBLANK_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET, VBLANK_ACK);
 		if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & LB_D5_VLINE_INTERRUPT)
@@ -6151,7 +6120,7 @@ restart_ih:
 						wake_up(&rdev->irq.vblank_queue);
 					}
 					if (atomic_read(&rdev->irq.pflip[0]))
-						radeon_crtc_handle_vblank(rdev, 0);
+						radeon_crtc_handle_flip(rdev, 0);
 					rdev->irq.stat_regs.evergreen.disp_int &= ~LB_D1_VBLANK_INTERRUPT;
 					DRM_DEBUG("IH: D1 vblank\n");
 				}
@@ -6177,7 +6146,7 @@ restart_ih:
 						wake_up(&rdev->irq.vblank_queue);
 					}
 					if (atomic_read(&rdev->irq.pflip[1]))
-						radeon_crtc_handle_vblank(rdev, 1);
+						radeon_crtc_handle_flip(rdev, 1);
 					rdev->irq.stat_regs.evergreen.disp_int_cont &= ~LB_D2_VBLANK_INTERRUPT;
 					DRM_DEBUG("IH: D2 vblank\n");
 				}
@@ -6203,7 +6172,7 @@ restart_ih:
 						wake_up(&rdev->irq.vblank_queue);
 					}
 					if (atomic_read(&rdev->irq.pflip[2]))
-						radeon_crtc_handle_vblank(rdev, 2);
+						radeon_crtc_handle_flip(rdev, 2);
 					rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~LB_D3_VBLANK_INTERRUPT;
 					DRM_DEBUG("IH: D3 vblank\n");
 				}
@@ -6229,7 +6198,7 @@ restart_ih:
 						wake_up(&rdev->irq.vblank_queue);
 					}
 					if (atomic_read(&rdev->irq.pflip[3]))
-						radeon_crtc_handle_vblank(rdev, 3);
+						radeon_crtc_handle_flip(rdev, 3);
 					rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~LB_D4_VBLANK_INTERRUPT;
 					DRM_DEBUG("IH: D4 vblank\n");
 				}
@@ -6255,7 +6224,7 @@ restart_ih:
 						wake_up(&rdev->irq.vblank_queue);
 					}
 					if (atomic_read(&rdev->irq.pflip[4]))
-						radeon_crtc_handle_vblank(rdev, 4);
+						radeon_crtc_handle_flip(rdev, 4);
 					rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~LB_D5_VBLANK_INTERRUPT;
 					DRM_DEBUG("IH: D5 vblank\n");
 				}
@@ -6281,7 +6250,7 @@ restart_ih:
 						wake_up(&rdev->irq.vblank_queue);
 					}
 					if (atomic_read(&rdev->irq.pflip[5]))
-						radeon_crtc_handle_vblank(rdev, 5);
+						radeon_crtc_handle_flip(rdev, 5);
 					rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~LB_D6_VBLANK_INTERRUPT;
 					DRM_DEBUG("IH: D6 vblank\n");
 				}
@@ -6297,15 +6266,6 @@ restart_ih:
 				break;
 			}
 			break;
-		case 8: /* D1 page flip */
-		case 10: /* D2 page flip */
-		case 12: /* D3 page flip */
-		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);
-			break;
 		case 42: /* HPD hotplug */
 			switch (src_data) {
 			case 0:
-- 
2.0.0

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH 2/2] drm/radeon: Remove radeon_kms_pflip_irq_get/put()
  2014-07-01  8:14               ` [PATCH 1/2] drm/radeon: Program page flips to execute in hblank instead of vblank Michel Dänzer
@ 2014-07-01  8:14                 ` Michel Dänzer
  2014-07-01 10:12                 ` [PATCH 1/2] drm/radeon: Program page flips to execute in hblank instead of vblank Christian König
  2014-07-01 16:46                 ` [PATCH " Dieter Nützel
  2 siblings, 0 replies; 34+ messages in thread
From: Michel Dänzer @ 2014-07-01  8:14 UTC (permalink / raw)
  To: dri-devel

From: Michel Dänzer <michel.daenzer@amd.com>

The vertical blank interrupt is already enabled/disabled via
drm_vblank_get/put(), so we only need to update the number of pending
page flips.

Signed-off-by: Michel Dänzer <michel.daenzer@amd.com>
---
 drivers/gpu/drm/radeon/radeon.h         |  2 --
 drivers/gpu/drm/radeon/radeon_display.c |  5 ++--
 drivers/gpu/drm/radeon/radeon_irq_kms.c | 52 ---------------------------------
 3 files changed, 2 insertions(+), 57 deletions(-)

diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index 7a45c93..e497ed5 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -769,8 +769,6 @@ int radeon_irq_kms_init(struct radeon_device *rdev);
 void radeon_irq_kms_fini(struct radeon_device *rdev);
 void radeon_irq_kms_sw_irq_get(struct radeon_device *rdev, int ring);
 void radeon_irq_kms_sw_irq_put(struct radeon_device *rdev, int ring);
-void radeon_irq_kms_pflip_irq_get(struct radeon_device *rdev, int crtc);
-void radeon_irq_kms_pflip_irq_put(struct radeon_device *rdev, int crtc);
 void radeon_irq_kms_enable_afmt(struct radeon_device *rdev, int block);
 void radeon_irq_kms_disable_afmt(struct radeon_device *rdev, int block);
 void radeon_irq_kms_enable_hpd(struct radeon_device *rdev, unsigned hpd_mask);
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c
index e66323e..2c54483 100644
--- a/drivers/gpu/drm/radeon/radeon_display.c
+++ b/drivers/gpu/drm/radeon/radeon_display.c
@@ -325,7 +325,7 @@ void radeon_crtc_handle_flip(struct radeon_device *rdev, int crtc_id)
 
 	drm_vblank_put(rdev->ddev, radeon_crtc->crtc_id);
 	radeon_fence_unref(&work->fence);
-	radeon_irq_kms_pflip_irq_put(rdev, work->crtc_id);
+	atomic_dec(&rdev->irq.pflip[radeon_crtc->crtc_id]);
 	queue_work(radeon_crtc->flip_queue, &work->unpin_work);
 }
 
@@ -435,8 +435,7 @@ static void radeon_flip_work_func(struct work_struct *__work)
 	/* We borrow the event spin lock for protecting flip_work */
 	spin_lock_irqsave(&crtc->dev->event_lock, flags);
 
-	/* set the proper interrupt */
-	radeon_irq_kms_pflip_irq_get(rdev, radeon_crtc->crtc_id);
+	atomic_inc(&rdev->irq.pflip[radeon_crtc->crtc_id]);
 
 	work->base = base;
 	radeon_crtc->flip_status = RADEON_FLIP_SUBMITTED;
diff --git a/drivers/gpu/drm/radeon/radeon_irq_kms.c b/drivers/gpu/drm/radeon/radeon_irq_kms.c
index 089c9ff..8633f82 100644
--- a/drivers/gpu/drm/radeon/radeon_irq_kms.c
+++ b/drivers/gpu/drm/radeon/radeon_irq_kms.c
@@ -366,58 +366,6 @@ void radeon_irq_kms_sw_irq_put(struct radeon_device *rdev, int ring)
 }
 
 /**
- * radeon_irq_kms_pflip_irq_get - enable pageflip interrupt
- *
- * @rdev: radeon device pointer
- * @crtc: crtc whose interrupt you want to enable
- *
- * Enables the pageflip interrupt for a specific crtc (all asics).
- * For pageflips we use the vblank interrupt source.
- */
-void radeon_irq_kms_pflip_irq_get(struct radeon_device *rdev, int crtc)
-{
-	unsigned long irqflags;
-
-	if (crtc < 0 || crtc >= rdev->num_crtc)
-		return;
-
-	if (!rdev->ddev->irq_enabled)
-		return;
-
-	if (atomic_inc_return(&rdev->irq.pflip[crtc]) == 1) {
-		spin_lock_irqsave(&rdev->irq.lock, irqflags);
-		radeon_irq_set(rdev);
-		spin_unlock_irqrestore(&rdev->irq.lock, irqflags);
-	}
-}
-
-/**
- * radeon_irq_kms_pflip_irq_put - disable pageflip interrupt
- *
- * @rdev: radeon device pointer
- * @crtc: crtc whose interrupt you want to disable
- *
- * Disables the pageflip interrupt for a specific crtc (all asics).
- * For pageflips we use the vblank interrupt source.
- */
-void radeon_irq_kms_pflip_irq_put(struct radeon_device *rdev, int crtc)
-{
-	unsigned long irqflags;
-
-	if (crtc < 0 || crtc >= rdev->num_crtc)
-		return;
-
-	if (!rdev->ddev->irq_enabled)
-		return;
-
-	if (atomic_dec_and_test(&rdev->irq.pflip[crtc])) {
-		spin_lock_irqsave(&rdev->irq.lock, irqflags);
-		radeon_irq_set(rdev);
-		spin_unlock_irqrestore(&rdev->irq.lock, irqflags);
-	}
-}
-
-/**
  * radeon_irq_kms_enable_afmt - enable audio format change interrupt
  *
  * @rdev: radeon device pointer
-- 
2.0.0

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 34+ messages in thread

* Re: [PATCH 1/2] drm/radeon: Program page flips to execute in hblank instead of vblank
  2014-07-01  8:14               ` [PATCH 1/2] drm/radeon: Program page flips to execute in hblank instead of vblank Michel Dänzer
  2014-07-01  8:14                 ` [PATCH 2/2] drm/radeon: Remove radeon_kms_pflip_irq_get/put() Michel Dänzer
@ 2014-07-01 10:12                 ` Christian König
  2014-07-02  3:55                   ` [PATCH v2 " Michel Dänzer
  2014-07-01 16:46                 ` [PATCH " Dieter Nützel
  2 siblings, 1 reply; 34+ messages in thread
From: Christian König @ 2014-07-01 10:12 UTC (permalink / raw)
  To: Michel Dänzer, dri-devel

Am 01.07.2014 10:14, schrieb Michel Dänzer:
> From: Michel Dänzer <michel.daenzer@amd.com>
>
> But move the programming back to the vertical blank interrupt handler.
> And signal the flip as being completed immediately after programming it
> to the hardware.
>
> This way we don't have to guess whether or not the hardware will execute
> the flip in a given vertical blank period, avoiding a whole lot of
> trouble.
>
> Also, not using the page flip interrupt anymore avoids problems due to
> completing page flips earlier than expected by userspace.
>
> Signed-off-by: Michel Dänzer <michel.daenzer@amd.com>

I would say to let's nuke rdev->irq.pflip as well and just rely on the 
flip_status to track weather or not there is an page flip scheduled.

Apart from that the two patches look good to me,
Christian.

> ---
>   drivers/gpu/drm/radeon/atombios_crtc.c  | 28 ++++-------
>   drivers/gpu/drm/radeon/cik.c            | 58 +++-------------------
>   drivers/gpu/drm/radeon/evergreen.c      | 86 +++++----------------------------
>   drivers/gpu/drm/radeon/r100.c           | 48 +++---------------
>   drivers/gpu/drm/radeon/r600.c           | 18 +------
>   drivers/gpu/drm/radeon/radeon.h         |  3 +-
>   drivers/gpu/drm/radeon/radeon_asic.c    | 22 ---------
>   drivers/gpu/drm/radeon/radeon_asic.h    |  4 --
>   drivers/gpu/drm/radeon/radeon_display.c | 51 ++-----------------
>   drivers/gpu/drm/radeon/radeon_mode.h    |  1 -
>   drivers/gpu/drm/radeon/rs600.c          | 28 +++--------
>   drivers/gpu/drm/radeon/rv770.c          | 24 ++-------
>   drivers/gpu/drm/radeon/si.c             | 52 +++-----------------
>   13 files changed, 59 insertions(+), 364 deletions(-)
>
> diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c
> index e911898..65cfdbb 100644
> --- a/drivers/gpu/drm/radeon/atombios_crtc.c
> +++ b/drivers/gpu/drm/radeon/atombios_crtc.c
> @@ -1284,6 +1284,10 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc,
>   		break;
>   	}
>   
> +	/* Make sure updates happen at vertical blank */
> +	WREG32(EVERGREEN_GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset, 0);
> +	WREG32(EVERGREEN_MASTER_UPDATE_MODE + radeon_crtc->crtc_offset, 0);
> +
>   	WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + radeon_crtc->crtc_offset,
>   	       upper_32_bits(fb_location));
>   	WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + radeon_crtc->crtc_offset,
> @@ -1321,15 +1325,6 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc,
>   	WREG32(EVERGREEN_VIEWPORT_SIZE + radeon_crtc->crtc_offset,
>   	       (viewport_w << 16) | viewport_h);
>   
> -	/* pageflip setup */
> -	/* make sure flip is at vb rather than hb */
> -	tmp = RREG32(EVERGREEN_GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset);
> -	tmp &= ~EVERGREEN_GRPH_SURFACE_UPDATE_H_RETRACE_EN;
> -	WREG32(EVERGREEN_GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset, tmp);
> -
> -	/* set pageflip to happen anywhere in vblank interval */
> -	WREG32(EVERGREEN_MASTER_UPDATE_MODE + radeon_crtc->crtc_offset, 0);
> -
>   	if (!atomic && fb && fb != crtc->primary->fb) {
>   		radeon_fb = to_radeon_framebuffer(fb);
>   		rbo = gem_to_radeon_bo(radeon_fb->obj);
> @@ -1360,7 +1355,7 @@ static int avivo_crtc_do_set_base(struct drm_crtc *crtc,
>   	uint64_t fb_location;
>   	uint32_t fb_format, fb_pitch_pixels, tiling_flags;
>   	u32 fb_swap = R600_D1GRPH_SWAP_ENDIAN_NONE;
> -	u32 tmp, viewport_w, viewport_h;
> +	u32 viewport_w, viewport_h;
>   	int r;
>   
>   	/* no fb bound */
> @@ -1451,6 +1446,10 @@ static int avivo_crtc_do_set_base(struct drm_crtc *crtc,
>   	else
>   		WREG32(AVIVO_D2VGA_CONTROL, 0);
>   
> +	/* Make sure updates happen at vertical blank */
> +	WREG32(AVIVO_D1GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset, 0);
> +	WREG32(AVIVO_D1MODE_MASTER_UPDATE_MODE + radeon_crtc->crtc_offset, 0);
> +
>   	if (rdev->family >= CHIP_RV770) {
>   		if (radeon_crtc->crtc_id) {
>   			WREG32(R700_D2GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, upper_32_bits(fb_location));
> @@ -1490,15 +1489,6 @@ static int avivo_crtc_do_set_base(struct drm_crtc *crtc,
>   	WREG32(AVIVO_D1MODE_VIEWPORT_SIZE + radeon_crtc->crtc_offset,
>   	       (viewport_w << 16) | viewport_h);
>   
> -	/* pageflip setup */
> -	/* make sure flip is at vb rather than hb */
> -	tmp = RREG32(AVIVO_D1GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset);
> -	tmp &= ~AVIVO_D1GRPH_SURFACE_UPDATE_H_RETRACE_EN;
> -	WREG32(AVIVO_D1GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset, tmp);
> -
> -	/* set pageflip to happen anywhere in vblank interval */
> -	WREG32(AVIVO_D1MODE_MASTER_UPDATE_MODE + radeon_crtc->crtc_offset, 0);
> -
>   	if (!atomic && fb && fb != crtc->primary->fb) {
>   		radeon_fb = to_radeon_framebuffer(fb);
>   		rbo = gem_to_radeon_bo(radeon_fb->obj);
> diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c
> index 0f4b38f..d0a994c 100644
> --- a/drivers/gpu/drm/radeon/cik.c
> +++ b/drivers/gpu/drm/radeon/cik.c
> @@ -7143,25 +7143,6 @@ int cik_irq_set(struct radeon_device *rdev)
>   		WREG32(LB_INTERRUPT_MASK + EVERGREEN_CRTC5_REGISTER_OFFSET, crtc6);
>   	}
>   
> -	if (rdev->num_crtc >= 2) {
> -		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET,
> -		       GRPH_PFLIP_INT_MASK);
> -		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET,
> -		       GRPH_PFLIP_INT_MASK);
> -	}
> -	if (rdev->num_crtc >= 4) {
> -		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET,
> -		       GRPH_PFLIP_INT_MASK);
> -		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET,
> -		       GRPH_PFLIP_INT_MASK);
> -	}
> -	if (rdev->num_crtc >= 6) {
> -		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET,
> -		       GRPH_PFLIP_INT_MASK);
> -		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET,
> -		       GRPH_PFLIP_INT_MASK);
> -	}
> -
>   	WREG32(DC_HPD1_INT_CONTROL, hpd1);
>   	WREG32(DC_HPD2_INT_CONTROL, hpd2);
>   	WREG32(DC_HPD3_INT_CONTROL, hpd3);
> @@ -7215,12 +7196,6 @@ static inline void cik_irq_ack(struct radeon_device *rdev)
>   			EVERGREEN_CRTC5_REGISTER_OFFSET);
>   	}
>   
> -	if (rdev->irq.stat_regs.cik.d1grph_int & GRPH_PFLIP_INT_OCCURRED)
> -		WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC0_REGISTER_OFFSET,
> -		       GRPH_PFLIP_INT_CLEAR);
> -	if (rdev->irq.stat_regs.cik.d2grph_int & GRPH_PFLIP_INT_OCCURRED)
> -		WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC1_REGISTER_OFFSET,
> -		       GRPH_PFLIP_INT_CLEAR);
>   	if (rdev->irq.stat_regs.cik.disp_int & LB_D1_VBLANK_INTERRUPT)
>   		WREG32(LB_VBLANK_STATUS + EVERGREEN_CRTC0_REGISTER_OFFSET, VBLANK_ACK);
>   	if (rdev->irq.stat_regs.cik.disp_int & LB_D1_VLINE_INTERRUPT)
> @@ -7231,12 +7206,6 @@ static inline void cik_irq_ack(struct radeon_device *rdev)
>   		WREG32(LB_VLINE_STATUS + EVERGREEN_CRTC1_REGISTER_OFFSET, VLINE_ACK);
>   
>   	if (rdev->num_crtc >= 4) {
> -		if (rdev->irq.stat_regs.cik.d3grph_int & GRPH_PFLIP_INT_OCCURRED)
> -			WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET,
> -			       GRPH_PFLIP_INT_CLEAR);
> -		if (rdev->irq.stat_regs.cik.d4grph_int & GRPH_PFLIP_INT_OCCURRED)
> -			WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC3_REGISTER_OFFSET,
> -			       GRPH_PFLIP_INT_CLEAR);
>   		if (rdev->irq.stat_regs.cik.disp_int_cont2 & LB_D3_VBLANK_INTERRUPT)
>   			WREG32(LB_VBLANK_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET, VBLANK_ACK);
>   		if (rdev->irq.stat_regs.cik.disp_int_cont2 & LB_D3_VLINE_INTERRUPT)
> @@ -7248,12 +7217,6 @@ static inline void cik_irq_ack(struct radeon_device *rdev)
>   	}
>   
>   	if (rdev->num_crtc >= 6) {
> -		if (rdev->irq.stat_regs.cik.d5grph_int & GRPH_PFLIP_INT_OCCURRED)
> -			WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET,
> -			       GRPH_PFLIP_INT_CLEAR);
> -		if (rdev->irq.stat_regs.cik.d6grph_int & GRPH_PFLIP_INT_OCCURRED)
> -			WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET,
> -			       GRPH_PFLIP_INT_CLEAR);
>   		if (rdev->irq.stat_regs.cik.disp_int_cont4 & LB_D5_VBLANK_INTERRUPT)
>   			WREG32(LB_VBLANK_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET, VBLANK_ACK);
>   		if (rdev->irq.stat_regs.cik.disp_int_cont4 & LB_D5_VLINE_INTERRUPT)
> @@ -7459,7 +7422,7 @@ restart_ih:
>   						wake_up(&rdev->irq.vblank_queue);
>   					}
>   					if (atomic_read(&rdev->irq.pflip[0]))
> -						radeon_crtc_handle_vblank(rdev, 0);
> +						radeon_crtc_handle_flip(rdev, 0);
>   					rdev->irq.stat_regs.cik.disp_int &= ~LB_D1_VBLANK_INTERRUPT;
>   					DRM_DEBUG("IH: D1 vblank\n");
>   				}
> @@ -7485,7 +7448,7 @@ restart_ih:
>   						wake_up(&rdev->irq.vblank_queue);
>   					}
>   					if (atomic_read(&rdev->irq.pflip[1]))
> -						radeon_crtc_handle_vblank(rdev, 1);
> +						radeon_crtc_handle_flip(rdev, 1);
>   					rdev->irq.stat_regs.cik.disp_int_cont &= ~LB_D2_VBLANK_INTERRUPT;
>   					DRM_DEBUG("IH: D2 vblank\n");
>   				}
> @@ -7511,7 +7474,7 @@ restart_ih:
>   						wake_up(&rdev->irq.vblank_queue);
>   					}
>   					if (atomic_read(&rdev->irq.pflip[2]))
> -						radeon_crtc_handle_vblank(rdev, 2);
> +						radeon_crtc_handle_flip(rdev, 2);
>   					rdev->irq.stat_regs.cik.disp_int_cont2 &= ~LB_D3_VBLANK_INTERRUPT;
>   					DRM_DEBUG("IH: D3 vblank\n");
>   				}
> @@ -7537,7 +7500,7 @@ restart_ih:
>   						wake_up(&rdev->irq.vblank_queue);
>   					}
>   					if (atomic_read(&rdev->irq.pflip[3]))
> -						radeon_crtc_handle_vblank(rdev, 3);
> +						radeon_crtc_handle_flip(rdev, 3);
>   					rdev->irq.stat_regs.cik.disp_int_cont3 &= ~LB_D4_VBLANK_INTERRUPT;
>   					DRM_DEBUG("IH: D4 vblank\n");
>   				}
> @@ -7563,7 +7526,7 @@ restart_ih:
>   						wake_up(&rdev->irq.vblank_queue);
>   					}
>   					if (atomic_read(&rdev->irq.pflip[4]))
> -						radeon_crtc_handle_vblank(rdev, 4);
> +						radeon_crtc_handle_flip(rdev, 4);
>   					rdev->irq.stat_regs.cik.disp_int_cont4 &= ~LB_D5_VBLANK_INTERRUPT;
>   					DRM_DEBUG("IH: D5 vblank\n");
>   				}
> @@ -7589,7 +7552,7 @@ restart_ih:
>   						wake_up(&rdev->irq.vblank_queue);
>   					}
>   					if (atomic_read(&rdev->irq.pflip[5]))
> -						radeon_crtc_handle_vblank(rdev, 5);
> +						radeon_crtc_handle_flip(rdev, 5);
>   					rdev->irq.stat_regs.cik.disp_int_cont5 &= ~LB_D6_VBLANK_INTERRUPT;
>   					DRM_DEBUG("IH: D6 vblank\n");
>   				}
> @@ -7605,15 +7568,6 @@ restart_ih:
>   				break;
>   			}
>   			break;
> -		case 8: /* D1 page flip */
> -		case 10: /* D2 page flip */
> -		case 12: /* D3 page flip */
> -		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);
> -			break;
>   		case 42: /* HPD hotplug */
>   			switch (src_data) {
>   			case 0:
> diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c
> index 0443183..e7d685a 100644
> --- a/drivers/gpu/drm/radeon/evergreen.c
> +++ b/drivers/gpu/drm/radeon/evergreen.c
> @@ -1308,16 +1308,15 @@ void dce4_wait_for_vblank(struct radeon_device *rdev, int crtc)
>    * @crtc_base: new address of the crtc (GPU MC address)
>    *
>    * Does the actual pageflip (evergreen+).
> - * During vblank we take the crtc lock and wait for the update_pending
> - * bit to go high, when it does, we release the lock, and allow the
> - * double buffered update to take place.
> - * Returns the current update pending status.
>    */
>   void evergreen_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base)
>   {
>   	struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];
>   	u32 tmp = RREG32(EVERGREEN_GRPH_UPDATE + radeon_crtc->crtc_offset);
> -	int i;
> +
> +	/* Take surface updates at horizontal blank */
> +	WREG32(EVERGREEN_GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset,
> +	       EVERGREEN_GRPH_SURFACE_UPDATE_H_RETRACE_EN);
>   
>   	/* Lock the graphics update lock */
>   	tmp |= EVERGREEN_GRPH_UPDATE_LOCK;
> @@ -1334,36 +1333,11 @@ void evergreen_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base)
>   	WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset,
>   	       (u32)crtc_base);
>   
> -	/* Wait for update_pending to go high. */
> -	for (i = 0; i < rdev->usec_timeout; i++) {
> -		if (RREG32(EVERGREEN_GRPH_UPDATE + radeon_crtc->crtc_offset) & EVERGREEN_GRPH_SURFACE_UPDATE_PENDING)
> -			break;
> -		udelay(1);
> -	}
> -	DRM_DEBUG("Update pending now high. Unlocking vupdate_lock.\n");
> -
> -	/* Unlock the lock, so double-buffering can take place inside vblank */
> +	/* Unlock the lock, so double-buffering can take place inside hblank */
>   	tmp &= ~EVERGREEN_GRPH_UPDATE_LOCK;
>   	WREG32(EVERGREEN_GRPH_UPDATE + radeon_crtc->crtc_offset, tmp);
>   }
>   
> -/**
> - * evergreen_page_flip_pending - check if page flip is still pending
> - *
> - * @rdev: radeon_device pointer
> - * @crtc_id: crtc to check
> - *
> - * Returns the current update pending status.
> - */
> -bool evergreen_page_flip_pending(struct radeon_device *rdev, int crtc_id)
> -{
> -	struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];
> -
> -	/* Return current update_pending status: */
> -	return !!(RREG32(EVERGREEN_GRPH_UPDATE + radeon_crtc->crtc_offset) &
> -		EVERGREEN_GRPH_SURFACE_UPDATE_PENDING);
> -}
> -
>   /* get temperature in millidegrees */
>   int evergreen_get_temp(struct radeon_device *rdev)
>   {
> @@ -4541,23 +4515,6 @@ int evergreen_irq_set(struct radeon_device *rdev)
>   		WREG32(INT_MASK + EVERGREEN_CRTC5_REGISTER_OFFSET, crtc6);
>   	}
>   
> -	WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET,
> -	       GRPH_PFLIP_INT_MASK);
> -	WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET,
> -	       GRPH_PFLIP_INT_MASK);
> -	if (rdev->num_crtc >= 4) {
> -		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET,
> -		       GRPH_PFLIP_INT_MASK);
> -		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET,
> -		       GRPH_PFLIP_INT_MASK);
> -	}
> -	if (rdev->num_crtc >= 6) {
> -		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET,
> -		       GRPH_PFLIP_INT_MASK);
> -		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET,
> -		       GRPH_PFLIP_INT_MASK);
> -	}
> -
>   	WREG32(DC_HPD1_INT_CONTROL, hpd1);
>   	WREG32(DC_HPD2_INT_CONTROL, hpd2);
>   	WREG32(DC_HPD3_INT_CONTROL, hpd3);
> @@ -4607,10 +4564,6 @@ static void evergreen_irq_ack(struct radeon_device *rdev)
>   	rdev->irq.stat_regs.evergreen.afmt_status5 = RREG32(AFMT_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET);
>   	rdev->irq.stat_regs.evergreen.afmt_status6 = RREG32(AFMT_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET);
>   
> -	if (rdev->irq.stat_regs.evergreen.d1grph_int & GRPH_PFLIP_INT_OCCURRED)
> -		WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC0_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR);
> -	if (rdev->irq.stat_regs.evergreen.d2grph_int & GRPH_PFLIP_INT_OCCURRED)
> -		WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC1_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR);
>   	if (rdev->irq.stat_regs.evergreen.disp_int & LB_D1_VBLANK_INTERRUPT)
>   		WREG32(VBLANK_STATUS + EVERGREEN_CRTC0_REGISTER_OFFSET, VBLANK_ACK);
>   	if (rdev->irq.stat_regs.evergreen.disp_int & LB_D1_VLINE_INTERRUPT)
> @@ -4621,10 +4574,6 @@ static void evergreen_irq_ack(struct radeon_device *rdev)
>   		WREG32(VLINE_STATUS + EVERGREEN_CRTC1_REGISTER_OFFSET, VLINE_ACK);
>   
>   	if (rdev->num_crtc >= 4) {
> -		if (rdev->irq.stat_regs.evergreen.d3grph_int & GRPH_PFLIP_INT_OCCURRED)
> -			WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR);
> -		if (rdev->irq.stat_regs.evergreen.d4grph_int & GRPH_PFLIP_INT_OCCURRED)
> -			WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC3_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR);
>   		if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & LB_D3_VBLANK_INTERRUPT)
>   			WREG32(VBLANK_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET, VBLANK_ACK);
>   		if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & LB_D3_VLINE_INTERRUPT)
> @@ -4636,10 +4585,6 @@ static void evergreen_irq_ack(struct radeon_device *rdev)
>   	}
>   
>   	if (rdev->num_crtc >= 6) {
> -		if (rdev->irq.stat_regs.evergreen.d5grph_int & GRPH_PFLIP_INT_OCCURRED)
> -			WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR);
> -		if (rdev->irq.stat_regs.evergreen.d6grph_int & GRPH_PFLIP_INT_OCCURRED)
> -			WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR);
>   		if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & LB_D5_VBLANK_INTERRUPT)
>   			WREG32(VBLANK_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET, VBLANK_ACK);
>   		if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & LB_D5_VLINE_INTERRUPT)
> @@ -4798,7 +4743,7 @@ restart_ih:
>   						wake_up(&rdev->irq.vblank_queue);
>   					}
>   					if (atomic_read(&rdev->irq.pflip[0]))
> -						radeon_crtc_handle_vblank(rdev, 0);
> +						radeon_crtc_handle_flip(rdev, 0);
>   					rdev->irq.stat_regs.evergreen.disp_int &= ~LB_D1_VBLANK_INTERRUPT;
>   					DRM_DEBUG("IH: D1 vblank\n");
>   				}
> @@ -4824,7 +4769,7 @@ restart_ih:
>   						wake_up(&rdev->irq.vblank_queue);
>   					}
>   					if (atomic_read(&rdev->irq.pflip[1]))
> -						radeon_crtc_handle_vblank(rdev, 1);
> +						radeon_crtc_handle_flip(rdev, 1);
>   					rdev->irq.stat_regs.evergreen.disp_int_cont &= ~LB_D2_VBLANK_INTERRUPT;
>   					DRM_DEBUG("IH: D2 vblank\n");
>   				}
> @@ -4850,7 +4795,7 @@ restart_ih:
>   						wake_up(&rdev->irq.vblank_queue);
>   					}
>   					if (atomic_read(&rdev->irq.pflip[2]))
> -						radeon_crtc_handle_vblank(rdev, 2);
> +						radeon_crtc_handle_flip(rdev, 2);
>   					rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~LB_D3_VBLANK_INTERRUPT;
>   					DRM_DEBUG("IH: D3 vblank\n");
>   				}
> @@ -4876,7 +4821,7 @@ restart_ih:
>   						wake_up(&rdev->irq.vblank_queue);
>   					}
>   					if (atomic_read(&rdev->irq.pflip[3]))
> -						radeon_crtc_handle_vblank(rdev, 3);
> +						radeon_crtc_handle_flip(rdev, 3);
>   					rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~LB_D4_VBLANK_INTERRUPT;
>   					DRM_DEBUG("IH: D4 vblank\n");
>   				}
> @@ -4902,7 +4847,7 @@ restart_ih:
>   						wake_up(&rdev->irq.vblank_queue);
>   					}
>   					if (atomic_read(&rdev->irq.pflip[4]))
> -						radeon_crtc_handle_vblank(rdev, 4);
> +						radeon_crtc_handle_flip(rdev, 4);
>   					rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~LB_D5_VBLANK_INTERRUPT;
>   					DRM_DEBUG("IH: D5 vblank\n");
>   				}
> @@ -4928,7 +4873,7 @@ restart_ih:
>   						wake_up(&rdev->irq.vblank_queue);
>   					}
>   					if (atomic_read(&rdev->irq.pflip[5]))
> -						radeon_crtc_handle_vblank(rdev, 5);
> +						radeon_crtc_handle_flip(rdev, 5);
>   					rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~LB_D6_VBLANK_INTERRUPT;
>   					DRM_DEBUG("IH: D6 vblank\n");
>   				}
> @@ -4944,15 +4889,6 @@ restart_ih:
>   				break;
>   			}
>   			break;
> -		case 8: /* D1 page flip */
> -		case 10: /* D2 page flip */
> -		case 12: /* D3 page flip */
> -		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);
> -			break;
>   		case 42: /* HPD hotplug */
>   			switch (src_data) {
>   			case 0:
> diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c
> index ad99813..8d9f092 100644
> --- a/drivers/gpu/drm/radeon/r100.c
> +++ b/drivers/gpu/drm/radeon/r100.c
> @@ -149,50 +149,18 @@ void r100_wait_for_vblank(struct radeon_device *rdev, int crtc)
>    * @crtc_base: new address of the crtc (GPU MC address)
>    *
>    * Does the actual pageflip (r1xx-r4xx).
> - * During vblank we take the crtc lock and wait for the update_pending
> - * bit to go high, when it does, we release the lock, and allow the
> - * double buffered update to take place.
>    */
>   void r100_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base)
>   {
>   	struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];
> -	u32 tmp = ((u32)crtc_base) | RADEON_CRTC_OFFSET__OFFSET_LOCK;
> -	int i;
> -
> -	/* Lock the graphics update lock */
> -	/* update the scanout addresses */
> -	WREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset, tmp);
> +	u32 crtc_offset_cntl = RREG32(RADEON_CRTC_OFFSET_CNTL);
>   
> -	/* Wait for update_pending to go high. */
> -	for (i = 0; i < rdev->usec_timeout; i++) {
> -		if (RREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset) & RADEON_CRTC_OFFSET__GUI_TRIG_OFFSET)
> -			break;
> -		udelay(1);
> -	}
> -	DRM_DEBUG("Update pending now high. Unlocking vupdate_lock.\n");
> -
> -	/* Unlock the lock, so double-buffering can take place inside vblank */
> -	tmp &= ~RADEON_CRTC_OFFSET__OFFSET_LOCK;
> -	WREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset, tmp);
> -
> -}
> -
> -/**
> - * r100_page_flip_pending - check if page flip is still pending
> - *
> - * @rdev: radeon_device pointer
> - * @crtc_id: crtc to check
> - *
> - * Check if the last pagefilp is still pending (r1xx-r4xx).
> - * Returns the current update pending status.
> - */
> -bool r100_page_flip_pending(struct radeon_device *rdev, int crtc_id)
> -{
> -	struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];
> +	/* Take surface updates at horizontal blank */
> +	WREG32(RADEON_CRTC_OFFSET_CNTL,
> +	       crtc_offset_cntl | RADEON_CRTC_OFFSET_FLIP_CNTL);
>   
> -	/* Return current update_pending status: */
> -	return !!(RREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset) &
> -		RADEON_CRTC_OFFSET__GUI_TRIG_OFFSET);
> +	/* Update the scanout address */
> +	WREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset, crtc_base);
>   }
>   
>   /**
> @@ -779,7 +747,7 @@ int r100_irq_process(struct radeon_device *rdev)
>   				wake_up(&rdev->irq.vblank_queue);
>   			}
>   			if (atomic_read(&rdev->irq.pflip[0]))
> -				radeon_crtc_handle_vblank(rdev, 0);
> +				radeon_crtc_handle_flip(rdev, 0);
>   		}
>   		if (status & RADEON_CRTC2_VBLANK_STAT) {
>   			if (rdev->irq.crtc_vblank_int[1]) {
> @@ -788,7 +756,7 @@ int r100_irq_process(struct radeon_device *rdev)
>   				wake_up(&rdev->irq.vblank_queue);
>   			}
>   			if (atomic_read(&rdev->irq.pflip[1]))
> -				radeon_crtc_handle_vblank(rdev, 1);
> +				radeon_crtc_handle_flip(rdev, 1);
>   		}
>   		if (status & RADEON_FP_DETECT_STAT) {
>   			queue_hotplug = true;
> diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c
> index ae54f76..8f318ec 100644
> --- a/drivers/gpu/drm/radeon/r600.c
> +++ b/drivers/gpu/drm/radeon/r600.c
> @@ -3614,8 +3614,6 @@ 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(GRBM_INT_CNTL, grbm_int_cntl);
>   	if (ASIC_IS_DCE3(rdev)) {
>   		WREG32(DC_HPD1_INT_CONTROL, hpd1);
> @@ -3672,10 +3670,6 @@ static void r600_irq_ack(struct radeon_device *rdev)
>   	rdev->irq.stat_regs.r600.d1grph_int = RREG32(D1GRPH_INTERRUPT_STATUS);
>   	rdev->irq.stat_regs.r600.d2grph_int = RREG32(D2GRPH_INTERRUPT_STATUS);
>   
> -	if (rdev->irq.stat_regs.r600.d1grph_int & DxGRPH_PFLIP_INT_OCCURRED)
> -		WREG32(D1GRPH_INTERRUPT_STATUS, DxGRPH_PFLIP_INT_CLEAR);
> -	if (rdev->irq.stat_regs.r600.d2grph_int & DxGRPH_PFLIP_INT_OCCURRED)
> -		WREG32(D2GRPH_INTERRUPT_STATUS, DxGRPH_PFLIP_INT_CLEAR);
>   	if (rdev->irq.stat_regs.r600.disp_int & LB_D1_VBLANK_INTERRUPT)
>   		WREG32(D1MODE_VBLANK_STATUS, DxMODE_VBLANK_ACK);
>   	if (rdev->irq.stat_regs.r600.disp_int & LB_D1_VLINE_INTERRUPT)
> @@ -3876,7 +3870,7 @@ restart_ih:
>   						wake_up(&rdev->irq.vblank_queue);
>   					}
>   					if (atomic_read(&rdev->irq.pflip[0]))
> -						radeon_crtc_handle_vblank(rdev, 0);
> +						radeon_crtc_handle_flip(rdev, 0);
>   					rdev->irq.stat_regs.r600.disp_int &= ~LB_D1_VBLANK_INTERRUPT;
>   					DRM_DEBUG("IH: D1 vblank\n");
>   				}
> @@ -3902,7 +3896,7 @@ restart_ih:
>   						wake_up(&rdev->irq.vblank_queue);
>   					}
>   					if (atomic_read(&rdev->irq.pflip[1]))
> -						radeon_crtc_handle_vblank(rdev, 1);
> +						radeon_crtc_handle_flip(rdev, 1);
>   					rdev->irq.stat_regs.r600.disp_int &= ~LB_D2_VBLANK_INTERRUPT;
>   					DRM_DEBUG("IH: D2 vblank\n");
>   				}
> @@ -3918,14 +3912,6 @@ restart_ih:
>   				break;
>   			}
>   			break;
> -		case 9: /* D1 pflip */
> -			DRM_DEBUG("IH: D1 flip\n");
> -			radeon_crtc_handle_flip(rdev, 0);
> -			break;
> -		case 11: /* D2 pflip */
> -			DRM_DEBUG("IH: D2 flip\n");
> -			radeon_crtc_handle_flip(rdev, 1);
> -			break;
>   		case 19: /* HPD/DAC hotplug */
>   			switch (src_data) {
>   			case 0:
> diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
> index 8e8ef08..7a45c93 100644
> --- a/drivers/gpu/drm/radeon/radeon.h
> +++ b/drivers/gpu/drm/radeon/radeon.h
> @@ -681,6 +681,7 @@ struct radeon_flip_work {
>   	struct work_struct		unpin_work;
>   	struct radeon_device		*rdev;
>   	int				crtc_id;
> +	uint64_t			base;
>   	struct drm_framebuffer		*fb;
>   	struct drm_pending_vblank_event *event;
>   	struct radeon_bo		*old_rbo;
> @@ -1884,7 +1885,6 @@ struct radeon_asic {
>   	/* pageflipping */
>   	struct {
>   		void (*page_flip)(struct radeon_device *rdev, int crtc, u64 crtc_base);
> -		bool (*page_flip_pending)(struct radeon_device *rdev, int crtc);
>   	} pflip;
>   };
>   
> @@ -2746,7 +2746,6 @@ void radeon_ring_write(struct radeon_ring *ring, uint32_t v);
>   #define radeon_pm_init_profile(rdev) (rdev)->asic->pm.init_profile((rdev))
>   #define radeon_pm_get_dynpm_state(rdev) (rdev)->asic->pm.get_dynpm_state((rdev))
>   #define radeon_page_flip(rdev, crtc, base) (rdev)->asic->pflip.page_flip((rdev), (crtc), (base))
> -#define radeon_page_flip_pending(rdev, crtc) (rdev)->asic->pflip.page_flip_pending((rdev), (crtc))
>   #define radeon_wait_for_vblank(rdev, crtc) (rdev)->asic->display.wait_for_vblank((rdev), (crtc))
>   #define radeon_mc_wait_for_idle(rdev) (rdev)->asic->mc_wait_for_idle((rdev))
>   #define radeon_get_xclk(rdev) (rdev)->asic->get_xclk((rdev))
> diff --git a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c
> index 7ef3fc6..9943fb1 100644
> --- a/drivers/gpu/drm/radeon/radeon_asic.c
> +++ b/drivers/gpu/drm/radeon/radeon_asic.c
> @@ -249,7 +249,6 @@ static struct radeon_asic r100_asic = {
>   	},
>   	.pflip = {
>   		.page_flip = &r100_page_flip,
> -		.page_flip_pending = &r100_page_flip_pending,
>   	},
>   };
>   
> @@ -315,7 +314,6 @@ static struct radeon_asic r200_asic = {
>   	},
>   	.pflip = {
>   		.page_flip = &r100_page_flip,
> -		.page_flip_pending = &r100_page_flip_pending,
>   	},
>   };
>   
> @@ -395,7 +393,6 @@ static struct radeon_asic r300_asic = {
>   	},
>   	.pflip = {
>   		.page_flip = &r100_page_flip,
> -		.page_flip_pending = &r100_page_flip_pending,
>   	},
>   };
>   
> @@ -461,7 +458,6 @@ static struct radeon_asic r300_asic_pcie = {
>   	},
>   	.pflip = {
>   		.page_flip = &r100_page_flip,
> -		.page_flip_pending = &r100_page_flip_pending,
>   	},
>   };
>   
> @@ -527,7 +523,6 @@ static struct radeon_asic r420_asic = {
>   	},
>   	.pflip = {
>   		.page_flip = &r100_page_flip,
> -		.page_flip_pending = &r100_page_flip_pending,
>   	},
>   };
>   
> @@ -593,7 +588,6 @@ static struct radeon_asic rs400_asic = {
>   	},
>   	.pflip = {
>   		.page_flip = &r100_page_flip,
> -		.page_flip_pending = &r100_page_flip_pending,
>   	},
>   };
>   
> @@ -662,7 +656,6 @@ static struct radeon_asic rs600_asic = {
>   	},
>   	.pflip = {
>   		.page_flip = &rs600_page_flip,
> -		.page_flip_pending = &rs600_page_flip_pending,
>   	},
>   };
>   
> @@ -730,7 +723,6 @@ static struct radeon_asic rs690_asic = {
>   	},
>   	.pflip = {
>   		.page_flip = &rs600_page_flip,
> -		.page_flip_pending = &rs600_page_flip_pending,
>   	},
>   };
>   
> @@ -796,7 +788,6 @@ static struct radeon_asic rv515_asic = {
>   	},
>   	.pflip = {
>   		.page_flip = &rs600_page_flip,
> -		.page_flip_pending = &rs600_page_flip_pending,
>   	},
>   };
>   
> @@ -862,7 +853,6 @@ static struct radeon_asic r520_asic = {
>   	},
>   	.pflip = {
>   		.page_flip = &rs600_page_flip,
> -		.page_flip_pending = &rs600_page_flip_pending,
>   	},
>   };
>   
> @@ -961,7 +951,6 @@ static struct radeon_asic r600_asic = {
>   	},
>   	.pflip = {
>   		.page_flip = &rs600_page_flip,
> -		.page_flip_pending = &rs600_page_flip_pending,
>   	},
>   };
>   
> @@ -1052,7 +1041,6 @@ static struct radeon_asic rv6xx_asic = {
>   	},
>   	.pflip = {
>   		.page_flip = &rs600_page_flip,
> -		.page_flip_pending = &rs600_page_flip_pending,
>   	},
>   };
>   
> @@ -1143,7 +1131,6 @@ static struct radeon_asic rs780_asic = {
>   	},
>   	.pflip = {
>   		.page_flip = &rs600_page_flip,
> -		.page_flip_pending = &rs600_page_flip_pending,
>   	},
>   };
>   
> @@ -1249,7 +1236,6 @@ static struct radeon_asic rv770_asic = {
>   	},
>   	.pflip = {
>   		.page_flip = &rv770_page_flip,
> -		.page_flip_pending = &rv770_page_flip_pending,
>   	},
>   };
>   
> @@ -1368,7 +1354,6 @@ static struct radeon_asic evergreen_asic = {
>   	},
>   	.pflip = {
>   		.page_flip = &evergreen_page_flip,
> -		.page_flip_pending = &evergreen_page_flip_pending,
>   	},
>   };
>   
> @@ -1460,7 +1445,6 @@ static struct radeon_asic sumo_asic = {
>   	},
>   	.pflip = {
>   		.page_flip = &evergreen_page_flip,
> -		.page_flip_pending = &evergreen_page_flip_pending,
>   	},
>   };
>   
> @@ -1553,7 +1537,6 @@ static struct radeon_asic btc_asic = {
>   	},
>   	.pflip = {
>   		.page_flip = &evergreen_page_flip,
> -		.page_flip_pending = &evergreen_page_flip_pending,
>   	},
>   };
>   
> @@ -1697,7 +1680,6 @@ static struct radeon_asic cayman_asic = {
>   	},
>   	.pflip = {
>   		.page_flip = &evergreen_page_flip,
> -		.page_flip_pending = &evergreen_page_flip_pending,
>   	},
>   };
>   
> @@ -1798,7 +1780,6 @@ static struct radeon_asic trinity_asic = {
>   	},
>   	.pflip = {
>   		.page_flip = &evergreen_page_flip,
> -		.page_flip_pending = &evergreen_page_flip_pending,
>   	},
>   };
>   
> @@ -1929,7 +1910,6 @@ static struct radeon_asic si_asic = {
>   	},
>   	.pflip = {
>   		.page_flip = &evergreen_page_flip,
> -		.page_flip_pending = &evergreen_page_flip_pending,
>   	},
>   };
>   
> @@ -2092,7 +2072,6 @@ static struct radeon_asic ci_asic = {
>   	},
>   	.pflip = {
>   		.page_flip = &evergreen_page_flip,
> -		.page_flip_pending = &evergreen_page_flip_pending,
>   	},
>   };
>   
> @@ -2197,7 +2176,6 @@ static struct radeon_asic kv_asic = {
>   	},
>   	.pflip = {
>   		.page_flip = &evergreen_page_flip,
> -		.page_flip_pending = &evergreen_page_flip_pending,
>   	},
>   };
>   
> diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h
> index 645a3de..170a80c 100644
> --- a/drivers/gpu/drm/radeon/radeon_asic.h
> +++ b/drivers/gpu/drm/radeon/radeon_asic.h
> @@ -137,7 +137,6 @@ extern void r100_pm_init_profile(struct radeon_device *rdev);
>   extern void r100_pm_get_dynpm_state(struct radeon_device *rdev);
>   extern void r100_page_flip(struct radeon_device *rdev, int crtc,
>   			   u64 crtc_base);
> -extern bool r100_page_flip_pending(struct radeon_device *rdev, int crtc);
>   extern void r100_wait_for_vblank(struct radeon_device *rdev, int crtc);
>   extern int r100_mc_wait_for_idle(struct radeon_device *rdev);
>   
> @@ -244,7 +243,6 @@ extern void rs600_pm_prepare(struct radeon_device *rdev);
>   extern void rs600_pm_finish(struct radeon_device *rdev);
>   extern void rs600_page_flip(struct radeon_device *rdev, int crtc,
>   			    u64 crtc_base);
> -extern bool rs600_page_flip_pending(struct radeon_device *rdev, int crtc);
>   void rs600_set_safe_registers(struct radeon_device *rdev);
>   extern void avivo_wait_for_vblank(struct radeon_device *rdev, int crtc);
>   extern int rs600_mc_wait_for_idle(struct radeon_device *rdev);
> @@ -449,7 +447,6 @@ int rv770_suspend(struct radeon_device *rdev);
>   int rv770_resume(struct radeon_device *rdev);
>   void rv770_pm_misc(struct radeon_device *rdev);
>   void rv770_page_flip(struct radeon_device *rdev, int crtc, u64 crtc_base);
> -bool rv770_page_flip_pending(struct radeon_device *rdev, int crtc);
>   void r700_vram_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc);
>   void r700_cp_stop(struct radeon_device *rdev);
>   void r700_cp_fini(struct radeon_device *rdev);
> @@ -517,7 +514,6 @@ int sumo_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk);
>   int evergreen_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk);
>   extern void evergreen_page_flip(struct radeon_device *rdev, int crtc,
>   				u64 crtc_base);
> -extern bool evergreen_page_flip_pending(struct radeon_device *rdev, int crtc);
>   extern void dce4_wait_for_vblank(struct radeon_device *rdev, int crtc);
>   void evergreen_disable_interrupt_state(struct radeon_device *rdev);
>   int evergreen_mc_wait_for_idle(struct radeon_device *rdev);
> diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c
> index 65882cd..e66323e 100644
> --- a/drivers/gpu/drm/radeon/radeon_display.c
> +++ b/drivers/gpu/drm/radeon/radeon_display.c
> @@ -281,50 +281,6 @@ static void radeon_unpin_work_func(struct work_struct *__work)
>   	kfree(work);
>   }
>   
> -void radeon_crtc_handle_vblank(struct radeon_device *rdev, int crtc_id)
> -{
> -	struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];
> -	unsigned long flags;
> -	u32 update_pending;
> -	int vpos, hpos;
> -
> -	/* can happen during initialization */
> -	if (radeon_crtc == NULL)
> -		return;
> -
> -	spin_lock_irqsave(&rdev->ddev->event_lock, flags);
> -	if (radeon_crtc->flip_status != RADEON_FLIP_SUBMITTED) {
> -		DRM_DEBUG_DRIVER("radeon_crtc->flip_status = %d != "
> -				 "RADEON_FLIP_SUBMITTED(%d)\n",
> -				 radeon_crtc->flip_status,
> -				 RADEON_FLIP_SUBMITTED);
> -		spin_unlock_irqrestore(&rdev->ddev->event_lock, flags);
> -		return;
> -	}
> -
> -	update_pending = radeon_page_flip_pending(rdev, crtc_id);
> -
> -	/* Has the pageflip already completed in crtc, or is it certain
> -	 * to complete in this vblank?
> -	 */
> -	if (update_pending &&
> -	    (DRM_SCANOUTPOS_VALID & radeon_get_crtc_scanoutpos(rdev->ddev, crtc_id, 0,
> -							       &vpos, &hpos, NULL, NULL)) &&
> -	    ((vpos >= (99 * rdev->mode_info.crtcs[crtc_id]->base.hwmode.crtc_vdisplay)/100) ||
> -	     (vpos < 0 && !ASIC_IS_AVIVO(rdev)))) {
> -		/* crtc didn't flip in this target vblank interval,
> -		 * but flip is pending in crtc. Based on the current
> -		 * scanout position we know that the current frame is
> -		 * (nearly) complete and the flip will (likely)
> -		 * complete before the start of the next frame.
> -		 */
> -		update_pending = 0;
> -	}
> -	spin_unlock_irqrestore(&rdev->ddev->event_lock, flags);
> -	if (!update_pending)
> -		radeon_crtc_handle_flip(rdev, crtc_id);
> -}
> -
>   /**
>    * radeon_crtc_handle_flip - page flip completed
>    *
> @@ -354,6 +310,9 @@ void radeon_crtc_handle_flip(struct radeon_device *rdev, int crtc_id)
>   		return;
>   	}
>   
> +	/* do the flip (mmio) */
> +	radeon_page_flip(rdev, radeon_crtc->crtc_id, work->base);
> +
>   	/* Pageflip completed. Clean up. */
>   	radeon_crtc->flip_status = RADEON_FLIP_NONE;
>   	radeon_crtc->flip_work = NULL;
> @@ -479,9 +438,7 @@ static void radeon_flip_work_func(struct work_struct *__work)
>   	/* set the proper interrupt */
>   	radeon_irq_kms_pflip_irq_get(rdev, radeon_crtc->crtc_id);
>   
> -	/* do the flip (mmio) */
> -	radeon_page_flip(rdev, radeon_crtc->crtc_id, base);
> -
> +	work->base = base;
>   	radeon_crtc->flip_status = RADEON_FLIP_SUBMITTED;
>   	spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
>   	up_read(&rdev->exclusive_lock);
> diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h
> index ed6b6e0..1810a12 100644
> --- a/drivers/gpu/drm/radeon/radeon_mode.h
> +++ b/drivers/gpu/drm/radeon/radeon_mode.h
> @@ -913,7 +913,6 @@ bool radeon_fbdev_robj_is_fb(struct radeon_device *rdev, struct radeon_bo *robj)
>   
>   void radeon_fb_output_poll_changed(struct radeon_device *rdev);
>   
> -void radeon_crtc_handle_vblank(struct radeon_device *rdev, int crtc_id);
>   void radeon_crtc_handle_flip(struct radeon_device *rdev, int crtc_id);
>   
>   int radeon_align_pitch(struct radeon_device *rdev, int width, int bpp, bool tiled);
> diff --git a/drivers/gpu/drm/radeon/rs600.c b/drivers/gpu/drm/radeon/rs600.c
> index 818f4eb..b5e63a7 100644
> --- a/drivers/gpu/drm/radeon/rs600.c
> +++ b/drivers/gpu/drm/radeon/rs600.c
> @@ -113,7 +113,10 @@ void rs600_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base)
>   {
>   	struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];
>   	u32 tmp = RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset);
> -	int i;
> +
> +	/* Take surface updates at horizontal blank */
> +	WREG32(AVIVO_D1GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset,
> +	       AVIVO_D1GRPH_SURFACE_UPDATE_H_RETRACE_EN);
>   
>   	/* Lock the graphics update lock */
>   	tmp |= AVIVO_D1GRPH_UPDATE_LOCK;
> @@ -125,28 +128,11 @@ void rs600_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base)
>   	WREG32(AVIVO_D1GRPH_PRIMARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset,
>   	       (u32)crtc_base);
>   
> -	/* Wait for update_pending to go high. */
> -	for (i = 0; i < rdev->usec_timeout; i++) {
> -		if (RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset) & AVIVO_D1GRPH_SURFACE_UPDATE_PENDING)
> -			break;
> -		udelay(1);
> -	}
> -	DRM_DEBUG("Update pending now high. Unlocking vupdate_lock.\n");
> -
> -	/* Unlock the lock, so double-buffering can take place inside vblank */
> +	/* Unlock the lock, so double-buffering can take place inside hblank */
>   	tmp &= ~AVIVO_D1GRPH_UPDATE_LOCK;
>   	WREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset, tmp);
>   }
>   
> -bool rs600_page_flip_pending(struct radeon_device *rdev, int crtc_id)
> -{
> -	struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];
> -
> -	/* Return current update_pending status: */
> -	return !!(RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset) &
> -		AVIVO_D1GRPH_SURFACE_UPDATE_PENDING);
> -}
> -
>   void avivo_program_fmt(struct drm_encoder *encoder)
>   {
>   	struct drm_device *dev = encoder->dev;
> @@ -790,7 +776,7 @@ int rs600_irq_process(struct radeon_device *rdev)
>   				wake_up(&rdev->irq.vblank_queue);
>   			}
>   			if (atomic_read(&rdev->irq.pflip[0]))
> -				radeon_crtc_handle_vblank(rdev, 0);
> +				radeon_crtc_handle_flip(rdev, 0);
>   		}
>   		if (G_007EDC_LB_D2_VBLANK_INTERRUPT(rdev->irq.stat_regs.r500.disp_int)) {
>   			if (rdev->irq.crtc_vblank_int[1]) {
> @@ -799,7 +785,7 @@ int rs600_irq_process(struct radeon_device *rdev)
>   				wake_up(&rdev->irq.vblank_queue);
>   			}
>   			if (atomic_read(&rdev->irq.pflip[1]))
> -				radeon_crtc_handle_vblank(rdev, 1);
> +				radeon_crtc_handle_flip(rdev, 1);
>   		}
>   		if (G_007EDC_DC_HOT_PLUG_DETECT1_INTERRUPT(rdev->irq.stat_regs.r500.disp_int)) {
>   			queue_hotplug = true;
> diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c
> index 97b7766..ef66be4 100644
> --- a/drivers/gpu/drm/radeon/rv770.c
> +++ b/drivers/gpu/drm/radeon/rv770.c
> @@ -805,7 +805,10 @@ void rv770_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base)
>   {
>   	struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];
>   	u32 tmp = RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset);
> -	int i;
> +
> +	/* Take surface updates at horizontal blank */
> +	WREG32(AVIVO_D1GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset,
> +	       AVIVO_D1GRPH_SURFACE_UPDATE_H_RETRACE_EN);
>   
>   	/* Lock the graphics update lock */
>   	tmp |= AVIVO_D1GRPH_UPDATE_LOCK;
> @@ -824,28 +827,11 @@ void rv770_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base)
>   	WREG32(D1GRPH_PRIMARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset,
>   	       (u32)crtc_base);
>   
> -	/* Wait for update_pending to go high. */
> -	for (i = 0; i < rdev->usec_timeout; i++) {
> -		if (RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset) & AVIVO_D1GRPH_SURFACE_UPDATE_PENDING)
> -			break;
> -		udelay(1);
> -	}
> -	DRM_DEBUG("Update pending now high. Unlocking vupdate_lock.\n");
> -
> -	/* Unlock the lock, so double-buffering can take place inside vblank */
> +	/* Unlock the lock, so double-buffering can take place inside hblank */
>   	tmp &= ~AVIVO_D1GRPH_UPDATE_LOCK;
>   	WREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset, tmp);
>   }
>   
> -bool rv770_page_flip_pending(struct radeon_device *rdev, int crtc_id)
> -{
> -	struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];
> -
> -	/* Return current update_pending status: */
> -	return !!(RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset) &
> -		AVIVO_D1GRPH_SURFACE_UPDATE_PENDING);
> -}
> -
>   /* get temperature in millidegrees */
>   int rv770_get_temp(struct radeon_device *rdev)
>   {
> diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c
> index c128bde..fee797f 100644
> --- a/drivers/gpu/drm/radeon/si.c
> +++ b/drivers/gpu/drm/radeon/si.c
> @@ -5917,25 +5917,6 @@ int si_irq_set(struct radeon_device *rdev)
>   		WREG32(INT_MASK + EVERGREEN_CRTC5_REGISTER_OFFSET, crtc6);
>   	}
>   
> -	if (rdev->num_crtc >= 2) {
> -		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET,
> -		       GRPH_PFLIP_INT_MASK);
> -		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET,
> -		       GRPH_PFLIP_INT_MASK);
> -	}
> -	if (rdev->num_crtc >= 4) {
> -		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET,
> -		       GRPH_PFLIP_INT_MASK);
> -		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET,
> -		       GRPH_PFLIP_INT_MASK);
> -	}
> -	if (rdev->num_crtc >= 6) {
> -		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET,
> -		       GRPH_PFLIP_INT_MASK);
> -		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET,
> -		       GRPH_PFLIP_INT_MASK);
> -	}
> -
>   	if (!ASIC_IS_NODCE(rdev)) {
>   		WREG32(DC_HPD1_INT_CONTROL, hpd1);
>   		WREG32(DC_HPD2_INT_CONTROL, hpd2);
> @@ -5974,10 +5955,6 @@ static inline void si_irq_ack(struct radeon_device *rdev)
>   		rdev->irq.stat_regs.evergreen.d6grph_int = RREG32(GRPH_INT_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET);
>   	}
>   
> -	if (rdev->irq.stat_regs.evergreen.d1grph_int & GRPH_PFLIP_INT_OCCURRED)
> -		WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC0_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR);
> -	if (rdev->irq.stat_regs.evergreen.d2grph_int & GRPH_PFLIP_INT_OCCURRED)
> -		WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC1_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR);
>   	if (rdev->irq.stat_regs.evergreen.disp_int & LB_D1_VBLANK_INTERRUPT)
>   		WREG32(VBLANK_STATUS + EVERGREEN_CRTC0_REGISTER_OFFSET, VBLANK_ACK);
>   	if (rdev->irq.stat_regs.evergreen.disp_int & LB_D1_VLINE_INTERRUPT)
> @@ -5988,10 +5965,6 @@ static inline void si_irq_ack(struct radeon_device *rdev)
>   		WREG32(VLINE_STATUS + EVERGREEN_CRTC1_REGISTER_OFFSET, VLINE_ACK);
>   
>   	if (rdev->num_crtc >= 4) {
> -		if (rdev->irq.stat_regs.evergreen.d3grph_int & GRPH_PFLIP_INT_OCCURRED)
> -			WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR);
> -		if (rdev->irq.stat_regs.evergreen.d4grph_int & GRPH_PFLIP_INT_OCCURRED)
> -			WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC3_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR);
>   		if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & LB_D3_VBLANK_INTERRUPT)
>   			WREG32(VBLANK_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET, VBLANK_ACK);
>   		if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & LB_D3_VLINE_INTERRUPT)
> @@ -6003,10 +5976,6 @@ static inline void si_irq_ack(struct radeon_device *rdev)
>   	}
>   
>   	if (rdev->num_crtc >= 6) {
> -		if (rdev->irq.stat_regs.evergreen.d5grph_int & GRPH_PFLIP_INT_OCCURRED)
> -			WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR);
> -		if (rdev->irq.stat_regs.evergreen.d6grph_int & GRPH_PFLIP_INT_OCCURRED)
> -			WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR);
>   		if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & LB_D5_VBLANK_INTERRUPT)
>   			WREG32(VBLANK_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET, VBLANK_ACK);
>   		if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & LB_D5_VLINE_INTERRUPT)
> @@ -6151,7 +6120,7 @@ restart_ih:
>   						wake_up(&rdev->irq.vblank_queue);
>   					}
>   					if (atomic_read(&rdev->irq.pflip[0]))
> -						radeon_crtc_handle_vblank(rdev, 0);
> +						radeon_crtc_handle_flip(rdev, 0);
>   					rdev->irq.stat_regs.evergreen.disp_int &= ~LB_D1_VBLANK_INTERRUPT;
>   					DRM_DEBUG("IH: D1 vblank\n");
>   				}
> @@ -6177,7 +6146,7 @@ restart_ih:
>   						wake_up(&rdev->irq.vblank_queue);
>   					}
>   					if (atomic_read(&rdev->irq.pflip[1]))
> -						radeon_crtc_handle_vblank(rdev, 1);
> +						radeon_crtc_handle_flip(rdev, 1);
>   					rdev->irq.stat_regs.evergreen.disp_int_cont &= ~LB_D2_VBLANK_INTERRUPT;
>   					DRM_DEBUG("IH: D2 vblank\n");
>   				}
> @@ -6203,7 +6172,7 @@ restart_ih:
>   						wake_up(&rdev->irq.vblank_queue);
>   					}
>   					if (atomic_read(&rdev->irq.pflip[2]))
> -						radeon_crtc_handle_vblank(rdev, 2);
> +						radeon_crtc_handle_flip(rdev, 2);
>   					rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~LB_D3_VBLANK_INTERRUPT;
>   					DRM_DEBUG("IH: D3 vblank\n");
>   				}
> @@ -6229,7 +6198,7 @@ restart_ih:
>   						wake_up(&rdev->irq.vblank_queue);
>   					}
>   					if (atomic_read(&rdev->irq.pflip[3]))
> -						radeon_crtc_handle_vblank(rdev, 3);
> +						radeon_crtc_handle_flip(rdev, 3);
>   					rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~LB_D4_VBLANK_INTERRUPT;
>   					DRM_DEBUG("IH: D4 vblank\n");
>   				}
> @@ -6255,7 +6224,7 @@ restart_ih:
>   						wake_up(&rdev->irq.vblank_queue);
>   					}
>   					if (atomic_read(&rdev->irq.pflip[4]))
> -						radeon_crtc_handle_vblank(rdev, 4);
> +						radeon_crtc_handle_flip(rdev, 4);
>   					rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~LB_D5_VBLANK_INTERRUPT;
>   					DRM_DEBUG("IH: D5 vblank\n");
>   				}
> @@ -6281,7 +6250,7 @@ restart_ih:
>   						wake_up(&rdev->irq.vblank_queue);
>   					}
>   					if (atomic_read(&rdev->irq.pflip[5]))
> -						radeon_crtc_handle_vblank(rdev, 5);
> +						radeon_crtc_handle_flip(rdev, 5);
>   					rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~LB_D6_VBLANK_INTERRUPT;
>   					DRM_DEBUG("IH: D6 vblank\n");
>   				}
> @@ -6297,15 +6266,6 @@ restart_ih:
>   				break;
>   			}
>   			break;
> -		case 8: /* D1 page flip */
> -		case 10: /* D2 page flip */
> -		case 12: /* D3 page flip */
> -		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);
> -			break;
>   		case 42: /* HPD hotplug */
>   			switch (src_data) {
>   			case 0:

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH v2] drm/radeon: Track the status of a page flip more explicitly
  2014-06-30  9:12   ` [PATCH v2] " Michel Dänzer
  2014-06-30  9:14     ` Christian König
@ 2014-07-01 16:23     ` Alex Deucher
  1 sibling, 0 replies; 34+ messages in thread
From: Alex Deucher @ 2014-07-01 16:23 UTC (permalink / raw)
  To: Michel Dänzer; +Cc: Maling list - DRI developers

On Mon, Jun 30, 2014 at 5:12 AM, Michel Dänzer <michel@daenzer.net> wrote:
> From: Michel Dänzer <michel.daenzer@amd.com>
>
> This prevents a panic: radeon_crtc_handle_page_flip() could run before
> radeon_flip_work_func(), triggering the BUG_ON() in drm_vblank_put().
>
> Tested-by: Dieter Nützel <Dieter@nuetzel-hh.de>
> Signed-off-by: Michel Dänzer <michel.daenzer@amd.com>
> ---
>
> v2: Update log message

Applied to to by -fixes tree.

Alex

>
>  drivers/gpu/drm/radeon/radeon_display.c | 19 ++++++++++++++-----
>  drivers/gpu/drm/radeon/radeon_mode.h    |  7 +++++++
>  2 files changed, 21 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c
> index 8b575a4..65882cd 100644
> --- a/drivers/gpu/drm/radeon/radeon_display.c
> +++ b/drivers/gpu/drm/radeon/radeon_display.c
> @@ -284,7 +284,6 @@ static void radeon_unpin_work_func(struct work_struct *__work)
>  void radeon_crtc_handle_vblank(struct radeon_device *rdev, int crtc_id)
>  {
>         struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];
> -       struct radeon_flip_work *work;
>         unsigned long flags;
>         u32 update_pending;
>         int vpos, hpos;
> @@ -294,8 +293,11 @@ void radeon_crtc_handle_vblank(struct radeon_device *rdev, int crtc_id)
>                 return;
>
>         spin_lock_irqsave(&rdev->ddev->event_lock, flags);
> -       work = radeon_crtc->flip_work;
> -       if (work == NULL) {
> +       if (radeon_crtc->flip_status != RADEON_FLIP_SUBMITTED) {
> +               DRM_DEBUG_DRIVER("radeon_crtc->flip_status = %d != "
> +                                "RADEON_FLIP_SUBMITTED(%d)\n",
> +                                radeon_crtc->flip_status,
> +                                RADEON_FLIP_SUBMITTED);
>                 spin_unlock_irqrestore(&rdev->ddev->event_lock, flags);
>                 return;
>         }
> @@ -343,12 +345,17 @@ void radeon_crtc_handle_flip(struct radeon_device *rdev, int crtc_id)
>
>         spin_lock_irqsave(&rdev->ddev->event_lock, flags);
>         work = radeon_crtc->flip_work;
> -       if (work == NULL) {
> +       if (radeon_crtc->flip_status != RADEON_FLIP_SUBMITTED) {
> +               DRM_DEBUG_DRIVER("radeon_crtc->flip_status = %d != "
> +                                "RADEON_FLIP_SUBMITTED(%d)\n",
> +                                radeon_crtc->flip_status,
> +                                RADEON_FLIP_SUBMITTED);
>                 spin_unlock_irqrestore(&rdev->ddev->event_lock, flags);
>                 return;
>         }
>
>         /* Pageflip completed. Clean up. */
> +       radeon_crtc->flip_status = RADEON_FLIP_NONE;
>         radeon_crtc->flip_work = NULL;
>
>         /* wakeup userspace */
> @@ -475,6 +482,7 @@ static void radeon_flip_work_func(struct work_struct *__work)
>         /* do the flip (mmio) */
>         radeon_page_flip(rdev, radeon_crtc->crtc_id, base);
>
> +       radeon_crtc->flip_status = RADEON_FLIP_SUBMITTED;
>         spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
>         up_read(&rdev->exclusive_lock);
>
> @@ -543,7 +551,7 @@ static int radeon_crtc_page_flip(struct drm_crtc *crtc,
>         /* We borrow the event spin lock for protecting flip_work */
>         spin_lock_irqsave(&crtc->dev->event_lock, flags);
>
> -       if (radeon_crtc->flip_work) {
> +       if (radeon_crtc->flip_status != RADEON_FLIP_NONE) {
>                 DRM_DEBUG_DRIVER("flip queue: crtc already busy\n");
>                 spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
>                 drm_gem_object_unreference_unlocked(&work->old_rbo->gem_base);
> @@ -551,6 +559,7 @@ static int radeon_crtc_page_flip(struct drm_crtc *crtc,
>                 kfree(work);
>                 return -EBUSY;
>         }
> +       radeon_crtc->flip_status = RADEON_FLIP_PENDING;
>         radeon_crtc->flip_work = work;
>
>         /* update crtc fb */
> diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h
> index b59096f..ed6b6e0 100644
> --- a/drivers/gpu/drm/radeon/radeon_mode.h
> +++ b/drivers/gpu/drm/radeon/radeon_mode.h
> @@ -301,6 +301,12 @@ struct radeon_atom_ss {
>         uint16_t amount;
>  };
>
> +enum radeon_flip_status {
> +       RADEON_FLIP_NONE,
> +       RADEON_FLIP_PENDING,
> +       RADEON_FLIP_SUBMITTED
> +};
> +
>  struct radeon_crtc {
>         struct drm_crtc base;
>         int crtc_id;
> @@ -326,6 +332,7 @@ struct radeon_crtc {
>         /* page flipping */
>         struct workqueue_struct *flip_queue;
>         struct radeon_flip_work *flip_work;
> +       enum radeon_flip_status flip_status;
>         /* pll sharing */
>         struct radeon_atom_ss ss;
>         bool ss_enabled;
> --
> 2.0.0
>
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH 1/2] drm/radeon: Program page flips to execute in hblank instead of vblank
  2014-07-01  8:14               ` [PATCH 1/2] drm/radeon: Program page flips to execute in hblank instead of vblank Michel Dänzer
  2014-07-01  8:14                 ` [PATCH 2/2] drm/radeon: Remove radeon_kms_pflip_irq_get/put() Michel Dänzer
  2014-07-01 10:12                 ` [PATCH 1/2] drm/radeon: Program page flips to execute in hblank instead of vblank Christian König
@ 2014-07-01 16:46                 ` Dieter Nützel
  2014-07-02  0:29                   ` Michel Dänzer
  2 siblings, 1 reply; 34+ messages in thread
From: Dieter Nützel @ 2014-07-01 16:46 UTC (permalink / raw)
  To: Michel Dänzer; +Cc: dri-devel

Am 01.07.2014 10:14, schrieb Michel Dänzer:
> From: Michel Dänzer <michel.daenzer@amd.com>
> 
> But move the programming back to the vertical blank interrupt handler.
> And signal the flip as being completed immediately after programming it
> to the hardware.
> 
> This way we don't have to guess whether or not the hardware will 
> execute
> the flip in a given vertical blank period, avoiding a whole lot of
> trouble.
> 
> Also, not using the page flip interrupt anymore avoids problems due to
> completing page flips earlier than expected by userspace.
> 
> Signed-off-by: Michel Dänzer <michel.daenzer@amd.com>

Michel,

against which tree is this first one?
Don't apply clean on 3.16-rc2.

Can't find this in 'my' source (radeon_display.c).

>>        radeon_crtc->flip_status = RADEON_FLIP_SUBMITTED; <<<
         spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
         up_read(&rdev->exclusive_lock);

Thanks,
Dieter
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH 1/2] drm/radeon: Program page flips to execute in hblank instead of vblank
  2014-07-01 16:46                 ` [PATCH " Dieter Nützel
@ 2014-07-02  0:29                   ` Michel Dänzer
  2014-07-02  3:01                     ` Dieter Nützel
  0 siblings, 1 reply; 34+ messages in thread
From: Michel Dänzer @ 2014-07-02  0:29 UTC (permalink / raw)
  To: Dieter Nützel; +Cc: dri-devel

On 02.07.2014 01:46, Dieter Nützel wrote:
> Am 01.07.2014 10:14, schrieb Michel Dänzer:
>> From: Michel Dänzer <michel.daenzer@amd.com>
>>
>> But move the programming back to the vertical blank interrupt handler.
>> And signal the flip as being completed immediately after programming it
>> to the hardware.
>>
>> This way we don't have to guess whether or not the hardware will execute
>> the flip in a given vertical blank period, avoiding a whole lot of
>> trouble.
>>
>> Also, not using the page flip interrupt anymore avoids problems due to
>> completing page flips earlier than expected by userspace.
>>
>> Signed-off-by: Michel Dänzer <michel.daenzer@amd.com>
> 
> Michel,
> 
> against which tree is this first one?
> Don't apply clean on 3.16-rc2.
> 
> Can't find this in 'my' source (radeon_display.c).
> 
>>>        radeon_crtc->flip_status = RADEON_FLIP_SUBMITTED; <<<
>         spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
>         up_read(&rdev->exclusive_lock);

The patch applies on top of my previous page flipping fix.


-- 
Earthling Michel Dänzer            |                  http://www.amd.com
Libre software enthusiast          |                Mesa and X developer
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH 1/2] drm/radeon: Program page flips to execute in hblank instead of vblank
  2014-07-02  0:29                   ` Michel Dänzer
@ 2014-07-02  3:01                     ` Dieter Nützel
  2014-07-02  3:11                       ` Michel Dänzer
  0 siblings, 1 reply; 34+ messages in thread
From: Dieter Nützel @ 2014-07-02  3:01 UTC (permalink / raw)
  To: Michel Dänzer; +Cc: dri-devel

Am 02.07.2014 02:29, schrieb Michel Dänzer:
> On 02.07.2014 01:46, Dieter Nützel wrote:
>> Am 01.07.2014 10:14, schrieb Michel Dänzer:
>>> From: Michel Dänzer <michel.daenzer@amd.com>
>>> 
>>> But move the programming back to the vertical blank interrupt 
>>> handler.
>>> And signal the flip as being completed immediately after programming 
>>> it
>>> to the hardware.
>>> 
>>> This way we don't have to guess whether or not the hardware will 
>>> execute
>>> the flip in a given vertical blank period, avoiding a whole lot of
>>> trouble.
>>> 
>>> Also, not using the page flip interrupt anymore avoids problems due 
>>> to
>>> completing page flips earlier than expected by userspace.
>>> 
>>> Signed-off-by: Michel Dänzer <michel.daenzer@amd.com>
>> 
>> Michel,
>> 
>> against which tree is this first one?
>> Don't apply clean on 3.16-rc2.
>> 
>> Can't find this in 'my' source (radeon_display.c).
>> 
>>>>        radeon_crtc->flip_status = RADEON_FLIP_SUBMITTED; <<<
>>         spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
>>         up_read(&rdev->exclusive_lock);
> 
> The patch applies on top of my previous page flipping fix.

Had some trouble with the first one but...
After digikam -> OpenGL Viewer (r600g/RV730 AGP)

[-]
[   503.736] (II) RADEON(0): Modeline "1920x1080"x60.0  172.80  1920 
2040 2248 2576  1080 1081 1084 1118 -hsync +vsync (67.1 kHz e)
[   999.627] (WW) RADEON(0): flip queue failed: Device or resource busy
[   999.627] (WW) RADEON(0): Page flip failed: Device or resource busy

Another day ;-)
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH 1/2] drm/radeon: Program page flips to execute in hblank instead of vblank
  2014-07-02  3:01                     ` Dieter Nützel
@ 2014-07-02  3:11                       ` Michel Dänzer
  2014-07-02  3:52                         ` Michel Dänzer
  0 siblings, 1 reply; 34+ messages in thread
From: Michel Dänzer @ 2014-07-02  3:11 UTC (permalink / raw)
  To: Dieter Nützel; +Cc: dri-devel

On 02.07.2014 12:01, Dieter Nützel wrote:
> Am 02.07.2014 02:29, schrieb Michel Dänzer:
>> On 02.07.2014 01:46, Dieter Nützel wrote:
>>> Am 01.07.2014 10:14, schrieb Michel Dänzer:
>>>> From: Michel Dänzer <michel.daenzer@amd.com>
>>>>
>>>> But move the programming back to the vertical blank interrupt handler.
>>>> And signal the flip as being completed immediately after programming it
>>>> to the hardware.
>>>>
>>>> This way we don't have to guess whether or not the hardware will
>>>> execute
>>>> the flip in a given vertical blank period, avoiding a whole lot of
>>>> trouble.
>>>>
>>>> Also, not using the page flip interrupt anymore avoids problems due to
>>>> completing page flips earlier than expected by userspace.
>>>>
>>>> Signed-off-by: Michel Dänzer <michel.daenzer@amd.com>
>>>
>>> Michel,
>>>
>>> against which tree is this first one?
>>> Don't apply clean on 3.16-rc2.
>>>
>>> Can't find this in 'my' source (radeon_display.c).
>>>
>>>>>        radeon_crtc->flip_status = RADEON_FLIP_SUBMITTED; <<<
>>>         spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
>>>         up_read(&rdev->exclusive_lock);
>>
>> The patch applies on top of my previous page flipping fix.
> 
> Had some trouble with the first one but...
> After digikam -> OpenGL Viewer (r600g/RV730 AGP)
> 
> [-]
> [   503.736] (II) RADEON(0): Modeline "1920x1080"x60.0  172.80  1920
> 2040 2248 2576  1080 1081 1084 1118 -hsync +vsync (67.1 kHz e)
> [   999.627] (WW) RADEON(0): flip queue failed: Device or resource busy
> [   999.627] (WW) RADEON(0): Page flip failed: Device or resource busy

I saw these as well. It means the Xorg driver tried to submit another
page flip before the previous one completed. That should be a Xorg
driver / Mesa issue, but I think the Xorg driver handles this case
gracefully with a copy instead of a flip.


-- 
Earthling Michel Dänzer            |                  http://www.amd.com
Libre software enthusiast          |                Mesa and X developer
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH 1/2] drm/radeon: Program page flips to execute in hblank instead of vblank
  2014-07-02  3:11                       ` Michel Dänzer
@ 2014-07-02  3:52                         ` Michel Dänzer
  0 siblings, 0 replies; 34+ messages in thread
From: Michel Dänzer @ 2014-07-02  3:52 UTC (permalink / raw)
  To: Dieter Nützel; +Cc: dri-devel

On 02.07.2014 12:11, Michel Dänzer wrote:
> On 02.07.2014 12:01, Dieter Nützel wrote:
>> Am 02.07.2014 02:29, schrieb Michel Dänzer:
>>> On 02.07.2014 01:46, Dieter Nützel wrote:
>>>> Am 01.07.2014 10:14, schrieb Michel Dänzer:
>>>>> From: Michel Dänzer <michel.daenzer@amd.com>
>>>>>
>>>>> But move the programming back to the vertical blank interrupt handler.
>>>>> And signal the flip as being completed immediately after programming it
>>>>> to the hardware.
>>>>>
>>>>> This way we don't have to guess whether or not the hardware will
>>>>> execute
>>>>> the flip in a given vertical blank period, avoiding a whole lot of
>>>>> trouble.
>>>>>
>>>>> Also, not using the page flip interrupt anymore avoids problems due to
>>>>> completing page flips earlier than expected by userspace.
>>>>>
>>>>> Signed-off-by: Michel Dänzer <michel.daenzer@amd.com>
>>>>
>>>> Michel,
>>>>
>>>> against which tree is this first one?
>>>> Don't apply clean on 3.16-rc2.
>>>>
>>>> Can't find this in 'my' source (radeon_display.c).
>>>>
>>>>>>        radeon_crtc->flip_status = RADEON_FLIP_SUBMITTED; <<<
>>>>         spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
>>>>         up_read(&rdev->exclusive_lock);
>>>
>>> The patch applies on top of my previous page flipping fix.
>>
>> Had some trouble with the first one but...
>> After digikam -> OpenGL Viewer (r600g/RV730 AGP)
>>
>> [-]
>> [   503.736] (II) RADEON(0): Modeline "1920x1080"x60.0  172.80  1920
>> 2040 2248 2576  1080 1081 1084 1118 -hsync +vsync (67.1 kHz e)
>> [   999.627] (WW) RADEON(0): flip queue failed: Device or resource busy
>> [   999.627] (WW) RADEON(0): Page flip failed: Device or resource busy
> 
> I saw these as well. It means the Xorg driver tried to submit another
> page flip before the previous one completed. That should be a Xorg
> driver / Mesa issue, but I think the Xorg driver handles this case
> gracefully with a copy instead of a flip.

I can also reproduce these with 3.15 without any additional page
flipping changes (and probably could with older kernels as well). It
happens for me when changing some GL apps from windowed to fullscreen
mode. I think the first flip is from kwin and the second, failing one
from the client.


-- 
Earthling Michel Dänzer            |                  http://www.amd.com
Libre software enthusiast          |                Mesa and X developer
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 34+ messages in thread

* [PATCH v2 1/2] drm/radeon: Program page flips to execute in hblank instead of vblank
  2014-07-01 10:12                 ` [PATCH 1/2] drm/radeon: Program page flips to execute in hblank instead of vblank Christian König
@ 2014-07-02  3:55                   ` Michel Dänzer
  2014-07-02  3:55                     ` [PATCH v2 2/2] drm/radeon: Remove radeon_kms_pflip_irq_get/put() and the pflip atomic Michel Dänzer
  2014-07-02 11:35                     ` [PATCH v2 1/2] drm/radeon: Program page flips to execute in hblank instead of vblank Christian König
  0 siblings, 2 replies; 34+ messages in thread
From: Michel Dänzer @ 2014-07-02  3:55 UTC (permalink / raw)
  To: dri-devel

From: Michel Dänzer <michel.daenzer@amd.com>

But move the programming back to the vertical blank interrupt handler.
And signal the flip as being completed immediately after programming it
to the hardware.

This way we don't have to guess whether or not the hardware will execute
the flip in a given vertical blank period, avoiding a whole lot of
trouble.

Also, not using the page flip interrupt anymore avoids problems due to
completing page flips earlier than expected by userspace.

Signed-off-by: Michel Dänzer <michel.daenzer@amd.com>
---

v2: Rename RADEON_FLIP_SUBMITTED => RADEON_FLIP_READY

 drivers/gpu/drm/radeon/atombios_crtc.c  | 28 ++++-------
 drivers/gpu/drm/radeon/cik.c            | 58 +++-------------------
 drivers/gpu/drm/radeon/evergreen.c      | 86 +++++----------------------------
 drivers/gpu/drm/radeon/r100.c           | 48 +++---------------
 drivers/gpu/drm/radeon/r600.c           | 18 +------
 drivers/gpu/drm/radeon/radeon.h         |  3 +-
 drivers/gpu/drm/radeon/radeon_asic.c    | 22 ---------
 drivers/gpu/drm/radeon/radeon_asic.h    |  4 --
 drivers/gpu/drm/radeon/radeon_display.c | 59 +++-------------------
 drivers/gpu/drm/radeon/radeon_mode.h    |  3 +-
 drivers/gpu/drm/radeon/rs600.c          | 28 +++--------
 drivers/gpu/drm/radeon/rv770.c          | 24 ++-------
 drivers/gpu/drm/radeon/si.c             | 52 +++-----------------
 13 files changed, 64 insertions(+), 369 deletions(-)

diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c
index e911898..65cfdbb 100644
--- a/drivers/gpu/drm/radeon/atombios_crtc.c
+++ b/drivers/gpu/drm/radeon/atombios_crtc.c
@@ -1284,6 +1284,10 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc,
 		break;
 	}
 
+	/* Make sure updates happen at vertical blank */
+	WREG32(EVERGREEN_GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset, 0);
+	WREG32(EVERGREEN_MASTER_UPDATE_MODE + radeon_crtc->crtc_offset, 0);
+
 	WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + radeon_crtc->crtc_offset,
 	       upper_32_bits(fb_location));
 	WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + radeon_crtc->crtc_offset,
@@ -1321,15 +1325,6 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc,
 	WREG32(EVERGREEN_VIEWPORT_SIZE + radeon_crtc->crtc_offset,
 	       (viewport_w << 16) | viewport_h);
 
-	/* pageflip setup */
-	/* make sure flip is at vb rather than hb */
-	tmp = RREG32(EVERGREEN_GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset);
-	tmp &= ~EVERGREEN_GRPH_SURFACE_UPDATE_H_RETRACE_EN;
-	WREG32(EVERGREEN_GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset, tmp);
-
-	/* set pageflip to happen anywhere in vblank interval */
-	WREG32(EVERGREEN_MASTER_UPDATE_MODE + radeon_crtc->crtc_offset, 0);
-
 	if (!atomic && fb && fb != crtc->primary->fb) {
 		radeon_fb = to_radeon_framebuffer(fb);
 		rbo = gem_to_radeon_bo(radeon_fb->obj);
@@ -1360,7 +1355,7 @@ static int avivo_crtc_do_set_base(struct drm_crtc *crtc,
 	uint64_t fb_location;
 	uint32_t fb_format, fb_pitch_pixels, tiling_flags;
 	u32 fb_swap = R600_D1GRPH_SWAP_ENDIAN_NONE;
-	u32 tmp, viewport_w, viewport_h;
+	u32 viewport_w, viewport_h;
 	int r;
 
 	/* no fb bound */
@@ -1451,6 +1446,10 @@ static int avivo_crtc_do_set_base(struct drm_crtc *crtc,
 	else
 		WREG32(AVIVO_D2VGA_CONTROL, 0);
 
+	/* Make sure updates happen at vertical blank */
+	WREG32(AVIVO_D1GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset, 0);
+	WREG32(AVIVO_D1MODE_MASTER_UPDATE_MODE + radeon_crtc->crtc_offset, 0);
+
 	if (rdev->family >= CHIP_RV770) {
 		if (radeon_crtc->crtc_id) {
 			WREG32(R700_D2GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, upper_32_bits(fb_location));
@@ -1490,15 +1489,6 @@ static int avivo_crtc_do_set_base(struct drm_crtc *crtc,
 	WREG32(AVIVO_D1MODE_VIEWPORT_SIZE + radeon_crtc->crtc_offset,
 	       (viewport_w << 16) | viewport_h);
 
-	/* pageflip setup */
-	/* make sure flip is at vb rather than hb */
-	tmp = RREG32(AVIVO_D1GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset);
-	tmp &= ~AVIVO_D1GRPH_SURFACE_UPDATE_H_RETRACE_EN;
-	WREG32(AVIVO_D1GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset, tmp);
-
-	/* set pageflip to happen anywhere in vblank interval */
-	WREG32(AVIVO_D1MODE_MASTER_UPDATE_MODE + radeon_crtc->crtc_offset, 0);
-
 	if (!atomic && fb && fb != crtc->primary->fb) {
 		radeon_fb = to_radeon_framebuffer(fb);
 		rbo = gem_to_radeon_bo(radeon_fb->obj);
diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c
index 0f4b38f..d0a994c 100644
--- a/drivers/gpu/drm/radeon/cik.c
+++ b/drivers/gpu/drm/radeon/cik.c
@@ -7143,25 +7143,6 @@ int cik_irq_set(struct radeon_device *rdev)
 		WREG32(LB_INTERRUPT_MASK + EVERGREEN_CRTC5_REGISTER_OFFSET, crtc6);
 	}
 
-	if (rdev->num_crtc >= 2) {
-		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET,
-		       GRPH_PFLIP_INT_MASK);
-		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET,
-		       GRPH_PFLIP_INT_MASK);
-	}
-	if (rdev->num_crtc >= 4) {
-		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET,
-		       GRPH_PFLIP_INT_MASK);
-		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET,
-		       GRPH_PFLIP_INT_MASK);
-	}
-	if (rdev->num_crtc >= 6) {
-		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET,
-		       GRPH_PFLIP_INT_MASK);
-		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET,
-		       GRPH_PFLIP_INT_MASK);
-	}
-
 	WREG32(DC_HPD1_INT_CONTROL, hpd1);
 	WREG32(DC_HPD2_INT_CONTROL, hpd2);
 	WREG32(DC_HPD3_INT_CONTROL, hpd3);
@@ -7215,12 +7196,6 @@ static inline void cik_irq_ack(struct radeon_device *rdev)
 			EVERGREEN_CRTC5_REGISTER_OFFSET);
 	}
 
-	if (rdev->irq.stat_regs.cik.d1grph_int & GRPH_PFLIP_INT_OCCURRED)
-		WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC0_REGISTER_OFFSET,
-		       GRPH_PFLIP_INT_CLEAR);
-	if (rdev->irq.stat_regs.cik.d2grph_int & GRPH_PFLIP_INT_OCCURRED)
-		WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC1_REGISTER_OFFSET,
-		       GRPH_PFLIP_INT_CLEAR);
 	if (rdev->irq.stat_regs.cik.disp_int & LB_D1_VBLANK_INTERRUPT)
 		WREG32(LB_VBLANK_STATUS + EVERGREEN_CRTC0_REGISTER_OFFSET, VBLANK_ACK);
 	if (rdev->irq.stat_regs.cik.disp_int & LB_D1_VLINE_INTERRUPT)
@@ -7231,12 +7206,6 @@ static inline void cik_irq_ack(struct radeon_device *rdev)
 		WREG32(LB_VLINE_STATUS + EVERGREEN_CRTC1_REGISTER_OFFSET, VLINE_ACK);
 
 	if (rdev->num_crtc >= 4) {
-		if (rdev->irq.stat_regs.cik.d3grph_int & GRPH_PFLIP_INT_OCCURRED)
-			WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET,
-			       GRPH_PFLIP_INT_CLEAR);
-		if (rdev->irq.stat_regs.cik.d4grph_int & GRPH_PFLIP_INT_OCCURRED)
-			WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC3_REGISTER_OFFSET,
-			       GRPH_PFLIP_INT_CLEAR);
 		if (rdev->irq.stat_regs.cik.disp_int_cont2 & LB_D3_VBLANK_INTERRUPT)
 			WREG32(LB_VBLANK_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET, VBLANK_ACK);
 		if (rdev->irq.stat_regs.cik.disp_int_cont2 & LB_D3_VLINE_INTERRUPT)
@@ -7248,12 +7217,6 @@ static inline void cik_irq_ack(struct radeon_device *rdev)
 	}
 
 	if (rdev->num_crtc >= 6) {
-		if (rdev->irq.stat_regs.cik.d5grph_int & GRPH_PFLIP_INT_OCCURRED)
-			WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET,
-			       GRPH_PFLIP_INT_CLEAR);
-		if (rdev->irq.stat_regs.cik.d6grph_int & GRPH_PFLIP_INT_OCCURRED)
-			WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET,
-			       GRPH_PFLIP_INT_CLEAR);
 		if (rdev->irq.stat_regs.cik.disp_int_cont4 & LB_D5_VBLANK_INTERRUPT)
 			WREG32(LB_VBLANK_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET, VBLANK_ACK);
 		if (rdev->irq.stat_regs.cik.disp_int_cont4 & LB_D5_VLINE_INTERRUPT)
@@ -7459,7 +7422,7 @@ restart_ih:
 						wake_up(&rdev->irq.vblank_queue);
 					}
 					if (atomic_read(&rdev->irq.pflip[0]))
-						radeon_crtc_handle_vblank(rdev, 0);
+						radeon_crtc_handle_flip(rdev, 0);
 					rdev->irq.stat_regs.cik.disp_int &= ~LB_D1_VBLANK_INTERRUPT;
 					DRM_DEBUG("IH: D1 vblank\n");
 				}
@@ -7485,7 +7448,7 @@ restart_ih:
 						wake_up(&rdev->irq.vblank_queue);
 					}
 					if (atomic_read(&rdev->irq.pflip[1]))
-						radeon_crtc_handle_vblank(rdev, 1);
+						radeon_crtc_handle_flip(rdev, 1);
 					rdev->irq.stat_regs.cik.disp_int_cont &= ~LB_D2_VBLANK_INTERRUPT;
 					DRM_DEBUG("IH: D2 vblank\n");
 				}
@@ -7511,7 +7474,7 @@ restart_ih:
 						wake_up(&rdev->irq.vblank_queue);
 					}
 					if (atomic_read(&rdev->irq.pflip[2]))
-						radeon_crtc_handle_vblank(rdev, 2);
+						radeon_crtc_handle_flip(rdev, 2);
 					rdev->irq.stat_regs.cik.disp_int_cont2 &= ~LB_D3_VBLANK_INTERRUPT;
 					DRM_DEBUG("IH: D3 vblank\n");
 				}
@@ -7537,7 +7500,7 @@ restart_ih:
 						wake_up(&rdev->irq.vblank_queue);
 					}
 					if (atomic_read(&rdev->irq.pflip[3]))
-						radeon_crtc_handle_vblank(rdev, 3);
+						radeon_crtc_handle_flip(rdev, 3);
 					rdev->irq.stat_regs.cik.disp_int_cont3 &= ~LB_D4_VBLANK_INTERRUPT;
 					DRM_DEBUG("IH: D4 vblank\n");
 				}
@@ -7563,7 +7526,7 @@ restart_ih:
 						wake_up(&rdev->irq.vblank_queue);
 					}
 					if (atomic_read(&rdev->irq.pflip[4]))
-						radeon_crtc_handle_vblank(rdev, 4);
+						radeon_crtc_handle_flip(rdev, 4);
 					rdev->irq.stat_regs.cik.disp_int_cont4 &= ~LB_D5_VBLANK_INTERRUPT;
 					DRM_DEBUG("IH: D5 vblank\n");
 				}
@@ -7589,7 +7552,7 @@ restart_ih:
 						wake_up(&rdev->irq.vblank_queue);
 					}
 					if (atomic_read(&rdev->irq.pflip[5]))
-						radeon_crtc_handle_vblank(rdev, 5);
+						radeon_crtc_handle_flip(rdev, 5);
 					rdev->irq.stat_regs.cik.disp_int_cont5 &= ~LB_D6_VBLANK_INTERRUPT;
 					DRM_DEBUG("IH: D6 vblank\n");
 				}
@@ -7605,15 +7568,6 @@ restart_ih:
 				break;
 			}
 			break;
-		case 8: /* D1 page flip */
-		case 10: /* D2 page flip */
-		case 12: /* D3 page flip */
-		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);
-			break;
 		case 42: /* HPD hotplug */
 			switch (src_data) {
 			case 0:
diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c
index 0443183..e7d685a 100644
--- a/drivers/gpu/drm/radeon/evergreen.c
+++ b/drivers/gpu/drm/radeon/evergreen.c
@@ -1308,16 +1308,15 @@ void dce4_wait_for_vblank(struct radeon_device *rdev, int crtc)
  * @crtc_base: new address of the crtc (GPU MC address)
  *
  * Does the actual pageflip (evergreen+).
- * During vblank we take the crtc lock and wait for the update_pending
- * bit to go high, when it does, we release the lock, and allow the
- * double buffered update to take place.
- * Returns the current update pending status.
  */
 void evergreen_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base)
 {
 	struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];
 	u32 tmp = RREG32(EVERGREEN_GRPH_UPDATE + radeon_crtc->crtc_offset);
-	int i;
+
+	/* Take surface updates at horizontal blank */
+	WREG32(EVERGREEN_GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset,
+	       EVERGREEN_GRPH_SURFACE_UPDATE_H_RETRACE_EN);
 
 	/* Lock the graphics update lock */
 	tmp |= EVERGREEN_GRPH_UPDATE_LOCK;
@@ -1334,36 +1333,11 @@ void evergreen_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base)
 	WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset,
 	       (u32)crtc_base);
 
-	/* Wait for update_pending to go high. */
-	for (i = 0; i < rdev->usec_timeout; i++) {
-		if (RREG32(EVERGREEN_GRPH_UPDATE + radeon_crtc->crtc_offset) & EVERGREEN_GRPH_SURFACE_UPDATE_PENDING)
-			break;
-		udelay(1);
-	}
-	DRM_DEBUG("Update pending now high. Unlocking vupdate_lock.\n");
-
-	/* Unlock the lock, so double-buffering can take place inside vblank */
+	/* Unlock the lock, so double-buffering can take place inside hblank */
 	tmp &= ~EVERGREEN_GRPH_UPDATE_LOCK;
 	WREG32(EVERGREEN_GRPH_UPDATE + radeon_crtc->crtc_offset, tmp);
 }
 
-/**
- * evergreen_page_flip_pending - check if page flip is still pending
- *
- * @rdev: radeon_device pointer
- * @crtc_id: crtc to check
- *
- * Returns the current update pending status.
- */
-bool evergreen_page_flip_pending(struct radeon_device *rdev, int crtc_id)
-{
-	struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];
-
-	/* Return current update_pending status: */
-	return !!(RREG32(EVERGREEN_GRPH_UPDATE + radeon_crtc->crtc_offset) &
-		EVERGREEN_GRPH_SURFACE_UPDATE_PENDING);
-}
-
 /* get temperature in millidegrees */
 int evergreen_get_temp(struct radeon_device *rdev)
 {
@@ -4541,23 +4515,6 @@ int evergreen_irq_set(struct radeon_device *rdev)
 		WREG32(INT_MASK + EVERGREEN_CRTC5_REGISTER_OFFSET, crtc6);
 	}
 
-	WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET,
-	       GRPH_PFLIP_INT_MASK);
-	WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET,
-	       GRPH_PFLIP_INT_MASK);
-	if (rdev->num_crtc >= 4) {
-		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET,
-		       GRPH_PFLIP_INT_MASK);
-		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET,
-		       GRPH_PFLIP_INT_MASK);
-	}
-	if (rdev->num_crtc >= 6) {
-		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET,
-		       GRPH_PFLIP_INT_MASK);
-		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET,
-		       GRPH_PFLIP_INT_MASK);
-	}
-
 	WREG32(DC_HPD1_INT_CONTROL, hpd1);
 	WREG32(DC_HPD2_INT_CONTROL, hpd2);
 	WREG32(DC_HPD3_INT_CONTROL, hpd3);
@@ -4607,10 +4564,6 @@ static void evergreen_irq_ack(struct radeon_device *rdev)
 	rdev->irq.stat_regs.evergreen.afmt_status5 = RREG32(AFMT_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET);
 	rdev->irq.stat_regs.evergreen.afmt_status6 = RREG32(AFMT_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET);
 
-	if (rdev->irq.stat_regs.evergreen.d1grph_int & GRPH_PFLIP_INT_OCCURRED)
-		WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC0_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR);
-	if (rdev->irq.stat_regs.evergreen.d2grph_int & GRPH_PFLIP_INT_OCCURRED)
-		WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC1_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR);
 	if (rdev->irq.stat_regs.evergreen.disp_int & LB_D1_VBLANK_INTERRUPT)
 		WREG32(VBLANK_STATUS + EVERGREEN_CRTC0_REGISTER_OFFSET, VBLANK_ACK);
 	if (rdev->irq.stat_regs.evergreen.disp_int & LB_D1_VLINE_INTERRUPT)
@@ -4621,10 +4574,6 @@ static void evergreen_irq_ack(struct radeon_device *rdev)
 		WREG32(VLINE_STATUS + EVERGREEN_CRTC1_REGISTER_OFFSET, VLINE_ACK);
 
 	if (rdev->num_crtc >= 4) {
-		if (rdev->irq.stat_regs.evergreen.d3grph_int & GRPH_PFLIP_INT_OCCURRED)
-			WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR);
-		if (rdev->irq.stat_regs.evergreen.d4grph_int & GRPH_PFLIP_INT_OCCURRED)
-			WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC3_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR);
 		if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & LB_D3_VBLANK_INTERRUPT)
 			WREG32(VBLANK_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET, VBLANK_ACK);
 		if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & LB_D3_VLINE_INTERRUPT)
@@ -4636,10 +4585,6 @@ static void evergreen_irq_ack(struct radeon_device *rdev)
 	}
 
 	if (rdev->num_crtc >= 6) {
-		if (rdev->irq.stat_regs.evergreen.d5grph_int & GRPH_PFLIP_INT_OCCURRED)
-			WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR);
-		if (rdev->irq.stat_regs.evergreen.d6grph_int & GRPH_PFLIP_INT_OCCURRED)
-			WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR);
 		if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & LB_D5_VBLANK_INTERRUPT)
 			WREG32(VBLANK_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET, VBLANK_ACK);
 		if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & LB_D5_VLINE_INTERRUPT)
@@ -4798,7 +4743,7 @@ restart_ih:
 						wake_up(&rdev->irq.vblank_queue);
 					}
 					if (atomic_read(&rdev->irq.pflip[0]))
-						radeon_crtc_handle_vblank(rdev, 0);
+						radeon_crtc_handle_flip(rdev, 0);
 					rdev->irq.stat_regs.evergreen.disp_int &= ~LB_D1_VBLANK_INTERRUPT;
 					DRM_DEBUG("IH: D1 vblank\n");
 				}
@@ -4824,7 +4769,7 @@ restart_ih:
 						wake_up(&rdev->irq.vblank_queue);
 					}
 					if (atomic_read(&rdev->irq.pflip[1]))
-						radeon_crtc_handle_vblank(rdev, 1);
+						radeon_crtc_handle_flip(rdev, 1);
 					rdev->irq.stat_regs.evergreen.disp_int_cont &= ~LB_D2_VBLANK_INTERRUPT;
 					DRM_DEBUG("IH: D2 vblank\n");
 				}
@@ -4850,7 +4795,7 @@ restart_ih:
 						wake_up(&rdev->irq.vblank_queue);
 					}
 					if (atomic_read(&rdev->irq.pflip[2]))
-						radeon_crtc_handle_vblank(rdev, 2);
+						radeon_crtc_handle_flip(rdev, 2);
 					rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~LB_D3_VBLANK_INTERRUPT;
 					DRM_DEBUG("IH: D3 vblank\n");
 				}
@@ -4876,7 +4821,7 @@ restart_ih:
 						wake_up(&rdev->irq.vblank_queue);
 					}
 					if (atomic_read(&rdev->irq.pflip[3]))
-						radeon_crtc_handle_vblank(rdev, 3);
+						radeon_crtc_handle_flip(rdev, 3);
 					rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~LB_D4_VBLANK_INTERRUPT;
 					DRM_DEBUG("IH: D4 vblank\n");
 				}
@@ -4902,7 +4847,7 @@ restart_ih:
 						wake_up(&rdev->irq.vblank_queue);
 					}
 					if (atomic_read(&rdev->irq.pflip[4]))
-						radeon_crtc_handle_vblank(rdev, 4);
+						radeon_crtc_handle_flip(rdev, 4);
 					rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~LB_D5_VBLANK_INTERRUPT;
 					DRM_DEBUG("IH: D5 vblank\n");
 				}
@@ -4928,7 +4873,7 @@ restart_ih:
 						wake_up(&rdev->irq.vblank_queue);
 					}
 					if (atomic_read(&rdev->irq.pflip[5]))
-						radeon_crtc_handle_vblank(rdev, 5);
+						radeon_crtc_handle_flip(rdev, 5);
 					rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~LB_D6_VBLANK_INTERRUPT;
 					DRM_DEBUG("IH: D6 vblank\n");
 				}
@@ -4944,15 +4889,6 @@ restart_ih:
 				break;
 			}
 			break;
-		case 8: /* D1 page flip */
-		case 10: /* D2 page flip */
-		case 12: /* D3 page flip */
-		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);
-			break;
 		case 42: /* HPD hotplug */
 			switch (src_data) {
 			case 0:
diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c
index 54674b7..1f2a960 100644
--- a/drivers/gpu/drm/radeon/r100.c
+++ b/drivers/gpu/drm/radeon/r100.c
@@ -149,50 +149,18 @@ void r100_wait_for_vblank(struct radeon_device *rdev, int crtc)
  * @crtc_base: new address of the crtc (GPU MC address)
  *
  * Does the actual pageflip (r1xx-r4xx).
- * During vblank we take the crtc lock and wait for the update_pending
- * bit to go high, when it does, we release the lock, and allow the
- * double buffered update to take place.
  */
 void r100_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base)
 {
 	struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];
-	u32 tmp = ((u32)crtc_base) | RADEON_CRTC_OFFSET__OFFSET_LOCK;
-	int i;
-
-	/* Lock the graphics update lock */
-	/* update the scanout addresses */
-	WREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset, tmp);
+	u32 crtc_offset_cntl = RREG32(RADEON_CRTC_OFFSET_CNTL);
 
-	/* Wait for update_pending to go high. */
-	for (i = 0; i < rdev->usec_timeout; i++) {
-		if (RREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset) & RADEON_CRTC_OFFSET__GUI_TRIG_OFFSET)
-			break;
-		udelay(1);
-	}
-	DRM_DEBUG("Update pending now high. Unlocking vupdate_lock.\n");
-
-	/* Unlock the lock, so double-buffering can take place inside vblank */
-	tmp &= ~RADEON_CRTC_OFFSET__OFFSET_LOCK;
-	WREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset, tmp);
-
-}
-
-/**
- * r100_page_flip_pending - check if page flip is still pending
- *
- * @rdev: radeon_device pointer
- * @crtc_id: crtc to check
- *
- * Check if the last pagefilp is still pending (r1xx-r4xx).
- * Returns the current update pending status.
- */
-bool r100_page_flip_pending(struct radeon_device *rdev, int crtc_id)
-{
-	struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];
+	/* Take surface updates at horizontal blank */
+	WREG32(RADEON_CRTC_OFFSET_CNTL,
+	       crtc_offset_cntl | RADEON_CRTC_OFFSET_FLIP_CNTL);
 
-	/* Return current update_pending status: */
-	return !!(RREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset) &
-		RADEON_CRTC_OFFSET__GUI_TRIG_OFFSET);
+	/* Update the scanout address */
+	WREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset, crtc_base);
 }
 
 /**
@@ -786,7 +754,7 @@ int r100_irq_process(struct radeon_device *rdev)
 				wake_up(&rdev->irq.vblank_queue);
 			}
 			if (atomic_read(&rdev->irq.pflip[0]))
-				radeon_crtc_handle_vblank(rdev, 0);
+				radeon_crtc_handle_flip(rdev, 0);
 		}
 		if (status & RADEON_CRTC2_VBLANK_STAT) {
 			if (rdev->irq.crtc_vblank_int[1]) {
@@ -795,7 +763,7 @@ int r100_irq_process(struct radeon_device *rdev)
 				wake_up(&rdev->irq.vblank_queue);
 			}
 			if (atomic_read(&rdev->irq.pflip[1]))
-				radeon_crtc_handle_vblank(rdev, 1);
+				radeon_crtc_handle_flip(rdev, 1);
 		}
 		if (status & RADEON_FP_DETECT_STAT) {
 			queue_hotplug = true;
diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c
index ae54f76..8f318ec 100644
--- a/drivers/gpu/drm/radeon/r600.c
+++ b/drivers/gpu/drm/radeon/r600.c
@@ -3614,8 +3614,6 @@ 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(GRBM_INT_CNTL, grbm_int_cntl);
 	if (ASIC_IS_DCE3(rdev)) {
 		WREG32(DC_HPD1_INT_CONTROL, hpd1);
@@ -3672,10 +3670,6 @@ static void r600_irq_ack(struct radeon_device *rdev)
 	rdev->irq.stat_regs.r600.d1grph_int = RREG32(D1GRPH_INTERRUPT_STATUS);
 	rdev->irq.stat_regs.r600.d2grph_int = RREG32(D2GRPH_INTERRUPT_STATUS);
 
-	if (rdev->irq.stat_regs.r600.d1grph_int & DxGRPH_PFLIP_INT_OCCURRED)
-		WREG32(D1GRPH_INTERRUPT_STATUS, DxGRPH_PFLIP_INT_CLEAR);
-	if (rdev->irq.stat_regs.r600.d2grph_int & DxGRPH_PFLIP_INT_OCCURRED)
-		WREG32(D2GRPH_INTERRUPT_STATUS, DxGRPH_PFLIP_INT_CLEAR);
 	if (rdev->irq.stat_regs.r600.disp_int & LB_D1_VBLANK_INTERRUPT)
 		WREG32(D1MODE_VBLANK_STATUS, DxMODE_VBLANK_ACK);
 	if (rdev->irq.stat_regs.r600.disp_int & LB_D1_VLINE_INTERRUPT)
@@ -3876,7 +3870,7 @@ restart_ih:
 						wake_up(&rdev->irq.vblank_queue);
 					}
 					if (atomic_read(&rdev->irq.pflip[0]))
-						radeon_crtc_handle_vblank(rdev, 0);
+						radeon_crtc_handle_flip(rdev, 0);
 					rdev->irq.stat_regs.r600.disp_int &= ~LB_D1_VBLANK_INTERRUPT;
 					DRM_DEBUG("IH: D1 vblank\n");
 				}
@@ -3902,7 +3896,7 @@ restart_ih:
 						wake_up(&rdev->irq.vblank_queue);
 					}
 					if (atomic_read(&rdev->irq.pflip[1]))
-						radeon_crtc_handle_vblank(rdev, 1);
+						radeon_crtc_handle_flip(rdev, 1);
 					rdev->irq.stat_regs.r600.disp_int &= ~LB_D2_VBLANK_INTERRUPT;
 					DRM_DEBUG("IH: D2 vblank\n");
 				}
@@ -3918,14 +3912,6 @@ restart_ih:
 				break;
 			}
 			break;
-		case 9: /* D1 pflip */
-			DRM_DEBUG("IH: D1 flip\n");
-			radeon_crtc_handle_flip(rdev, 0);
-			break;
-		case 11: /* D2 pflip */
-			DRM_DEBUG("IH: D2 flip\n");
-			radeon_crtc_handle_flip(rdev, 1);
-			break;
 		case 19: /* HPD/DAC hotplug */
 			switch (src_data) {
 			case 0:
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index 8e8ef08..7a45c93 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -681,6 +681,7 @@ struct radeon_flip_work {
 	struct work_struct		unpin_work;
 	struct radeon_device		*rdev;
 	int				crtc_id;
+	uint64_t			base;
 	struct drm_framebuffer		*fb;
 	struct drm_pending_vblank_event *event;
 	struct radeon_bo		*old_rbo;
@@ -1884,7 +1885,6 @@ struct radeon_asic {
 	/* pageflipping */
 	struct {
 		void (*page_flip)(struct radeon_device *rdev, int crtc, u64 crtc_base);
-		bool (*page_flip_pending)(struct radeon_device *rdev, int crtc);
 	} pflip;
 };
 
@@ -2746,7 +2746,6 @@ void radeon_ring_write(struct radeon_ring *ring, uint32_t v);
 #define radeon_pm_init_profile(rdev) (rdev)->asic->pm.init_profile((rdev))
 #define radeon_pm_get_dynpm_state(rdev) (rdev)->asic->pm.get_dynpm_state((rdev))
 #define radeon_page_flip(rdev, crtc, base) (rdev)->asic->pflip.page_flip((rdev), (crtc), (base))
-#define radeon_page_flip_pending(rdev, crtc) (rdev)->asic->pflip.page_flip_pending((rdev), (crtc))
 #define radeon_wait_for_vblank(rdev, crtc) (rdev)->asic->display.wait_for_vblank((rdev), (crtc))
 #define radeon_mc_wait_for_idle(rdev) (rdev)->asic->mc_wait_for_idle((rdev))
 #define radeon_get_xclk(rdev) (rdev)->asic->get_xclk((rdev))
diff --git a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c
index baee3cd..662c181 100644
--- a/drivers/gpu/drm/radeon/radeon_asic.c
+++ b/drivers/gpu/drm/radeon/radeon_asic.c
@@ -252,7 +252,6 @@ static struct radeon_asic r100_asic = {
 	},
 	.pflip = {
 		.page_flip = &r100_page_flip,
-		.page_flip_pending = &r100_page_flip_pending,
 	},
 };
 
@@ -319,7 +318,6 @@ static struct radeon_asic r200_asic = {
 	},
 	.pflip = {
 		.page_flip = &r100_page_flip,
-		.page_flip_pending = &r100_page_flip_pending,
 	},
 };
 
@@ -400,7 +398,6 @@ static struct radeon_asic r300_asic = {
 	},
 	.pflip = {
 		.page_flip = &r100_page_flip,
-		.page_flip_pending = &r100_page_flip_pending,
 	},
 };
 
@@ -467,7 +464,6 @@ static struct radeon_asic r300_asic_pcie = {
 	},
 	.pflip = {
 		.page_flip = &r100_page_flip,
-		.page_flip_pending = &r100_page_flip_pending,
 	},
 };
 
@@ -534,7 +530,6 @@ static struct radeon_asic r420_asic = {
 	},
 	.pflip = {
 		.page_flip = &r100_page_flip,
-		.page_flip_pending = &r100_page_flip_pending,
 	},
 };
 
@@ -601,7 +596,6 @@ static struct radeon_asic rs400_asic = {
 	},
 	.pflip = {
 		.page_flip = &r100_page_flip,
-		.page_flip_pending = &r100_page_flip_pending,
 	},
 };
 
@@ -670,7 +664,6 @@ static struct radeon_asic rs600_asic = {
 	},
 	.pflip = {
 		.page_flip = &rs600_page_flip,
-		.page_flip_pending = &rs600_page_flip_pending,
 	},
 };
 
@@ -739,7 +732,6 @@ static struct radeon_asic rs690_asic = {
 	},
 	.pflip = {
 		.page_flip = &rs600_page_flip,
-		.page_flip_pending = &rs600_page_flip_pending,
 	},
 };
 
@@ -806,7 +798,6 @@ static struct radeon_asic rv515_asic = {
 	},
 	.pflip = {
 		.page_flip = &rs600_page_flip,
-		.page_flip_pending = &rs600_page_flip_pending,
 	},
 };
 
@@ -873,7 +864,6 @@ static struct radeon_asic r520_asic = {
 	},
 	.pflip = {
 		.page_flip = &rs600_page_flip,
-		.page_flip_pending = &rs600_page_flip_pending,
 	},
 };
 
@@ -972,7 +962,6 @@ static struct radeon_asic r600_asic = {
 	},
 	.pflip = {
 		.page_flip = &rs600_page_flip,
-		.page_flip_pending = &rs600_page_flip_pending,
 	},
 };
 
@@ -1063,7 +1052,6 @@ static struct radeon_asic rv6xx_asic = {
 	},
 	.pflip = {
 		.page_flip = &rs600_page_flip,
-		.page_flip_pending = &rs600_page_flip_pending,
 	},
 };
 
@@ -1154,7 +1142,6 @@ static struct radeon_asic rs780_asic = {
 	},
 	.pflip = {
 		.page_flip = &rs600_page_flip,
-		.page_flip_pending = &rs600_page_flip_pending,
 	},
 };
 
@@ -1260,7 +1247,6 @@ static struct radeon_asic rv770_asic = {
 	},
 	.pflip = {
 		.page_flip = &rv770_page_flip,
-		.page_flip_pending = &rv770_page_flip_pending,
 	},
 };
 
@@ -1379,7 +1365,6 @@ static struct radeon_asic evergreen_asic = {
 	},
 	.pflip = {
 		.page_flip = &evergreen_page_flip,
-		.page_flip_pending = &evergreen_page_flip_pending,
 	},
 };
 
@@ -1471,7 +1456,6 @@ static struct radeon_asic sumo_asic = {
 	},
 	.pflip = {
 		.page_flip = &evergreen_page_flip,
-		.page_flip_pending = &evergreen_page_flip_pending,
 	},
 };
 
@@ -1564,7 +1548,6 @@ static struct radeon_asic btc_asic = {
 	},
 	.pflip = {
 		.page_flip = &evergreen_page_flip,
-		.page_flip_pending = &evergreen_page_flip_pending,
 	},
 };
 
@@ -1708,7 +1691,6 @@ static struct radeon_asic cayman_asic = {
 	},
 	.pflip = {
 		.page_flip = &evergreen_page_flip,
-		.page_flip_pending = &evergreen_page_flip_pending,
 	},
 };
 
@@ -1809,7 +1791,6 @@ static struct radeon_asic trinity_asic = {
 	},
 	.pflip = {
 		.page_flip = &evergreen_page_flip,
-		.page_flip_pending = &evergreen_page_flip_pending,
 	},
 };
 
@@ -1940,7 +1921,6 @@ static struct radeon_asic si_asic = {
 	},
 	.pflip = {
 		.page_flip = &evergreen_page_flip,
-		.page_flip_pending = &evergreen_page_flip_pending,
 	},
 };
 
@@ -2103,7 +2083,6 @@ static struct radeon_asic ci_asic = {
 	},
 	.pflip = {
 		.page_flip = &evergreen_page_flip,
-		.page_flip_pending = &evergreen_page_flip_pending,
 	},
 };
 
@@ -2208,7 +2187,6 @@ static struct radeon_asic kv_asic = {
 	},
 	.pflip = {
 		.page_flip = &evergreen_page_flip,
-		.page_flip_pending = &evergreen_page_flip_pending,
 	},
 };
 
diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h
index f05270e..b49bfcd 100644
--- a/drivers/gpu/drm/radeon/radeon_asic.h
+++ b/drivers/gpu/drm/radeon/radeon_asic.h
@@ -138,7 +138,6 @@ extern void r100_pm_init_profile(struct radeon_device *rdev);
 extern void r100_pm_get_dynpm_state(struct radeon_device *rdev);
 extern void r100_page_flip(struct radeon_device *rdev, int crtc,
 			   u64 crtc_base);
-extern bool r100_page_flip_pending(struct radeon_device *rdev, int crtc);
 extern void r100_wait_for_vblank(struct radeon_device *rdev, int crtc);
 extern int r100_mc_wait_for_idle(struct radeon_device *rdev);
 
@@ -247,7 +246,6 @@ extern void rs600_pm_prepare(struct radeon_device *rdev);
 extern void rs600_pm_finish(struct radeon_device *rdev);
 extern void rs600_page_flip(struct radeon_device *rdev, int crtc,
 			    u64 crtc_base);
-extern bool rs600_page_flip_pending(struct radeon_device *rdev, int crtc);
 void rs600_set_safe_registers(struct radeon_device *rdev);
 extern void avivo_wait_for_vblank(struct radeon_device *rdev, int crtc);
 extern int rs600_mc_wait_for_idle(struct radeon_device *rdev);
@@ -452,7 +450,6 @@ int rv770_suspend(struct radeon_device *rdev);
 int rv770_resume(struct radeon_device *rdev);
 void rv770_pm_misc(struct radeon_device *rdev);
 void rv770_page_flip(struct radeon_device *rdev, int crtc, u64 crtc_base);
-bool rv770_page_flip_pending(struct radeon_device *rdev, int crtc);
 void r700_vram_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc);
 void r700_cp_stop(struct radeon_device *rdev);
 void r700_cp_fini(struct radeon_device *rdev);
@@ -520,7 +517,6 @@ int sumo_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk);
 int evergreen_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk);
 extern void evergreen_page_flip(struct radeon_device *rdev, int crtc,
 				u64 crtc_base);
-extern bool evergreen_page_flip_pending(struct radeon_device *rdev, int crtc);
 extern void dce4_wait_for_vblank(struct radeon_device *rdev, int crtc);
 void evergreen_disable_interrupt_state(struct radeon_device *rdev);
 int evergreen_mc_wait_for_idle(struct radeon_device *rdev);
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c
index 65882cd..103d0c6 100644
--- a/drivers/gpu/drm/radeon/radeon_display.c
+++ b/drivers/gpu/drm/radeon/radeon_display.c
@@ -281,50 +281,6 @@ static void radeon_unpin_work_func(struct work_struct *__work)
 	kfree(work);
 }
 
-void radeon_crtc_handle_vblank(struct radeon_device *rdev, int crtc_id)
-{
-	struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];
-	unsigned long flags;
-	u32 update_pending;
-	int vpos, hpos;
-
-	/* can happen during initialization */
-	if (radeon_crtc == NULL)
-		return;
-
-	spin_lock_irqsave(&rdev->ddev->event_lock, flags);
-	if (radeon_crtc->flip_status != RADEON_FLIP_SUBMITTED) {
-		DRM_DEBUG_DRIVER("radeon_crtc->flip_status = %d != "
-				 "RADEON_FLIP_SUBMITTED(%d)\n",
-				 radeon_crtc->flip_status,
-				 RADEON_FLIP_SUBMITTED);
-		spin_unlock_irqrestore(&rdev->ddev->event_lock, flags);
-		return;
-	}
-
-	update_pending = radeon_page_flip_pending(rdev, crtc_id);
-
-	/* Has the pageflip already completed in crtc, or is it certain
-	 * to complete in this vblank?
-	 */
-	if (update_pending &&
-	    (DRM_SCANOUTPOS_VALID & radeon_get_crtc_scanoutpos(rdev->ddev, crtc_id, 0,
-							       &vpos, &hpos, NULL, NULL)) &&
-	    ((vpos >= (99 * rdev->mode_info.crtcs[crtc_id]->base.hwmode.crtc_vdisplay)/100) ||
-	     (vpos < 0 && !ASIC_IS_AVIVO(rdev)))) {
-		/* crtc didn't flip in this target vblank interval,
-		 * but flip is pending in crtc. Based on the current
-		 * scanout position we know that the current frame is
-		 * (nearly) complete and the flip will (likely)
-		 * complete before the start of the next frame.
-		 */
-		update_pending = 0;
-	}
-	spin_unlock_irqrestore(&rdev->ddev->event_lock, flags);
-	if (!update_pending)
-		radeon_crtc_handle_flip(rdev, crtc_id);
-}
-
 /**
  * radeon_crtc_handle_flip - page flip completed
  *
@@ -345,15 +301,18 @@ void radeon_crtc_handle_flip(struct radeon_device *rdev, int crtc_id)
 
 	spin_lock_irqsave(&rdev->ddev->event_lock, flags);
 	work = radeon_crtc->flip_work;
-	if (radeon_crtc->flip_status != RADEON_FLIP_SUBMITTED) {
+	if (radeon_crtc->flip_status != RADEON_FLIP_READY) {
 		DRM_DEBUG_DRIVER("radeon_crtc->flip_status = %d != "
-				 "RADEON_FLIP_SUBMITTED(%d)\n",
+				 "RADEON_FLIP_READY(%d)\n",
 				 radeon_crtc->flip_status,
-				 RADEON_FLIP_SUBMITTED);
+				 RADEON_FLIP_READY);
 		spin_unlock_irqrestore(&rdev->ddev->event_lock, flags);
 		return;
 	}
 
+	/* do the flip (mmio) */
+	radeon_page_flip(rdev, radeon_crtc->crtc_id, work->base);
+
 	/* Pageflip completed. Clean up. */
 	radeon_crtc->flip_status = RADEON_FLIP_NONE;
 	radeon_crtc->flip_work = NULL;
@@ -479,10 +438,8 @@ static void radeon_flip_work_func(struct work_struct *__work)
 	/* set the proper interrupt */
 	radeon_irq_kms_pflip_irq_get(rdev, radeon_crtc->crtc_id);
 
-	/* do the flip (mmio) */
-	radeon_page_flip(rdev, radeon_crtc->crtc_id, base);
-
-	radeon_crtc->flip_status = RADEON_FLIP_SUBMITTED;
+	work->base = base;
+	radeon_crtc->flip_status = RADEON_FLIP_READY;
 	spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
 	up_read(&rdev->exclusive_lock);
 
diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h
index ed6b6e0..00955e3 100644
--- a/drivers/gpu/drm/radeon/radeon_mode.h
+++ b/drivers/gpu/drm/radeon/radeon_mode.h
@@ -304,7 +304,7 @@ struct radeon_atom_ss {
 enum radeon_flip_status {
 	RADEON_FLIP_NONE,
 	RADEON_FLIP_PENDING,
-	RADEON_FLIP_SUBMITTED
+	RADEON_FLIP_READY
 };
 
 struct radeon_crtc {
@@ -913,7 +913,6 @@ bool radeon_fbdev_robj_is_fb(struct radeon_device *rdev, struct radeon_bo *robj)
 
 void radeon_fb_output_poll_changed(struct radeon_device *rdev);
 
-void radeon_crtc_handle_vblank(struct radeon_device *rdev, int crtc_id);
 void radeon_crtc_handle_flip(struct radeon_device *rdev, int crtc_id);
 
 int radeon_align_pitch(struct radeon_device *rdev, int width, int bpp, bool tiled);
diff --git a/drivers/gpu/drm/radeon/rs600.c b/drivers/gpu/drm/radeon/rs600.c
index 818f4eb..b5e63a7 100644
--- a/drivers/gpu/drm/radeon/rs600.c
+++ b/drivers/gpu/drm/radeon/rs600.c
@@ -113,7 +113,10 @@ void rs600_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base)
 {
 	struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];
 	u32 tmp = RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset);
-	int i;
+
+	/* Take surface updates at horizontal blank */
+	WREG32(AVIVO_D1GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset,
+	       AVIVO_D1GRPH_SURFACE_UPDATE_H_RETRACE_EN);
 
 	/* Lock the graphics update lock */
 	tmp |= AVIVO_D1GRPH_UPDATE_LOCK;
@@ -125,28 +128,11 @@ void rs600_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base)
 	WREG32(AVIVO_D1GRPH_PRIMARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset,
 	       (u32)crtc_base);
 
-	/* Wait for update_pending to go high. */
-	for (i = 0; i < rdev->usec_timeout; i++) {
-		if (RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset) & AVIVO_D1GRPH_SURFACE_UPDATE_PENDING)
-			break;
-		udelay(1);
-	}
-	DRM_DEBUG("Update pending now high. Unlocking vupdate_lock.\n");
-
-	/* Unlock the lock, so double-buffering can take place inside vblank */
+	/* Unlock the lock, so double-buffering can take place inside hblank */
 	tmp &= ~AVIVO_D1GRPH_UPDATE_LOCK;
 	WREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset, tmp);
 }
 
-bool rs600_page_flip_pending(struct radeon_device *rdev, int crtc_id)
-{
-	struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];
-
-	/* Return current update_pending status: */
-	return !!(RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset) &
-		AVIVO_D1GRPH_SURFACE_UPDATE_PENDING);
-}
-
 void avivo_program_fmt(struct drm_encoder *encoder)
 {
 	struct drm_device *dev = encoder->dev;
@@ -790,7 +776,7 @@ int rs600_irq_process(struct radeon_device *rdev)
 				wake_up(&rdev->irq.vblank_queue);
 			}
 			if (atomic_read(&rdev->irq.pflip[0]))
-				radeon_crtc_handle_vblank(rdev, 0);
+				radeon_crtc_handle_flip(rdev, 0);
 		}
 		if (G_007EDC_LB_D2_VBLANK_INTERRUPT(rdev->irq.stat_regs.r500.disp_int)) {
 			if (rdev->irq.crtc_vblank_int[1]) {
@@ -799,7 +785,7 @@ int rs600_irq_process(struct radeon_device *rdev)
 				wake_up(&rdev->irq.vblank_queue);
 			}
 			if (atomic_read(&rdev->irq.pflip[1]))
-				radeon_crtc_handle_vblank(rdev, 1);
+				radeon_crtc_handle_flip(rdev, 1);
 		}
 		if (G_007EDC_DC_HOT_PLUG_DETECT1_INTERRUPT(rdev->irq.stat_regs.r500.disp_int)) {
 			queue_hotplug = true;
diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c
index 97b7766..ef66be4 100644
--- a/drivers/gpu/drm/radeon/rv770.c
+++ b/drivers/gpu/drm/radeon/rv770.c
@@ -805,7 +805,10 @@ void rv770_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base)
 {
 	struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];
 	u32 tmp = RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset);
-	int i;
+
+	/* Take surface updates at horizontal blank */
+	WREG32(AVIVO_D1GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset,
+	       AVIVO_D1GRPH_SURFACE_UPDATE_H_RETRACE_EN);
 
 	/* Lock the graphics update lock */
 	tmp |= AVIVO_D1GRPH_UPDATE_LOCK;
@@ -824,28 +827,11 @@ void rv770_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base)
 	WREG32(D1GRPH_PRIMARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset,
 	       (u32)crtc_base);
 
-	/* Wait for update_pending to go high. */
-	for (i = 0; i < rdev->usec_timeout; i++) {
-		if (RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset) & AVIVO_D1GRPH_SURFACE_UPDATE_PENDING)
-			break;
-		udelay(1);
-	}
-	DRM_DEBUG("Update pending now high. Unlocking vupdate_lock.\n");
-
-	/* Unlock the lock, so double-buffering can take place inside vblank */
+	/* Unlock the lock, so double-buffering can take place inside hblank */
 	tmp &= ~AVIVO_D1GRPH_UPDATE_LOCK;
 	WREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset, tmp);
 }
 
-bool rv770_page_flip_pending(struct radeon_device *rdev, int crtc_id)
-{
-	struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];
-
-	/* Return current update_pending status: */
-	return !!(RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset) &
-		AVIVO_D1GRPH_SURFACE_UPDATE_PENDING);
-}
-
 /* get temperature in millidegrees */
 int rv770_get_temp(struct radeon_device *rdev)
 {
diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c
index c128bde..fee797f 100644
--- a/drivers/gpu/drm/radeon/si.c
+++ b/drivers/gpu/drm/radeon/si.c
@@ -5917,25 +5917,6 @@ int si_irq_set(struct radeon_device *rdev)
 		WREG32(INT_MASK + EVERGREEN_CRTC5_REGISTER_OFFSET, crtc6);
 	}
 
-	if (rdev->num_crtc >= 2) {
-		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET,
-		       GRPH_PFLIP_INT_MASK);
-		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET,
-		       GRPH_PFLIP_INT_MASK);
-	}
-	if (rdev->num_crtc >= 4) {
-		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET,
-		       GRPH_PFLIP_INT_MASK);
-		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET,
-		       GRPH_PFLIP_INT_MASK);
-	}
-	if (rdev->num_crtc >= 6) {
-		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET,
-		       GRPH_PFLIP_INT_MASK);
-		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET,
-		       GRPH_PFLIP_INT_MASK);
-	}
-
 	if (!ASIC_IS_NODCE(rdev)) {
 		WREG32(DC_HPD1_INT_CONTROL, hpd1);
 		WREG32(DC_HPD2_INT_CONTROL, hpd2);
@@ -5974,10 +5955,6 @@ static inline void si_irq_ack(struct radeon_device *rdev)
 		rdev->irq.stat_regs.evergreen.d6grph_int = RREG32(GRPH_INT_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET);
 	}
 
-	if (rdev->irq.stat_regs.evergreen.d1grph_int & GRPH_PFLIP_INT_OCCURRED)
-		WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC0_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR);
-	if (rdev->irq.stat_regs.evergreen.d2grph_int & GRPH_PFLIP_INT_OCCURRED)
-		WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC1_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR);
 	if (rdev->irq.stat_regs.evergreen.disp_int & LB_D1_VBLANK_INTERRUPT)
 		WREG32(VBLANK_STATUS + EVERGREEN_CRTC0_REGISTER_OFFSET, VBLANK_ACK);
 	if (rdev->irq.stat_regs.evergreen.disp_int & LB_D1_VLINE_INTERRUPT)
@@ -5988,10 +5965,6 @@ static inline void si_irq_ack(struct radeon_device *rdev)
 		WREG32(VLINE_STATUS + EVERGREEN_CRTC1_REGISTER_OFFSET, VLINE_ACK);
 
 	if (rdev->num_crtc >= 4) {
-		if (rdev->irq.stat_regs.evergreen.d3grph_int & GRPH_PFLIP_INT_OCCURRED)
-			WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR);
-		if (rdev->irq.stat_regs.evergreen.d4grph_int & GRPH_PFLIP_INT_OCCURRED)
-			WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC3_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR);
 		if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & LB_D3_VBLANK_INTERRUPT)
 			WREG32(VBLANK_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET, VBLANK_ACK);
 		if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & LB_D3_VLINE_INTERRUPT)
@@ -6003,10 +5976,6 @@ static inline void si_irq_ack(struct radeon_device *rdev)
 	}
 
 	if (rdev->num_crtc >= 6) {
-		if (rdev->irq.stat_regs.evergreen.d5grph_int & GRPH_PFLIP_INT_OCCURRED)
-			WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR);
-		if (rdev->irq.stat_regs.evergreen.d6grph_int & GRPH_PFLIP_INT_OCCURRED)
-			WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR);
 		if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & LB_D5_VBLANK_INTERRUPT)
 			WREG32(VBLANK_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET, VBLANK_ACK);
 		if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & LB_D5_VLINE_INTERRUPT)
@@ -6151,7 +6120,7 @@ restart_ih:
 						wake_up(&rdev->irq.vblank_queue);
 					}
 					if (atomic_read(&rdev->irq.pflip[0]))
-						radeon_crtc_handle_vblank(rdev, 0);
+						radeon_crtc_handle_flip(rdev, 0);
 					rdev->irq.stat_regs.evergreen.disp_int &= ~LB_D1_VBLANK_INTERRUPT;
 					DRM_DEBUG("IH: D1 vblank\n");
 				}
@@ -6177,7 +6146,7 @@ restart_ih:
 						wake_up(&rdev->irq.vblank_queue);
 					}
 					if (atomic_read(&rdev->irq.pflip[1]))
-						radeon_crtc_handle_vblank(rdev, 1);
+						radeon_crtc_handle_flip(rdev, 1);
 					rdev->irq.stat_regs.evergreen.disp_int_cont &= ~LB_D2_VBLANK_INTERRUPT;
 					DRM_DEBUG("IH: D2 vblank\n");
 				}
@@ -6203,7 +6172,7 @@ restart_ih:
 						wake_up(&rdev->irq.vblank_queue);
 					}
 					if (atomic_read(&rdev->irq.pflip[2]))
-						radeon_crtc_handle_vblank(rdev, 2);
+						radeon_crtc_handle_flip(rdev, 2);
 					rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~LB_D3_VBLANK_INTERRUPT;
 					DRM_DEBUG("IH: D3 vblank\n");
 				}
@@ -6229,7 +6198,7 @@ restart_ih:
 						wake_up(&rdev->irq.vblank_queue);
 					}
 					if (atomic_read(&rdev->irq.pflip[3]))
-						radeon_crtc_handle_vblank(rdev, 3);
+						radeon_crtc_handle_flip(rdev, 3);
 					rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~LB_D4_VBLANK_INTERRUPT;
 					DRM_DEBUG("IH: D4 vblank\n");
 				}
@@ -6255,7 +6224,7 @@ restart_ih:
 						wake_up(&rdev->irq.vblank_queue);
 					}
 					if (atomic_read(&rdev->irq.pflip[4]))
-						radeon_crtc_handle_vblank(rdev, 4);
+						radeon_crtc_handle_flip(rdev, 4);
 					rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~LB_D5_VBLANK_INTERRUPT;
 					DRM_DEBUG("IH: D5 vblank\n");
 				}
@@ -6281,7 +6250,7 @@ restart_ih:
 						wake_up(&rdev->irq.vblank_queue);
 					}
 					if (atomic_read(&rdev->irq.pflip[5]))
-						radeon_crtc_handle_vblank(rdev, 5);
+						radeon_crtc_handle_flip(rdev, 5);
 					rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~LB_D6_VBLANK_INTERRUPT;
 					DRM_DEBUG("IH: D6 vblank\n");
 				}
@@ -6297,15 +6266,6 @@ restart_ih:
 				break;
 			}
 			break;
-		case 8: /* D1 page flip */
-		case 10: /* D2 page flip */
-		case 12: /* D3 page flip */
-		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);
-			break;
 		case 42: /* HPD hotplug */
 			switch (src_data) {
 			case 0:
-- 
2.0.0

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH v2 2/2] drm/radeon: Remove radeon_kms_pflip_irq_get/put() and the pflip atomic
  2014-07-02  3:55                   ` [PATCH v2 " Michel Dänzer
@ 2014-07-02  3:55                     ` Michel Dänzer
  2014-07-02 10:10                       ` [PATCH 1/2] drm/radeon: Move pinning the BO back to radeon_crtc_page_flip() Michel Dänzer
  2014-07-02 11:35                     ` [PATCH v2 1/2] drm/radeon: Program page flips to execute in hblank instead of vblank Christian König
  1 sibling, 1 reply; 34+ messages in thread
From: Michel Dänzer @ 2014-07-02  3:55 UTC (permalink / raw)
  To: dri-devel

From: Michel Dänzer <michel.daenzer@amd.com>

The vertical blank interrupt is already enabled/disabled via
drm_vblank_get/put(), and radeon_crtc_handle_flip() now bails gracefully
when there is no page flip ready.

Signed-off-by: Michel Dänzer <michel.daenzer@amd.com>
---

v2: Remove the pflip atomic as well

 drivers/gpu/drm/radeon/cik.c            | 36 ++++++++--------------
 drivers/gpu/drm/radeon/evergreen.c      | 36 ++++++++--------------
 drivers/gpu/drm/radeon/r100.c           | 12 +++-----
 drivers/gpu/drm/radeon/r600.c           | 12 +++-----
 drivers/gpu/drm/radeon/radeon.h         |  3 --
 drivers/gpu/drm/radeon/radeon_display.c |  5 ---
 drivers/gpu/drm/radeon/radeon_irq_kms.c | 54 ---------------------------------
 drivers/gpu/drm/radeon/rs600.c          | 12 +++-----
 drivers/gpu/drm/radeon/si.c             | 36 ++++++++--------------
 9 files changed, 48 insertions(+), 158 deletions(-)

diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c
index d0a994c..43ac3cb 100644
--- a/drivers/gpu/drm/radeon/cik.c
+++ b/drivers/gpu/drm/radeon/cik.c
@@ -7053,33 +7053,27 @@ int cik_irq_set(struct radeon_device *rdev)
 		dma_cntl1 |= TRAP_ENABLE;
 	}
 
-	if (rdev->irq.crtc_vblank_int[0] ||
-	    atomic_read(&rdev->irq.pflip[0])) {
+	if (rdev->irq.crtc_vblank_int[0]) {
 		DRM_DEBUG("cik_irq_set: vblank 0\n");
 		crtc1 |= VBLANK_INTERRUPT_MASK;
 	}
-	if (rdev->irq.crtc_vblank_int[1] ||
-	    atomic_read(&rdev->irq.pflip[1])) {
+	if (rdev->irq.crtc_vblank_int[1]) {
 		DRM_DEBUG("cik_irq_set: vblank 1\n");
 		crtc2 |= VBLANK_INTERRUPT_MASK;
 	}
-	if (rdev->irq.crtc_vblank_int[2] ||
-	    atomic_read(&rdev->irq.pflip[2])) {
+	if (rdev->irq.crtc_vblank_int[2]) {
 		DRM_DEBUG("cik_irq_set: vblank 2\n");
 		crtc3 |= VBLANK_INTERRUPT_MASK;
 	}
-	if (rdev->irq.crtc_vblank_int[3] ||
-	    atomic_read(&rdev->irq.pflip[3])) {
+	if (rdev->irq.crtc_vblank_int[3]) {
 		DRM_DEBUG("cik_irq_set: vblank 3\n");
 		crtc4 |= VBLANK_INTERRUPT_MASK;
 	}
-	if (rdev->irq.crtc_vblank_int[4] ||
-	    atomic_read(&rdev->irq.pflip[4])) {
+	if (rdev->irq.crtc_vblank_int[4]) {
 		DRM_DEBUG("cik_irq_set: vblank 4\n");
 		crtc5 |= VBLANK_INTERRUPT_MASK;
 	}
-	if (rdev->irq.crtc_vblank_int[5] ||
-	    atomic_read(&rdev->irq.pflip[5])) {
+	if (rdev->irq.crtc_vblank_int[5]) {
 		DRM_DEBUG("cik_irq_set: vblank 5\n");
 		crtc6 |= VBLANK_INTERRUPT_MASK;
 	}
@@ -7421,8 +7415,7 @@ restart_ih:
 						rdev->pm.vblank_sync = true;
 						wake_up(&rdev->irq.vblank_queue);
 					}
-					if (atomic_read(&rdev->irq.pflip[0]))
-						radeon_crtc_handle_flip(rdev, 0);
+					radeon_crtc_handle_flip(rdev, 0);
 					rdev->irq.stat_regs.cik.disp_int &= ~LB_D1_VBLANK_INTERRUPT;
 					DRM_DEBUG("IH: D1 vblank\n");
 				}
@@ -7447,8 +7440,7 @@ restart_ih:
 						rdev->pm.vblank_sync = true;
 						wake_up(&rdev->irq.vblank_queue);
 					}
-					if (atomic_read(&rdev->irq.pflip[1]))
-						radeon_crtc_handle_flip(rdev, 1);
+					radeon_crtc_handle_flip(rdev, 1);
 					rdev->irq.stat_regs.cik.disp_int_cont &= ~LB_D2_VBLANK_INTERRUPT;
 					DRM_DEBUG("IH: D2 vblank\n");
 				}
@@ -7473,8 +7465,7 @@ restart_ih:
 						rdev->pm.vblank_sync = true;
 						wake_up(&rdev->irq.vblank_queue);
 					}
-					if (atomic_read(&rdev->irq.pflip[2]))
-						radeon_crtc_handle_flip(rdev, 2);
+					radeon_crtc_handle_flip(rdev, 2);
 					rdev->irq.stat_regs.cik.disp_int_cont2 &= ~LB_D3_VBLANK_INTERRUPT;
 					DRM_DEBUG("IH: D3 vblank\n");
 				}
@@ -7499,8 +7490,7 @@ restart_ih:
 						rdev->pm.vblank_sync = true;
 						wake_up(&rdev->irq.vblank_queue);
 					}
-					if (atomic_read(&rdev->irq.pflip[3]))
-						radeon_crtc_handle_flip(rdev, 3);
+					radeon_crtc_handle_flip(rdev, 3);
 					rdev->irq.stat_regs.cik.disp_int_cont3 &= ~LB_D4_VBLANK_INTERRUPT;
 					DRM_DEBUG("IH: D4 vblank\n");
 				}
@@ -7525,8 +7515,7 @@ restart_ih:
 						rdev->pm.vblank_sync = true;
 						wake_up(&rdev->irq.vblank_queue);
 					}
-					if (atomic_read(&rdev->irq.pflip[4]))
-						radeon_crtc_handle_flip(rdev, 4);
+					radeon_crtc_handle_flip(rdev, 4);
 					rdev->irq.stat_regs.cik.disp_int_cont4 &= ~LB_D5_VBLANK_INTERRUPT;
 					DRM_DEBUG("IH: D5 vblank\n");
 				}
@@ -7551,8 +7540,7 @@ restart_ih:
 						rdev->pm.vblank_sync = true;
 						wake_up(&rdev->irq.vblank_queue);
 					}
-					if (atomic_read(&rdev->irq.pflip[5]))
-						radeon_crtc_handle_flip(rdev, 5);
+					radeon_crtc_handle_flip(rdev, 5);
 					rdev->irq.stat_regs.cik.disp_int_cont5 &= ~LB_D6_VBLANK_INTERRUPT;
 					DRM_DEBUG("IH: D6 vblank\n");
 				}
diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c
index e7d685a..9233dbf 100644
--- a/drivers/gpu/drm/radeon/evergreen.c
+++ b/drivers/gpu/drm/radeon/evergreen.c
@@ -4411,33 +4411,27 @@ int evergreen_irq_set(struct radeon_device *rdev)
 		thermal_int |= THERM_INT_MASK_HIGH | THERM_INT_MASK_LOW;
 	}
 
-	if (rdev->irq.crtc_vblank_int[0] ||
-	    atomic_read(&rdev->irq.pflip[0])) {
+	if (rdev->irq.crtc_vblank_int[0]) {
 		DRM_DEBUG("evergreen_irq_set: vblank 0\n");
 		crtc1 |= VBLANK_INT_MASK;
 	}
-	if (rdev->irq.crtc_vblank_int[1] ||
-	    atomic_read(&rdev->irq.pflip[1])) {
+	if (rdev->irq.crtc_vblank_int[1]) {
 		DRM_DEBUG("evergreen_irq_set: vblank 1\n");
 		crtc2 |= VBLANK_INT_MASK;
 	}
-	if (rdev->irq.crtc_vblank_int[2] ||
-	    atomic_read(&rdev->irq.pflip[2])) {
+	if (rdev->irq.crtc_vblank_int[2]) {
 		DRM_DEBUG("evergreen_irq_set: vblank 2\n");
 		crtc3 |= VBLANK_INT_MASK;
 	}
-	if (rdev->irq.crtc_vblank_int[3] ||
-	    atomic_read(&rdev->irq.pflip[3])) {
+	if (rdev->irq.crtc_vblank_int[3]) {
 		DRM_DEBUG("evergreen_irq_set: vblank 3\n");
 		crtc4 |= VBLANK_INT_MASK;
 	}
-	if (rdev->irq.crtc_vblank_int[4] ||
-	    atomic_read(&rdev->irq.pflip[4])) {
+	if (rdev->irq.crtc_vblank_int[4]) {
 		DRM_DEBUG("evergreen_irq_set: vblank 4\n");
 		crtc5 |= VBLANK_INT_MASK;
 	}
-	if (rdev->irq.crtc_vblank_int[5] ||
-	    atomic_read(&rdev->irq.pflip[5])) {
+	if (rdev->irq.crtc_vblank_int[5]) {
 		DRM_DEBUG("evergreen_irq_set: vblank 5\n");
 		crtc6 |= VBLANK_INT_MASK;
 	}
@@ -4742,8 +4736,7 @@ restart_ih:
 						rdev->pm.vblank_sync = true;
 						wake_up(&rdev->irq.vblank_queue);
 					}
-					if (atomic_read(&rdev->irq.pflip[0]))
-						radeon_crtc_handle_flip(rdev, 0);
+					radeon_crtc_handle_flip(rdev, 0);
 					rdev->irq.stat_regs.evergreen.disp_int &= ~LB_D1_VBLANK_INTERRUPT;
 					DRM_DEBUG("IH: D1 vblank\n");
 				}
@@ -4768,8 +4761,7 @@ restart_ih:
 						rdev->pm.vblank_sync = true;
 						wake_up(&rdev->irq.vblank_queue);
 					}
-					if (atomic_read(&rdev->irq.pflip[1]))
-						radeon_crtc_handle_flip(rdev, 1);
+					radeon_crtc_handle_flip(rdev, 1);
 					rdev->irq.stat_regs.evergreen.disp_int_cont &= ~LB_D2_VBLANK_INTERRUPT;
 					DRM_DEBUG("IH: D2 vblank\n");
 				}
@@ -4794,8 +4786,7 @@ restart_ih:
 						rdev->pm.vblank_sync = true;
 						wake_up(&rdev->irq.vblank_queue);
 					}
-					if (atomic_read(&rdev->irq.pflip[2]))
-						radeon_crtc_handle_flip(rdev, 2);
+					radeon_crtc_handle_flip(rdev, 2);
 					rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~LB_D3_VBLANK_INTERRUPT;
 					DRM_DEBUG("IH: D3 vblank\n");
 				}
@@ -4820,8 +4811,7 @@ restart_ih:
 						rdev->pm.vblank_sync = true;
 						wake_up(&rdev->irq.vblank_queue);
 					}
-					if (atomic_read(&rdev->irq.pflip[3]))
-						radeon_crtc_handle_flip(rdev, 3);
+					radeon_crtc_handle_flip(rdev, 3);
 					rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~LB_D4_VBLANK_INTERRUPT;
 					DRM_DEBUG("IH: D4 vblank\n");
 				}
@@ -4846,8 +4836,7 @@ restart_ih:
 						rdev->pm.vblank_sync = true;
 						wake_up(&rdev->irq.vblank_queue);
 					}
-					if (atomic_read(&rdev->irq.pflip[4]))
-						radeon_crtc_handle_flip(rdev, 4);
+					radeon_crtc_handle_flip(rdev, 4);
 					rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~LB_D5_VBLANK_INTERRUPT;
 					DRM_DEBUG("IH: D5 vblank\n");
 				}
@@ -4872,8 +4861,7 @@ restart_ih:
 						rdev->pm.vblank_sync = true;
 						wake_up(&rdev->irq.vblank_queue);
 					}
-					if (atomic_read(&rdev->irq.pflip[5]))
-						radeon_crtc_handle_flip(rdev, 5);
+					radeon_crtc_handle_flip(rdev, 5);
 					rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~LB_D6_VBLANK_INTERRUPT;
 					DRM_DEBUG("IH: D6 vblank\n");
 				}
diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c
index 1f2a960..8fd7294 100644
--- a/drivers/gpu/drm/radeon/r100.c
+++ b/drivers/gpu/drm/radeon/r100.c
@@ -687,12 +687,10 @@ int r100_irq_set(struct radeon_device *rdev)
 	if (atomic_read(&rdev->irq.ring_int[RADEON_RING_TYPE_GFX_INDEX])) {
 		tmp |= RADEON_SW_INT_ENABLE;
 	}
-	if (rdev->irq.crtc_vblank_int[0] ||
-	    atomic_read(&rdev->irq.pflip[0])) {
+	if (rdev->irq.crtc_vblank_int[0]) {
 		tmp |= RADEON_CRTC_VBLANK_MASK;
 	}
-	if (rdev->irq.crtc_vblank_int[1] ||
-	    atomic_read(&rdev->irq.pflip[1])) {
+	if (rdev->irq.crtc_vblank_int[1]) {
 		tmp |= RADEON_CRTC2_VBLANK_MASK;
 	}
 	if (rdev->irq.hpd[0]) {
@@ -753,8 +751,7 @@ int r100_irq_process(struct radeon_device *rdev)
 				rdev->pm.vblank_sync = true;
 				wake_up(&rdev->irq.vblank_queue);
 			}
-			if (atomic_read(&rdev->irq.pflip[0]))
-				radeon_crtc_handle_flip(rdev, 0);
+			radeon_crtc_handle_flip(rdev, 0);
 		}
 		if (status & RADEON_CRTC2_VBLANK_STAT) {
 			if (rdev->irq.crtc_vblank_int[1]) {
@@ -762,8 +759,7 @@ int r100_irq_process(struct radeon_device *rdev)
 				rdev->pm.vblank_sync = true;
 				wake_up(&rdev->irq.vblank_queue);
 			}
-			if (atomic_read(&rdev->irq.pflip[1]))
-				radeon_crtc_handle_flip(rdev, 1);
+			radeon_crtc_handle_flip(rdev, 1);
 		}
 		if (status & RADEON_FP_DETECT_STAT) {
 			queue_hotplug = true;
diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c
index 8f318ec..02deff37 100644
--- a/drivers/gpu/drm/radeon/r600.c
+++ b/drivers/gpu/drm/radeon/r600.c
@@ -3568,13 +3568,11 @@ int r600_irq_set(struct radeon_device *rdev)
 		dma_cntl |= TRAP_ENABLE;
 	}
 
-	if (rdev->irq.crtc_vblank_int[0] ||
-	    atomic_read(&rdev->irq.pflip[0])) {
+	if (rdev->irq.crtc_vblank_int[0]) {
 		DRM_DEBUG("r600_irq_set: vblank 0\n");
 		mode_int |= D1MODE_VBLANK_INT_MASK;
 	}
-	if (rdev->irq.crtc_vblank_int[1] ||
-	    atomic_read(&rdev->irq.pflip[1])) {
+	if (rdev->irq.crtc_vblank_int[1]) {
 		DRM_DEBUG("r600_irq_set: vblank 1\n");
 		mode_int |= D2MODE_VBLANK_INT_MASK;
 	}
@@ -3869,8 +3867,7 @@ restart_ih:
 						rdev->pm.vblank_sync = true;
 						wake_up(&rdev->irq.vblank_queue);
 					}
-					if (atomic_read(&rdev->irq.pflip[0]))
-						radeon_crtc_handle_flip(rdev, 0);
+					radeon_crtc_handle_flip(rdev, 0);
 					rdev->irq.stat_regs.r600.disp_int &= ~LB_D1_VBLANK_INTERRUPT;
 					DRM_DEBUG("IH: D1 vblank\n");
 				}
@@ -3895,8 +3892,7 @@ restart_ih:
 						rdev->pm.vblank_sync = true;
 						wake_up(&rdev->irq.vblank_queue);
 					}
-					if (atomic_read(&rdev->irq.pflip[1]))
-						radeon_crtc_handle_flip(rdev, 1);
+					radeon_crtc_handle_flip(rdev, 1);
 					rdev->irq.stat_regs.r600.disp_int &= ~LB_D2_VBLANK_INTERRUPT;
 					DRM_DEBUG("IH: D2 vblank\n");
 				}
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index 7a45c93..a1416f3 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -757,7 +757,6 @@ struct radeon_irq {
 	spinlock_t			lock;
 	atomic_t			ring_int[RADEON_NUM_RINGS];
 	bool				crtc_vblank_int[RADEON_MAX_CRTCS];
-	atomic_t			pflip[RADEON_MAX_CRTCS];
 	wait_queue_head_t		vblank_queue;
 	bool				hpd[RADEON_MAX_HPD_PINS];
 	bool				afmt[RADEON_MAX_AFMT_BLOCKS];
@@ -769,8 +768,6 @@ int radeon_irq_kms_init(struct radeon_device *rdev);
 void radeon_irq_kms_fini(struct radeon_device *rdev);
 void radeon_irq_kms_sw_irq_get(struct radeon_device *rdev, int ring);
 void radeon_irq_kms_sw_irq_put(struct radeon_device *rdev, int ring);
-void radeon_irq_kms_pflip_irq_get(struct radeon_device *rdev, int crtc);
-void radeon_irq_kms_pflip_irq_put(struct radeon_device *rdev, int crtc);
 void radeon_irq_kms_enable_afmt(struct radeon_device *rdev, int block);
 void radeon_irq_kms_disable_afmt(struct radeon_device *rdev, int block);
 void radeon_irq_kms_enable_hpd(struct radeon_device *rdev, unsigned hpd_mask);
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c
index 103d0c6..2742edd 100644
--- a/drivers/gpu/drm/radeon/radeon_display.c
+++ b/drivers/gpu/drm/radeon/radeon_display.c
@@ -325,7 +325,6 @@ void radeon_crtc_handle_flip(struct radeon_device *rdev, int crtc_id)
 
 	drm_vblank_put(rdev->ddev, radeon_crtc->crtc_id);
 	radeon_fence_unref(&work->fence);
-	radeon_irq_kms_pflip_irq_put(rdev, work->crtc_id);
 	queue_work(radeon_crtc->flip_queue, &work->unpin_work);
 }
 
@@ -434,10 +433,6 @@ static void radeon_flip_work_func(struct work_struct *__work)
 
 	/* We borrow the event spin lock for protecting flip_work */
 	spin_lock_irqsave(&crtc->dev->event_lock, flags);
-
-	/* set the proper interrupt */
-	radeon_irq_kms_pflip_irq_get(rdev, radeon_crtc->crtc_id);
-
 	work->base = base;
 	radeon_crtc->flip_status = RADEON_FLIP_READY;
 	spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
diff --git a/drivers/gpu/drm/radeon/radeon_irq_kms.c b/drivers/gpu/drm/radeon/radeon_irq_kms.c
index 089c9ff..5c1caec 100644
--- a/drivers/gpu/drm/radeon/radeon_irq_kms.c
+++ b/drivers/gpu/drm/radeon/radeon_irq_kms.c
@@ -127,7 +127,6 @@ void radeon_driver_irq_preinstall_kms(struct drm_device *dev)
 		rdev->irq.hpd[i] = false;
 	for (i = 0; i < RADEON_MAX_CRTCS; i++) {
 		rdev->irq.crtc_vblank_int[i] = false;
-		atomic_set(&rdev->irq.pflip[i], 0);
 		rdev->irq.afmt[i] = false;
 	}
 	radeon_irq_set(rdev);
@@ -175,7 +174,6 @@ void radeon_driver_irq_uninstall_kms(struct drm_device *dev)
 		rdev->irq.hpd[i] = false;
 	for (i = 0; i < RADEON_MAX_CRTCS; i++) {
 		rdev->irq.crtc_vblank_int[i] = false;
-		atomic_set(&rdev->irq.pflip[i], 0);
 		rdev->irq.afmt[i] = false;
 	}
 	radeon_irq_set(rdev);
@@ -366,58 +364,6 @@ void radeon_irq_kms_sw_irq_put(struct radeon_device *rdev, int ring)
 }
 
 /**
- * radeon_irq_kms_pflip_irq_get - enable pageflip interrupt
- *
- * @rdev: radeon device pointer
- * @crtc: crtc whose interrupt you want to enable
- *
- * Enables the pageflip interrupt for a specific crtc (all asics).
- * For pageflips we use the vblank interrupt source.
- */
-void radeon_irq_kms_pflip_irq_get(struct radeon_device *rdev, int crtc)
-{
-	unsigned long irqflags;
-
-	if (crtc < 0 || crtc >= rdev->num_crtc)
-		return;
-
-	if (!rdev->ddev->irq_enabled)
-		return;
-
-	if (atomic_inc_return(&rdev->irq.pflip[crtc]) == 1) {
-		spin_lock_irqsave(&rdev->irq.lock, irqflags);
-		radeon_irq_set(rdev);
-		spin_unlock_irqrestore(&rdev->irq.lock, irqflags);
-	}
-}
-
-/**
- * radeon_irq_kms_pflip_irq_put - disable pageflip interrupt
- *
- * @rdev: radeon device pointer
- * @crtc: crtc whose interrupt you want to disable
- *
- * Disables the pageflip interrupt for a specific crtc (all asics).
- * For pageflips we use the vblank interrupt source.
- */
-void radeon_irq_kms_pflip_irq_put(struct radeon_device *rdev, int crtc)
-{
-	unsigned long irqflags;
-
-	if (crtc < 0 || crtc >= rdev->num_crtc)
-		return;
-
-	if (!rdev->ddev->irq_enabled)
-		return;
-
-	if (atomic_dec_and_test(&rdev->irq.pflip[crtc])) {
-		spin_lock_irqsave(&rdev->irq.lock, irqflags);
-		radeon_irq_set(rdev);
-		spin_unlock_irqrestore(&rdev->irq.lock, irqflags);
-	}
-}
-
-/**
  * radeon_irq_kms_enable_afmt - enable audio format change interrupt
  *
  * @rdev: radeon device pointer
diff --git a/drivers/gpu/drm/radeon/rs600.c b/drivers/gpu/drm/radeon/rs600.c
index b5e63a7..62b044a 100644
--- a/drivers/gpu/drm/radeon/rs600.c
+++ b/drivers/gpu/drm/radeon/rs600.c
@@ -664,12 +664,10 @@ int rs600_irq_set(struct radeon_device *rdev)
 	if (atomic_read(&rdev->irq.ring_int[RADEON_RING_TYPE_GFX_INDEX])) {
 		tmp |= S_000040_SW_INT_EN(1);
 	}
-	if (rdev->irq.crtc_vblank_int[0] ||
-	    atomic_read(&rdev->irq.pflip[0])) {
+	if (rdev->irq.crtc_vblank_int[0]) {
 		mode_int |= S_006540_D1MODE_VBLANK_INT_MASK(1);
 	}
-	if (rdev->irq.crtc_vblank_int[1] ||
-	    atomic_read(&rdev->irq.pflip[1])) {
+	if (rdev->irq.crtc_vblank_int[1]) {
 		mode_int |= S_006540_D2MODE_VBLANK_INT_MASK(1);
 	}
 	if (rdev->irq.hpd[0]) {
@@ -775,8 +773,7 @@ int rs600_irq_process(struct radeon_device *rdev)
 				rdev->pm.vblank_sync = true;
 				wake_up(&rdev->irq.vblank_queue);
 			}
-			if (atomic_read(&rdev->irq.pflip[0]))
-				radeon_crtc_handle_flip(rdev, 0);
+			radeon_crtc_handle_flip(rdev, 0);
 		}
 		if (G_007EDC_LB_D2_VBLANK_INTERRUPT(rdev->irq.stat_regs.r500.disp_int)) {
 			if (rdev->irq.crtc_vblank_int[1]) {
@@ -784,8 +781,7 @@ int rs600_irq_process(struct radeon_device *rdev)
 				rdev->pm.vblank_sync = true;
 				wake_up(&rdev->irq.vblank_queue);
 			}
-			if (atomic_read(&rdev->irq.pflip[1]))
-				radeon_crtc_handle_flip(rdev, 1);
+			radeon_crtc_handle_flip(rdev, 1);
 		}
 		if (G_007EDC_DC_HOT_PLUG_DETECT1_INTERRUPT(rdev->irq.stat_regs.r500.disp_int)) {
 			queue_hotplug = true;
diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c
index fee797f..3dce9f9 100644
--- a/drivers/gpu/drm/radeon/si.c
+++ b/drivers/gpu/drm/radeon/si.c
@@ -5835,33 +5835,27 @@ int si_irq_set(struct radeon_device *rdev)
 		DRM_DEBUG("si_irq_set: sw int dma1\n");
 		dma_cntl1 |= TRAP_ENABLE;
 	}
-	if (rdev->irq.crtc_vblank_int[0] ||
-	    atomic_read(&rdev->irq.pflip[0])) {
+	if (rdev->irq.crtc_vblank_int[0]) {
 		DRM_DEBUG("si_irq_set: vblank 0\n");
 		crtc1 |= VBLANK_INT_MASK;
 	}
-	if (rdev->irq.crtc_vblank_int[1] ||
-	    atomic_read(&rdev->irq.pflip[1])) {
+	if (rdev->irq.crtc_vblank_int[1]) {
 		DRM_DEBUG("si_irq_set: vblank 1\n");
 		crtc2 |= VBLANK_INT_MASK;
 	}
-	if (rdev->irq.crtc_vblank_int[2] ||
-	    atomic_read(&rdev->irq.pflip[2])) {
+	if (rdev->irq.crtc_vblank_int[2]) {
 		DRM_DEBUG("si_irq_set: vblank 2\n");
 		crtc3 |= VBLANK_INT_MASK;
 	}
-	if (rdev->irq.crtc_vblank_int[3] ||
-	    atomic_read(&rdev->irq.pflip[3])) {
+	if (rdev->irq.crtc_vblank_int[3]) {
 		DRM_DEBUG("si_irq_set: vblank 3\n");
 		crtc4 |= VBLANK_INT_MASK;
 	}
-	if (rdev->irq.crtc_vblank_int[4] ||
-	    atomic_read(&rdev->irq.pflip[4])) {
+	if (rdev->irq.crtc_vblank_int[4]) {
 		DRM_DEBUG("si_irq_set: vblank 4\n");
 		crtc5 |= VBLANK_INT_MASK;
 	}
-	if (rdev->irq.crtc_vblank_int[5] ||
-	    atomic_read(&rdev->irq.pflip[5])) {
+	if (rdev->irq.crtc_vblank_int[5]) {
 		DRM_DEBUG("si_irq_set: vblank 5\n");
 		crtc6 |= VBLANK_INT_MASK;
 	}
@@ -6119,8 +6113,7 @@ restart_ih:
 						rdev->pm.vblank_sync = true;
 						wake_up(&rdev->irq.vblank_queue);
 					}
-					if (atomic_read(&rdev->irq.pflip[0]))
-						radeon_crtc_handle_flip(rdev, 0);
+					radeon_crtc_handle_flip(rdev, 0);
 					rdev->irq.stat_regs.evergreen.disp_int &= ~LB_D1_VBLANK_INTERRUPT;
 					DRM_DEBUG("IH: D1 vblank\n");
 				}
@@ -6145,8 +6138,7 @@ restart_ih:
 						rdev->pm.vblank_sync = true;
 						wake_up(&rdev->irq.vblank_queue);
 					}
-					if (atomic_read(&rdev->irq.pflip[1]))
-						radeon_crtc_handle_flip(rdev, 1);
+					radeon_crtc_handle_flip(rdev, 1);
 					rdev->irq.stat_regs.evergreen.disp_int_cont &= ~LB_D2_VBLANK_INTERRUPT;
 					DRM_DEBUG("IH: D2 vblank\n");
 				}
@@ -6171,8 +6163,7 @@ restart_ih:
 						rdev->pm.vblank_sync = true;
 						wake_up(&rdev->irq.vblank_queue);
 					}
-					if (atomic_read(&rdev->irq.pflip[2]))
-						radeon_crtc_handle_flip(rdev, 2);
+					radeon_crtc_handle_flip(rdev, 2);
 					rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~LB_D3_VBLANK_INTERRUPT;
 					DRM_DEBUG("IH: D3 vblank\n");
 				}
@@ -6197,8 +6188,7 @@ restart_ih:
 						rdev->pm.vblank_sync = true;
 						wake_up(&rdev->irq.vblank_queue);
 					}
-					if (atomic_read(&rdev->irq.pflip[3]))
-						radeon_crtc_handle_flip(rdev, 3);
+					radeon_crtc_handle_flip(rdev, 3);
 					rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~LB_D4_VBLANK_INTERRUPT;
 					DRM_DEBUG("IH: D4 vblank\n");
 				}
@@ -6223,8 +6213,7 @@ restart_ih:
 						rdev->pm.vblank_sync = true;
 						wake_up(&rdev->irq.vblank_queue);
 					}
-					if (atomic_read(&rdev->irq.pflip[4]))
-						radeon_crtc_handle_flip(rdev, 4);
+					radeon_crtc_handle_flip(rdev, 4);
 					rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~LB_D5_VBLANK_INTERRUPT;
 					DRM_DEBUG("IH: D5 vblank\n");
 				}
@@ -6249,8 +6238,7 @@ restart_ih:
 						rdev->pm.vblank_sync = true;
 						wake_up(&rdev->irq.vblank_queue);
 					}
-					if (atomic_read(&rdev->irq.pflip[5]))
-						radeon_crtc_handle_flip(rdev, 5);
+					radeon_crtc_handle_flip(rdev, 5);
 					rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~LB_D6_VBLANK_INTERRUPT;
 					DRM_DEBUG("IH: D6 vblank\n");
 				}
-- 
2.0.0

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH 1/2] drm/radeon: Move pinning the BO back to radeon_crtc_page_flip()
  2014-07-02  3:55                     ` [PATCH v2 2/2] drm/radeon: Remove radeon_kms_pflip_irq_get/put() and the pflip atomic Michel Dänzer
@ 2014-07-02 10:10                       ` Michel Dänzer
  2014-07-02 10:10                         ` [PATCH 2/2] drm/radeon: Complete page flip even if waiting on the BO fence fails Michel Dänzer
  2014-07-02 11:42                         ` [PATCH 1/2] drm/radeon: Move pinning the BO back to radeon_crtc_page_flip() Christian König
  0 siblings, 2 replies; 34+ messages in thread
From: Michel Dänzer @ 2014-07-02 10:10 UTC (permalink / raw)
  To: dri-devel

From: Michel Dänzer <michel.daenzer@amd.com>

As well as enabling the vblank interrupt. These shouldn't take any
significant amount of time, but at least pinning the BO has actually been
seen to fail in practice before, in which case we need to let userspace
know about it.

Signed-off-by: Michel Dänzer <michel.daenzer@amd.com>
---
 drivers/gpu/drm/radeon/radeon.h         |   2 -
 drivers/gpu/drm/radeon/radeon_display.c | 174 ++++++++++++++++----------------
 2 files changed, 88 insertions(+), 88 deletions(-)

diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index 19a8551..dbe39c8 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -682,10 +682,8 @@ struct radeon_flip_work {
 	struct radeon_device		*rdev;
 	int				crtc_id;
 	uint64_t			base;
-	struct drm_framebuffer		*fb;
 	struct drm_pending_vblank_event *event;
 	struct radeon_bo		*old_rbo;
-	struct radeon_bo		*new_rbo;
 	struct radeon_fence		*fence;
 };
 
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c
index 2742edd..82ae9e3 100644
--- a/drivers/gpu/drm/radeon/radeon_display.c
+++ b/drivers/gpu/drm/radeon/radeon_display.c
@@ -343,11 +343,6 @@ static void radeon_flip_work_func(struct work_struct *__work)
 	struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[work->crtc_id];
 
 	struct drm_crtc *crtc = &radeon_crtc->base;
-	struct drm_framebuffer *fb = work->fb;
-
-	uint32_t tiling_flags, pitch_pixels;
-	uint64_t base;
-
 	unsigned long flags;
 	int r;
 
@@ -368,26 +363,87 @@ static void radeon_flip_work_func(struct work_struct *__work)
 			radeon_fence_unref(&work->fence);
 	}
 
+	/* We borrow the event spin lock for protecting flip_status */
+	spin_lock_irqsave(&crtc->dev->event_lock, flags);
+	radeon_crtc->flip_status = RADEON_FLIP_READY;
+	spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
+	up_read(&rdev->exclusive_lock);
+
+	return;
+
+cleanup:
+	drm_gem_object_unreference_unlocked(&work->old_rbo->gem_base);
+	radeon_fence_unref(&work->fence);
+	kfree(work);
+	up_read(&rdev->exclusive_lock);
+}
+
+static int radeon_crtc_page_flip(struct drm_crtc *crtc,
+				 struct drm_framebuffer *fb,
+				 struct drm_pending_vblank_event *event,
+				 uint32_t page_flip_flags)
+{
+	struct drm_device *dev = crtc->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
+	struct radeon_framebuffer *old_radeon_fb;
+	struct radeon_framebuffer *new_radeon_fb;
+	struct drm_gem_object *obj;
+	struct radeon_flip_work *work;
+	struct radeon_bo *new_rbo;
+	uint32_t tiling_flags, pitch_pixels;
+	uint64_t base;
+	unsigned long flags;
+	int r;
+
+	work = kzalloc(sizeof *work, GFP_KERNEL);
+	if (work == NULL)
+		return -ENOMEM;
+
+	INIT_WORK(&work->flip_work, radeon_flip_work_func);
+	INIT_WORK(&work->unpin_work, radeon_unpin_work_func);
+
+	work->rdev = rdev;
+	work->crtc_id = radeon_crtc->crtc_id;
+	work->event = event;
+
+	/* schedule unpin of the old buffer */
+	old_radeon_fb = to_radeon_framebuffer(crtc->primary->fb);
+	obj = old_radeon_fb->obj;
+
+	/* take a reference to the old object */
+	drm_gem_object_reference(obj);
+	work->old_rbo = gem_to_radeon_bo(obj);
+
+	new_radeon_fb = to_radeon_framebuffer(fb);
+	obj = new_radeon_fb->obj;
+	new_rbo = gem_to_radeon_bo(obj);
+
+	spin_lock(&new_rbo->tbo.bdev->fence_lock);
+	if (new_rbo->tbo.sync_obj)
+		work->fence = radeon_fence_ref(new_rbo->tbo.sync_obj);
+	spin_unlock(&new_rbo->tbo.bdev->fence_lock);
+
 	/* pin the new buffer */
-	DRM_DEBUG_DRIVER("flip-ioctl() cur_fbo = %p, cur_bbo = %p\n",
-			 work->old_rbo, work->new_rbo);
+	DRM_DEBUG_DRIVER("flip-ioctl() cur_rbo = %p, new_rbo = %p\n",
+			 work->old_rbo, new_rbo);
 
-	r = radeon_bo_reserve(work->new_rbo, false);
+	r = radeon_bo_reserve(new_rbo, false);
 	if (unlikely(r != 0)) {
 		DRM_ERROR("failed to reserve new rbo buffer before flip\n");
 		goto cleanup;
 	}
 	/* Only 27 bit offset for legacy CRTC */
-	r = radeon_bo_pin_restricted(work->new_rbo, RADEON_GEM_DOMAIN_VRAM,
+	r = radeon_bo_pin_restricted(new_rbo, RADEON_GEM_DOMAIN_VRAM,
 				     ASIC_IS_AVIVO(rdev) ? 0 : 1 << 27, &base);
 	if (unlikely(r != 0)) {
-		radeon_bo_unreserve(work->new_rbo);
+		radeon_bo_unreserve(new_rbo);
 		r = -EINVAL;
 		DRM_ERROR("failed to pin new rbo buffer before flip\n");
 		goto cleanup;
 	}
-	radeon_bo_get_tiling_flags(work->new_rbo, &tiling_flags, NULL);
-	radeon_bo_unreserve(work->new_rbo);
+	radeon_bo_get_tiling_flags(new_rbo, &tiling_flags, NULL);
+	radeon_bo_unreserve(new_rbo);
 
 	if (!ASIC_IS_AVIVO(rdev)) {
 		/* crtc offset is from display base addr not FB location */
@@ -424,6 +480,7 @@ static void radeon_flip_work_func(struct work_struct *__work)
 		}
 		base &= ~7;
 	}
+	work->base = base;
 
 	r = drm_vblank_get(crtc->dev, radeon_crtc->crtc_id);
 	if (r) {
@@ -433,83 +490,12 @@ static void radeon_flip_work_func(struct work_struct *__work)
 
 	/* We borrow the event spin lock for protecting flip_work */
 	spin_lock_irqsave(&crtc->dev->event_lock, flags);
-	work->base = base;
-	radeon_crtc->flip_status = RADEON_FLIP_READY;
-	spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
-	up_read(&rdev->exclusive_lock);
-
-	return;
-
-pflip_cleanup:
-	if (unlikely(radeon_bo_reserve(work->new_rbo, false) != 0)) {
-		DRM_ERROR("failed to reserve new rbo in error path\n");
-		goto cleanup;
-	}
-	if (unlikely(radeon_bo_unpin(work->new_rbo) != 0)) {
-		DRM_ERROR("failed to unpin new rbo in error path\n");
-	}
-	radeon_bo_unreserve(work->new_rbo);
-
-cleanup:
-	drm_gem_object_unreference_unlocked(&work->old_rbo->gem_base);
-	radeon_fence_unref(&work->fence);
-	kfree(work);
-	up_read(&rdev->exclusive_lock);
-}
-
-static int radeon_crtc_page_flip(struct drm_crtc *crtc,
-				 struct drm_framebuffer *fb,
-				 struct drm_pending_vblank_event *event,
-				 uint32_t page_flip_flags)
-{
-	struct drm_device *dev = crtc->dev;
-	struct radeon_device *rdev = dev->dev_private;
-	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
-	struct radeon_framebuffer *old_radeon_fb;
-	struct radeon_framebuffer *new_radeon_fb;
-	struct drm_gem_object *obj;
-	struct radeon_flip_work *work;
-	unsigned long flags;
-
-	work = kzalloc(sizeof *work, GFP_KERNEL);
-	if (work == NULL)
-		return -ENOMEM;
-
-	INIT_WORK(&work->flip_work, radeon_flip_work_func);
-	INIT_WORK(&work->unpin_work, radeon_unpin_work_func);
-
-	work->rdev = rdev;
-	work->crtc_id = radeon_crtc->crtc_id;
-	work->fb = fb;
-	work->event = event;
-
-	/* schedule unpin of the old buffer */
-	old_radeon_fb = to_radeon_framebuffer(crtc->primary->fb);
-	obj = old_radeon_fb->obj;
-
-	/* take a reference to the old object */
-	drm_gem_object_reference(obj);
-	work->old_rbo = gem_to_radeon_bo(obj);
-
-	new_radeon_fb = to_radeon_framebuffer(fb);
-	obj = new_radeon_fb->obj;
-	work->new_rbo = gem_to_radeon_bo(obj);
-
-	spin_lock(&work->new_rbo->tbo.bdev->fence_lock);
-	if (work->new_rbo->tbo.sync_obj)
-		work->fence = radeon_fence_ref(work->new_rbo->tbo.sync_obj);
-	spin_unlock(&work->new_rbo->tbo.bdev->fence_lock);
-
-	/* We borrow the event spin lock for protecting flip_work */
-	spin_lock_irqsave(&crtc->dev->event_lock, flags);
 
 	if (radeon_crtc->flip_status != RADEON_FLIP_NONE) {
 		DRM_DEBUG_DRIVER("flip queue: crtc already busy\n");
 		spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
-		drm_gem_object_unreference_unlocked(&work->old_rbo->gem_base);
-		radeon_fence_unref(&work->fence);
-		kfree(work);
-		return -EBUSY;
+		r = -EBUSY;
+		goto pflip_cleanup;
 	}
 	radeon_crtc->flip_status = RADEON_FLIP_PENDING;
 	radeon_crtc->flip_work = work;
@@ -520,8 +506,24 @@ static int radeon_crtc_page_flip(struct drm_crtc *crtc,
 	spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
 
 	queue_work(radeon_crtc->flip_queue, &work->flip_work);
-
 	return 0;
+
+pflip_cleanup:
+	if (unlikely(radeon_bo_reserve(new_rbo, false) != 0)) {
+		DRM_ERROR("failed to reserve new rbo in error path\n");
+		goto cleanup;
+	}
+	if (unlikely(radeon_bo_unpin(new_rbo) != 0)) {
+		DRM_ERROR("failed to unpin new rbo in error path\n");
+	}
+	radeon_bo_unreserve(new_rbo);
+
+cleanup:
+	drm_gem_object_unreference_unlocked(&work->old_rbo->gem_base);
+	radeon_fence_unref(&work->fence);
+	kfree(work);
+
+	return r;
 }
 
 static int
-- 
2.0.0

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH 2/2] drm/radeon: Complete page flip even if waiting on the BO fence fails
  2014-07-02 10:10                       ` [PATCH 1/2] drm/radeon: Move pinning the BO back to radeon_crtc_page_flip() Michel Dänzer
@ 2014-07-02 10:10                         ` Michel Dänzer
  2014-07-02 11:42                         ` [PATCH 1/2] drm/radeon: Move pinning the BO back to radeon_crtc_page_flip() Christian König
  1 sibling, 0 replies; 34+ messages in thread
From: Michel Dänzer @ 2014-07-02 10:10 UTC (permalink / raw)
  To: dri-devel

From: Michel Dänzer <michel.daenzer@amd.com>

Otherwise the DRM core and userspace will be confused about which BO the
CRTC is scanning out.

Signed-off-by: Michel Dänzer <michel.daenzer@amd.com>
---
 drivers/gpu/drm/radeon/radeon_display.c | 24 +++++++++---------------
 1 file changed, 9 insertions(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c
index 82ae9e3..9da4933 100644
--- a/drivers/gpu/drm/radeon/radeon_display.c
+++ b/drivers/gpu/drm/radeon/radeon_display.c
@@ -347,20 +347,22 @@ static void radeon_flip_work_func(struct work_struct *__work)
 	int r;
 
         down_read(&rdev->exclusive_lock);
-	while (work->fence) {
+	if (work->fence) {
 		r = radeon_fence_wait(work->fence, false);
 		if (r == -EDEADLK) {
 			up_read(&rdev->exclusive_lock);
 			r = radeon_gpu_reset(rdev);
 			down_read(&rdev->exclusive_lock);
 		}
+		if (r)
+			DRM_ERROR("failed to wait on page flip fence (%d)!\n", r);
 
-		if (r) {
-			DRM_ERROR("failed to wait on page flip fence (%d)!\n",
-				  r);
-			goto cleanup;
-		} else
-			radeon_fence_unref(&work->fence);
+		/* We continue with the page flip even if we failed to wait on
+		 * the fence, otherwise the DRM core and userspace will be
+		 * confused about which BO the CRTC is scanning out
+		 */
+
+		radeon_fence_unref(&work->fence);
 	}
 
 	/* We borrow the event spin lock for protecting flip_status */
@@ -368,14 +370,6 @@ static void radeon_flip_work_func(struct work_struct *__work)
 	radeon_crtc->flip_status = RADEON_FLIP_READY;
 	spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
 	up_read(&rdev->exclusive_lock);
-
-	return;
-
-cleanup:
-	drm_gem_object_unreference_unlocked(&work->old_rbo->gem_base);
-	radeon_fence_unref(&work->fence);
-	kfree(work);
-	up_read(&rdev->exclusive_lock);
 }
 
 static int radeon_crtc_page_flip(struct drm_crtc *crtc,
-- 
2.0.0

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 34+ messages in thread

* Re: [PATCH v2 1/2] drm/radeon: Program page flips to execute in hblank instead of vblank
  2014-07-02  3:55                   ` [PATCH v2 " Michel Dänzer
  2014-07-02  3:55                     ` [PATCH v2 2/2] drm/radeon: Remove radeon_kms_pflip_irq_get/put() and the pflip atomic Michel Dänzer
@ 2014-07-02 11:35                     ` Christian König
  1 sibling, 0 replies; 34+ messages in thread
From: Christian König @ 2014-07-02 11:35 UTC (permalink / raw)
  To: Michel Dänzer, dri-devel

Am 02.07.2014 05:55, schrieb Michel Dänzer:
> From: Michel Dänzer <michel.daenzer@amd.com>
>
> But move the programming back to the vertical blank interrupt handler.
> And signal the flip as being completed immediately after programming it
> to the hardware.
>
> This way we don't have to guess whether or not the hardware will execute
> the flip in a given vertical blank period, avoiding a whole lot of
> trouble.
>
> Also, not using the page flip interrupt anymore avoids problems due to
> completing page flips earlier than expected by userspace.
>
> Signed-off-by: Michel Dänzer <michel.daenzer@amd.com>

Both patches are Reviewed-by: Christian König <christian.koenig@amd.com>

> ---
>
> v2: Rename RADEON_FLIP_SUBMITTED => RADEON_FLIP_READY
>
>   drivers/gpu/drm/radeon/atombios_crtc.c  | 28 ++++-------
>   drivers/gpu/drm/radeon/cik.c            | 58 +++-------------------
>   drivers/gpu/drm/radeon/evergreen.c      | 86 +++++----------------------------
>   drivers/gpu/drm/radeon/r100.c           | 48 +++---------------
>   drivers/gpu/drm/radeon/r600.c           | 18 +------
>   drivers/gpu/drm/radeon/radeon.h         |  3 +-
>   drivers/gpu/drm/radeon/radeon_asic.c    | 22 ---------
>   drivers/gpu/drm/radeon/radeon_asic.h    |  4 --
>   drivers/gpu/drm/radeon/radeon_display.c | 59 +++-------------------
>   drivers/gpu/drm/radeon/radeon_mode.h    |  3 +-
>   drivers/gpu/drm/radeon/rs600.c          | 28 +++--------
>   drivers/gpu/drm/radeon/rv770.c          | 24 ++-------
>   drivers/gpu/drm/radeon/si.c             | 52 +++-----------------
>   13 files changed, 64 insertions(+), 369 deletions(-)
>
> diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c
> index e911898..65cfdbb 100644
> --- a/drivers/gpu/drm/radeon/atombios_crtc.c
> +++ b/drivers/gpu/drm/radeon/atombios_crtc.c
> @@ -1284,6 +1284,10 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc,
>   		break;
>   	}
>   
> +	/* Make sure updates happen at vertical blank */
> +	WREG32(EVERGREEN_GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset, 0);
> +	WREG32(EVERGREEN_MASTER_UPDATE_MODE + radeon_crtc->crtc_offset, 0);
> +
>   	WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + radeon_crtc->crtc_offset,
>   	       upper_32_bits(fb_location));
>   	WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + radeon_crtc->crtc_offset,
> @@ -1321,15 +1325,6 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc,
>   	WREG32(EVERGREEN_VIEWPORT_SIZE + radeon_crtc->crtc_offset,
>   	       (viewport_w << 16) | viewport_h);
>   
> -	/* pageflip setup */
> -	/* make sure flip is at vb rather than hb */
> -	tmp = RREG32(EVERGREEN_GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset);
> -	tmp &= ~EVERGREEN_GRPH_SURFACE_UPDATE_H_RETRACE_EN;
> -	WREG32(EVERGREEN_GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset, tmp);
> -
> -	/* set pageflip to happen anywhere in vblank interval */
> -	WREG32(EVERGREEN_MASTER_UPDATE_MODE + radeon_crtc->crtc_offset, 0);
> -
>   	if (!atomic && fb && fb != crtc->primary->fb) {
>   		radeon_fb = to_radeon_framebuffer(fb);
>   		rbo = gem_to_radeon_bo(radeon_fb->obj);
> @@ -1360,7 +1355,7 @@ static int avivo_crtc_do_set_base(struct drm_crtc *crtc,
>   	uint64_t fb_location;
>   	uint32_t fb_format, fb_pitch_pixels, tiling_flags;
>   	u32 fb_swap = R600_D1GRPH_SWAP_ENDIAN_NONE;
> -	u32 tmp, viewport_w, viewport_h;
> +	u32 viewport_w, viewport_h;
>   	int r;
>   
>   	/* no fb bound */
> @@ -1451,6 +1446,10 @@ static int avivo_crtc_do_set_base(struct drm_crtc *crtc,
>   	else
>   		WREG32(AVIVO_D2VGA_CONTROL, 0);
>   
> +	/* Make sure updates happen at vertical blank */
> +	WREG32(AVIVO_D1GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset, 0);
> +	WREG32(AVIVO_D1MODE_MASTER_UPDATE_MODE + radeon_crtc->crtc_offset, 0);
> +
>   	if (rdev->family >= CHIP_RV770) {
>   		if (radeon_crtc->crtc_id) {
>   			WREG32(R700_D2GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, upper_32_bits(fb_location));
> @@ -1490,15 +1489,6 @@ static int avivo_crtc_do_set_base(struct drm_crtc *crtc,
>   	WREG32(AVIVO_D1MODE_VIEWPORT_SIZE + radeon_crtc->crtc_offset,
>   	       (viewport_w << 16) | viewport_h);
>   
> -	/* pageflip setup */
> -	/* make sure flip is at vb rather than hb */
> -	tmp = RREG32(AVIVO_D1GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset);
> -	tmp &= ~AVIVO_D1GRPH_SURFACE_UPDATE_H_RETRACE_EN;
> -	WREG32(AVIVO_D1GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset, tmp);
> -
> -	/* set pageflip to happen anywhere in vblank interval */
> -	WREG32(AVIVO_D1MODE_MASTER_UPDATE_MODE + radeon_crtc->crtc_offset, 0);
> -
>   	if (!atomic && fb && fb != crtc->primary->fb) {
>   		radeon_fb = to_radeon_framebuffer(fb);
>   		rbo = gem_to_radeon_bo(radeon_fb->obj);
> diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c
> index 0f4b38f..d0a994c 100644
> --- a/drivers/gpu/drm/radeon/cik.c
> +++ b/drivers/gpu/drm/radeon/cik.c
> @@ -7143,25 +7143,6 @@ int cik_irq_set(struct radeon_device *rdev)
>   		WREG32(LB_INTERRUPT_MASK + EVERGREEN_CRTC5_REGISTER_OFFSET, crtc6);
>   	}
>   
> -	if (rdev->num_crtc >= 2) {
> -		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET,
> -		       GRPH_PFLIP_INT_MASK);
> -		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET,
> -		       GRPH_PFLIP_INT_MASK);
> -	}
> -	if (rdev->num_crtc >= 4) {
> -		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET,
> -		       GRPH_PFLIP_INT_MASK);
> -		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET,
> -		       GRPH_PFLIP_INT_MASK);
> -	}
> -	if (rdev->num_crtc >= 6) {
> -		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET,
> -		       GRPH_PFLIP_INT_MASK);
> -		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET,
> -		       GRPH_PFLIP_INT_MASK);
> -	}
> -
>   	WREG32(DC_HPD1_INT_CONTROL, hpd1);
>   	WREG32(DC_HPD2_INT_CONTROL, hpd2);
>   	WREG32(DC_HPD3_INT_CONTROL, hpd3);
> @@ -7215,12 +7196,6 @@ static inline void cik_irq_ack(struct radeon_device *rdev)
>   			EVERGREEN_CRTC5_REGISTER_OFFSET);
>   	}
>   
> -	if (rdev->irq.stat_regs.cik.d1grph_int & GRPH_PFLIP_INT_OCCURRED)
> -		WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC0_REGISTER_OFFSET,
> -		       GRPH_PFLIP_INT_CLEAR);
> -	if (rdev->irq.stat_regs.cik.d2grph_int & GRPH_PFLIP_INT_OCCURRED)
> -		WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC1_REGISTER_OFFSET,
> -		       GRPH_PFLIP_INT_CLEAR);
>   	if (rdev->irq.stat_regs.cik.disp_int & LB_D1_VBLANK_INTERRUPT)
>   		WREG32(LB_VBLANK_STATUS + EVERGREEN_CRTC0_REGISTER_OFFSET, VBLANK_ACK);
>   	if (rdev->irq.stat_regs.cik.disp_int & LB_D1_VLINE_INTERRUPT)
> @@ -7231,12 +7206,6 @@ static inline void cik_irq_ack(struct radeon_device *rdev)
>   		WREG32(LB_VLINE_STATUS + EVERGREEN_CRTC1_REGISTER_OFFSET, VLINE_ACK);
>   
>   	if (rdev->num_crtc >= 4) {
> -		if (rdev->irq.stat_regs.cik.d3grph_int & GRPH_PFLIP_INT_OCCURRED)
> -			WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET,
> -			       GRPH_PFLIP_INT_CLEAR);
> -		if (rdev->irq.stat_regs.cik.d4grph_int & GRPH_PFLIP_INT_OCCURRED)
> -			WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC3_REGISTER_OFFSET,
> -			       GRPH_PFLIP_INT_CLEAR);
>   		if (rdev->irq.stat_regs.cik.disp_int_cont2 & LB_D3_VBLANK_INTERRUPT)
>   			WREG32(LB_VBLANK_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET, VBLANK_ACK);
>   		if (rdev->irq.stat_regs.cik.disp_int_cont2 & LB_D3_VLINE_INTERRUPT)
> @@ -7248,12 +7217,6 @@ static inline void cik_irq_ack(struct radeon_device *rdev)
>   	}
>   
>   	if (rdev->num_crtc >= 6) {
> -		if (rdev->irq.stat_regs.cik.d5grph_int & GRPH_PFLIP_INT_OCCURRED)
> -			WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET,
> -			       GRPH_PFLIP_INT_CLEAR);
> -		if (rdev->irq.stat_regs.cik.d6grph_int & GRPH_PFLIP_INT_OCCURRED)
> -			WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET,
> -			       GRPH_PFLIP_INT_CLEAR);
>   		if (rdev->irq.stat_regs.cik.disp_int_cont4 & LB_D5_VBLANK_INTERRUPT)
>   			WREG32(LB_VBLANK_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET, VBLANK_ACK);
>   		if (rdev->irq.stat_regs.cik.disp_int_cont4 & LB_D5_VLINE_INTERRUPT)
> @@ -7459,7 +7422,7 @@ restart_ih:
>   						wake_up(&rdev->irq.vblank_queue);
>   					}
>   					if (atomic_read(&rdev->irq.pflip[0]))
> -						radeon_crtc_handle_vblank(rdev, 0);
> +						radeon_crtc_handle_flip(rdev, 0);
>   					rdev->irq.stat_regs.cik.disp_int &= ~LB_D1_VBLANK_INTERRUPT;
>   					DRM_DEBUG("IH: D1 vblank\n");
>   				}
> @@ -7485,7 +7448,7 @@ restart_ih:
>   						wake_up(&rdev->irq.vblank_queue);
>   					}
>   					if (atomic_read(&rdev->irq.pflip[1]))
> -						radeon_crtc_handle_vblank(rdev, 1);
> +						radeon_crtc_handle_flip(rdev, 1);
>   					rdev->irq.stat_regs.cik.disp_int_cont &= ~LB_D2_VBLANK_INTERRUPT;
>   					DRM_DEBUG("IH: D2 vblank\n");
>   				}
> @@ -7511,7 +7474,7 @@ restart_ih:
>   						wake_up(&rdev->irq.vblank_queue);
>   					}
>   					if (atomic_read(&rdev->irq.pflip[2]))
> -						radeon_crtc_handle_vblank(rdev, 2);
> +						radeon_crtc_handle_flip(rdev, 2);
>   					rdev->irq.stat_regs.cik.disp_int_cont2 &= ~LB_D3_VBLANK_INTERRUPT;
>   					DRM_DEBUG("IH: D3 vblank\n");
>   				}
> @@ -7537,7 +7500,7 @@ restart_ih:
>   						wake_up(&rdev->irq.vblank_queue);
>   					}
>   					if (atomic_read(&rdev->irq.pflip[3]))
> -						radeon_crtc_handle_vblank(rdev, 3);
> +						radeon_crtc_handle_flip(rdev, 3);
>   					rdev->irq.stat_regs.cik.disp_int_cont3 &= ~LB_D4_VBLANK_INTERRUPT;
>   					DRM_DEBUG("IH: D4 vblank\n");
>   				}
> @@ -7563,7 +7526,7 @@ restart_ih:
>   						wake_up(&rdev->irq.vblank_queue);
>   					}
>   					if (atomic_read(&rdev->irq.pflip[4]))
> -						radeon_crtc_handle_vblank(rdev, 4);
> +						radeon_crtc_handle_flip(rdev, 4);
>   					rdev->irq.stat_regs.cik.disp_int_cont4 &= ~LB_D5_VBLANK_INTERRUPT;
>   					DRM_DEBUG("IH: D5 vblank\n");
>   				}
> @@ -7589,7 +7552,7 @@ restart_ih:
>   						wake_up(&rdev->irq.vblank_queue);
>   					}
>   					if (atomic_read(&rdev->irq.pflip[5]))
> -						radeon_crtc_handle_vblank(rdev, 5);
> +						radeon_crtc_handle_flip(rdev, 5);
>   					rdev->irq.stat_regs.cik.disp_int_cont5 &= ~LB_D6_VBLANK_INTERRUPT;
>   					DRM_DEBUG("IH: D6 vblank\n");
>   				}
> @@ -7605,15 +7568,6 @@ restart_ih:
>   				break;
>   			}
>   			break;
> -		case 8: /* D1 page flip */
> -		case 10: /* D2 page flip */
> -		case 12: /* D3 page flip */
> -		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);
> -			break;
>   		case 42: /* HPD hotplug */
>   			switch (src_data) {
>   			case 0:
> diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c
> index 0443183..e7d685a 100644
> --- a/drivers/gpu/drm/radeon/evergreen.c
> +++ b/drivers/gpu/drm/radeon/evergreen.c
> @@ -1308,16 +1308,15 @@ void dce4_wait_for_vblank(struct radeon_device *rdev, int crtc)
>    * @crtc_base: new address of the crtc (GPU MC address)
>    *
>    * Does the actual pageflip (evergreen+).
> - * During vblank we take the crtc lock and wait for the update_pending
> - * bit to go high, when it does, we release the lock, and allow the
> - * double buffered update to take place.
> - * Returns the current update pending status.
>    */
>   void evergreen_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base)
>   {
>   	struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];
>   	u32 tmp = RREG32(EVERGREEN_GRPH_UPDATE + radeon_crtc->crtc_offset);
> -	int i;
> +
> +	/* Take surface updates at horizontal blank */
> +	WREG32(EVERGREEN_GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset,
> +	       EVERGREEN_GRPH_SURFACE_UPDATE_H_RETRACE_EN);
>   
>   	/* Lock the graphics update lock */
>   	tmp |= EVERGREEN_GRPH_UPDATE_LOCK;
> @@ -1334,36 +1333,11 @@ void evergreen_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base)
>   	WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset,
>   	       (u32)crtc_base);
>   
> -	/* Wait for update_pending to go high. */
> -	for (i = 0; i < rdev->usec_timeout; i++) {
> -		if (RREG32(EVERGREEN_GRPH_UPDATE + radeon_crtc->crtc_offset) & EVERGREEN_GRPH_SURFACE_UPDATE_PENDING)
> -			break;
> -		udelay(1);
> -	}
> -	DRM_DEBUG("Update pending now high. Unlocking vupdate_lock.\n");
> -
> -	/* Unlock the lock, so double-buffering can take place inside vblank */
> +	/* Unlock the lock, so double-buffering can take place inside hblank */
>   	tmp &= ~EVERGREEN_GRPH_UPDATE_LOCK;
>   	WREG32(EVERGREEN_GRPH_UPDATE + radeon_crtc->crtc_offset, tmp);
>   }
>   
> -/**
> - * evergreen_page_flip_pending - check if page flip is still pending
> - *
> - * @rdev: radeon_device pointer
> - * @crtc_id: crtc to check
> - *
> - * Returns the current update pending status.
> - */
> -bool evergreen_page_flip_pending(struct radeon_device *rdev, int crtc_id)
> -{
> -	struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];
> -
> -	/* Return current update_pending status: */
> -	return !!(RREG32(EVERGREEN_GRPH_UPDATE + radeon_crtc->crtc_offset) &
> -		EVERGREEN_GRPH_SURFACE_UPDATE_PENDING);
> -}
> -
>   /* get temperature in millidegrees */
>   int evergreen_get_temp(struct radeon_device *rdev)
>   {
> @@ -4541,23 +4515,6 @@ int evergreen_irq_set(struct radeon_device *rdev)
>   		WREG32(INT_MASK + EVERGREEN_CRTC5_REGISTER_OFFSET, crtc6);
>   	}
>   
> -	WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET,
> -	       GRPH_PFLIP_INT_MASK);
> -	WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET,
> -	       GRPH_PFLIP_INT_MASK);
> -	if (rdev->num_crtc >= 4) {
> -		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET,
> -		       GRPH_PFLIP_INT_MASK);
> -		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET,
> -		       GRPH_PFLIP_INT_MASK);
> -	}
> -	if (rdev->num_crtc >= 6) {
> -		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET,
> -		       GRPH_PFLIP_INT_MASK);
> -		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET,
> -		       GRPH_PFLIP_INT_MASK);
> -	}
> -
>   	WREG32(DC_HPD1_INT_CONTROL, hpd1);
>   	WREG32(DC_HPD2_INT_CONTROL, hpd2);
>   	WREG32(DC_HPD3_INT_CONTROL, hpd3);
> @@ -4607,10 +4564,6 @@ static void evergreen_irq_ack(struct radeon_device *rdev)
>   	rdev->irq.stat_regs.evergreen.afmt_status5 = RREG32(AFMT_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET);
>   	rdev->irq.stat_regs.evergreen.afmt_status6 = RREG32(AFMT_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET);
>   
> -	if (rdev->irq.stat_regs.evergreen.d1grph_int & GRPH_PFLIP_INT_OCCURRED)
> -		WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC0_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR);
> -	if (rdev->irq.stat_regs.evergreen.d2grph_int & GRPH_PFLIP_INT_OCCURRED)
> -		WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC1_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR);
>   	if (rdev->irq.stat_regs.evergreen.disp_int & LB_D1_VBLANK_INTERRUPT)
>   		WREG32(VBLANK_STATUS + EVERGREEN_CRTC0_REGISTER_OFFSET, VBLANK_ACK);
>   	if (rdev->irq.stat_regs.evergreen.disp_int & LB_D1_VLINE_INTERRUPT)
> @@ -4621,10 +4574,6 @@ static void evergreen_irq_ack(struct radeon_device *rdev)
>   		WREG32(VLINE_STATUS + EVERGREEN_CRTC1_REGISTER_OFFSET, VLINE_ACK);
>   
>   	if (rdev->num_crtc >= 4) {
> -		if (rdev->irq.stat_regs.evergreen.d3grph_int & GRPH_PFLIP_INT_OCCURRED)
> -			WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR);
> -		if (rdev->irq.stat_regs.evergreen.d4grph_int & GRPH_PFLIP_INT_OCCURRED)
> -			WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC3_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR);
>   		if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & LB_D3_VBLANK_INTERRUPT)
>   			WREG32(VBLANK_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET, VBLANK_ACK);
>   		if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & LB_D3_VLINE_INTERRUPT)
> @@ -4636,10 +4585,6 @@ static void evergreen_irq_ack(struct radeon_device *rdev)
>   	}
>   
>   	if (rdev->num_crtc >= 6) {
> -		if (rdev->irq.stat_regs.evergreen.d5grph_int & GRPH_PFLIP_INT_OCCURRED)
> -			WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR);
> -		if (rdev->irq.stat_regs.evergreen.d6grph_int & GRPH_PFLIP_INT_OCCURRED)
> -			WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR);
>   		if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & LB_D5_VBLANK_INTERRUPT)
>   			WREG32(VBLANK_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET, VBLANK_ACK);
>   		if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & LB_D5_VLINE_INTERRUPT)
> @@ -4798,7 +4743,7 @@ restart_ih:
>   						wake_up(&rdev->irq.vblank_queue);
>   					}
>   					if (atomic_read(&rdev->irq.pflip[0]))
> -						radeon_crtc_handle_vblank(rdev, 0);
> +						radeon_crtc_handle_flip(rdev, 0);
>   					rdev->irq.stat_regs.evergreen.disp_int &= ~LB_D1_VBLANK_INTERRUPT;
>   					DRM_DEBUG("IH: D1 vblank\n");
>   				}
> @@ -4824,7 +4769,7 @@ restart_ih:
>   						wake_up(&rdev->irq.vblank_queue);
>   					}
>   					if (atomic_read(&rdev->irq.pflip[1]))
> -						radeon_crtc_handle_vblank(rdev, 1);
> +						radeon_crtc_handle_flip(rdev, 1);
>   					rdev->irq.stat_regs.evergreen.disp_int_cont &= ~LB_D2_VBLANK_INTERRUPT;
>   					DRM_DEBUG("IH: D2 vblank\n");
>   				}
> @@ -4850,7 +4795,7 @@ restart_ih:
>   						wake_up(&rdev->irq.vblank_queue);
>   					}
>   					if (atomic_read(&rdev->irq.pflip[2]))
> -						radeon_crtc_handle_vblank(rdev, 2);
> +						radeon_crtc_handle_flip(rdev, 2);
>   					rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~LB_D3_VBLANK_INTERRUPT;
>   					DRM_DEBUG("IH: D3 vblank\n");
>   				}
> @@ -4876,7 +4821,7 @@ restart_ih:
>   						wake_up(&rdev->irq.vblank_queue);
>   					}
>   					if (atomic_read(&rdev->irq.pflip[3]))
> -						radeon_crtc_handle_vblank(rdev, 3);
> +						radeon_crtc_handle_flip(rdev, 3);
>   					rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~LB_D4_VBLANK_INTERRUPT;
>   					DRM_DEBUG("IH: D4 vblank\n");
>   				}
> @@ -4902,7 +4847,7 @@ restart_ih:
>   						wake_up(&rdev->irq.vblank_queue);
>   					}
>   					if (atomic_read(&rdev->irq.pflip[4]))
> -						radeon_crtc_handle_vblank(rdev, 4);
> +						radeon_crtc_handle_flip(rdev, 4);
>   					rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~LB_D5_VBLANK_INTERRUPT;
>   					DRM_DEBUG("IH: D5 vblank\n");
>   				}
> @@ -4928,7 +4873,7 @@ restart_ih:
>   						wake_up(&rdev->irq.vblank_queue);
>   					}
>   					if (atomic_read(&rdev->irq.pflip[5]))
> -						radeon_crtc_handle_vblank(rdev, 5);
> +						radeon_crtc_handle_flip(rdev, 5);
>   					rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~LB_D6_VBLANK_INTERRUPT;
>   					DRM_DEBUG("IH: D6 vblank\n");
>   				}
> @@ -4944,15 +4889,6 @@ restart_ih:
>   				break;
>   			}
>   			break;
> -		case 8: /* D1 page flip */
> -		case 10: /* D2 page flip */
> -		case 12: /* D3 page flip */
> -		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);
> -			break;
>   		case 42: /* HPD hotplug */
>   			switch (src_data) {
>   			case 0:
> diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c
> index 54674b7..1f2a960 100644
> --- a/drivers/gpu/drm/radeon/r100.c
> +++ b/drivers/gpu/drm/radeon/r100.c
> @@ -149,50 +149,18 @@ void r100_wait_for_vblank(struct radeon_device *rdev, int crtc)
>    * @crtc_base: new address of the crtc (GPU MC address)
>    *
>    * Does the actual pageflip (r1xx-r4xx).
> - * During vblank we take the crtc lock and wait for the update_pending
> - * bit to go high, when it does, we release the lock, and allow the
> - * double buffered update to take place.
>    */
>   void r100_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base)
>   {
>   	struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];
> -	u32 tmp = ((u32)crtc_base) | RADEON_CRTC_OFFSET__OFFSET_LOCK;
> -	int i;
> -
> -	/* Lock the graphics update lock */
> -	/* update the scanout addresses */
> -	WREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset, tmp);
> +	u32 crtc_offset_cntl = RREG32(RADEON_CRTC_OFFSET_CNTL);
>   
> -	/* Wait for update_pending to go high. */
> -	for (i = 0; i < rdev->usec_timeout; i++) {
> -		if (RREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset) & RADEON_CRTC_OFFSET__GUI_TRIG_OFFSET)
> -			break;
> -		udelay(1);
> -	}
> -	DRM_DEBUG("Update pending now high. Unlocking vupdate_lock.\n");
> -
> -	/* Unlock the lock, so double-buffering can take place inside vblank */
> -	tmp &= ~RADEON_CRTC_OFFSET__OFFSET_LOCK;
> -	WREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset, tmp);
> -
> -}
> -
> -/**
> - * r100_page_flip_pending - check if page flip is still pending
> - *
> - * @rdev: radeon_device pointer
> - * @crtc_id: crtc to check
> - *
> - * Check if the last pagefilp is still pending (r1xx-r4xx).
> - * Returns the current update pending status.
> - */
> -bool r100_page_flip_pending(struct radeon_device *rdev, int crtc_id)
> -{
> -	struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];
> +	/* Take surface updates at horizontal blank */
> +	WREG32(RADEON_CRTC_OFFSET_CNTL,
> +	       crtc_offset_cntl | RADEON_CRTC_OFFSET_FLIP_CNTL);
>   
> -	/* Return current update_pending status: */
> -	return !!(RREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset) &
> -		RADEON_CRTC_OFFSET__GUI_TRIG_OFFSET);
> +	/* Update the scanout address */
> +	WREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset, crtc_base);
>   }
>   
>   /**
> @@ -786,7 +754,7 @@ int r100_irq_process(struct radeon_device *rdev)
>   				wake_up(&rdev->irq.vblank_queue);
>   			}
>   			if (atomic_read(&rdev->irq.pflip[0]))
> -				radeon_crtc_handle_vblank(rdev, 0);
> +				radeon_crtc_handle_flip(rdev, 0);
>   		}
>   		if (status & RADEON_CRTC2_VBLANK_STAT) {
>   			if (rdev->irq.crtc_vblank_int[1]) {
> @@ -795,7 +763,7 @@ int r100_irq_process(struct radeon_device *rdev)
>   				wake_up(&rdev->irq.vblank_queue);
>   			}
>   			if (atomic_read(&rdev->irq.pflip[1]))
> -				radeon_crtc_handle_vblank(rdev, 1);
> +				radeon_crtc_handle_flip(rdev, 1);
>   		}
>   		if (status & RADEON_FP_DETECT_STAT) {
>   			queue_hotplug = true;
> diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c
> index ae54f76..8f318ec 100644
> --- a/drivers/gpu/drm/radeon/r600.c
> +++ b/drivers/gpu/drm/radeon/r600.c
> @@ -3614,8 +3614,6 @@ 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(GRBM_INT_CNTL, grbm_int_cntl);
>   	if (ASIC_IS_DCE3(rdev)) {
>   		WREG32(DC_HPD1_INT_CONTROL, hpd1);
> @@ -3672,10 +3670,6 @@ static void r600_irq_ack(struct radeon_device *rdev)
>   	rdev->irq.stat_regs.r600.d1grph_int = RREG32(D1GRPH_INTERRUPT_STATUS);
>   	rdev->irq.stat_regs.r600.d2grph_int = RREG32(D2GRPH_INTERRUPT_STATUS);
>   
> -	if (rdev->irq.stat_regs.r600.d1grph_int & DxGRPH_PFLIP_INT_OCCURRED)
> -		WREG32(D1GRPH_INTERRUPT_STATUS, DxGRPH_PFLIP_INT_CLEAR);
> -	if (rdev->irq.stat_regs.r600.d2grph_int & DxGRPH_PFLIP_INT_OCCURRED)
> -		WREG32(D2GRPH_INTERRUPT_STATUS, DxGRPH_PFLIP_INT_CLEAR);
>   	if (rdev->irq.stat_regs.r600.disp_int & LB_D1_VBLANK_INTERRUPT)
>   		WREG32(D1MODE_VBLANK_STATUS, DxMODE_VBLANK_ACK);
>   	if (rdev->irq.stat_regs.r600.disp_int & LB_D1_VLINE_INTERRUPT)
> @@ -3876,7 +3870,7 @@ restart_ih:
>   						wake_up(&rdev->irq.vblank_queue);
>   					}
>   					if (atomic_read(&rdev->irq.pflip[0]))
> -						radeon_crtc_handle_vblank(rdev, 0);
> +						radeon_crtc_handle_flip(rdev, 0);
>   					rdev->irq.stat_regs.r600.disp_int &= ~LB_D1_VBLANK_INTERRUPT;
>   					DRM_DEBUG("IH: D1 vblank\n");
>   				}
> @@ -3902,7 +3896,7 @@ restart_ih:
>   						wake_up(&rdev->irq.vblank_queue);
>   					}
>   					if (atomic_read(&rdev->irq.pflip[1]))
> -						radeon_crtc_handle_vblank(rdev, 1);
> +						radeon_crtc_handle_flip(rdev, 1);
>   					rdev->irq.stat_regs.r600.disp_int &= ~LB_D2_VBLANK_INTERRUPT;
>   					DRM_DEBUG("IH: D2 vblank\n");
>   				}
> @@ -3918,14 +3912,6 @@ restart_ih:
>   				break;
>   			}
>   			break;
> -		case 9: /* D1 pflip */
> -			DRM_DEBUG("IH: D1 flip\n");
> -			radeon_crtc_handle_flip(rdev, 0);
> -			break;
> -		case 11: /* D2 pflip */
> -			DRM_DEBUG("IH: D2 flip\n");
> -			radeon_crtc_handle_flip(rdev, 1);
> -			break;
>   		case 19: /* HPD/DAC hotplug */
>   			switch (src_data) {
>   			case 0:
> diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
> index 8e8ef08..7a45c93 100644
> --- a/drivers/gpu/drm/radeon/radeon.h
> +++ b/drivers/gpu/drm/radeon/radeon.h
> @@ -681,6 +681,7 @@ struct radeon_flip_work {
>   	struct work_struct		unpin_work;
>   	struct radeon_device		*rdev;
>   	int				crtc_id;
> +	uint64_t			base;
>   	struct drm_framebuffer		*fb;
>   	struct drm_pending_vblank_event *event;
>   	struct radeon_bo		*old_rbo;
> @@ -1884,7 +1885,6 @@ struct radeon_asic {
>   	/* pageflipping */
>   	struct {
>   		void (*page_flip)(struct radeon_device *rdev, int crtc, u64 crtc_base);
> -		bool (*page_flip_pending)(struct radeon_device *rdev, int crtc);
>   	} pflip;
>   };
>   
> @@ -2746,7 +2746,6 @@ void radeon_ring_write(struct radeon_ring *ring, uint32_t v);
>   #define radeon_pm_init_profile(rdev) (rdev)->asic->pm.init_profile((rdev))
>   #define radeon_pm_get_dynpm_state(rdev) (rdev)->asic->pm.get_dynpm_state((rdev))
>   #define radeon_page_flip(rdev, crtc, base) (rdev)->asic->pflip.page_flip((rdev), (crtc), (base))
> -#define radeon_page_flip_pending(rdev, crtc) (rdev)->asic->pflip.page_flip_pending((rdev), (crtc))
>   #define radeon_wait_for_vblank(rdev, crtc) (rdev)->asic->display.wait_for_vblank((rdev), (crtc))
>   #define radeon_mc_wait_for_idle(rdev) (rdev)->asic->mc_wait_for_idle((rdev))
>   #define radeon_get_xclk(rdev) (rdev)->asic->get_xclk((rdev))
> diff --git a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c
> index baee3cd..662c181 100644
> --- a/drivers/gpu/drm/radeon/radeon_asic.c
> +++ b/drivers/gpu/drm/radeon/radeon_asic.c
> @@ -252,7 +252,6 @@ static struct radeon_asic r100_asic = {
>   	},
>   	.pflip = {
>   		.page_flip = &r100_page_flip,
> -		.page_flip_pending = &r100_page_flip_pending,
>   	},
>   };
>   
> @@ -319,7 +318,6 @@ static struct radeon_asic r200_asic = {
>   	},
>   	.pflip = {
>   		.page_flip = &r100_page_flip,
> -		.page_flip_pending = &r100_page_flip_pending,
>   	},
>   };
>   
> @@ -400,7 +398,6 @@ static struct radeon_asic r300_asic = {
>   	},
>   	.pflip = {
>   		.page_flip = &r100_page_flip,
> -		.page_flip_pending = &r100_page_flip_pending,
>   	},
>   };
>   
> @@ -467,7 +464,6 @@ static struct radeon_asic r300_asic_pcie = {
>   	},
>   	.pflip = {
>   		.page_flip = &r100_page_flip,
> -		.page_flip_pending = &r100_page_flip_pending,
>   	},
>   };
>   
> @@ -534,7 +530,6 @@ static struct radeon_asic r420_asic = {
>   	},
>   	.pflip = {
>   		.page_flip = &r100_page_flip,
> -		.page_flip_pending = &r100_page_flip_pending,
>   	},
>   };
>   
> @@ -601,7 +596,6 @@ static struct radeon_asic rs400_asic = {
>   	},
>   	.pflip = {
>   		.page_flip = &r100_page_flip,
> -		.page_flip_pending = &r100_page_flip_pending,
>   	},
>   };
>   
> @@ -670,7 +664,6 @@ static struct radeon_asic rs600_asic = {
>   	},
>   	.pflip = {
>   		.page_flip = &rs600_page_flip,
> -		.page_flip_pending = &rs600_page_flip_pending,
>   	},
>   };
>   
> @@ -739,7 +732,6 @@ static struct radeon_asic rs690_asic = {
>   	},
>   	.pflip = {
>   		.page_flip = &rs600_page_flip,
> -		.page_flip_pending = &rs600_page_flip_pending,
>   	},
>   };
>   
> @@ -806,7 +798,6 @@ static struct radeon_asic rv515_asic = {
>   	},
>   	.pflip = {
>   		.page_flip = &rs600_page_flip,
> -		.page_flip_pending = &rs600_page_flip_pending,
>   	},
>   };
>   
> @@ -873,7 +864,6 @@ static struct radeon_asic r520_asic = {
>   	},
>   	.pflip = {
>   		.page_flip = &rs600_page_flip,
> -		.page_flip_pending = &rs600_page_flip_pending,
>   	},
>   };
>   
> @@ -972,7 +962,6 @@ static struct radeon_asic r600_asic = {
>   	},
>   	.pflip = {
>   		.page_flip = &rs600_page_flip,
> -		.page_flip_pending = &rs600_page_flip_pending,
>   	},
>   };
>   
> @@ -1063,7 +1052,6 @@ static struct radeon_asic rv6xx_asic = {
>   	},
>   	.pflip = {
>   		.page_flip = &rs600_page_flip,
> -		.page_flip_pending = &rs600_page_flip_pending,
>   	},
>   };
>   
> @@ -1154,7 +1142,6 @@ static struct radeon_asic rs780_asic = {
>   	},
>   	.pflip = {
>   		.page_flip = &rs600_page_flip,
> -		.page_flip_pending = &rs600_page_flip_pending,
>   	},
>   };
>   
> @@ -1260,7 +1247,6 @@ static struct radeon_asic rv770_asic = {
>   	},
>   	.pflip = {
>   		.page_flip = &rv770_page_flip,
> -		.page_flip_pending = &rv770_page_flip_pending,
>   	},
>   };
>   
> @@ -1379,7 +1365,6 @@ static struct radeon_asic evergreen_asic = {
>   	},
>   	.pflip = {
>   		.page_flip = &evergreen_page_flip,
> -		.page_flip_pending = &evergreen_page_flip_pending,
>   	},
>   };
>   
> @@ -1471,7 +1456,6 @@ static struct radeon_asic sumo_asic = {
>   	},
>   	.pflip = {
>   		.page_flip = &evergreen_page_flip,
> -		.page_flip_pending = &evergreen_page_flip_pending,
>   	},
>   };
>   
> @@ -1564,7 +1548,6 @@ static struct radeon_asic btc_asic = {
>   	},
>   	.pflip = {
>   		.page_flip = &evergreen_page_flip,
> -		.page_flip_pending = &evergreen_page_flip_pending,
>   	},
>   };
>   
> @@ -1708,7 +1691,6 @@ static struct radeon_asic cayman_asic = {
>   	},
>   	.pflip = {
>   		.page_flip = &evergreen_page_flip,
> -		.page_flip_pending = &evergreen_page_flip_pending,
>   	},
>   };
>   
> @@ -1809,7 +1791,6 @@ static struct radeon_asic trinity_asic = {
>   	},
>   	.pflip = {
>   		.page_flip = &evergreen_page_flip,
> -		.page_flip_pending = &evergreen_page_flip_pending,
>   	},
>   };
>   
> @@ -1940,7 +1921,6 @@ static struct radeon_asic si_asic = {
>   	},
>   	.pflip = {
>   		.page_flip = &evergreen_page_flip,
> -		.page_flip_pending = &evergreen_page_flip_pending,
>   	},
>   };
>   
> @@ -2103,7 +2083,6 @@ static struct radeon_asic ci_asic = {
>   	},
>   	.pflip = {
>   		.page_flip = &evergreen_page_flip,
> -		.page_flip_pending = &evergreen_page_flip_pending,
>   	},
>   };
>   
> @@ -2208,7 +2187,6 @@ static struct radeon_asic kv_asic = {
>   	},
>   	.pflip = {
>   		.page_flip = &evergreen_page_flip,
> -		.page_flip_pending = &evergreen_page_flip_pending,
>   	},
>   };
>   
> diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h
> index f05270e..b49bfcd 100644
> --- a/drivers/gpu/drm/radeon/radeon_asic.h
> +++ b/drivers/gpu/drm/radeon/radeon_asic.h
> @@ -138,7 +138,6 @@ extern void r100_pm_init_profile(struct radeon_device *rdev);
>   extern void r100_pm_get_dynpm_state(struct radeon_device *rdev);
>   extern void r100_page_flip(struct radeon_device *rdev, int crtc,
>   			   u64 crtc_base);
> -extern bool r100_page_flip_pending(struct radeon_device *rdev, int crtc);
>   extern void r100_wait_for_vblank(struct radeon_device *rdev, int crtc);
>   extern int r100_mc_wait_for_idle(struct radeon_device *rdev);
>   
> @@ -247,7 +246,6 @@ extern void rs600_pm_prepare(struct radeon_device *rdev);
>   extern void rs600_pm_finish(struct radeon_device *rdev);
>   extern void rs600_page_flip(struct radeon_device *rdev, int crtc,
>   			    u64 crtc_base);
> -extern bool rs600_page_flip_pending(struct radeon_device *rdev, int crtc);
>   void rs600_set_safe_registers(struct radeon_device *rdev);
>   extern void avivo_wait_for_vblank(struct radeon_device *rdev, int crtc);
>   extern int rs600_mc_wait_for_idle(struct radeon_device *rdev);
> @@ -452,7 +450,6 @@ int rv770_suspend(struct radeon_device *rdev);
>   int rv770_resume(struct radeon_device *rdev);
>   void rv770_pm_misc(struct radeon_device *rdev);
>   void rv770_page_flip(struct radeon_device *rdev, int crtc, u64 crtc_base);
> -bool rv770_page_flip_pending(struct radeon_device *rdev, int crtc);
>   void r700_vram_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc);
>   void r700_cp_stop(struct radeon_device *rdev);
>   void r700_cp_fini(struct radeon_device *rdev);
> @@ -520,7 +517,6 @@ int sumo_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk);
>   int evergreen_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk);
>   extern void evergreen_page_flip(struct radeon_device *rdev, int crtc,
>   				u64 crtc_base);
> -extern bool evergreen_page_flip_pending(struct radeon_device *rdev, int crtc);
>   extern void dce4_wait_for_vblank(struct radeon_device *rdev, int crtc);
>   void evergreen_disable_interrupt_state(struct radeon_device *rdev);
>   int evergreen_mc_wait_for_idle(struct radeon_device *rdev);
> diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c
> index 65882cd..103d0c6 100644
> --- a/drivers/gpu/drm/radeon/radeon_display.c
> +++ b/drivers/gpu/drm/radeon/radeon_display.c
> @@ -281,50 +281,6 @@ static void radeon_unpin_work_func(struct work_struct *__work)
>   	kfree(work);
>   }
>   
> -void radeon_crtc_handle_vblank(struct radeon_device *rdev, int crtc_id)
> -{
> -	struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];
> -	unsigned long flags;
> -	u32 update_pending;
> -	int vpos, hpos;
> -
> -	/* can happen during initialization */
> -	if (radeon_crtc == NULL)
> -		return;
> -
> -	spin_lock_irqsave(&rdev->ddev->event_lock, flags);
> -	if (radeon_crtc->flip_status != RADEON_FLIP_SUBMITTED) {
> -		DRM_DEBUG_DRIVER("radeon_crtc->flip_status = %d != "
> -				 "RADEON_FLIP_SUBMITTED(%d)\n",
> -				 radeon_crtc->flip_status,
> -				 RADEON_FLIP_SUBMITTED);
> -		spin_unlock_irqrestore(&rdev->ddev->event_lock, flags);
> -		return;
> -	}
> -
> -	update_pending = radeon_page_flip_pending(rdev, crtc_id);
> -
> -	/* Has the pageflip already completed in crtc, or is it certain
> -	 * to complete in this vblank?
> -	 */
> -	if (update_pending &&
> -	    (DRM_SCANOUTPOS_VALID & radeon_get_crtc_scanoutpos(rdev->ddev, crtc_id, 0,
> -							       &vpos, &hpos, NULL, NULL)) &&
> -	    ((vpos >= (99 * rdev->mode_info.crtcs[crtc_id]->base.hwmode.crtc_vdisplay)/100) ||
> -	     (vpos < 0 && !ASIC_IS_AVIVO(rdev)))) {
> -		/* crtc didn't flip in this target vblank interval,
> -		 * but flip is pending in crtc. Based on the current
> -		 * scanout position we know that the current frame is
> -		 * (nearly) complete and the flip will (likely)
> -		 * complete before the start of the next frame.
> -		 */
> -		update_pending = 0;
> -	}
> -	spin_unlock_irqrestore(&rdev->ddev->event_lock, flags);
> -	if (!update_pending)
> -		radeon_crtc_handle_flip(rdev, crtc_id);
> -}
> -
>   /**
>    * radeon_crtc_handle_flip - page flip completed
>    *
> @@ -345,15 +301,18 @@ void radeon_crtc_handle_flip(struct radeon_device *rdev, int crtc_id)
>   
>   	spin_lock_irqsave(&rdev->ddev->event_lock, flags);
>   	work = radeon_crtc->flip_work;
> -	if (radeon_crtc->flip_status != RADEON_FLIP_SUBMITTED) {
> +	if (radeon_crtc->flip_status != RADEON_FLIP_READY) {
>   		DRM_DEBUG_DRIVER("radeon_crtc->flip_status = %d != "
> -				 "RADEON_FLIP_SUBMITTED(%d)\n",
> +				 "RADEON_FLIP_READY(%d)\n",
>   				 radeon_crtc->flip_status,
> -				 RADEON_FLIP_SUBMITTED);
> +				 RADEON_FLIP_READY);
>   		spin_unlock_irqrestore(&rdev->ddev->event_lock, flags);
>   		return;
>   	}
>   
> +	/* do the flip (mmio) */
> +	radeon_page_flip(rdev, radeon_crtc->crtc_id, work->base);
> +
>   	/* Pageflip completed. Clean up. */
>   	radeon_crtc->flip_status = RADEON_FLIP_NONE;
>   	radeon_crtc->flip_work = NULL;
> @@ -479,10 +438,8 @@ static void radeon_flip_work_func(struct work_struct *__work)
>   	/* set the proper interrupt */
>   	radeon_irq_kms_pflip_irq_get(rdev, radeon_crtc->crtc_id);
>   
> -	/* do the flip (mmio) */
> -	radeon_page_flip(rdev, radeon_crtc->crtc_id, base);
> -
> -	radeon_crtc->flip_status = RADEON_FLIP_SUBMITTED;
> +	work->base = base;
> +	radeon_crtc->flip_status = RADEON_FLIP_READY;
>   	spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
>   	up_read(&rdev->exclusive_lock);
>   
> diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h
> index ed6b6e0..00955e3 100644
> --- a/drivers/gpu/drm/radeon/radeon_mode.h
> +++ b/drivers/gpu/drm/radeon/radeon_mode.h
> @@ -304,7 +304,7 @@ struct radeon_atom_ss {
>   enum radeon_flip_status {
>   	RADEON_FLIP_NONE,
>   	RADEON_FLIP_PENDING,
> -	RADEON_FLIP_SUBMITTED
> +	RADEON_FLIP_READY
>   };
>   
>   struct radeon_crtc {
> @@ -913,7 +913,6 @@ bool radeon_fbdev_robj_is_fb(struct radeon_device *rdev, struct radeon_bo *robj)
>   
>   void radeon_fb_output_poll_changed(struct radeon_device *rdev);
>   
> -void radeon_crtc_handle_vblank(struct radeon_device *rdev, int crtc_id);
>   void radeon_crtc_handle_flip(struct radeon_device *rdev, int crtc_id);
>   
>   int radeon_align_pitch(struct radeon_device *rdev, int width, int bpp, bool tiled);
> diff --git a/drivers/gpu/drm/radeon/rs600.c b/drivers/gpu/drm/radeon/rs600.c
> index 818f4eb..b5e63a7 100644
> --- a/drivers/gpu/drm/radeon/rs600.c
> +++ b/drivers/gpu/drm/radeon/rs600.c
> @@ -113,7 +113,10 @@ void rs600_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base)
>   {
>   	struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];
>   	u32 tmp = RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset);
> -	int i;
> +
> +	/* Take surface updates at horizontal blank */
> +	WREG32(AVIVO_D1GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset,
> +	       AVIVO_D1GRPH_SURFACE_UPDATE_H_RETRACE_EN);
>   
>   	/* Lock the graphics update lock */
>   	tmp |= AVIVO_D1GRPH_UPDATE_LOCK;
> @@ -125,28 +128,11 @@ void rs600_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base)
>   	WREG32(AVIVO_D1GRPH_PRIMARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset,
>   	       (u32)crtc_base);
>   
> -	/* Wait for update_pending to go high. */
> -	for (i = 0; i < rdev->usec_timeout; i++) {
> -		if (RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset) & AVIVO_D1GRPH_SURFACE_UPDATE_PENDING)
> -			break;
> -		udelay(1);
> -	}
> -	DRM_DEBUG("Update pending now high. Unlocking vupdate_lock.\n");
> -
> -	/* Unlock the lock, so double-buffering can take place inside vblank */
> +	/* Unlock the lock, so double-buffering can take place inside hblank */
>   	tmp &= ~AVIVO_D1GRPH_UPDATE_LOCK;
>   	WREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset, tmp);
>   }
>   
> -bool rs600_page_flip_pending(struct radeon_device *rdev, int crtc_id)
> -{
> -	struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];
> -
> -	/* Return current update_pending status: */
> -	return !!(RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset) &
> -		AVIVO_D1GRPH_SURFACE_UPDATE_PENDING);
> -}
> -
>   void avivo_program_fmt(struct drm_encoder *encoder)
>   {
>   	struct drm_device *dev = encoder->dev;
> @@ -790,7 +776,7 @@ int rs600_irq_process(struct radeon_device *rdev)
>   				wake_up(&rdev->irq.vblank_queue);
>   			}
>   			if (atomic_read(&rdev->irq.pflip[0]))
> -				radeon_crtc_handle_vblank(rdev, 0);
> +				radeon_crtc_handle_flip(rdev, 0);
>   		}
>   		if (G_007EDC_LB_D2_VBLANK_INTERRUPT(rdev->irq.stat_regs.r500.disp_int)) {
>   			if (rdev->irq.crtc_vblank_int[1]) {
> @@ -799,7 +785,7 @@ int rs600_irq_process(struct radeon_device *rdev)
>   				wake_up(&rdev->irq.vblank_queue);
>   			}
>   			if (atomic_read(&rdev->irq.pflip[1]))
> -				radeon_crtc_handle_vblank(rdev, 1);
> +				radeon_crtc_handle_flip(rdev, 1);
>   		}
>   		if (G_007EDC_DC_HOT_PLUG_DETECT1_INTERRUPT(rdev->irq.stat_regs.r500.disp_int)) {
>   			queue_hotplug = true;
> diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c
> index 97b7766..ef66be4 100644
> --- a/drivers/gpu/drm/radeon/rv770.c
> +++ b/drivers/gpu/drm/radeon/rv770.c
> @@ -805,7 +805,10 @@ void rv770_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base)
>   {
>   	struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];
>   	u32 tmp = RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset);
> -	int i;
> +
> +	/* Take surface updates at horizontal blank */
> +	WREG32(AVIVO_D1GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset,
> +	       AVIVO_D1GRPH_SURFACE_UPDATE_H_RETRACE_EN);
>   
>   	/* Lock the graphics update lock */
>   	tmp |= AVIVO_D1GRPH_UPDATE_LOCK;
> @@ -824,28 +827,11 @@ void rv770_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base)
>   	WREG32(D1GRPH_PRIMARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset,
>   	       (u32)crtc_base);
>   
> -	/* Wait for update_pending to go high. */
> -	for (i = 0; i < rdev->usec_timeout; i++) {
> -		if (RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset) & AVIVO_D1GRPH_SURFACE_UPDATE_PENDING)
> -			break;
> -		udelay(1);
> -	}
> -	DRM_DEBUG("Update pending now high. Unlocking vupdate_lock.\n");
> -
> -	/* Unlock the lock, so double-buffering can take place inside vblank */
> +	/* Unlock the lock, so double-buffering can take place inside hblank */
>   	tmp &= ~AVIVO_D1GRPH_UPDATE_LOCK;
>   	WREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset, tmp);
>   }
>   
> -bool rv770_page_flip_pending(struct radeon_device *rdev, int crtc_id)
> -{
> -	struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];
> -
> -	/* Return current update_pending status: */
> -	return !!(RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset) &
> -		AVIVO_D1GRPH_SURFACE_UPDATE_PENDING);
> -}
> -
>   /* get temperature in millidegrees */
>   int rv770_get_temp(struct radeon_device *rdev)
>   {
> diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c
> index c128bde..fee797f 100644
> --- a/drivers/gpu/drm/radeon/si.c
> +++ b/drivers/gpu/drm/radeon/si.c
> @@ -5917,25 +5917,6 @@ int si_irq_set(struct radeon_device *rdev)
>   		WREG32(INT_MASK + EVERGREEN_CRTC5_REGISTER_OFFSET, crtc6);
>   	}
>   
> -	if (rdev->num_crtc >= 2) {
> -		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET,
> -		       GRPH_PFLIP_INT_MASK);
> -		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET,
> -		       GRPH_PFLIP_INT_MASK);
> -	}
> -	if (rdev->num_crtc >= 4) {
> -		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET,
> -		       GRPH_PFLIP_INT_MASK);
> -		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET,
> -		       GRPH_PFLIP_INT_MASK);
> -	}
> -	if (rdev->num_crtc >= 6) {
> -		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET,
> -		       GRPH_PFLIP_INT_MASK);
> -		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET,
> -		       GRPH_PFLIP_INT_MASK);
> -	}
> -
>   	if (!ASIC_IS_NODCE(rdev)) {
>   		WREG32(DC_HPD1_INT_CONTROL, hpd1);
>   		WREG32(DC_HPD2_INT_CONTROL, hpd2);
> @@ -5974,10 +5955,6 @@ static inline void si_irq_ack(struct radeon_device *rdev)
>   		rdev->irq.stat_regs.evergreen.d6grph_int = RREG32(GRPH_INT_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET);
>   	}
>   
> -	if (rdev->irq.stat_regs.evergreen.d1grph_int & GRPH_PFLIP_INT_OCCURRED)
> -		WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC0_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR);
> -	if (rdev->irq.stat_regs.evergreen.d2grph_int & GRPH_PFLIP_INT_OCCURRED)
> -		WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC1_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR);
>   	if (rdev->irq.stat_regs.evergreen.disp_int & LB_D1_VBLANK_INTERRUPT)
>   		WREG32(VBLANK_STATUS + EVERGREEN_CRTC0_REGISTER_OFFSET, VBLANK_ACK);
>   	if (rdev->irq.stat_regs.evergreen.disp_int & LB_D1_VLINE_INTERRUPT)
> @@ -5988,10 +5965,6 @@ static inline void si_irq_ack(struct radeon_device *rdev)
>   		WREG32(VLINE_STATUS + EVERGREEN_CRTC1_REGISTER_OFFSET, VLINE_ACK);
>   
>   	if (rdev->num_crtc >= 4) {
> -		if (rdev->irq.stat_regs.evergreen.d3grph_int & GRPH_PFLIP_INT_OCCURRED)
> -			WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR);
> -		if (rdev->irq.stat_regs.evergreen.d4grph_int & GRPH_PFLIP_INT_OCCURRED)
> -			WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC3_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR);
>   		if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & LB_D3_VBLANK_INTERRUPT)
>   			WREG32(VBLANK_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET, VBLANK_ACK);
>   		if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & LB_D3_VLINE_INTERRUPT)
> @@ -6003,10 +5976,6 @@ static inline void si_irq_ack(struct radeon_device *rdev)
>   	}
>   
>   	if (rdev->num_crtc >= 6) {
> -		if (rdev->irq.stat_regs.evergreen.d5grph_int & GRPH_PFLIP_INT_OCCURRED)
> -			WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR);
> -		if (rdev->irq.stat_regs.evergreen.d6grph_int & GRPH_PFLIP_INT_OCCURRED)
> -			WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR);
>   		if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & LB_D5_VBLANK_INTERRUPT)
>   			WREG32(VBLANK_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET, VBLANK_ACK);
>   		if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & LB_D5_VLINE_INTERRUPT)
> @@ -6151,7 +6120,7 @@ restart_ih:
>   						wake_up(&rdev->irq.vblank_queue);
>   					}
>   					if (atomic_read(&rdev->irq.pflip[0]))
> -						radeon_crtc_handle_vblank(rdev, 0);
> +						radeon_crtc_handle_flip(rdev, 0);
>   					rdev->irq.stat_regs.evergreen.disp_int &= ~LB_D1_VBLANK_INTERRUPT;
>   					DRM_DEBUG("IH: D1 vblank\n");
>   				}
> @@ -6177,7 +6146,7 @@ restart_ih:
>   						wake_up(&rdev->irq.vblank_queue);
>   					}
>   					if (atomic_read(&rdev->irq.pflip[1]))
> -						radeon_crtc_handle_vblank(rdev, 1);
> +						radeon_crtc_handle_flip(rdev, 1);
>   					rdev->irq.stat_regs.evergreen.disp_int_cont &= ~LB_D2_VBLANK_INTERRUPT;
>   					DRM_DEBUG("IH: D2 vblank\n");
>   				}
> @@ -6203,7 +6172,7 @@ restart_ih:
>   						wake_up(&rdev->irq.vblank_queue);
>   					}
>   					if (atomic_read(&rdev->irq.pflip[2]))
> -						radeon_crtc_handle_vblank(rdev, 2);
> +						radeon_crtc_handle_flip(rdev, 2);
>   					rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~LB_D3_VBLANK_INTERRUPT;
>   					DRM_DEBUG("IH: D3 vblank\n");
>   				}
> @@ -6229,7 +6198,7 @@ restart_ih:
>   						wake_up(&rdev->irq.vblank_queue);
>   					}
>   					if (atomic_read(&rdev->irq.pflip[3]))
> -						radeon_crtc_handle_vblank(rdev, 3);
> +						radeon_crtc_handle_flip(rdev, 3);
>   					rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~LB_D4_VBLANK_INTERRUPT;
>   					DRM_DEBUG("IH: D4 vblank\n");
>   				}
> @@ -6255,7 +6224,7 @@ restart_ih:
>   						wake_up(&rdev->irq.vblank_queue);
>   					}
>   					if (atomic_read(&rdev->irq.pflip[4]))
> -						radeon_crtc_handle_vblank(rdev, 4);
> +						radeon_crtc_handle_flip(rdev, 4);
>   					rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~LB_D5_VBLANK_INTERRUPT;
>   					DRM_DEBUG("IH: D5 vblank\n");
>   				}
> @@ -6281,7 +6250,7 @@ restart_ih:
>   						wake_up(&rdev->irq.vblank_queue);
>   					}
>   					if (atomic_read(&rdev->irq.pflip[5]))
> -						radeon_crtc_handle_vblank(rdev, 5);
> +						radeon_crtc_handle_flip(rdev, 5);
>   					rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~LB_D6_VBLANK_INTERRUPT;
>   					DRM_DEBUG("IH: D6 vblank\n");
>   				}
> @@ -6297,15 +6266,6 @@ restart_ih:
>   				break;
>   			}
>   			break;
> -		case 8: /* D1 page flip */
> -		case 10: /* D2 page flip */
> -		case 12: /* D3 page flip */
> -		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);
> -			break;
>   		case 42: /* HPD hotplug */
>   			switch (src_data) {
>   			case 0:

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH 1/2] drm/radeon: Move pinning the BO back to radeon_crtc_page_flip()
  2014-07-02 10:10                       ` [PATCH 1/2] drm/radeon: Move pinning the BO back to radeon_crtc_page_flip() Michel Dänzer
  2014-07-02 10:10                         ` [PATCH 2/2] drm/radeon: Complete page flip even if waiting on the BO fence fails Michel Dänzer
@ 2014-07-02 11:42                         ` Christian König
  1 sibling, 0 replies; 34+ messages in thread
From: Christian König @ 2014-07-02 11:42 UTC (permalink / raw)
  To: Michel Dänzer, dri-devel

Am 02.07.2014 12:10, schrieb Michel Dänzer:
> From: Michel Dänzer <michel.daenzer@amd.com>
>
> As well as enabling the vblank interrupt. These shouldn't take any
> significant amount of time, but at least pinning the BO has actually been
> seen to fail in practice before, in which case we need to let userspace
> know about it.
>
> Signed-off-by: Michel Dänzer <michel.daenzer@amd.com>

Both patches are Reviewed-by: Christian König <christian.koenig@amd.com>

> ---
>   drivers/gpu/drm/radeon/radeon.h         |   2 -
>   drivers/gpu/drm/radeon/radeon_display.c | 174 ++++++++++++++++----------------
>   2 files changed, 88 insertions(+), 88 deletions(-)
>
> diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
> index 19a8551..dbe39c8 100644
> --- a/drivers/gpu/drm/radeon/radeon.h
> +++ b/drivers/gpu/drm/radeon/radeon.h
> @@ -682,10 +682,8 @@ struct radeon_flip_work {
>   	struct radeon_device		*rdev;
>   	int				crtc_id;
>   	uint64_t			base;
> -	struct drm_framebuffer		*fb;
>   	struct drm_pending_vblank_event *event;
>   	struct radeon_bo		*old_rbo;
> -	struct radeon_bo		*new_rbo;
>   	struct radeon_fence		*fence;
>   };
>   
> diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c
> index 2742edd..82ae9e3 100644
> --- a/drivers/gpu/drm/radeon/radeon_display.c
> +++ b/drivers/gpu/drm/radeon/radeon_display.c
> @@ -343,11 +343,6 @@ static void radeon_flip_work_func(struct work_struct *__work)
>   	struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[work->crtc_id];
>   
>   	struct drm_crtc *crtc = &radeon_crtc->base;
> -	struct drm_framebuffer *fb = work->fb;
> -
> -	uint32_t tiling_flags, pitch_pixels;
> -	uint64_t base;
> -
>   	unsigned long flags;
>   	int r;
>   
> @@ -368,26 +363,87 @@ static void radeon_flip_work_func(struct work_struct *__work)
>   			radeon_fence_unref(&work->fence);
>   	}
>   
> +	/* We borrow the event spin lock for protecting flip_status */
> +	spin_lock_irqsave(&crtc->dev->event_lock, flags);
> +	radeon_crtc->flip_status = RADEON_FLIP_READY;
> +	spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
> +	up_read(&rdev->exclusive_lock);
> +
> +	return;
> +
> +cleanup:
> +	drm_gem_object_unreference_unlocked(&work->old_rbo->gem_base);
> +	radeon_fence_unref(&work->fence);
> +	kfree(work);
> +	up_read(&rdev->exclusive_lock);
> +}
> +
> +static int radeon_crtc_page_flip(struct drm_crtc *crtc,
> +				 struct drm_framebuffer *fb,
> +				 struct drm_pending_vblank_event *event,
> +				 uint32_t page_flip_flags)
> +{
> +	struct drm_device *dev = crtc->dev;
> +	struct radeon_device *rdev = dev->dev_private;
> +	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
> +	struct radeon_framebuffer *old_radeon_fb;
> +	struct radeon_framebuffer *new_radeon_fb;
> +	struct drm_gem_object *obj;
> +	struct radeon_flip_work *work;
> +	struct radeon_bo *new_rbo;
> +	uint32_t tiling_flags, pitch_pixels;
> +	uint64_t base;
> +	unsigned long flags;
> +	int r;
> +
> +	work = kzalloc(sizeof *work, GFP_KERNEL);
> +	if (work == NULL)
> +		return -ENOMEM;
> +
> +	INIT_WORK(&work->flip_work, radeon_flip_work_func);
> +	INIT_WORK(&work->unpin_work, radeon_unpin_work_func);
> +
> +	work->rdev = rdev;
> +	work->crtc_id = radeon_crtc->crtc_id;
> +	work->event = event;
> +
> +	/* schedule unpin of the old buffer */
> +	old_radeon_fb = to_radeon_framebuffer(crtc->primary->fb);
> +	obj = old_radeon_fb->obj;
> +
> +	/* take a reference to the old object */
> +	drm_gem_object_reference(obj);
> +	work->old_rbo = gem_to_radeon_bo(obj);
> +
> +	new_radeon_fb = to_radeon_framebuffer(fb);
> +	obj = new_radeon_fb->obj;
> +	new_rbo = gem_to_radeon_bo(obj);
> +
> +	spin_lock(&new_rbo->tbo.bdev->fence_lock);
> +	if (new_rbo->tbo.sync_obj)
> +		work->fence = radeon_fence_ref(new_rbo->tbo.sync_obj);
> +	spin_unlock(&new_rbo->tbo.bdev->fence_lock);
> +
>   	/* pin the new buffer */
> -	DRM_DEBUG_DRIVER("flip-ioctl() cur_fbo = %p, cur_bbo = %p\n",
> -			 work->old_rbo, work->new_rbo);
> +	DRM_DEBUG_DRIVER("flip-ioctl() cur_rbo = %p, new_rbo = %p\n",
> +			 work->old_rbo, new_rbo);
>   
> -	r = radeon_bo_reserve(work->new_rbo, false);
> +	r = radeon_bo_reserve(new_rbo, false);
>   	if (unlikely(r != 0)) {
>   		DRM_ERROR("failed to reserve new rbo buffer before flip\n");
>   		goto cleanup;
>   	}
>   	/* Only 27 bit offset for legacy CRTC */
> -	r = radeon_bo_pin_restricted(work->new_rbo, RADEON_GEM_DOMAIN_VRAM,
> +	r = radeon_bo_pin_restricted(new_rbo, RADEON_GEM_DOMAIN_VRAM,
>   				     ASIC_IS_AVIVO(rdev) ? 0 : 1 << 27, &base);
>   	if (unlikely(r != 0)) {
> -		radeon_bo_unreserve(work->new_rbo);
> +		radeon_bo_unreserve(new_rbo);
>   		r = -EINVAL;
>   		DRM_ERROR("failed to pin new rbo buffer before flip\n");
>   		goto cleanup;
>   	}
> -	radeon_bo_get_tiling_flags(work->new_rbo, &tiling_flags, NULL);
> -	radeon_bo_unreserve(work->new_rbo);
> +	radeon_bo_get_tiling_flags(new_rbo, &tiling_flags, NULL);
> +	radeon_bo_unreserve(new_rbo);
>   
>   	if (!ASIC_IS_AVIVO(rdev)) {
>   		/* crtc offset is from display base addr not FB location */
> @@ -424,6 +480,7 @@ static void radeon_flip_work_func(struct work_struct *__work)
>   		}
>   		base &= ~7;
>   	}
> +	work->base = base;
>   
>   	r = drm_vblank_get(crtc->dev, radeon_crtc->crtc_id);
>   	if (r) {
> @@ -433,83 +490,12 @@ static void radeon_flip_work_func(struct work_struct *__work)
>   
>   	/* We borrow the event spin lock for protecting flip_work */
>   	spin_lock_irqsave(&crtc->dev->event_lock, flags);
> -	work->base = base;
> -	radeon_crtc->flip_status = RADEON_FLIP_READY;
> -	spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
> -	up_read(&rdev->exclusive_lock);
> -
> -	return;
> -
> -pflip_cleanup:
> -	if (unlikely(radeon_bo_reserve(work->new_rbo, false) != 0)) {
> -		DRM_ERROR("failed to reserve new rbo in error path\n");
> -		goto cleanup;
> -	}
> -	if (unlikely(radeon_bo_unpin(work->new_rbo) != 0)) {
> -		DRM_ERROR("failed to unpin new rbo in error path\n");
> -	}
> -	radeon_bo_unreserve(work->new_rbo);
> -
> -cleanup:
> -	drm_gem_object_unreference_unlocked(&work->old_rbo->gem_base);
> -	radeon_fence_unref(&work->fence);
> -	kfree(work);
> -	up_read(&rdev->exclusive_lock);
> -}
> -
> -static int radeon_crtc_page_flip(struct drm_crtc *crtc,
> -				 struct drm_framebuffer *fb,
> -				 struct drm_pending_vblank_event *event,
> -				 uint32_t page_flip_flags)
> -{
> -	struct drm_device *dev = crtc->dev;
> -	struct radeon_device *rdev = dev->dev_private;
> -	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
> -	struct radeon_framebuffer *old_radeon_fb;
> -	struct radeon_framebuffer *new_radeon_fb;
> -	struct drm_gem_object *obj;
> -	struct radeon_flip_work *work;
> -	unsigned long flags;
> -
> -	work = kzalloc(sizeof *work, GFP_KERNEL);
> -	if (work == NULL)
> -		return -ENOMEM;
> -
> -	INIT_WORK(&work->flip_work, radeon_flip_work_func);
> -	INIT_WORK(&work->unpin_work, radeon_unpin_work_func);
> -
> -	work->rdev = rdev;
> -	work->crtc_id = radeon_crtc->crtc_id;
> -	work->fb = fb;
> -	work->event = event;
> -
> -	/* schedule unpin of the old buffer */
> -	old_radeon_fb = to_radeon_framebuffer(crtc->primary->fb);
> -	obj = old_radeon_fb->obj;
> -
> -	/* take a reference to the old object */
> -	drm_gem_object_reference(obj);
> -	work->old_rbo = gem_to_radeon_bo(obj);
> -
> -	new_radeon_fb = to_radeon_framebuffer(fb);
> -	obj = new_radeon_fb->obj;
> -	work->new_rbo = gem_to_radeon_bo(obj);
> -
> -	spin_lock(&work->new_rbo->tbo.bdev->fence_lock);
> -	if (work->new_rbo->tbo.sync_obj)
> -		work->fence = radeon_fence_ref(work->new_rbo->tbo.sync_obj);
> -	spin_unlock(&work->new_rbo->tbo.bdev->fence_lock);
> -
> -	/* We borrow the event spin lock for protecting flip_work */
> -	spin_lock_irqsave(&crtc->dev->event_lock, flags);
>   
>   	if (radeon_crtc->flip_status != RADEON_FLIP_NONE) {
>   		DRM_DEBUG_DRIVER("flip queue: crtc already busy\n");
>   		spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
> -		drm_gem_object_unreference_unlocked(&work->old_rbo->gem_base);
> -		radeon_fence_unref(&work->fence);
> -		kfree(work);
> -		return -EBUSY;
> +		r = -EBUSY;
> +		goto pflip_cleanup;
>   	}
>   	radeon_crtc->flip_status = RADEON_FLIP_PENDING;
>   	radeon_crtc->flip_work = work;
> @@ -520,8 +506,24 @@ static int radeon_crtc_page_flip(struct drm_crtc *crtc,
>   	spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
>   
>   	queue_work(radeon_crtc->flip_queue, &work->flip_work);
> -
>   	return 0;
> +
> +pflip_cleanup:
> +	if (unlikely(radeon_bo_reserve(new_rbo, false) != 0)) {
> +		DRM_ERROR("failed to reserve new rbo in error path\n");
> +		goto cleanup;
> +	}
> +	if (unlikely(radeon_bo_unpin(new_rbo) != 0)) {
> +		DRM_ERROR("failed to unpin new rbo in error path\n");
> +	}
> +	radeon_bo_unreserve(new_rbo);
> +
> +cleanup:
> +	drm_gem_object_unreference_unlocked(&work->old_rbo->gem_base);
> +	radeon_fence_unref(&work->fence);
> +	kfree(work);
> +
> +	return r;
>   }
>   
>   static int

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 34+ messages in thread

end of thread, other threads:[~2014-07-02 11:42 UTC | newest]

Thread overview: 34+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-06-26  9:29 [PATCH 1/2] drm/radeon: Only enable and handle pageflip interrupts when needed Michel Dänzer
2014-06-26  9:29 ` [PATCH 2/2] drm/radeon: Track the status of a page flip more explicitly Michel Dänzer
2014-06-30  9:12   ` [PATCH v2] " Michel Dänzer
2014-06-30  9:14     ` Christian König
2014-07-01 16:23     ` Alex Deucher
2014-06-26 10:39 ` [PATCH 1/2] drm/radeon: Only enable and handle pageflip interrupts when needed Christian König
2014-06-26 11:51   ` Dieter Nützel
2014-06-27  0:53   ` Dieter Nützel
2014-06-27  1:03     ` Michel Dänzer
2014-06-27  1:08       ` Dieter Nützel
2014-06-27  2:06       ` Dieter Nützel
2014-06-27  3:03         ` Michel Dänzer
2014-06-27  3:17           ` Michel Dänzer
2014-06-27  2:58   ` Michel Dänzer
2014-06-27  8:18     ` Christian König
2014-06-27  9:44       ` Michel Dänzer
2014-06-27 10:47         ` Christian König
2014-06-30  9:34           ` Michel Dänzer
2014-06-30 12:31             ` Christian König
2014-06-30 16:22               ` Dieter Nützel
2014-07-01  8:14               ` [PATCH 1/2] drm/radeon: Program page flips to execute in hblank instead of vblank Michel Dänzer
2014-07-01  8:14                 ` [PATCH 2/2] drm/radeon: Remove radeon_kms_pflip_irq_get/put() Michel Dänzer
2014-07-01 10:12                 ` [PATCH 1/2] drm/radeon: Program page flips to execute in hblank instead of vblank Christian König
2014-07-02  3:55                   ` [PATCH v2 " Michel Dänzer
2014-07-02  3:55                     ` [PATCH v2 2/2] drm/radeon: Remove radeon_kms_pflip_irq_get/put() and the pflip atomic Michel Dänzer
2014-07-02 10:10                       ` [PATCH 1/2] drm/radeon: Move pinning the BO back to radeon_crtc_page_flip() Michel Dänzer
2014-07-02 10:10                         ` [PATCH 2/2] drm/radeon: Complete page flip even if waiting on the BO fence fails Michel Dänzer
2014-07-02 11:42                         ` [PATCH 1/2] drm/radeon: Move pinning the BO back to radeon_crtc_page_flip() Christian König
2014-07-02 11:35                     ` [PATCH v2 1/2] drm/radeon: Program page flips to execute in hblank instead of vblank Christian König
2014-07-01 16:46                 ` [PATCH " Dieter Nützel
2014-07-02  0:29                   ` Michel Dänzer
2014-07-02  3:01                     ` Dieter Nützel
2014-07-02  3:11                       ` Michel Dänzer
2014-07-02  3:52                         ` Michel Dänzer

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.