drm/i915: Restore GT performance in headless mode with DMC loaded
authorTvrtko Ursulin <tvrtko.ursulin@intel.com>
Tue, 5 Dec 2017 13:28:54 +0000 (13:28 +0000)
committerImre Deak <imre.deak@intel.com>
Fri, 8 Dec 2017 10:23:07 +0000 (12:23 +0200)
It seems that the DMC likes to transition between the DC states a lot when
there are no connected displays (no active power domains) during command
submission.

This activity on DC states has a negative impact on the performance of the
chip with huge latencies observed in the interrupt handlers and elsewhere.
Simple tests like igt/gem_latency -n 0 are slowed down by a factor of
eight.

Work around it by introducing a new power domain named,
POWER_DOMAIN_GT_IRQ, associtated with the "DC off" power well, which is
held for the duration of command submission activity.

CNL has the same problem which will be addressed as a follow-up. Doing
that requires a fix for a DC6 context corruption problem in the CNL DMC
firmware which is yet to be released.

v2:
 * Add commit text as comment in i915_gem_mark_busy. (Chris Wilson)
 * Protect macro body with braces. (Jani Nikula)

v3:
 * Add dedicated power domain for clarity. (Chris, Imre)
 * Commit message and comment text updates.
 * Apply to all big-core GEN9 parts apart for Skylake which is pending DMC
   firmware release.

v4:
 * Power domain should be inner to device runtime pm. (Chris)
 * Simplify NEEDS_CSR_GT_PERF_WA macro. (Chris)
 * Handle async DMC loading by moving the GT_IRQ power domain logic into
   intel_runtime_pm. (Daniel, Chris)
 * Include small core GEN9 as well. (Imre)

v5
 * Special handling for async DMC load is not needed since on failure the
   power domain reference is kept permanently taken. (Imre)

v6:
 * Drop the NEEDS_CSR_GT_PERF_WA macro since all firmwares have now been
   deployed. (Imre, Chris)

Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=100572
Testcase: igt/gem_exec_nop/headless
Cc: Imre Deak <imre.deak@intel.com>
Acked-by: Chris Wilson <chris@chris-wilson.co.uk> (v2)
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Dmitry Rogozhkin <dmitry.v.rogozhkin@intel.com>
Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch> (v5)
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
[Imre: Add note about applying the WA on CNL as a follow-up]
Signed-off-by: Imre Deak <imre.deak@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20171205132854.26380-1-tvrtko.ursulin@linux.intel.com
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_gem.c
drivers/gpu/drm/i915/i915_gem_request.c
drivers/gpu/drm/i915/intel_runtime_pm.c

index f9386e793c8709f15d463c51ab156d87cac4ef3f..d57859cfad8eec428e88f7daacdadcc59f284c26 100644 (file)
@@ -398,6 +398,7 @@ enum intel_display_power_domain {
        POWER_DOMAIN_AUX_D,
        POWER_DOMAIN_GMBUS,
        POWER_DOMAIN_MODESET,
+       POWER_DOMAIN_GT_IRQ,
        POWER_DOMAIN_INIT,
 
        POWER_DOMAIN_NUM,
index c7b5db78fbb48d5efbb96b16a229637d75e3a1d7..fcc9b53864f0ad4646774b24f34be27f07c0a5ba 100644 (file)
@@ -3386,6 +3386,9 @@ i915_gem_idle_work_handler(struct work_struct *work)
 
        if (INTEL_GEN(dev_priv) >= 6)
                gen6_rps_idle(dev_priv);
+
+       intel_display_power_put(dev_priv, POWER_DOMAIN_GT_IRQ);
+
        intel_runtime_pm_put(dev_priv);
 out_unlock:
        mutex_unlock(&dev_priv->drm.struct_mutex);
index a90bdd26571f58cffe8300d1a1b74eebf3c6005b..c28a4ceb016df2daa949db31805213aec2620182 100644 (file)
@@ -252,6 +252,20 @@ static void mark_busy(struct drm_i915_private *i915)
        GEM_BUG_ON(!i915->gt.active_requests);
 
        intel_runtime_pm_get_noresume(i915);
+
+       /*
+        * It seems that the DMC likes to transition between the DC states a lot
+        * when there are no connected displays (no active power domains) during
+        * command submission.
+        *
+        * This activity has negative impact on the performance of the chip with
+        * huge latencies observed in the interrupt handler and elsewhere.
+        *
+        * Work around it by grabbing a GT IRQ power domain whilst there is any
+        * GT activity, preventing any DC state transitions.
+        */
+       intel_display_power_get(i915, POWER_DOMAIN_GT_IRQ);
+
        i915->gt.awake = true;
 
        intel_enable_gt_powersave(i915);
index 8315499452dc91494284455229d3f15ca6c9bac3..96ab74f3d101c1b3673324704d4fed6b2ef09c2a 100644 (file)
@@ -130,6 +130,8 @@ intel_display_power_domain_str(enum intel_display_power_domain domain)
                return "INIT";
        case POWER_DOMAIN_MODESET:
                return "MODESET";
+       case POWER_DOMAIN_GT_IRQ:
+               return "GT_IRQ";
        default:
                MISSING_CASE(domain);
                return "?";
@@ -1705,6 +1707,7 @@ void intel_display_power_put(struct drm_i915_private *dev_priv,
        BIT_ULL(POWER_DOMAIN_INIT))
 #define SKL_DISPLAY_DC_OFF_POWER_DOMAINS (             \
        SKL_DISPLAY_POWERWELL_2_POWER_DOMAINS |         \
+       BIT_ULL(POWER_DOMAIN_GT_IRQ) |                  \
        BIT_ULL(POWER_DOMAIN_MODESET) |                 \
        BIT_ULL(POWER_DOMAIN_AUX_A) |                   \
        BIT_ULL(POWER_DOMAIN_INIT))
@@ -1727,6 +1730,7 @@ void intel_display_power_put(struct drm_i915_private *dev_priv,
        BIT_ULL(POWER_DOMAIN_INIT))
 #define BXT_DISPLAY_DC_OFF_POWER_DOMAINS (             \
        BXT_DISPLAY_POWERWELL_2_POWER_DOMAINS |         \
+       BIT_ULL(POWER_DOMAIN_GT_IRQ) |                  \
        BIT_ULL(POWER_DOMAIN_MODESET) |                 \
        BIT_ULL(POWER_DOMAIN_AUX_A) |                   \
        BIT_ULL(POWER_DOMAIN_INIT))
@@ -1785,6 +1789,7 @@ void intel_display_power_put(struct drm_i915_private *dev_priv,
        BIT_ULL(POWER_DOMAIN_INIT))
 #define GLK_DISPLAY_DC_OFF_POWER_DOMAINS (             \
        GLK_DISPLAY_POWERWELL_2_POWER_DOMAINS |         \
+       BIT_ULL(POWER_DOMAIN_GT_IRQ) |                  \
        BIT_ULL(POWER_DOMAIN_MODESET) |                 \
        BIT_ULL(POWER_DOMAIN_AUX_A) |                   \
        BIT_ULL(POWER_DOMAIN_INIT))