Commit d52ad9cb authored by Maarten Lankhorst's avatar Maarten Lankhorst

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

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: default avatarMaarten Lankhorst <maarten.lankhorst@linux.intel.com>
References: https://bugs.freedesktop.org/show_bug.cgi?id=105685
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=105681
Link: https://patchwork.freedesktop.org/patch/msgid/20180328100526.36467-1-maarten.lankhorst@linux.intel.comAcked-by: default avatarJani Nikula <jani.nikula@linux.intel.com>
[mlankhorst: Reset FBC reason if underrun had occurred. (vivijim)]
Reviewed-by: default avatarRodrigo Vivi <rodrigo.vivi@intel.com>
parent daeb725e
...@@ -4732,6 +4732,67 @@ static int i915_drrs_ctl_set(void *data, u64 val) ...@@ -4732,6 +4732,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"); 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[] = { static const struct drm_info_list i915_debugfs_list[] = {
{"i915_capabilities", i915_capabilities, 0}, {"i915_capabilities", i915_capabilities, 0},
{"i915_gem_objects", i915_gem_object_info, 0}, {"i915_gem_objects", i915_gem_object_info, 0},
...@@ -4799,6 +4860,7 @@ static const struct i915_debugfs_files { ...@@ -4799,6 +4860,7 @@ static const struct i915_debugfs_files {
{"i915_error_state", &i915_error_state_fops}, {"i915_error_state", &i915_error_state_fops},
{"i915_gpu_info", &i915_gpu_info_fops}, {"i915_gpu_info", &i915_gpu_info_fops},
#endif #endif
{"i915_fifo_underrun_reset", &i915_fifo_underrun_reset_ops},
{"i915_next_seqno", &i915_next_seqno_fops}, {"i915_next_seqno", &i915_next_seqno_fops},
{"i915_display_crc_ctl", &i915_display_crc_ctl_fops}, {"i915_display_crc_ctl", &i915_display_crc_ctl_fops},
{"i915_pri_wm_latency", &i915_pri_wm_latency_fops}, {"i915_pri_wm_latency", &i915_pri_wm_latency_fops},
......
...@@ -13019,10 +13019,25 @@ static void intel_begin_crtc_commit(struct drm_crtc *crtc, ...@@ -13019,10 +13019,25 @@ static void intel_begin_crtc_commit(struct drm_crtc *crtc,
intel_cstate); 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, static void intel_finish_crtc_commit(struct drm_crtc *crtc,
struct drm_crtc_state *old_crtc_state) 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_crtc *intel_crtc = to_intel_crtc(crtc);
struct intel_atomic_state *old_intel_state = struct intel_atomic_state *old_intel_state =
to_intel_atomic_state(old_crtc_state->state); to_intel_atomic_state(old_crtc_state->state);
...@@ -13033,17 +13048,8 @@ static void intel_finish_crtc_commit(struct drm_crtc *crtc, ...@@ -13033,17 +13048,8 @@ static void intel_finish_crtc_commit(struct drm_crtc *crtc,
if (new_crtc_state->update_pipe && if (new_crtc_state->update_pipe &&
!needs_modeset(&new_crtc_state->base) && !needs_modeset(&new_crtc_state->base) &&
old_crtc_state->mode.private_flags & I915_MODE_FLAG_INHERITED) { old_crtc_state->mode.private_flags & I915_MODE_FLAG_INHERITED)
if (!IS_GEN2(dev_priv)) intel_crtc_arm_fifo_underrun(intel_crtc, new_crtc_state);
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);
}
}
} }
/** /**
......
...@@ -1597,6 +1597,8 @@ void hsw_disable_ips(const struct intel_crtc_state *crtc_state); ...@@ -1597,6 +1597,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); enum intel_display_power_domain intel_port_to_power_domain(enum port port);
void intel_mode_from_pipe_config(struct drm_display_mode *mode, void intel_mode_from_pipe_config(struct drm_display_mode *mode,
struct intel_crtc_state *pipe_config); 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_update_scaler_crtc(struct intel_crtc_state *crtc_state);
int skl_max_scale(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state, int skl_max_scale(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state,
...@@ -1784,6 +1786,7 @@ void intel_fbc_flush(struct drm_i915_private *dev_priv, ...@@ -1784,6 +1786,7 @@ void intel_fbc_flush(struct drm_i915_private *dev_priv,
unsigned int frontbuffer_bits, enum fb_op_origin origin); unsigned int frontbuffer_bits, enum fb_op_origin origin);
void intel_fbc_cleanup_cfb(struct drm_i915_private *dev_priv); void intel_fbc_cleanup_cfb(struct drm_i915_private *dev_priv);
void intel_fbc_handle_fifo_underrun_irq(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 */ /* intel_hdmi.c */
void intel_hdmi_init(struct drm_i915_private *dev_priv, i915_reg_t hdmi_reg, void intel_hdmi_init(struct drm_i915_private *dev_priv, i915_reg_t hdmi_reg,
......
...@@ -1272,6 +1272,34 @@ static void intel_fbc_underrun_work_fn(struct work_struct *work) ...@@ -1272,6 +1272,34 @@ static void intel_fbc_underrun_work_fn(struct work_struct *work)
mutex_unlock(&fbc->lock); 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.no_fbc_reason = "FIFO underrun cleared";
}
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 * intel_fbc_handle_fifo_underrun_irq - disable FBC when we get a FIFO underrun
* @dev_priv: i915 device instance * @dev_priv: i915 device instance
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment