Commit 2f6b90da authored by Thomas Hellström's avatar Thomas Hellström
Browse files

drm/i915: Use vma resources for async unbinding



Implement async (non-blocking) unbinding by not syncing the vma before
calling unbind on the vma_resource.
Add the resulting unbind fence to the object's dma_resv from where it is
picked up by the ttm migration code.
Ideally these unbind fences should be coalesced with the migration blit
fence to avoid stalling the migration blit waiting for unbind, as they
can certainly go on in parallel, but since we don't yet have a
reasonable data structure to use to coalesce fences and attach the
resulting fence to a timeline, we defer that for now.

Note that with async unbinding, even while the unbind waits for the
preceding bind to complete before unbinding, the vma itself might have been
destroyed in the process, clearing the vma pages. Therefore we can
only allow async unbinding if we have a refcounted sg-list and keep a
refcount on that for the vma resource pages to stay intact until
binding occurs. If this condition is not met, a request for an async
unbind is diverted to a sync unbind.

v2:
- Use a separate kmem_cache for vma resources for now to isolate their
  memory allocation and aid debugging.
- Move the check for vm closed to the actual unbinding thread. Regardless
  of whether the vm is closed, we need the unbind fence to properly wait
  for capture.
- Clear vma_res::vm on unbind and update its documentation.
v4:
- Take cache coloring into account when searching for vma resources
  pending unbind. (Matthew Auld)
v5:
- Fix timeout and error check in i915_vma_resource_bind_dep_await().
- Avoid taking a reference on the object for async binding if
  async unbind capable.
- Fix braces around a single-line if statement.
v6:
- Fix up the cache coloring adjustment. (Kernel test robot <lkp@intel.com>)
- Don't allow async unbinding if the vma_res pages are not the same as
  the object pages. (Matthew Auld)
v7:
- s/unsigned long/u64/ in a number of places (Matthew Auld)

Signed-off-by: default avatarThomas Hellström <thomas.hellstrom@linux.intel.com>
Reviewed-by: default avatarMatthew Auld <matthew.auld@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20220110172219.107131-5-thomas.hellstrom@linux.intel.com
parent ebf3c361
Loading
Loading
Loading
Loading
+10 −1
Original line number Diff line number Diff line
@@ -142,7 +142,16 @@ int i915_ttm_move_notify(struct ttm_buffer_object *bo)
	struct drm_i915_gem_object *obj = i915_ttm_to_gem(bo);
	int ret;

	ret = i915_gem_object_unbind(obj, I915_GEM_OBJECT_UNBIND_ACTIVE);
	/*
	 * Note: The async unbinding here will actually transform the
	 * blocking wait for unbind into a wait before finally submitting
	 * evict / migration blit and thus stall the migration timeline
	 * which may not be good for overall throughput. We should make
	 * sure we await the unbind fences *after* the migration blit
	 * instead of *before* as we currently do.
	 */
	ret = i915_gem_object_unbind(obj, I915_GEM_OBJECT_UNBIND_ACTIVE |
				     I915_GEM_OBJECT_UNBIND_ASYNC);
	if (ret)
		return ret;

+1 −1
Original line number Diff line number Diff line
@@ -131,7 +131,7 @@ void i915_ggtt_suspend(struct i915_ggtt *ggtt)
			continue;

		if (!i915_vma_is_bound(vma, I915_VMA_GLOBAL_BIND)) {
			__i915_vma_evict(vma);
			__i915_vma_evict(vma, false);
			drm_mm_remove_node(&vma->node);
		}
	}
+4 −0
Original line number Diff line number Diff line
@@ -160,6 +160,9 @@ static void __i915_vm_release(struct work_struct *work)
	struct i915_address_space *vm =
		container_of(work, struct i915_address_space, release_work);

	/* Synchronize async unbinds. */
	i915_vma_resource_bind_dep_sync_all(vm);

	vm->cleanup(vm);
	i915_address_space_fini(vm);

@@ -188,6 +191,7 @@ void i915_address_space_init(struct i915_address_space *vm, int subclass)
	if (!kref_read(&vm->resv_ref))
		kref_init(&vm->resv_ref);

	vm->pending_unbind = RB_ROOT_CACHED;
	INIT_WORK(&vm->release_work, __i915_vm_release);
	atomic_set(&vm->open, 1);

+3 −0
Original line number Diff line number Diff line
@@ -265,6 +265,9 @@ struct i915_address_space {
	/* Flags used when creating page-table objects for this vm */
	unsigned long lmem_pt_obj_flags;

	/* Interval tree for pending unbind vma resources */
	struct rb_root_cached pending_unbind;

	struct drm_i915_gem_object *
		(*alloc_pt_dma)(struct i915_address_space *vm, int sz);
	struct drm_i915_gem_object *
+1 −0
Original line number Diff line number Diff line
@@ -1878,6 +1878,7 @@ int i915_gem_object_unbind(struct drm_i915_gem_object *obj,
#define I915_GEM_OBJECT_UNBIND_BARRIER BIT(1)
#define I915_GEM_OBJECT_UNBIND_TEST BIT(2)
#define I915_GEM_OBJECT_UNBIND_VM_TRYLOCK BIT(3)
#define I915_GEM_OBJECT_UNBIND_ASYNC BIT(4)

void i915_gem_runtime_suspend(struct drm_i915_private *dev_priv);

Loading