Skip to content

Commit 2248a28

Browse files
ideakairlied
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 latest upstream gt_pm refactoring. v6: - s/i915_rc6_/intel_rc6_/ - Don't return a value from i915_rc6_ctx_wa_check(). v7: - Rebased on latest gt rc6 refactoring. Signed-off-by: Imre Deak <[email protected]> Signed-off-by: Mika Kuoppala <[email protected]> [airlied: pull this later version of this patch into drm-next to make resolving the conflict mess easier.] Signed-off-by: Dave Airlie <[email protected]>
1 parent 94bc7f5 commit 2248a28

File tree

7 files changed

+86
-2
lines changed

7 files changed

+86
-2
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
@@ -61,6 +61,9 @@ static int __gt_unpark(struct intel_wakeref *wf)
6161
gt->awake = intel_display_power_get(i915, POWER_DOMAIN_GT_IRQ);
6262
GEM_BUG_ON(!gt->awake);
6363

64+
if (NEEDS_RC6_CTX_CORRUPTION_WA(i915))
65+
intel_uncore_forcewake_get(&i915->uncore, FORCEWAKE_ALL);
66+
6467
intel_rps_unpark(&gt->rps);
6568
i915_pmu_gt_unparked(i915);
6669

@@ -86,6 +89,11 @@ static int __gt_park(struct intel_wakeref *wf)
8689
/* Everything switched off, flush any residual interrupt just in case */
8790
intel_synchronize_irq(i915);
8891

92+
if (NEEDS_RC6_CTX_CORRUPTION_WA(i915)) {
93+
intel_rc6_ctx_wa_check(&i915->gt.rc6);
94+
intel_uncore_forcewake_put(&i915->uncore, FORCEWAKE_ALL);
95+
}
96+
8997
GEM_BUG_ON(!wakeref);
9098
intel_display_power_put(i915, POWER_DOMAIN_GT_IRQ, wakeref);
9199

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

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -486,6 +486,66 @@ static void rpm_put(struct intel_rc6 *rc6)
486486
rc6->wakeref = false;
487487
}
488488

489+
static bool intel_rc6_ctx_corrupted(struct intel_rc6 *rc6)
490+
{
491+
return !intel_uncore_read(rc6_to_uncore(rc6), GEN8_RC6_CTX_INFO);
492+
}
493+
494+
static void intel_rc6_ctx_wa_init(struct intel_rc6 *rc6)
495+
{
496+
struct drm_i915_private *i915 = rc6_to_i915(rc6);
497+
498+
if (!NEEDS_RC6_CTX_CORRUPTION_WA(i915))
499+
return;
500+
501+
if (intel_rc6_ctx_corrupted(rc6)) {
502+
DRM_INFO("RC6 context corrupted, disabling runtime power management\n");
503+
rc6->ctx_corrupted = true;
504+
}
505+
}
506+
507+
/**
508+
* intel_rc6_ctx_wa_resume - system resume sequence for the RC6 CTX WA
509+
* @rc6: rc6 state
510+
*
511+
* Perform any steps needed to re-init the RC6 CTX WA after system resume.
512+
*/
513+
void intel_rc6_ctx_wa_resume(struct intel_rc6 *rc6)
514+
{
515+
if (rc6->ctx_corrupted && !intel_rc6_ctx_corrupted(rc6)) {
516+
DRM_INFO("RC6 context restored, re-enabling runtime power management\n");
517+
rc6->ctx_corrupted = false;
518+
}
519+
}
520+
521+
/**
522+
* intel_rc6_ctx_wa_check - check for a new RC6 CTX corruption
523+
* @rc6: rc6 state
524+
*
525+
* Check if an RC6 CTX corruption has happened since the last check and if so
526+
* disable RC6 and runtime power management.
527+
*/
528+
void intel_rc6_ctx_wa_check(struct intel_rc6 *rc6)
529+
{
530+
struct drm_i915_private *i915 = rc6_to_i915(rc6);
531+
532+
if (!NEEDS_RC6_CTX_CORRUPTION_WA(i915))
533+
return;
534+
535+
if (rc6->ctx_corrupted)
536+
return;
537+
538+
if (!intel_rc6_ctx_corrupted(rc6))
539+
return;
540+
541+
DRM_NOTE("RC6 context corruption, disabling runtime power management\n");
542+
543+
intel_rc6_disable(rc6);
544+
rc6->ctx_corrupted = true;
545+
546+
return;
547+
}
548+
489549
static void __intel_rc6_disable(struct intel_rc6 *rc6)
490550
{
491551
struct drm_i915_private *i915 = rc6_to_i915(rc6);
@@ -510,6 +570,8 @@ void intel_rc6_init(struct intel_rc6 *rc6)
510570
if (!rc6_supported(rc6))
511571
return;
512572

573+
intel_rc6_ctx_wa_init(rc6);
574+
513575
if (IS_CHERRYVIEW(i915))
514576
err = chv_rc6_init(rc6);
515577
else if (IS_VALLEYVIEW(i915))
@@ -544,6 +606,9 @@ void intel_rc6_enable(struct intel_rc6 *rc6)
544606

545607
GEM_BUG_ON(rc6->enabled);
546608

609+
if (rc6->ctx_corrupted)
610+
return;
611+
547612
intel_uncore_forcewake_get(uncore, FORCEWAKE_ALL);
548613

549614
if (IS_CHERRYVIEW(i915))

drivers/gpu/drm/i915/gt/intel_rc6.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,7 @@ void intel_rc6_disable(struct intel_rc6 *rc6);
2222
u64 intel_rc6_residency_ns(struct intel_rc6 *rc6, i915_reg_t reg);
2323
u64 intel_rc6_residency_us(struct intel_rc6 *rc6, i915_reg_t reg);
2424

25+
void intel_rc6_ctx_wa_check(struct intel_rc6 *rc6);
26+
void intel_rc6_ctx_wa_resume(struct intel_rc6 *rc6);
27+
2528
#endif /* INTEL_RC6_H */

drivers/gpu/drm/i915/gt/intel_rc6_types.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ struct intel_rc6 {
2323
bool supported : 1;
2424
bool enabled : 1;
2525
bool wakeref : 1;
26+
bool ctx_corrupted : 1;
2627
};
2728

2829
#endif /* INTEL_RC6_TYPES_H */

drivers/gpu/drm/i915/i915_drv.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@
6363
#include "gem/i915_gem_ioctls.h"
6464
#include "gt/intel_gt.h"
6565
#include "gt/intel_gt_pm.h"
66+
#include "gt/intel_rc6.h"
6667

6768
#include "i915_debugfs.h"
6869
#include "i915_drv.h"
@@ -1819,6 +1820,8 @@ static int i915_drm_resume(struct drm_device *dev)
18191820

18201821
disable_rpm_wakeref_asserts(&dev_priv->runtime_pm);
18211822

1823+
intel_rc6_ctx_wa_resume(&dev_priv->gt.rc6);
1824+
18221825
intel_gt_sanitize(&dev_priv->gt, true);
18231826

18241827
ret = i915_ggtt_enable_hw(dev_priv);

drivers/gpu/drm/i915/i915_drv.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1649,10 +1649,12 @@ IS_SUBPLATFORM(const struct drm_i915_private *i915,
16491649
/* Early gen2 have a totally busted CS tlb and require pinned batches. */
16501650
#define HAS_BROKEN_CS_TLB(dev_priv) (IS_I830(dev_priv) || IS_I845G(dev_priv))
16511651

1652+
#define NEEDS_RC6_CTX_CORRUPTION_WA(dev_priv) \
1653+
(IS_BROADWELL(dev_priv) || IS_GEN(dev_priv, 9))
1654+
16521655
/* WaRsDisableCoarsePowerGating:skl,cnl */
16531656
#define NEEDS_WaRsDisableCoarsePowerGating(dev_priv) \
1654-
(IS_CANNONLAKE(dev_priv) || \
1655-
IS_SKL_GT3(dev_priv) || IS_SKL_GT4(dev_priv))
1657+
(IS_CANNONLAKE(dev_priv) || IS_GEN(dev_priv, 9))
16561658

16571659
#define HAS_GMBUS_IRQ(dev_priv) (INTEL_GEN(dev_priv) >= 4)
16581660
#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
@@ -474,6 +474,8 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg)
474474
#define ECOCHK_PPGTT_WT_HSW (0x2 << 3)
475475
#define ECOCHK_PPGTT_WB_HSW (0x3 << 3)
476476

477+
#define GEN8_RC6_CTX_INFO _MMIO(0x8504)
478+
477479
#define GAC_ECO_BITS _MMIO(0x14090)
478480
#define ECOBITS_SNB_BIT (1 << 13)
479481
#define ECOBITS_PPGTT_CACHE64B (3 << 8)

0 commit comments

Comments
 (0)