@@ -2989,6 +2989,13 @@ static void i915_hangcheck_elapsed(struct work_struct *work)
if (!i915.enable_hangcheck)
return;
+ /* If the runtime pm is off, then the GPU is asleep and we are
+ * completely idle, so we can belatedly cancel hangcheck. Hangcheck
+ * will be restarted on the next request.
+ */
+ if (!intel_runtime_get_noidle(dev_priv))
+ return;
+
for_each_ring(ring, dev_priv, i) {
u64 acthd;
u32 seqno;
@@ -3080,6 +3087,8 @@ static void i915_hangcheck_elapsed(struct work_struct *work)
}
}
+ intel_runtime_pm_put(dev_priv);
+
if (rings_hung)
return i915_handle_error(dev, true, "Ring hung");
@@ -1429,6 +1429,7 @@ void intel_display_power_put(struct drm_i915_private *dev_priv,
enum intel_display_power_domain domain);
void intel_runtime_pm_get(struct drm_i915_private *dev_priv);
void intel_runtime_pm_get_noresume(struct drm_i915_private *dev_priv);
+bool intel_runtime_pm_get_noidle(struct drm_i915_private *dev_priv);
void intel_runtime_pm_put(struct drm_i915_private *dev_priv);
void intel_display_set_init_power(struct drm_i915_private *dev, bool enable);
@@ -2263,6 +2263,29 @@ void intel_runtime_pm_get_noresume(struct drm_i915_private *dev_priv)
}
/**
+ * intel_runtime_pm_get_noidle - grab a runtime pm reference if not idle
+ * @dev_priv: i915 device instance
+ *
+ * This function grabs a device-level runtime pm reference if it the device
+ * is not idle.
+ *
+ * Any successful call must have a symmetric call to intel_runtime_pm_put()
+ * to release the reference.
+ *
+ * See intel_runtime_pm_get() for more.
+ */
+bool intel_runtime_pm_get_noidle(struct drm_i915_private *dev_priv)
+{
+ struct drm_device *dev = dev_priv->dev;
+ struct device *device = &dev->pdev->dev;
+
+ if (!HAS_RUNTIME_PM(dev))
+ return true;
+
+ return !!pm_runtime_get_noidle(device);
+}
+
+/**
* intel_runtime_pm_put - release a runtime pm reference
* @dev_priv: i915 device instance
*