[Intel-gfx] [PATCH] drm/i915: Ensure that while(INREG()) are bounded.

Chris Wilson chris at chris-wilson.co.uk
Fri Aug 6 17:11:54 CEST 2010


Add a new macro, wait_for, to simplify the act of waiting on a register
to change state. wait_for() takes three arguments, the condition to
inspect on every loop, the maximum amount of time to wait and whether to
yield the cpu for a length of time after each check.

Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
---
 drivers/gpu/drm/i915/intel_crt.c     |   17 ++++------
 drivers/gpu/drm/i915/intel_display.c |   54 +++++++---------------------------
 drivers/gpu/drm/i915/intel_dp.c      |   25 +++++----------
 drivers/gpu/drm/i915/intel_drv.h     |   14 +++++++++
 drivers/gpu/drm/i915/intel_lvds.c    |   12 +++----
 5 files changed, 46 insertions(+), 76 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c
index d4d0c1c..45e043c 100644
--- a/drivers/gpu/drm/i915/intel_crt.c
+++ b/drivers/gpu/drm/i915/intel_crt.c
@@ -187,8 +187,9 @@ static bool intel_ironlake_crt_detect_hotplug(struct drm_connector *connector)
 	DRM_DEBUG_KMS("pch crt adpa 0x%x", adpa);
 	I915_WRITE(PCH_ADPA, adpa);
 
-	while ((I915_READ(PCH_ADPA) & ADPA_CRT_HOTPLUG_FORCE_TRIGGER) != 0)
-		;
+	if (wait_for((I915_READ(PCH_ADPA) & ADPA_CRT_HOTPLUG_FORCE_TRIGGER) == 0,
+		     1000, 1))
+		DRM_DEBUG_DRIVER("timed out waiting for FORCE_TRIGGER");
 
 	if (HAS_PCH_CPT(dev)) {
 		I915_WRITE(PCH_ADPA, temp);
@@ -239,17 +240,13 @@ static bool intel_crt_detect_hotplug(struct drm_connector *connector)
 	hotplug_en |= CRT_HOTPLUG_FORCE_DETECT;
 
 	for (i = 0; i < tries ; i++) {
-		unsigned long timeout;
 		/* turn on the FORCE_DETECT */
 		I915_WRITE(PORT_HOTPLUG_EN, hotplug_en);
-		timeout = jiffies + msecs_to_jiffies(1000);
 		/* wait for FORCE_DETECT to go off */
-		do {
-			if (!(I915_READ(PORT_HOTPLUG_EN) &
-					CRT_HOTPLUG_FORCE_DETECT))
-				break;
-			msleep(1);
-		} while (time_after(timeout, jiffies));
+		if (wait_for((I915_READ(PORT_HOTPLUG_EN) &
+			      CRT_HOTPLUG_FORCE_DETECT) == 0,
+			     1000, 1))
+			DRM_DEBUG_DRIVER("timed out waiting for FORCE_DETECT to go off");
 	}
 
 	stat = I915_READ(PORT_HOTPLUG_STAT);
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 5cae58a..958d9aa 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -1034,7 +1034,6 @@ static void i8xx_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
 void i8xx_disable_fbc(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	unsigned long timeout = jiffies + msecs_to_jiffies(1);
 	u32 fbc_ctl;
 
 	if (!I915_HAS_FBC(dev))
@@ -1049,12 +1048,9 @@ void i8xx_disable_fbc(struct drm_device *dev)
 	I915_WRITE(FBC_CONTROL, fbc_ctl);
 
 	/* Wait for compressing bit to clear */
-	while (I915_READ(FBC_STATUS) & FBC_STAT_COMPRESSING) {
-		if (time_after(jiffies, timeout)) {
-			DRM_DEBUG_DRIVER("FBC idle timed out\n");
-			break;
-		}
-		; /* do nothing */
+	if (wait_for((I915_READ(FBC_STATUS) & FBC_STAT_COMPRESSING) == 0, 10, 0)) {
+		DRM_DEBUG_KMS("FBC idle timed out\n");
+		return;
 	}
 
 	intel_wait_for_vblank(dev);
@@ -1845,7 +1841,6 @@ static int ironlake_crtc_dpms(struct drm_crtc *crtc, int mode)
 	int trans_vsync_reg = (pipe == 0) ? TRANS_VSYNC_A : TRANS_VSYNC_B;
 	int trans_dpll_sel = (pipe == 0) ? 0 : 1;
 	u32 temp;
-	int n;
 	u32 pipe_bpc;
 
 	temp = I915_READ(pipeconf_reg);
@@ -2040,9 +2035,8 @@ static int ironlake_crtc_dpms(struct drm_crtc *crtc, int mode)
 			temp |= pipe_bpc;
 			I915_WRITE(transconf_reg, temp | TRANS_ENABLE);
 
-			while ((I915_READ(transconf_reg) & TRANS_STATE_ENABLE) == 0)
-				;
-
+			if (wait_for(I915_READ(transconf_reg) & TRANS_STATE_ENABLE, 10, 0))
+				DRM_DEBUG_KMS("failed to enable transcoder\n");
 		}
 
 		intel_crtc_load_lut(crtc);
@@ -2074,19 +2068,9 @@ static int ironlake_crtc_dpms(struct drm_crtc *crtc, int mode)
 		if (temp & PIPEACONF_ENABLE) {
 			I915_WRITE(pipeconf_reg, temp & ~PIPEACONF_ENABLE);
 
-			n = 0;
 			/* wait for cpu pipe off, pipe state */
-			while (I915_READ(pipeconf_reg) & I965_PIPECONF_ACTIVE) {
-				n++;
-				if (n < 60) {
-					udelay(500);
-					continue;
-				} else {
-					DRM_DEBUG_KMS("pipe %d off delay\n",
-								pipe);
-					break;
-				}
-			}
+			if (wait_for((I915_READ(pipeconf_reg) & I965_PIPECONF_ACTIVE) == 0, 50, 1))
+				DRM_DEBUG_KMS("failed to turn off cpu pipe\n");
 		} else
 			DRM_DEBUG_KMS("crtc %d is disabled\n", pipe);
 
@@ -2137,19 +2121,9 @@ static int ironlake_crtc_dpms(struct drm_crtc *crtc, int mode)
 		if (temp & TRANS_ENABLE) {
 			I915_WRITE(transconf_reg, temp & ~TRANS_ENABLE);
 
-			n = 0;
 			/* wait for PCH transcoder off, transcoder state */
-			while (I915_READ(transconf_reg) & TRANS_STATE_ENABLE) {
-				n++;
-				if (n < 60) {
-					udelay(500);
-					continue;
-				} else {
-					DRM_DEBUG_KMS("transcoder %d off "
-							"delay\n", pipe);
-					break;
-				}
-			}
+			if (wait_for((I915_READ(transconf_reg) & TRANS_STATE_ENABLE) == 0, 50, 1))
+				DRM_DEBUG_KMS("failed to disable transcoder\n");
 		}
 
 		if (HAS_PCH_CPT(dev)) {
@@ -5383,7 +5357,6 @@ void ironlake_enable_drps(struct drm_device *dev)
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	u32 rgvmodectl = I915_READ(MEMMODECTL);
 	u8 fmax, fmin, fstart, vstart;
-	int i = 0;
 
 	/* 100ms RC evaluation intervals */
 	I915_WRITE(RCUPEI, 100000);
@@ -5427,13 +5400,8 @@ void ironlake_enable_drps(struct drm_device *dev)
 	rgvmodectl |= MEMMODE_SWMODE_EN;
 	I915_WRITE(MEMMODECTL, rgvmodectl);
 
-	while (I915_READ(MEMSWCTL) & MEMCTL_CMD_STS) {
-		if (i++ > 100) {
-			DRM_ERROR("stuck trying to change perf mode\n");
-			break;
-		}
-		msleep(1);
-	}
+	if (wait_for((I915_READ(MEMSWCTL) & MEMCTL_CMD_STS) == 0, 1, 0))
+		DRM_DEBUG_DRIVER("stuck trying to change perf mode\n");
 	msleep(1);
 
 	ironlake_set_drps(dev, fstart);
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 3e98b10..581e0b0 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -761,22 +761,18 @@ intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
 static void ironlake_edp_panel_on (struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	unsigned long timeout = jiffies + msecs_to_jiffies(5000);
-	u32 pp, pp_status;
+	u32 pp;
 
-	pp_status = I915_READ(PCH_PP_STATUS);
-	if (pp_status & PP_ON)
+	if (I915_READ(PCH_PP_STATUS) & PP_ON)
 		return;
 
 	pp = I915_READ(PCH_PP_CONTROL);
 	pp |= PANEL_UNLOCK_REGS | POWER_TARGET_ON;
 	I915_WRITE(PCH_PP_CONTROL, pp);
-	do {
-		pp_status = I915_READ(PCH_PP_STATUS);
-	} while (((pp_status & PP_ON) == 0) && !time_after(jiffies, timeout));
 
-	if (time_after(jiffies, timeout))
-		DRM_DEBUG_KMS("panel on wait timed out: 0x%08x\n", pp_status);
+	if (wait_for(I915_READ(PCH_PP_STATUS) & PP_ON, 5000, 10))
+		DRM_DEBUG_DRIVER("panel on wait timed out: 0x%08x\n",
+				 I915_READ(PCH_PP_STATUS));
 
 	pp &= ~(PANEL_UNLOCK_REGS | EDP_FORCE_VDD);
 	I915_WRITE(PCH_PP_CONTROL, pp);
@@ -785,18 +781,15 @@ static void ironlake_edp_panel_on (struct drm_device *dev)
 static void ironlake_edp_panel_off (struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	unsigned long timeout = jiffies + msecs_to_jiffies(5000);
-	u32 pp, pp_status;
+	u32 pp;
 
 	pp = I915_READ(PCH_PP_CONTROL);
 	pp &= ~POWER_TARGET_ON;
 	I915_WRITE(PCH_PP_CONTROL, pp);
-	do {
-		pp_status = I915_READ(PCH_PP_STATUS);
-	} while ((pp_status & PP_ON) && !time_after(jiffies, timeout));
 
-	if (time_after(jiffies, timeout))
-		DRM_DEBUG_KMS("panel off wait timed out\n");
+	if (wait_for((I915_READ(PCH_PP_STATUS) & PP_ON) == 0, 5000, 10))
+		DRM_DEBUG_DRIVER("panel on wait timed out: 0x%08x\n",
+				 I915_READ(PCH_PP_STATUS));
 
 	/* Make sure VDD is enabled so DP AUX will work */
 	pp |= EDP_FORCE_VDD;
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 34fc531..80d7184 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -32,6 +32,20 @@
 #include "drm_crtc.h"
 
 #include "drm_crtc_helper.h"
+
+#define wait_for(COND, MS, W) ({ \
+	unsigned long timeout__ = jiffies + msecs_to_jiffies(MS);	\
+	int ret__ = 0;							\
+	while (! (COND)) {						\
+		if (time_after(jiffies, timeout__)) {			\
+			ret__ = -ETIMEDOUT;				\
+			break;						\
+		}							\
+		if (W) msleep(W);					\
+	}								\
+	ret__;								\
+})
+
 /*
  * Display related stuff
  */
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
index c15490d..01b063c 100644
--- a/drivers/gpu/drm/i915/intel_lvds.c
+++ b/drivers/gpu/drm/i915/intel_lvds.c
@@ -96,7 +96,7 @@ static u32 intel_lvds_get_max_backlight(struct drm_device *dev)
 static void intel_lvds_set_power(struct drm_device *dev, bool on)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	u32 pp_status, ctl_reg, status_reg, lvds_reg;
+	u32 ctl_reg, status_reg, lvds_reg;
 
 	if (HAS_PCH_SPLIT(dev)) {
 		ctl_reg = PCH_PP_CONTROL;
@@ -114,9 +114,8 @@ static void intel_lvds_set_power(struct drm_device *dev, bool on)
 
 		I915_WRITE(ctl_reg, I915_READ(ctl_reg) |
 			   POWER_TARGET_ON);
-		do {
-			pp_status = I915_READ(status_reg);
-		} while ((pp_status & PP_ON) == 0);
+		if (wait_for(I915_READ(status_reg) & PP_ON, 1000, 0))
+			DRM_DEBUG_DRIVER("timed out waiting to enable LVDS pipe");
 
 		intel_lvds_set_backlight(dev, dev_priv->backlight_duty_cycle);
 	} else {
@@ -124,9 +123,8 @@ static void intel_lvds_set_power(struct drm_device *dev, bool on)
 
 		I915_WRITE(ctl_reg, I915_READ(ctl_reg) &
 			   ~POWER_TARGET_ON);
-		do {
-			pp_status = I915_READ(status_reg);
-		} while (pp_status & PP_ON);
+		if (wait_for((I915_READ(status_reg) & PP_ON) == 0, 1000, 0))
+			DRM_DEBUG_DRIVER("timed out waiting for LVDS pipe to turn off");
 
 		I915_WRITE(lvds_reg, I915_READ(lvds_reg) & ~LVDS_PORT_EN);
 		POSTING_READ(lvds_reg);
-- 
1.7.1




More information about the Intel-gfx mailing list