summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/intel_fbc.c
diff options
context:
space:
mode:
authorDave Airlie2016-10-25 08:36:13 +0200
committerDave Airlie2016-10-25 08:39:43 +0200
commit5481e27f6fd06b7cb902072e81d6b083db8155eb (patch)
tree3bef5a7b19a3661e740d33754d1cf981f117ea66 /drivers/gpu/drm/i915/intel_fbc.c
parentMerge tag 'topic/drm-misc-2016-10-24' of git://anongit.freedesktop.org/drm-in... (diff)
parentdrm/i915: Update DRIVER_DATE to 20161024 (diff)
downloadkernel-qcow2-linux-5481e27f6fd06b7cb902072e81d6b083db8155eb.tar.gz
kernel-qcow2-linux-5481e27f6fd06b7cb902072e81d6b083db8155eb.tar.xz
kernel-qcow2-linux-5481e27f6fd06b7cb902072e81d6b083db8155eb.zip
Merge tag 'drm-intel-next-2016-10-24' of git://anongit.freedesktop.org/drm-intel into drm-next
- first slice of the gvt device model (Zhenyu et al) - compression support for gpu error states (Chris) - sunset clause on gpu errors resulting in dmesg noise telling users how to report them - .rodata diet from Tvrtko - switch over lots of macros to only take dev_priv (Tvrtko) - underrun suppression for dp link training (Ville) - lspcon (hmdi 2.0 on skl/bxt) support from Shashank Sharma, polish from Jani - gen9 wm fixes from Paulo&Lyude - updated ddi programming for kbl (Rodrigo) - respect alternate aux/ddc pins (from vbt) for all ddi ports (Ville) * tag 'drm-intel-next-2016-10-24' of git://anongit.freedesktop.org/drm-intel: (227 commits) drm/i915: Update DRIVER_DATE to 20161024 drm/i915: Stop setting SNB min-freq-table 0 on powersave setup drm/i915/dp: add lane_count check in intel_dp_check_link_status drm/i915: Fix whitespace issues drm/i915: Clean up DDI DDC/AUX CH sanitation drm/i915: Respect alternate_ddc_pin for all DDI ports drm/i915: Respect alternate_aux_channel for all DDI ports drm/i915/gen9: Remove WaEnableYV12BugFixInHalfSliceChicken7 drm/i915: KBL - Recommended buffer translation programming for DisplayPort drm/i915: Move down skl/kbl ddi iboost and n_edp_entires fixup drm/i915: Add a sunset clause to GPU hang logging drm/i915: Stop reporting error details in dmesg as well as the error-state drm/i915/gvt: do not ignore return value of create_scratch_page drm/i915/gvt: fix spare warnings on odd constant _Bool cast drm/i915/gvt: mark symbols static where possible drm/i915/gvt: fix sparse warnings on different address spaces drm/i915/gvt: properly access enabled intel_engine_cs drm/i915/gvt: Remove defunct vmap_batch() drm/i915/gvt: Use common mapping routines for shadow_bb object drm/i915/gvt: Use common mapping routines for indirect_ctx object ...
Diffstat (limited to 'drivers/gpu/drm/i915/intel_fbc.c')
-rw-r--r--drivers/gpu/drm/i915/intel_fbc.c67
1 files changed, 67 insertions, 0 deletions
diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c
index afc040be1172..49048d9d7895 100644
--- a/drivers/gpu/drm/i915/intel_fbc.c
+++ b/drivers/gpu/drm/i915/intel_fbc.c
@@ -774,6 +774,14 @@ static bool intel_fbc_can_activate(struct intel_crtc *crtc)
struct intel_fbc *fbc = &dev_priv->fbc;
struct intel_fbc_state_cache *cache = &fbc->state_cache;
+ /* We don't need to use a state cache here since this information is
+ * global for all CRTC.
+ */
+ if (fbc->underrun_detected) {
+ fbc->no_fbc_reason = "underrun detected";
+ return false;
+ }
+
if (!cache->plane.visible) {
fbc->no_fbc_reason = "primary plane not visible";
return false;
@@ -859,6 +867,11 @@ static bool intel_fbc_can_choose(struct intel_crtc *crtc)
return false;
}
+ if (fbc->underrun_detected) {
+ fbc->no_fbc_reason = "underrun detected";
+ return false;
+ }
+
if (fbc_on_pipe_a_only(dev_priv) && crtc->pipe != PIPE_A) {
fbc->no_fbc_reason = "no enabled pipes can have FBC";
return false;
@@ -1221,6 +1234,59 @@ void intel_fbc_global_disable(struct drm_i915_private *dev_priv)
cancel_work_sync(&fbc->work.work);
}
+static void intel_fbc_underrun_work_fn(struct work_struct *work)
+{
+ struct drm_i915_private *dev_priv =
+ container_of(work, struct drm_i915_private, fbc.underrun_work);
+ struct intel_fbc *fbc = &dev_priv->fbc;
+
+ mutex_lock(&fbc->lock);
+
+ /* Maybe we were scheduled twice. */
+ if (fbc->underrun_detected)
+ goto out;
+
+ DRM_DEBUG_KMS("Disabling FBC due to FIFO underrun.\n");
+ fbc->underrun_detected = true;
+
+ intel_fbc_deactivate(dev_priv);
+out:
+ mutex_unlock(&fbc->lock);
+}
+
+/**
+ * intel_fbc_handle_fifo_underrun_irq - disable FBC when we get a FIFO underrun
+ * @dev_priv: i915 device instance
+ *
+ * Without FBC, most underruns are harmless and don't really cause too many
+ * problems, except for an annoying message on dmesg. With FBC, underruns can
+ * become black screens or even worse, especially when paired with bad
+ * watermarks. So in order for us to be on the safe side, completely disable FBC
+ * in case we ever detect a FIFO underrun on any pipe. An underrun on any pipe
+ * already suggests that watermarks may be bad, so try to be as safe as
+ * possible.
+ *
+ * This function is called from the IRQ handler.
+ */
+void intel_fbc_handle_fifo_underrun_irq(struct drm_i915_private *dev_priv)
+{
+ struct intel_fbc *fbc = &dev_priv->fbc;
+
+ if (!fbc_supported(dev_priv))
+ return;
+
+ /* There's no guarantee that underrun_detected won't be set to true
+ * right after this check and before the work is scheduled, but that's
+ * not a problem since we'll check it again under the work function
+ * while FBC is locked. This check here is just to prevent us from
+ * unnecessarily scheduling the work, and it relies on the fact that we
+ * never switch underrun_detect back to false after it's true. */
+ if (READ_ONCE(fbc->underrun_detected))
+ return;
+
+ schedule_work(&fbc->underrun_work);
+}
+
/**
* intel_fbc_init_pipe_state - initialize FBC's CRTC visibility tracking
* @dev_priv: i915 device instance
@@ -1292,6 +1358,7 @@ void intel_fbc_init(struct drm_i915_private *dev_priv)
enum pipe pipe;
INIT_WORK(&fbc->work.work, intel_fbc_work_fn);
+ INIT_WORK(&fbc->underrun_work, intel_fbc_underrun_work_fn);
mutex_init(&fbc->lock);
fbc->enabled = false;
fbc->active = false;