drm/i915: Accurately track when we mark the hardware as idle/busy
We currently call intel_mark_idle() too often, as we do so as a
side-effect of processing the request queue. However, we the calls to
intel_mark_idle() are expected to be paired with a call to
intel_mark_busy() (or else we try to idle the hardware by accessing
registers that are already disabled). Make the idle/busy tracking
explicit to prevent the multiple calls.
v2: We can drop some of the complexity in __i915_add_request() as
queue_delayed_work() already behaves as we want (not requeuing the item
if it is already in the queue) and mark_busy/mark_idle imply that the
idle task is inactive.
v3: We do still need to cancel the pending idle task so that it is sent
again after the current busy load completes (not in the middle of it).
Reported-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Paulo Zanoni <paulo.r.zanoni@intel.com>
Reviewed-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
Tested-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 842b07e..ef26312 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -8197,8 +8197,12 @@
{
struct drm_i915_private *dev_priv = dev->dev_private;
+ if (dev_priv->mm.busy)
+ return;
+
hsw_package_c8_gpu_busy(dev_priv);
i915_update_gfx_val(dev_priv);
+ dev_priv->mm.busy = true;
}
void intel_mark_idle(struct drm_device *dev)
@@ -8206,6 +8210,11 @@
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_crtc *crtc;
+ if (!dev_priv->mm.busy)
+ return;
+
+ dev_priv->mm.busy = false;
+
hsw_package_c8_gpu_idle(dev_priv);
if (!i915.powersave)