summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorImre Deak <imre.deak@intel.com>2018-07-09 11:24:27 -0400
committerJon Bloomfield <jon.bloomfield@intel.com>2019-11-05 14:43:07 -0500
commit7e34f4e4aad3fd34c02b294a3cf2321adf5b4438 (patch)
tree309a2f84fac09bf9e294dbeb4dd49d6c1d71ce48
parent1d85a299c4db57c55e0229615132c964d17aa765 (diff)
drm/i915/gen8+: Add RC6 CTX corruption WA
In some circumstances the RC6 context can get corrupted. We can detect this and take the required action, that is disable RC6 and runtime PM. The HW recovers from the corrupted state after a system suspend/resume cycle, so detect the recovery and re-enable RC6 and runtime PM. v2: rebase (Mika) v3: - Move intel_suspend_gt_powersave() to the end of the GEM suspend sequence. - Add commit message. v4: - Rebased on intel_uncore_forcewake_put(i915->uncore, ...) API change. v5: rebased on gem/gt split (Mika) Signed-off-by: Imre Deak <imre.deak@intel.com> Signed-off-by: Mika Kuoppala <mika.kuoppala@linux.intel.com>
-rw-r--r--drivers/gpu/drm/i915/gt/intel_gt_pm.c8
-rw-r--r--drivers/gpu/drm/i915/i915_drv.c4
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h8
-rw-r--r--drivers/gpu/drm/i915/i915_reg.h2
-rw-r--r--drivers/gpu/drm/i915/intel_pm.c114
-rw-r--r--drivers/gpu/drm/i915/intel_pm.h3
6 files changed, 135 insertions, 4 deletions
diff --git a/drivers/gpu/drm/i915/gt/intel_gt_pm.c b/drivers/gpu/drm/i915/gt/intel_gt_pm.c
index 1363e069ec83..fac75afed35b 100644
--- a/drivers/gpu/drm/i915/gt/intel_gt_pm.c
+++ b/drivers/gpu/drm/i915/gt/intel_gt_pm.c
@@ -38,6 +38,9 @@ static int __gt_unpark(struct intel_wakeref *wf)
38 gt->awake = intel_display_power_get(i915, POWER_DOMAIN_GT_IRQ); 38 gt->awake = intel_display_power_get(i915, POWER_DOMAIN_GT_IRQ);
39 GEM_BUG_ON(!gt->awake); 39 GEM_BUG_ON(!gt->awake);
40 40
41 if (NEEDS_RC6_CTX_CORRUPTION_WA(i915))
42 intel_uncore_forcewake_get(&i915->uncore, FORCEWAKE_ALL);
43
41 intel_enable_gt_powersave(i915); 44 intel_enable_gt_powersave(i915);
42 45
43 i915_update_gfx_val(i915); 46 i915_update_gfx_val(i915);
@@ -67,6 +70,11 @@ static int __gt_park(struct intel_wakeref *wf)
67 if (INTEL_GEN(i915) >= 6) 70 if (INTEL_GEN(i915) >= 6)
68 gen6_rps_idle(i915); 71 gen6_rps_idle(i915);
69 72
73 if (NEEDS_RC6_CTX_CORRUPTION_WA(i915)) {
74 i915_rc6_ctx_wa_check(i915);
75 intel_uncore_forcewake_put(&i915->uncore, FORCEWAKE_ALL);
76 }
77
70 /* Everything switched off, flush any residual interrupt just in case */ 78 /* Everything switched off, flush any residual interrupt just in case */
71 intel_synchronize_irq(i915); 79 intel_synchronize_irq(i915);
72 80
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index bb6f86c7067a..fe4d7cabfdf1 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -1850,6 +1850,8 @@ static int i915_drm_suspend_late(struct drm_device *dev, bool hibernation)
1850 1850
1851 i915_gem_suspend_late(dev_priv); 1851 i915_gem_suspend_late(dev_priv);
1852 1852
1853 i915_rc6_ctx_wa_suspend(dev_priv);
1854
1853 intel_uncore_suspend(&dev_priv->uncore); 1855 intel_uncore_suspend(&dev_priv->uncore);
1854 1856
1855 intel_power_domains_suspend(dev_priv, 1857 intel_power_domains_suspend(dev_priv,
@@ -2053,6 +2055,8 @@ static int i915_drm_resume_early(struct drm_device *dev)
2053 2055
2054 intel_power_domains_resume(dev_priv); 2056 intel_power_domains_resume(dev_priv);
2055 2057
2058 i915_rc6_ctx_wa_resume(dev_priv);
2059
2056 intel_gt_sanitize(&dev_priv->gt, true); 2060 intel_gt_sanitize(&dev_priv->gt, true);
2057 2061
2058 enable_rpm_wakeref_asserts(&dev_priv->runtime_pm); 2062 enable_rpm_wakeref_asserts(&dev_priv->runtime_pm);
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index b20424e66097..89b6112bd66b 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -593,6 +593,8 @@ struct intel_rps {
593 593
594struct intel_rc6 { 594struct intel_rc6 {
595 bool enabled; 595 bool enabled;
596 bool ctx_corrupted;
597 intel_wakeref_t ctx_corrupted_wakeref;
596 u64 prev_hw_residency[4]; 598 u64 prev_hw_residency[4];
597 u64 cur_residency[4]; 599 u64 cur_residency[4];
598}; 600};
@@ -2117,10 +2119,12 @@ IS_SUBPLATFORM(const struct drm_i915_private *i915,
2117/* Early gen2 have a totally busted CS tlb and require pinned batches. */ 2119/* Early gen2 have a totally busted CS tlb and require pinned batches. */
2118#define HAS_BROKEN_CS_TLB(dev_priv) (IS_I830(dev_priv) || IS_I845G(dev_priv)) 2120#define HAS_BROKEN_CS_TLB(dev_priv) (IS_I830(dev_priv) || IS_I845G(dev_priv))
2119 2121
2122#define NEEDS_RC6_CTX_CORRUPTION_WA(dev_priv) \
2123 (IS_BROADWELL(dev_priv) || IS_GEN(dev_priv, 9))
2124
2120/* WaRsDisableCoarsePowerGating:skl,cnl */ 2125/* WaRsDisableCoarsePowerGating:skl,cnl */
2121#define NEEDS_WaRsDisableCoarsePowerGating(dev_priv) \ 2126#define NEEDS_WaRsDisableCoarsePowerGating(dev_priv) \
2122 (IS_CANNONLAKE(dev_priv) || \ 2127 (IS_CANNONLAKE(dev_priv) || IS_GEN(dev_priv, 9))
2123 IS_SKL_GT3(dev_priv) || IS_SKL_GT4(dev_priv))
2124 2128
2125#define HAS_GMBUS_IRQ(dev_priv) (INTEL_GEN(dev_priv) >= 4) 2129#define HAS_GMBUS_IRQ(dev_priv) (INTEL_GEN(dev_priv) >= 4)
2126#define HAS_GMBUS_BURST_READ(dev_priv) (INTEL_GEN(dev_priv) >= 10 || \ 2130#define HAS_GMBUS_BURST_READ(dev_priv) (INTEL_GEN(dev_priv) >= 10 || \
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 9b76d63cc1ac..f8ee9aba3955 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -471,6 +471,8 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg)
471#define ECOCHK_PPGTT_WT_HSW (0x2 << 3) 471#define ECOCHK_PPGTT_WT_HSW (0x2 << 3)
472#define ECOCHK_PPGTT_WB_HSW (0x3 << 3) 472#define ECOCHK_PPGTT_WB_HSW (0x3 << 3)
473 473
474#define GEN8_RC6_CTX_INFO _MMIO(0x8504)
475
474#define GAC_ECO_BITS _MMIO(0x14090) 476#define GAC_ECO_BITS _MMIO(0x14090)
475#define ECOBITS_SNB_BIT (1 << 13) 477#define ECOBITS_SNB_BIT (1 << 13)
476#define ECOBITS_PPGTT_CACHE64B (3 << 8) 478#define ECOBITS_PPGTT_CACHE64B (3 << 8)
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index b5903ee25dea..2efe1d12d5a9 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -8552,6 +8552,100 @@ static void intel_init_emon(struct drm_i915_private *dev_priv)
8552 dev_priv->ips.corr = (lcfuse & LCFUSE_HIV_MASK); 8552 dev_priv->ips.corr = (lcfuse & LCFUSE_HIV_MASK);
8553} 8553}
8554 8554
8555static bool i915_rc6_ctx_corrupted(struct drm_i915_private *dev_priv)
8556{
8557 return !I915_READ(GEN8_RC6_CTX_INFO);
8558}
8559
8560static void i915_rc6_ctx_wa_init(struct drm_i915_private *i915)
8561{
8562 if (!NEEDS_RC6_CTX_CORRUPTION_WA(i915))
8563 return;
8564
8565 if (i915_rc6_ctx_corrupted(i915)) {
8566 DRM_INFO("RC6 context corrupted, disabling runtime power management\n");
8567 i915->gt_pm.rc6.ctx_corrupted = true;
8568 i915->gt_pm.rc6.ctx_corrupted_wakeref =
8569 intel_runtime_pm_get(&i915->runtime_pm);
8570 }
8571}
8572
8573static void i915_rc6_ctx_wa_cleanup(struct drm_i915_private *i915)
8574{
8575 if (i915->gt_pm.rc6.ctx_corrupted) {
8576 intel_runtime_pm_put(&i915->runtime_pm,
8577 i915->gt_pm.rc6.ctx_corrupted_wakeref);
8578 i915->gt_pm.rc6.ctx_corrupted = false;
8579 }
8580}
8581
8582/**
8583 * i915_rc6_ctx_wa_suspend - system suspend sequence for the RC6 CTX WA
8584 * @i915: i915 device
8585 *
8586 * Perform any steps needed to clean up the RC6 CTX WA before system suspend.
8587 */
8588void i915_rc6_ctx_wa_suspend(struct drm_i915_private *i915)
8589{
8590 if (i915->gt_pm.rc6.ctx_corrupted)
8591 intel_runtime_pm_put(&i915->runtime_pm,
8592 i915->gt_pm.rc6.ctx_corrupted_wakeref);
8593}
8594
8595/**
8596 * i915_rc6_ctx_wa_resume - system resume sequence for the RC6 CTX WA
8597 * @i915: i915 device
8598 *
8599 * Perform any steps needed to re-init the RC6 CTX WA after system resume.
8600 */
8601void i915_rc6_ctx_wa_resume(struct drm_i915_private *i915)
8602{
8603 if (!i915->gt_pm.rc6.ctx_corrupted)
8604 return;
8605
8606 if (i915_rc6_ctx_corrupted(i915)) {
8607 i915->gt_pm.rc6.ctx_corrupted_wakeref =
8608 intel_runtime_pm_get(&i915->runtime_pm);
8609 return;
8610 }
8611
8612 DRM_INFO("RC6 context restored, re-enabling runtime power management\n");
8613 i915->gt_pm.rc6.ctx_corrupted = false;
8614}
8615
8616static void intel_disable_rc6(struct drm_i915_private *dev_priv);
8617
8618/**
8619 * i915_rc6_ctx_wa_check - check for a new RC6 CTX corruption
8620 * @i915: i915 device
8621 *
8622 * Check if an RC6 CTX corruption has happened since the last check and if so
8623 * disable RC6 and runtime power management.
8624 *
8625 * Return false if no context corruption has happened since the last call of
8626 * this function, true otherwise.
8627*/
8628bool i915_rc6_ctx_wa_check(struct drm_i915_private *i915)
8629{
8630 if (!NEEDS_RC6_CTX_CORRUPTION_WA(i915))
8631 return false;
8632
8633 if (i915->gt_pm.rc6.ctx_corrupted)
8634 return false;
8635
8636 if (!i915_rc6_ctx_corrupted(i915))
8637 return false;
8638
8639 DRM_NOTE("RC6 context corruption, disabling runtime power management\n");
8640
8641 intel_disable_rc6(i915);
8642 i915->gt_pm.rc6.ctx_corrupted = true;
8643 i915->gt_pm.rc6.ctx_corrupted_wakeref =
8644 intel_runtime_pm_get_noresume(&i915->runtime_pm);
8645
8646 return true;
8647}
8648
8555void intel_init_gt_powersave(struct drm_i915_private *dev_priv) 8649void intel_init_gt_powersave(struct drm_i915_private *dev_priv)
8556{ 8650{
8557 struct intel_rps *rps = &dev_priv->gt_pm.rps; 8651 struct intel_rps *rps = &dev_priv->gt_pm.rps;
@@ -8565,6 +8659,8 @@ void intel_init_gt_powersave(struct drm_i915_private *dev_priv)
8565 pm_runtime_get(&dev_priv->drm.pdev->dev); 8659 pm_runtime_get(&dev_priv->drm.pdev->dev);
8566 } 8660 }
8567 8661
8662 i915_rc6_ctx_wa_init(dev_priv);
8663
8568 /* Initialize RPS limits (for userspace) */ 8664 /* Initialize RPS limits (for userspace) */
8569 if (IS_CHERRYVIEW(dev_priv)) 8665 if (IS_CHERRYVIEW(dev_priv))
8570 cherryview_init_gt_powersave(dev_priv); 8666 cherryview_init_gt_powersave(dev_priv);
@@ -8603,6 +8699,8 @@ void intel_cleanup_gt_powersave(struct drm_i915_private *dev_priv)
8603 if (IS_VALLEYVIEW(dev_priv)) 8699 if (IS_VALLEYVIEW(dev_priv))
8604 valleyview_cleanup_gt_powersave(dev_priv); 8700 valleyview_cleanup_gt_powersave(dev_priv);
8605 8701
8702 i915_rc6_ctx_wa_cleanup(dev_priv);
8703
8606 if (!HAS_RC6(dev_priv)) 8704 if (!HAS_RC6(dev_priv))
8607 pm_runtime_put(&dev_priv->drm.pdev->dev); 8705 pm_runtime_put(&dev_priv->drm.pdev->dev);
8608} 8706}
@@ -8631,7 +8729,7 @@ static inline void intel_disable_llc_pstate(struct drm_i915_private *i915)
8631 i915->gt_pm.llc_pstate.enabled = false; 8729 i915->gt_pm.llc_pstate.enabled = false;
8632} 8730}
8633 8731
8634static void intel_disable_rc6(struct drm_i915_private *dev_priv) 8732static void __intel_disable_rc6(struct drm_i915_private *dev_priv)
8635{ 8733{
8636 lockdep_assert_held(&dev_priv->gt_pm.rps.lock); 8734 lockdep_assert_held(&dev_priv->gt_pm.rps.lock);
8637 8735
@@ -8650,6 +8748,15 @@ static void intel_disable_rc6(struct drm_i915_private *dev_priv)
8650 dev_priv->gt_pm.rc6.enabled = false; 8748 dev_priv->gt_pm.rc6.enabled = false;
8651} 8749}
8652 8750
8751static void intel_disable_rc6(struct drm_i915_private *dev_priv)
8752{
8753 struct intel_rps *rps = &dev_priv->gt_pm.rps;
8754
8755 mutex_lock(&rps->lock);
8756 __intel_disable_rc6(dev_priv);
8757 mutex_unlock(&rps->lock);
8758}
8759
8653static void intel_disable_rps(struct drm_i915_private *dev_priv) 8760static void intel_disable_rps(struct drm_i915_private *dev_priv)
8654{ 8761{
8655 lockdep_assert_held(&dev_priv->gt_pm.rps.lock); 8762 lockdep_assert_held(&dev_priv->gt_pm.rps.lock);
@@ -8675,7 +8782,7 @@ void intel_disable_gt_powersave(struct drm_i915_private *dev_priv)
8675{ 8782{
8676 mutex_lock(&dev_priv->gt_pm.rps.lock); 8783 mutex_lock(&dev_priv->gt_pm.rps.lock);
8677 8784
8678 intel_disable_rc6(dev_priv); 8785 __intel_disable_rc6(dev_priv);
8679 intel_disable_rps(dev_priv); 8786 intel_disable_rps(dev_priv);
8680 if (HAS_LLC(dev_priv)) 8787 if (HAS_LLC(dev_priv))
8681 intel_disable_llc_pstate(dev_priv); 8788 intel_disable_llc_pstate(dev_priv);
@@ -8702,6 +8809,9 @@ static void intel_enable_rc6(struct drm_i915_private *dev_priv)
8702 if (dev_priv->gt_pm.rc6.enabled) 8809 if (dev_priv->gt_pm.rc6.enabled)
8703 return; 8810 return;
8704 8811
8812 if (dev_priv->gt_pm.rc6.ctx_corrupted)
8813 return;
8814
8705 if (IS_CHERRYVIEW(dev_priv)) 8815 if (IS_CHERRYVIEW(dev_priv))
8706 cherryview_enable_rc6(dev_priv); 8816 cherryview_enable_rc6(dev_priv);
8707 else if (IS_VALLEYVIEW(dev_priv)) 8817 else if (IS_VALLEYVIEW(dev_priv))
diff --git a/drivers/gpu/drm/i915/intel_pm.h b/drivers/gpu/drm/i915/intel_pm.h
index e3573e1e16e3..0f7390c850ec 100644
--- a/drivers/gpu/drm/i915/intel_pm.h
+++ b/drivers/gpu/drm/i915/intel_pm.h
@@ -36,6 +36,9 @@ void intel_cleanup_gt_powersave(struct drm_i915_private *dev_priv);
36void intel_sanitize_gt_powersave(struct drm_i915_private *dev_priv); 36void intel_sanitize_gt_powersave(struct drm_i915_private *dev_priv);
37void intel_enable_gt_powersave(struct drm_i915_private *dev_priv); 37void intel_enable_gt_powersave(struct drm_i915_private *dev_priv);
38void intel_disable_gt_powersave(struct drm_i915_private *dev_priv); 38void intel_disable_gt_powersave(struct drm_i915_private *dev_priv);
39bool i915_rc6_ctx_wa_check(struct drm_i915_private *i915);
40void i915_rc6_ctx_wa_suspend(struct drm_i915_private *i915);
41void i915_rc6_ctx_wa_resume(struct drm_i915_private *i915);
39void gen6_rps_busy(struct drm_i915_private *dev_priv); 42void gen6_rps_busy(struct drm_i915_private *dev_priv);
40void gen6_rps_idle(struct drm_i915_private *dev_priv); 43void gen6_rps_idle(struct drm_i915_private *dev_priv);
41void gen6_rps_boost(struct i915_request *rq); 44void gen6_rps_boost(struct i915_request *rq);