[Intel-gfx] [PATCH] drm/i915: Keep user GGTT alive for a minimum of 250ms

Chris Wilson chris at chris-wilson.co.uk
Thu May 23 14:33:54 UTC 2019


Do not allow runtime pm autosuspend to remove userspace GGTT mmaps too
quickly. For example, igt sets the autosuspend delay to 0, and so we
immediately attempt to perform runtime suspend upon releasing the
wakeref. Unfortunately, that involves tearing down GGTT mmaps as they
require an active device.

Override the autosuspend for GGTT mmaps, by keeping the wakeref around
for 250ms after populating the PTE for a fresh mmap.

Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
Cc: Mika Kuoppala <mika.kuoppala at linux.intel.com>
---
 drivers/gpu/drm/i915/Kconfig.profile |  4 ++++
 drivers/gpu/drm/i915/i915_drv.h      |  4 ++++
 drivers/gpu/drm/i915/i915_gem.c      | 30 ++++++++++++++++++++++++++++
 3 files changed, 38 insertions(+)

diff --git a/drivers/gpu/drm/i915/Kconfig.profile b/drivers/gpu/drm/i915/Kconfig.profile
index 0e5db98da8f3..0f997e221868 100644
--- a/drivers/gpu/drm/i915/Kconfig.profile
+++ b/drivers/gpu/drm/i915/Kconfig.profile
@@ -1,3 +1,7 @@
+config DRM_I915_USERFAULT_AUTOSUSPEND
+	int
+	default 250 # milliseconds
+
 config DRM_I915_SPIN_REQUEST
 	int
 	default 5 # microseconds
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 311e19154672..98ba51f255cc 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -874,6 +874,10 @@ struct i915_gem_mm {
 	 */
 	struct list_head userfault_list;
 
+	/* Manual runtime pm autosuspend delay for user GGTT mmaps */
+	intel_wakeref_t userfault_wakeref;
+	struct timer_list userfault_timer;
+
 	/**
 	 * List of objects which are pending destruction.
 	 */
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index d3b7dac527dc..4cb730d52684 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -1720,6 +1720,29 @@ compute_partial_view(const struct drm_i915_gem_object *obj,
 	return view;
 }
 
+static void __userfault_timeout(struct timer_list *t)
+{
+	struct drm_i915_private *i915 =
+		from_timer(i915, t, mm.userfault_timer);
+
+	intel_runtime_pm_put(i915, xchg(&i915->mm.userfault_wakeref, 0));
+}
+
+static void userfault_autosuspend(struct drm_i915_private *i915)
+{
+	intel_wakeref_t wakeref;
+
+	if (!CONFIG_DRM_I915_USERFAULT_AUTOSUSPEND)
+		return;
+
+	wakeref = intel_runtime_pm_get(i915);
+	if (cmpxchg(&i915->mm.userfault_wakeref, 0, wakeref))
+		intel_runtime_pm_put(i915, wakeref);
+
+	mod_timer(&i915->mm.userfault_timer,
+		  jiffies + msecs_to_jiffies_timeout(CONFIG_DRM_I915_USERFAULT_AUTOSUSPEND));
+}
+
 /**
  * i915_gem_fault - fault a page into the GTT
  * @vmf: fault info
@@ -1834,6 +1857,7 @@ vm_fault_t i915_gem_fault(struct vm_fault *vmf)
 	assert_rpm_wakelock_held(dev_priv);
 	if (!i915_vma_set_userfault(vma) && !obj->userfault_count++)
 		list_add(&obj->userfault_link, &dev_priv->mm.userfault_list);
+	userfault_autosuspend(dev_priv);
 	GEM_BUG_ON(!obj->userfault_count);
 
 	i915_vma_set_ggtt_write(vma);
@@ -4671,6 +4695,10 @@ void i915_gem_fini(struct drm_i915_private *dev_priv)
 {
 	GEM_BUG_ON(dev_priv->gt.awake);
 
+	if (del_timer_sync(&dev_priv->mm.userfault_timer))
+		__userfault_timeout(&dev_priv->mm.userfault_timer);
+	GEM_BUG_ON(dev_priv->mm.userfault_wakeref);
+
 	i915_gem_suspend_late(dev_priv);
 	intel_disable_gt_powersave(dev_priv);
 
@@ -4748,6 +4776,8 @@ static void i915_gem_init__mm(struct drm_i915_private *i915)
 	INIT_LIST_HEAD(&i915->mm.fence_list);
 	INIT_LIST_HEAD(&i915->mm.userfault_list);
 
+	timer_setup(&i915->mm.userfault_timer, __userfault_timeout, 0);
+
 	INIT_WORK(&i915->mm.free_work, __i915_gem_free_work);
 }
 
-- 
2.20.1



More information about the Intel-gfx mailing list