Commit 86ceaaae authored by Jonathan Cavitt's avatar Jonathan Cavitt Committed by Andi Shyti

drm/i915/gem: Atomically invalidate userptr on mmu-notifier

Never block for outstanding work on userptr object upon receipt of a
mmu-notifier. The reason we originally did so was to immediately unbind
the userptr and unpin its pages, but since that has been dropped in
commit b4b9731b ("drm/i915: Simplify userptr locking"), we never
return the pages to the system i.e. never drop our page->mapcount and so
do not allow the page and CPU PTE to be revoked. Based on this history,
we know we are safe to drop the wait entirely.

Upon return from mmu-notifier, we will still have the userptr pages
pinned preventing the following PTE operation (such as try_to_unmap)
adjusting the vm_area_struct, so it is safe to keep the pages around for
as long as we still have i/o pending.

We do not have any means currently to asynchronously revalidate the
userptr pages, that is always prior to next use.
Signed-off-by: default avatarChris Wilson <chris.p.wilson@linux.intel.com>
Signed-off-by: default avatarJonathan Cavitt <jonathan.cavitt@intel.com>
Reviewed-by: default avatarAndi Shyti <andi.shyti@linux.intel.com>
Signed-off-by: default avatarAndi Shyti <andi.shyti@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20231128162505.3493942-1-jonathan.cavitt@intel.com
parent 31accc37
......@@ -2159,12 +2159,6 @@ static int eb_move_to_gpu(struct i915_execbuffer *eb)
#ifdef CONFIG_MMU_NOTIFIER
if (!err && (eb->args->flags & __EXEC_USERPTR_USED)) {
read_lock(&eb->i915->mm.notifier_lock);
/*
* count is always at least 1, otherwise __EXEC_USERPTR_USED
* could not have been set
*/
for (i = 0; i < count; i++) {
struct eb_vma *ev = &eb->vma[i];
struct drm_i915_gem_object *obj = ev->vma->obj;
......@@ -2176,8 +2170,6 @@ static int eb_move_to_gpu(struct i915_execbuffer *eb)
if (err)
break;
}
read_unlock(&eb->i915->mm.notifier_lock);
}
#endif
......
......@@ -42,7 +42,6 @@
#include "i915_drv.h"
#include "i915_gem_ioctls.h"
#include "i915_gem_object.h"
#include "i915_gem_userptr.h"
#include "i915_scatterlist.h"
#ifdef CONFIG_MMU_NOTIFIER
......@@ -61,36 +60,7 @@ static bool i915_gem_userptr_invalidate(struct mmu_interval_notifier *mni,
const struct mmu_notifier_range *range,
unsigned long cur_seq)
{
struct drm_i915_gem_object *obj = container_of(mni, struct drm_i915_gem_object, userptr.notifier);
struct drm_i915_private *i915 = to_i915(obj->base.dev);
long r;
if (!mmu_notifier_range_blockable(range))
return false;
write_lock(&i915->mm.notifier_lock);
mmu_interval_set_seq(mni, cur_seq);
write_unlock(&i915->mm.notifier_lock);
/*
* We don't wait when the process is exiting. This is valid
* because the object will be cleaned up anyway.
*
* This is also temporarily required as a hack, because we
* cannot currently force non-consistent batch buffers to preempt
* and reschedule by waiting on it, hanging processes on exit.
*/
if (current->flags & PF_EXITING)
return true;
/* we will unbind on next submission, still have userptr pins */
r = dma_resv_wait_timeout(obj->base.resv, DMA_RESV_USAGE_BOOKKEEP, false,
MAX_SCHEDULE_TIMEOUT);
if (r <= 0)
drm_err(&i915->drm, "(%ld) failed to wait for idle\n", r);
return true;
}
......@@ -580,15 +550,3 @@ i915_gem_userptr_ioctl(struct drm_device *dev,
#endif
}
int i915_gem_init_userptr(struct drm_i915_private *dev_priv)
{
#ifdef CONFIG_MMU_NOTIFIER
rwlock_init(&dev_priv->mm.notifier_lock);
#endif
return 0;
}
void i915_gem_cleanup_userptr(struct drm_i915_private *dev_priv)
{
}
/* SPDX-License-Identifier: MIT */
/*
* Copyright © 2021 Intel Corporation
*/
#ifndef __I915_GEM_USERPTR_H__
#define __I915_GEM_USERPTR_H__
struct drm_i915_private;
int i915_gem_init_userptr(struct drm_i915_private *dev_priv);
void i915_gem_cleanup_userptr(struct drm_i915_private *dev_priv);
#endif /* __I915_GEM_USERPTR_H__ */
......@@ -165,14 +165,6 @@ struct i915_gem_mm {
struct notifier_block vmap_notifier;
struct shrinker shrinker;
#ifdef CONFIG_MMU_NOTIFIER
/**
* notifier_lock for mmu notifiers, memory may not be allocated
* while holding this lock.
*/
rwlock_t notifier_lock;
#endif
/* shrinker accounting, also useful for userland debugging */
u64 shrink_memory;
u32 shrink_count;
......
......@@ -48,7 +48,6 @@
#include "gem/i915_gem_object_frontbuffer.h"
#include "gem/i915_gem_pm.h"
#include "gem/i915_gem_region.h"
#include "gem/i915_gem_userptr.h"
#include "gt/intel_engine_user.h"
#include "gt/intel_gt.h"
#include "gt/intel_gt_pm.h"
......@@ -1165,10 +1164,6 @@ int i915_gem_init(struct drm_i915_private *dev_priv)
if (intel_vgpu_active(dev_priv) && !intel_vgpu_has_huge_gtt(dev_priv))
RUNTIME_INFO(dev_priv)->page_sizes = I915_GTT_PAGE_SIZE_4K;
ret = i915_gem_init_userptr(dev_priv);
if (ret)
return ret;
for_each_gt(gt, dev_priv, i) {
intel_uc_fetch_firmwares(&gt->uc);
intel_wopcm_init(&gt->wopcm);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment