@@ -1,3 +1,7 @@
+config DRM_I915_USERFAULT_AUTOSUSPEND
+ int
+ default 250 # milliseconds
+
config DRM_I915_SPIN_REQUEST
int
default 5 # microseconds
@@ -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.
*/
@@ -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);
}
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@chris-wilson.co.uk> Cc: Mika Kuoppala <mika.kuoppala@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(+)