drm/i915: Convert hsw_compute_linetime_wm to use in-flight state
authorMatt Roper <matthew.d.roper@intel.com>
Thu, 3 Dec 2015 19:37:39 +0000 (11:37 -0800)
committerMaarten Lankhorst <maarten.lankhorst@linux.intel.com>
Wed, 6 Jan 2016 10:35:29 +0000 (11:35 +0100)
When watermark calculation was moved up to the atomic check phase, the
code was updated to calculate based on in-flight atomic state rather
than already-committed state.  However the hsw_compute_linetime_wm()
didn't get updated and continued to pull values out of the
currently-committed CRTC state.  On platforms that call this function
(HSW/BDW only), this will cause problems when we go to enable the CRTC
since we'll pull the current mode (off) rather than the mode we're
calculating for and wind up with a divide by zero error.

This was an oversight in commit:

        commit a28170f3389f4e42db95e595b0d86384a79de696
        Author: Matt Roper <matthew.d.roper@intel.com>
        Date:   Thu Sep 24 15:53:16 2015 -0700

            drm/i915: Calculate ILK-style watermarks during atomic check (v3)

Signed-off-by: Matt Roper <matthew.d.roper@intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/1449171462-30763-5-git-send-email-matthew.d.roper@intel.com
Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
drivers/gpu/drm/i915/intel_pm.c

index 02fe081..0f22d11 100644 (file)
@@ -1998,14 +1998,19 @@ static void ilk_compute_wm_level(const struct drm_i915_private *dev_priv,
 }
 
 static uint32_t
-hsw_compute_linetime_wm(struct drm_device *dev, struct drm_crtc *crtc)
+hsw_compute_linetime_wm(struct drm_device *dev,
+                       struct intel_crtc_state *cstate)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-       const struct drm_display_mode *adjusted_mode = &intel_crtc->config->base.adjusted_mode;
+       const struct drm_display_mode *adjusted_mode =
+               &cstate->base.adjusted_mode;
        u32 linetime, ips_linetime;
 
-       if (!intel_crtc->active)
+       if (!cstate->base.active)
+               return 0;
+       if (WARN_ON(adjusted_mode->crtc_clock == 0))
+               return 0;
+       if (WARN_ON(dev_priv->cdclk_freq == 0))
                return 0;
 
        /* The WM are computed with base on how long it takes to fill a single
@@ -2313,8 +2318,7 @@ static int ilk_compute_pipe_wm(struct intel_crtc *intel_crtc,
                             pristate, sprstate, curstate, &pipe_wm->wm[0]);
 
        if (IS_HASWELL(dev) || IS_BROADWELL(dev))
-               pipe_wm->linetime = hsw_compute_linetime_wm(dev,
-                                                           &intel_crtc->base);
+               pipe_wm->linetime = hsw_compute_linetime_wm(dev, cstate);
 
        /* LP0 watermarks always use 1/2 DDB partitioning */
        ilk_compute_wm_maximums(dev, 0, &config, INTEL_DDB_PART_1_2, &max);