@@ -8552,6 +8552,100 @@ static void intel_init_emon(struct drm_i915_private *dev_priv)
8552
8552
dev_priv -> ips .corr = (lcfuse & LCFUSE_HIV_MASK );
8553
8553
}
8554
8554
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
+
8555
8649
void intel_init_gt_powersave (struct drm_i915_private * dev_priv )
8556
8650
{
8557
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
8659
pm_runtime_get (& dev_priv -> drm .pdev -> dev );
8566
8660
}
8567
8661
8662
+ i915_rc6_ctx_wa_init (dev_priv );
8663
+
8568
8664
/* Initialize RPS limits (for userspace) */
8569
8665
if (IS_CHERRYVIEW (dev_priv ))
8570
8666
cherryview_init_gt_powersave (dev_priv );
@@ -8603,6 +8699,8 @@ void intel_cleanup_gt_powersave(struct drm_i915_private *dev_priv)
8603
8699
if (IS_VALLEYVIEW (dev_priv ))
8604
8700
valleyview_cleanup_gt_powersave (dev_priv );
8605
8701
8702
+ i915_rc6_ctx_wa_cleanup (dev_priv );
8703
+
8606
8704
if (!HAS_RC6 (dev_priv ))
8607
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
8729
i915 -> gt_pm .llc_pstate .enabled = false;
8632
8730
}
8633
8731
8634
- static void intel_disable_rc6 (struct drm_i915_private * dev_priv )
8732
+ static void __intel_disable_rc6 (struct drm_i915_private * dev_priv )
8635
8733
{
8636
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
8748
dev_priv -> gt_pm .rc6 .enabled = false;
8651
8749
}
8652
8750
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
+
8653
8760
static void intel_disable_rps (struct drm_i915_private * dev_priv )
8654
8761
{
8655
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
8783
mutex_lock (& dev_priv -> gt_pm .rps .lock );
8677
8784
8678
- intel_disable_rc6 (dev_priv );
8785
+ __intel_disable_rc6 (dev_priv );
8679
8786
intel_disable_rps (dev_priv );
8680
8787
if (HAS_LLC (dev_priv ))
8681
8788
intel_disable_llc_pstate (dev_priv );
@@ -8702,6 +8809,9 @@ static void intel_enable_rc6(struct drm_i915_private *dev_priv)
8702
8809
if (dev_priv -> gt_pm .rc6 .enabled )
8703
8810
return ;
8704
8811
8812
+ if (dev_priv -> gt_pm .rc6 .ctx_corrupted )
8813
+ return ;
8814
+
8705
8815
if (IS_CHERRYVIEW (dev_priv ))
8706
8816
cherryview_enable_rc6 (dev_priv );
8707
8817
else if (IS_VALLEYVIEW (dev_priv ))
0 commit comments