Skip to content

Commit 7e34f4e

Browse files
ideakjbloomfi-intel
authored andcommitted
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 <[email protected]> Signed-off-by: Mika Kuoppala <[email protected]>
1 parent 1d85a29 commit 7e34f4e

File tree

6 files changed

+135
-4
lines changed

6 files changed

+135
-4
lines changed

drivers/gpu/drm/i915/gt/intel_gt_pm.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@ static int __gt_unpark(struct intel_wakeref *wf)
3838
gt->awake = intel_display_power_get(i915, POWER_DOMAIN_GT_IRQ);
3939
GEM_BUG_ON(!gt->awake);
4040

41+
if (NEEDS_RC6_CTX_CORRUPTION_WA(i915))
42+
intel_uncore_forcewake_get(&i915->uncore, FORCEWAKE_ALL);
43+
4144
intel_enable_gt_powersave(i915);
4245

4346
i915_update_gfx_val(i915);
@@ -67,6 +70,11 @@ static int __gt_park(struct intel_wakeref *wf)
6770
if (INTEL_GEN(i915) >= 6)
6871
gen6_rps_idle(i915);
6972

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+
7078
/* Everything switched off, flush any residual interrupt just in case */
7179
intel_synchronize_irq(i915);
7280

drivers/gpu/drm/i915/i915_drv.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1850,6 +1850,8 @@ static int i915_drm_suspend_late(struct drm_device *dev, bool hibernation)
18501850

18511851
i915_gem_suspend_late(dev_priv);
18521852

1853+
i915_rc6_ctx_wa_suspend(dev_priv);
1854+
18531855
intel_uncore_suspend(&dev_priv->uncore);
18541856

18551857
intel_power_domains_suspend(dev_priv,
@@ -2053,6 +2055,8 @@ static int i915_drm_resume_early(struct drm_device *dev)
20532055

20542056
intel_power_domains_resume(dev_priv);
20552057

2058+
i915_rc6_ctx_wa_resume(dev_priv);
2059+
20562060
intel_gt_sanitize(&dev_priv->gt, true);
20572061

20582062
enable_rpm_wakeref_asserts(&dev_priv->runtime_pm);

drivers/gpu/drm/i915/i915_drv.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -593,6 +593,8 @@ struct intel_rps {
593593

594594
struct intel_rc6 {
595595
bool enabled;
596+
bool ctx_corrupted;
597+
intel_wakeref_t ctx_corrupted_wakeref;
596598
u64 prev_hw_residency[4];
597599
u64 cur_residency[4];
598600
};
@@ -2117,10 +2119,12 @@ IS_SUBPLATFORM(const struct drm_i915_private *i915,
21172119
/* Early gen2 have a totally busted CS tlb and require pinned batches. */
21182120
#define HAS_BROKEN_CS_TLB(dev_priv) (IS_I830(dev_priv) || IS_I845G(dev_priv))
21192121

2122+
#define NEEDS_RC6_CTX_CORRUPTION_WA(dev_priv) \
2123+
(IS_BROADWELL(dev_priv) || IS_GEN(dev_priv, 9))
2124+
21202125
/* WaRsDisableCoarsePowerGating:skl,cnl */
21212126
#define NEEDS_WaRsDisableCoarsePowerGating(dev_priv) \
2122-
(IS_CANNONLAKE(dev_priv) || \
2123-
IS_SKL_GT3(dev_priv) || IS_SKL_GT4(dev_priv))
2127+
(IS_CANNONLAKE(dev_priv) || IS_GEN(dev_priv, 9))
21242128

21252129
#define HAS_GMBUS_IRQ(dev_priv) (INTEL_GEN(dev_priv) >= 4)
21262130
#define HAS_GMBUS_BURST_READ(dev_priv) (INTEL_GEN(dev_priv) >= 10 || \

drivers/gpu/drm/i915/i915_reg.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -471,6 +471,8 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg)
471471
#define ECOCHK_PPGTT_WT_HSW (0x2 << 3)
472472
#define ECOCHK_PPGTT_WB_HSW (0x3 << 3)
473473

474+
#define GEN8_RC6_CTX_INFO _MMIO(0x8504)
475+
474476
#define GAC_ECO_BITS _MMIO(0x14090)
475477
#define ECOBITS_SNB_BIT (1 << 13)
476478
#define ECOBITS_PPGTT_CACHE64B (3 << 8)

drivers/gpu/drm/i915/intel_pm.c

Lines changed: 112 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8552,6 +8552,100 @@ static void intel_init_emon(struct drm_i915_private *dev_priv)
85528552
dev_priv->ips.corr = (lcfuse & LCFUSE_HIV_MASK);
85538553
}
85548554

8555+
static bool i915_rc6_ctx_corrupted(struct drm_i915_private *dev_priv)
8556+
{
8557+
return !I915_READ(GEN8_RC6_CTX_INFO);
8558+
}
8559+
8560+
static 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+
8573+
static 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+
*/
8588+
void 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+
*/
8601+
void 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+
8616+
static 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+
*/
8628+
bool 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+
85558649
void intel_init_gt_powersave(struct drm_i915_private *dev_priv)
85568650
{
85578651
struct intel_rps *rps = &dev_priv->gt_pm.rps;
@@ -8565,6 +8659,8 @@ void intel_init_gt_powersave(struct drm_i915_private *dev_priv)
85658659
pm_runtime_get(&dev_priv->drm.pdev->dev);
85668660
}
85678661

8662+
i915_rc6_ctx_wa_init(dev_priv);
8663+
85688664
/* Initialize RPS limits (for userspace) */
85698665
if (IS_CHERRYVIEW(dev_priv))
85708666
cherryview_init_gt_powersave(dev_priv);
@@ -8603,6 +8699,8 @@ void intel_cleanup_gt_powersave(struct drm_i915_private *dev_priv)
86038699
if (IS_VALLEYVIEW(dev_priv))
86048700
valleyview_cleanup_gt_powersave(dev_priv);
86058701

8702+
i915_rc6_ctx_wa_cleanup(dev_priv);
8703+
86068704
if (!HAS_RC6(dev_priv))
86078705
pm_runtime_put(&dev_priv->drm.pdev->dev);
86088706
}
@@ -8631,7 +8729,7 @@ static inline void intel_disable_llc_pstate(struct drm_i915_private *i915)
86318729
i915->gt_pm.llc_pstate.enabled = false;
86328730
}
86338731

8634-
static void intel_disable_rc6(struct drm_i915_private *dev_priv)
8732+
static void __intel_disable_rc6(struct drm_i915_private *dev_priv)
86358733
{
86368734
lockdep_assert_held(&dev_priv->gt_pm.rps.lock);
86378735

@@ -8650,6 +8748,15 @@ static void intel_disable_rc6(struct drm_i915_private *dev_priv)
86508748
dev_priv->gt_pm.rc6.enabled = false;
86518749
}
86528750

8751+
static 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+
86538760
static void intel_disable_rps(struct drm_i915_private *dev_priv)
86548761
{
86558762
lockdep_assert_held(&dev_priv->gt_pm.rps.lock);
@@ -8675,7 +8782,7 @@ void intel_disable_gt_powersave(struct drm_i915_private *dev_priv)
86758782
{
86768783
mutex_lock(&dev_priv->gt_pm.rps.lock);
86778784

8678-
intel_disable_rc6(dev_priv);
8785+
__intel_disable_rc6(dev_priv);
86798786
intel_disable_rps(dev_priv);
86808787
if (HAS_LLC(dev_priv))
86818788
intel_disable_llc_pstate(dev_priv);
@@ -8702,6 +8809,9 @@ static void intel_enable_rc6(struct drm_i915_private *dev_priv)
87028809
if (dev_priv->gt_pm.rc6.enabled)
87038810
return;
87048811

8812+
if (dev_priv->gt_pm.rc6.ctx_corrupted)
8813+
return;
8814+
87058815
if (IS_CHERRYVIEW(dev_priv))
87068816
cherryview_enable_rc6(dev_priv);
87078817
else if (IS_VALLEYVIEW(dev_priv))

drivers/gpu/drm/i915/intel_pm.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@ void intel_cleanup_gt_powersave(struct drm_i915_private *dev_priv);
3636
void intel_sanitize_gt_powersave(struct drm_i915_private *dev_priv);
3737
void intel_enable_gt_powersave(struct drm_i915_private *dev_priv);
3838
void intel_disable_gt_powersave(struct drm_i915_private *dev_priv);
39+
bool i915_rc6_ctx_wa_check(struct drm_i915_private *i915);
40+
void i915_rc6_ctx_wa_suspend(struct drm_i915_private *i915);
41+
void i915_rc6_ctx_wa_resume(struct drm_i915_private *i915);
3942
void gen6_rps_busy(struct drm_i915_private *dev_priv);
4043
void gen6_rps_idle(struct drm_i915_private *dev_priv);
4144
void gen6_rps_boost(struct i915_request *rq);

0 commit comments

Comments
 (0)