diff mbox

drm/i915: Add debugfs file to clear FIFO underruns.

Message ID 20180328100526.36467-1-maarten.lankhorst@linux.intel.com (mailing list archive)
State New, archived
Headers show

Commit Message

Maarten Lankhorst March 28, 2018, 10:05 a.m. UTC
Adding a i915_fifo_underrun_reset debugfs file will make it possible
for IGT tests to clear FIFO underrun fallout at the start of each
subtest, and make re-enable FBC so tests always have maximum exposure
to features used by IGT. FIFO underruns and FBC bugs will no longer
hide when an earlier subtests disables both.

Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=105685
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=105681
---
 drivers/gpu/drm/i915/i915_debugfs.c  | 62 ++++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/intel_display.c | 30 ++++++++++-------
 drivers/gpu/drm/i915/intel_drv.h     |  3 ++
 drivers/gpu/drm/i915/intel_fbc.c     | 26 +++++++++++++++
 4 files changed, 109 insertions(+), 12 deletions(-)

Comments

Jani Nikula March 28, 2018, 10:21 a.m. UTC | #1
On Wed, 28 Mar 2018, Maarten Lankhorst <maarten.lankhorst@linux.intel.com> wrote:
> Adding a i915_fifo_underrun_reset debugfs file will make it possible
> for IGT tests to clear FIFO underrun fallout at the start of each
> subtest, and make re-enable FBC so tests always have maximum exposure
> to features used by IGT. FIFO underruns and FBC bugs will no longer
> hide when an earlier subtests disables both.
>
> Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
> Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=105685
> Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=105681

FWIW, ack on the idea, didn't look at the implementation.

BR,
Jani.

> ---
>  drivers/gpu/drm/i915/i915_debugfs.c  | 62 ++++++++++++++++++++++++++++++++++++
>  drivers/gpu/drm/i915/intel_display.c | 30 ++++++++++-------
>  drivers/gpu/drm/i915/intel_drv.h     |  3 ++
>  drivers/gpu/drm/i915/intel_fbc.c     | 26 +++++++++++++++
>  4 files changed, 109 insertions(+), 12 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
> index 7816cd53100a..27188de2c32b 100644
> --- a/drivers/gpu/drm/i915/i915_debugfs.c
> +++ b/drivers/gpu/drm/i915/i915_debugfs.c
> @@ -4731,6 +4731,67 @@ static int i915_drrs_ctl_set(void *data, u64 val)
>  
>  DEFINE_SIMPLE_ATTRIBUTE(i915_drrs_ctl_fops, NULL, i915_drrs_ctl_set, "%llu\n");
>  
> +static ssize_t
> +i915_fifo_underrun_reset_write(struct file *filp,
> +			       const char __user *ubuf,
> +			       size_t cnt, loff_t *ppos)
> +{
> +	struct drm_i915_private *dev_priv = filp->private_data;
> +	struct intel_crtc *intel_crtc;
> +	struct drm_device *dev = &dev_priv->drm;
> +	int ret;
> +	bool reset;
> +
> +	ret = kstrtobool_from_user(ubuf, cnt, &reset);
> +	if (ret)
> +		return ret;
> +
> +	if (!reset)
> +		return cnt;
> +
> +	for_each_intel_crtc(dev, intel_crtc) {
> +		struct drm_crtc_commit *commit;
> +		struct intel_crtc_state *crtc_state;
> +
> +		ret = drm_modeset_lock_single_interruptible(&intel_crtc->base.mutex);
> +		if (ret)
> +			return ret;
> +
> +		crtc_state = to_intel_crtc_state(intel_crtc->base.state);
> +		commit = crtc_state->base.commit;
> +		if (commit) {
> +			ret = wait_for_completion_interruptible(&commit->hw_done);
> +			if (!ret)
> +				ret = wait_for_completion_interruptible(&commit->flip_done);
> +		}
> +
> +		if (!ret && crtc_state->base.active) {
> +			DRM_DEBUG_KMS("Re-arming FIFO underruns on pipe %c\n",
> +				      pipe_name(intel_crtc->pipe));
> +
> +			intel_crtc_arm_fifo_underrun(intel_crtc, crtc_state);
> +		}
> +
> +		drm_modeset_unlock(&intel_crtc->base.mutex);
> +
> +		if (ret)
> +			return ret;
> +	}
> +
> +	ret = intel_fbc_reset_underrun(dev_priv);
> +	if (ret)
> +		return ret;
> +
> +	return cnt;
> +}
> +
> +static const struct file_operations i915_fifo_underrun_reset_ops = {
> +	.owner = THIS_MODULE,
> +	.open = simple_open,
> +	.write = i915_fifo_underrun_reset_write,
> +	.llseek = default_llseek,
> +};
> +
>  static const struct drm_info_list i915_debugfs_list[] = {
>  	{"i915_capabilities", i915_capabilities, 0},
>  	{"i915_gem_objects", i915_gem_object_info, 0},
> @@ -4798,6 +4859,7 @@ static const struct i915_debugfs_files {
>  	{"i915_error_state", &i915_error_state_fops},
>  	{"i915_gpu_info", &i915_gpu_info_fops},
>  #endif
> +	{"i915_fifo_underrun_reset", &i915_fifo_underrun_reset_ops},
>  	{"i915_next_seqno", &i915_next_seqno_fops},
>  	{"i915_display_crc_ctl", &i915_display_crc_ctl_fops},
>  	{"i915_pri_wm_latency", &i915_pri_wm_latency_fops},
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 4c30c7c04f9c..3df0e8193b83 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -12960,10 +12960,25 @@ static void intel_begin_crtc_commit(struct drm_crtc *crtc,
>  							   intel_cstate);
>  }
>  
> +void intel_crtc_arm_fifo_underrun(struct intel_crtc *crtc,
> +				  struct intel_crtc_state *crtc_state)
> +{
> +	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
> +
> +	if (!IS_GEN2(dev_priv))
> +		intel_set_cpu_fifo_underrun_reporting(dev_priv, crtc->pipe, true);
> +
> +	if (crtc_state->has_pch_encoder) {
> +		enum pipe pch_transcoder =
> +			intel_crtc_pch_transcoder(crtc);
> +
> +		intel_set_pch_fifo_underrun_reporting(dev_priv, pch_transcoder, true);
> +	}
> +}
> +
>  static void intel_finish_crtc_commit(struct drm_crtc *crtc,
>  				     struct drm_crtc_state *old_crtc_state)
>  {
> -	struct drm_i915_private *dev_priv = to_i915(crtc->dev);
>  	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
>  	struct intel_atomic_state *old_intel_state =
>  		to_intel_atomic_state(old_crtc_state->state);
> @@ -12974,17 +12989,8 @@ static void intel_finish_crtc_commit(struct drm_crtc *crtc,
>  
>  	if (new_crtc_state->update_pipe &&
>  	    !needs_modeset(&new_crtc_state->base) &&
> -	    old_crtc_state->mode.private_flags & I915_MODE_FLAG_INHERITED) {
> -		if (!IS_GEN2(dev_priv))
> -			intel_set_cpu_fifo_underrun_reporting(dev_priv, intel_crtc->pipe, true);
> -
> -		if (new_crtc_state->has_pch_encoder) {
> -			enum pipe pch_transcoder =
> -				intel_crtc_pch_transcoder(intel_crtc);
> -
> -			intel_set_pch_fifo_underrun_reporting(dev_priv, pch_transcoder, true);
> -		}
> -	}
> +	    old_crtc_state->mode.private_flags & I915_MODE_FLAG_INHERITED)
> +		intel_crtc_arm_fifo_underrun(intel_crtc, new_crtc_state);
>  }
>  
>  /**
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index d1452fd2a58d..ca005c989e9f 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -1592,6 +1592,8 @@ void hsw_disable_ips(const struct intel_crtc_state *crtc_state);
>  enum intel_display_power_domain intel_port_to_power_domain(enum port port);
>  void intel_mode_from_pipe_config(struct drm_display_mode *mode,
>  				 struct intel_crtc_state *pipe_config);
> +void intel_crtc_arm_fifo_underrun(struct intel_crtc *crtc,
> +				  struct intel_crtc_state *crtc_state);
>  
>  int skl_update_scaler_crtc(struct intel_crtc_state *crtc_state);
>  int skl_max_scale(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state);
> @@ -1777,6 +1779,7 @@ void intel_fbc_flush(struct drm_i915_private *dev_priv,
>  		     unsigned int frontbuffer_bits, enum fb_op_origin origin);
>  void intel_fbc_cleanup_cfb(struct drm_i915_private *dev_priv);
>  void intel_fbc_handle_fifo_underrun_irq(struct drm_i915_private *dev_priv);
> +int intel_fbc_reset_underrun(struct drm_i915_private *dev_priv);
>  
>  /* intel_hdmi.c */
>  void intel_hdmi_init(struct drm_i915_private *dev_priv, i915_reg_t hdmi_reg,
> diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c
> index 707d49c12638..308bdd136d33 100644
> --- a/drivers/gpu/drm/i915/intel_fbc.c
> +++ b/drivers/gpu/drm/i915/intel_fbc.c
> @@ -1272,6 +1272,32 @@ static void intel_fbc_underrun_work_fn(struct work_struct *work)
>  	mutex_unlock(&fbc->lock);
>  }
>  
> +/*
> + * intel_fbc_reset_underrun - reset FBC fifo underrun status.
> + * @dev_priv: i915 device instance
> + *
> + * See intel_fbc_handle_fifo_underrun_irq(). For automated testing we
> + * want to re-enable FBC after an underrun to increase test coverage.
> + */
> +int intel_fbc_reset_underrun(struct drm_i915_private *dev_priv)
> +{
> +	int ret;
> +
> +	cancel_work_sync(&dev_priv->fbc.underrun_work);
> +
> +	ret = mutex_lock_interruptible(&dev_priv->fbc.lock);
> +	if (ret)
> +		return ret;
> +
> +	if (dev_priv->fbc.underrun_detected)
> +		DRM_DEBUG_KMS("Re-allowing FBC after fifo underrun\n");
> +
> +	dev_priv->fbc.underrun_detected = false;
> +	mutex_unlock(&dev_priv->fbc.lock);
> +
> +	return 0;
> +}
> +
>  /**
>   * intel_fbc_handle_fifo_underrun_irq - disable FBC when we get a FIFO underrun
>   * @dev_priv: i915 device instance
Maarten Lankhorst March 28, 2018, 4:20 p.m. UTC | #2
Op 28-03-18 om 12:21 schreef Jani Nikula:
> On Wed, 28 Mar 2018, Maarten Lankhorst <maarten.lankhorst@linux.intel.com> wrote:
>> Adding a i915_fifo_underrun_reset debugfs file will make it possible
>> for IGT tests to clear FIFO underrun fallout at the start of each
>> subtest, and make re-enable FBC so tests always have maximum exposure
>> to features used by IGT. FIFO underruns and FBC bugs will no longer
>> hide when an earlier subtests disables both.
>>
>> Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
>> Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=105685
>> Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=105681
> FWIW, ack on the idea, didn't look at the implementation.
Well I had a NV12 test that produced FIFO underruns, did some quick testing against the i915_fifo_underrun_reset file and manually writing it does reset FIFO underruns.
Immediately after i915_fbc_status still reads "FBC disabled: underrun detected", but this is cleared by the next atomic commit. So I think it works, and can be used for igt in the way I wrote it.

~Maarten
Rodrigo Vivi April 9, 2018, 7:48 p.m. UTC | #3
On Wed, Mar 28, 2018 at 06:20:26PM +0200, Maarten Lankhorst wrote:
> Op 28-03-18 om 12:21 schreef Jani Nikula:
> > On Wed, 28 Mar 2018, Maarten Lankhorst <maarten.lankhorst@linux.intel.com> wrote:
> >> Adding a i915_fifo_underrun_reset debugfs file will make it possible
> >> for IGT tests to clear FIFO underrun fallout at the start of each
> >> subtest, and make re-enable FBC so tests always have maximum exposure
> >> to features used by IGT. FIFO underruns and FBC bugs will no longer
> >> hide when an earlier subtests disables both.
> >>
> >> Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
> >> Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=105685
> >> Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=105681
> > FWIW, ack on the idea, didn't look at the implementation.
> Well I had a NV12 test that produced FIFO underruns, did some quick testing against the i915_fifo_underrun_reset file and manually writing it does reset FIFO underruns.
> Immediately after i915_fbc_status still reads "FBC disabled: underrun detected", but this is cleared by the next atomic commit. So I think it works, and can be used for igt in the way I wrote it.

What about a error message change on fbc_status to reflect this temporary state?
Just to avoid later confusion on expectation.

But the approach and code look sane for me, so anyways:

Reviewed-by: Rodrigo Vivi <rodrigo.vivi@intel.com>

> 
> ~Maarten
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Maarten Lankhorst April 10, 2018, 2:31 p.m. UTC | #4
Op 09-04-18 om 21:48 schreef Rodrigo Vivi:
> On Wed, Mar 28, 2018 at 06:20:26PM +0200, Maarten Lankhorst wrote:
>> Op 28-03-18 om 12:21 schreef Jani Nikula:
>>> On Wed, 28 Mar 2018, Maarten Lankhorst <maarten.lankhorst@linux.intel.com> wrote:
>>>> Adding a i915_fifo_underrun_reset debugfs file will make it possible
>>>> for IGT tests to clear FIFO underrun fallout at the start of each
>>>> subtest, and make re-enable FBC so tests always have maximum exposure
>>>> to features used by IGT. FIFO underruns and FBC bugs will no longer
>>>> hide when an earlier subtests disables both.
>>>>
>>>> Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
>>>> Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=105685
>>>> Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=105681
>>> FWIW, ack on the idea, didn't look at the implementation.
>> Well I had a NV12 test that produced FIFO underruns, did some quick testing against the i915_fifo_underrun_reset file and manually writing it does reset FIFO underruns.
>> Immediately after i915_fbc_status still reads "FBC disabled: underrun detected", but this is cleared by the next atomic commit. So I think it works, and can be used for igt in the way I wrote it.
> What about a error message change on fbc_status to reflect this temporary state?
> Just to avoid later confusion on expectation.
Done, if an underrun is cleared, the reason will be set to 'FIFO underrun cleared'.
> But the approach and code look sane for me, so anyways:
>
> Reviewed-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
Thanks for reviewing, pushed. :)
diff mbox

Patch

diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index 7816cd53100a..27188de2c32b 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -4731,6 +4731,67 @@  static int i915_drrs_ctl_set(void *data, u64 val)
 
 DEFINE_SIMPLE_ATTRIBUTE(i915_drrs_ctl_fops, NULL, i915_drrs_ctl_set, "%llu\n");
 
+static ssize_t
+i915_fifo_underrun_reset_write(struct file *filp,
+			       const char __user *ubuf,
+			       size_t cnt, loff_t *ppos)
+{
+	struct drm_i915_private *dev_priv = filp->private_data;
+	struct intel_crtc *intel_crtc;
+	struct drm_device *dev = &dev_priv->drm;
+	int ret;
+	bool reset;
+
+	ret = kstrtobool_from_user(ubuf, cnt, &reset);
+	if (ret)
+		return ret;
+
+	if (!reset)
+		return cnt;
+
+	for_each_intel_crtc(dev, intel_crtc) {
+		struct drm_crtc_commit *commit;
+		struct intel_crtc_state *crtc_state;
+
+		ret = drm_modeset_lock_single_interruptible(&intel_crtc->base.mutex);
+		if (ret)
+			return ret;
+
+		crtc_state = to_intel_crtc_state(intel_crtc->base.state);
+		commit = crtc_state->base.commit;
+		if (commit) {
+			ret = wait_for_completion_interruptible(&commit->hw_done);
+			if (!ret)
+				ret = wait_for_completion_interruptible(&commit->flip_done);
+		}
+
+		if (!ret && crtc_state->base.active) {
+			DRM_DEBUG_KMS("Re-arming FIFO underruns on pipe %c\n",
+				      pipe_name(intel_crtc->pipe));
+
+			intel_crtc_arm_fifo_underrun(intel_crtc, crtc_state);
+		}
+
+		drm_modeset_unlock(&intel_crtc->base.mutex);
+
+		if (ret)
+			return ret;
+	}
+
+	ret = intel_fbc_reset_underrun(dev_priv);
+	if (ret)
+		return ret;
+
+	return cnt;
+}
+
+static const struct file_operations i915_fifo_underrun_reset_ops = {
+	.owner = THIS_MODULE,
+	.open = simple_open,
+	.write = i915_fifo_underrun_reset_write,
+	.llseek = default_llseek,
+};
+
 static const struct drm_info_list i915_debugfs_list[] = {
 	{"i915_capabilities", i915_capabilities, 0},
 	{"i915_gem_objects", i915_gem_object_info, 0},
@@ -4798,6 +4859,7 @@  static const struct i915_debugfs_files {
 	{"i915_error_state", &i915_error_state_fops},
 	{"i915_gpu_info", &i915_gpu_info_fops},
 #endif
+	{"i915_fifo_underrun_reset", &i915_fifo_underrun_reset_ops},
 	{"i915_next_seqno", &i915_next_seqno_fops},
 	{"i915_display_crc_ctl", &i915_display_crc_ctl_fops},
 	{"i915_pri_wm_latency", &i915_pri_wm_latency_fops},
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 4c30c7c04f9c..3df0e8193b83 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -12960,10 +12960,25 @@  static void intel_begin_crtc_commit(struct drm_crtc *crtc,
 							   intel_cstate);
 }
 
+void intel_crtc_arm_fifo_underrun(struct intel_crtc *crtc,
+				  struct intel_crtc_state *crtc_state)
+{
+	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+
+	if (!IS_GEN2(dev_priv))
+		intel_set_cpu_fifo_underrun_reporting(dev_priv, crtc->pipe, true);
+
+	if (crtc_state->has_pch_encoder) {
+		enum pipe pch_transcoder =
+			intel_crtc_pch_transcoder(crtc);
+
+		intel_set_pch_fifo_underrun_reporting(dev_priv, pch_transcoder, true);
+	}
+}
+
 static void intel_finish_crtc_commit(struct drm_crtc *crtc,
 				     struct drm_crtc_state *old_crtc_state)
 {
-	struct drm_i915_private *dev_priv = to_i915(crtc->dev);
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	struct intel_atomic_state *old_intel_state =
 		to_intel_atomic_state(old_crtc_state->state);
@@ -12974,17 +12989,8 @@  static void intel_finish_crtc_commit(struct drm_crtc *crtc,
 
 	if (new_crtc_state->update_pipe &&
 	    !needs_modeset(&new_crtc_state->base) &&
-	    old_crtc_state->mode.private_flags & I915_MODE_FLAG_INHERITED) {
-		if (!IS_GEN2(dev_priv))
-			intel_set_cpu_fifo_underrun_reporting(dev_priv, intel_crtc->pipe, true);
-
-		if (new_crtc_state->has_pch_encoder) {
-			enum pipe pch_transcoder =
-				intel_crtc_pch_transcoder(intel_crtc);
-
-			intel_set_pch_fifo_underrun_reporting(dev_priv, pch_transcoder, true);
-		}
-	}
+	    old_crtc_state->mode.private_flags & I915_MODE_FLAG_INHERITED)
+		intel_crtc_arm_fifo_underrun(intel_crtc, new_crtc_state);
 }
 
 /**
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index d1452fd2a58d..ca005c989e9f 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -1592,6 +1592,8 @@  void hsw_disable_ips(const struct intel_crtc_state *crtc_state);
 enum intel_display_power_domain intel_port_to_power_domain(enum port port);
 void intel_mode_from_pipe_config(struct drm_display_mode *mode,
 				 struct intel_crtc_state *pipe_config);
+void intel_crtc_arm_fifo_underrun(struct intel_crtc *crtc,
+				  struct intel_crtc_state *crtc_state);
 
 int skl_update_scaler_crtc(struct intel_crtc_state *crtc_state);
 int skl_max_scale(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state);
@@ -1777,6 +1779,7 @@  void intel_fbc_flush(struct drm_i915_private *dev_priv,
 		     unsigned int frontbuffer_bits, enum fb_op_origin origin);
 void intel_fbc_cleanup_cfb(struct drm_i915_private *dev_priv);
 void intel_fbc_handle_fifo_underrun_irq(struct drm_i915_private *dev_priv);
+int intel_fbc_reset_underrun(struct drm_i915_private *dev_priv);
 
 /* intel_hdmi.c */
 void intel_hdmi_init(struct drm_i915_private *dev_priv, i915_reg_t hdmi_reg,
diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c
index 707d49c12638..308bdd136d33 100644
--- a/drivers/gpu/drm/i915/intel_fbc.c
+++ b/drivers/gpu/drm/i915/intel_fbc.c
@@ -1272,6 +1272,32 @@  static void intel_fbc_underrun_work_fn(struct work_struct *work)
 	mutex_unlock(&fbc->lock);
 }
 
+/*
+ * intel_fbc_reset_underrun - reset FBC fifo underrun status.
+ * @dev_priv: i915 device instance
+ *
+ * See intel_fbc_handle_fifo_underrun_irq(). For automated testing we
+ * want to re-enable FBC after an underrun to increase test coverage.
+ */
+int intel_fbc_reset_underrun(struct drm_i915_private *dev_priv)
+{
+	int ret;
+
+	cancel_work_sync(&dev_priv->fbc.underrun_work);
+
+	ret = mutex_lock_interruptible(&dev_priv->fbc.lock);
+	if (ret)
+		return ret;
+
+	if (dev_priv->fbc.underrun_detected)
+		DRM_DEBUG_KMS("Re-allowing FBC after fifo underrun\n");
+
+	dev_priv->fbc.underrun_detected = false;
+	mutex_unlock(&dev_priv->fbc.lock);
+
+	return 0;
+}
+
 /**
  * intel_fbc_handle_fifo_underrun_irq - disable FBC when we get a FIFO underrun
  * @dev_priv: i915 device instance