Commit e3793468 authored by Chris Wilson's avatar Chris Wilson
Browse files

drm/i915: Use the async worker to avoid reclaim tainting the ggtt->mutex

On Braswell and Broxton (also known as Valleyview and Apollolake), we
need to serialise updates of the GGTT using the big stop_machine()
hammer. This has the side effect of appearing to lockdep as a possible
reclaim (since it uses the cpuhp mutex and that is tainted by per-cpu
allocations). However, we want to use vm->mutex (including ggtt->mutex)
from within the shrinker and so must avoid such possible taints. For this
purpose, we introduced the asynchronous vma binding and we can apply it
to the PIN_GLOBAL so long as take care to add the necessary waits for
the worker afterwards.

Closes: https://gitlab.freedesktop.org/drm/intel/issues/211


Signed-off-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: default avatarMatthew Auld <matthew.auld@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20200130181710.2030251-3-chris@chris-wilson.co.uk
parent e986209c
Loading
Loading
Loading
Loading
+3 −4
Original line number Diff line number Diff line
@@ -527,7 +527,6 @@ static int pin_ggtt_status_page(struct intel_engine_cs *engine,
{
	unsigned int flags;

	flags = PIN_GLOBAL;
	if (!HAS_LLC(engine->i915) && i915_ggtt_has_aperture(engine->gt->ggtt))
		/*
		 * On g33, we cannot place HWS above 256MiB, so
@@ -540,11 +539,11 @@ static int pin_ggtt_status_page(struct intel_engine_cs *engine,
		 * above the mappable region (even though we never
		 * actually map it).
		 */
		flags |= PIN_MAPPABLE;
		flags = PIN_MAPPABLE;
	else
		flags |= PIN_HIGH;
		flags = PIN_HIGH;

	return i915_vma_pin(vma, 0, 0, flags);
	return i915_ggtt_pin(vma, 0, flags);
}

static int init_status_page(struct intel_engine_cs *engine)
+6 −0
Original line number Diff line number Diff line
@@ -106,6 +106,11 @@ static bool needs_idle_maps(struct drm_i915_private *i915)

void i915_ggtt_suspend(struct i915_ggtt *ggtt)
{
	struct i915_vma *vma;

	list_for_each_entry(vma, &ggtt->vm.bound_list, vm_link)
		i915_vma_wait_for_bind(vma);

	ggtt->vm.clear_range(&ggtt->vm, 0, ggtt->vm.total);
	ggtt->invalidate(ggtt);

@@ -841,6 +846,7 @@ static int gen8_gmch_probe(struct i915_ggtt *ggtt)
	    IS_CHERRYVIEW(i915) /* fails with concurrent use/update */) {
		ggtt->vm.insert_entries = bxt_vtd_ggtt_insert_entries__BKL;
		ggtt->vm.insert_page    = bxt_vtd_ggtt_insert_page__BKL;
		ggtt->vm.bind_async_flags = I915_VMA_GLOBAL_BIND;
	}

	ggtt->invalidate = gen8_ggtt_invalidate;
+1 −1
Original line number Diff line number Diff line
@@ -344,7 +344,7 @@ static int intel_gt_init_scratch(struct intel_gt *gt, unsigned int size)
		goto err_unref;
	}

	ret = i915_vma_pin(vma, 0, 0, PIN_GLOBAL | PIN_HIGH);
	ret = i915_ggtt_pin(vma, 0, PIN_HIGH);
	if (ret)
		goto err_unref;

+1 −1
Original line number Diff line number Diff line
@@ -3255,7 +3255,7 @@ static int lrc_setup_wa_ctx(struct intel_engine_cs *engine)
		goto err;
	}

	err = i915_vma_pin(vma, 0, 0, PIN_GLOBAL | PIN_HIGH);
	err = i915_ggtt_pin(vma, 0, PIN_HIGH);
	if (err)
		goto err;

+2 −4
Original line number Diff line number Diff line
@@ -31,17 +31,15 @@ int intel_ring_pin(struct intel_ring *ring)
	if (atomic_fetch_inc(&ring->pin_count))
		return 0;

	flags = PIN_GLOBAL;

	/* Ring wraparound at offset 0 sometimes hangs. No idea why. */
	flags |= PIN_OFFSET_BIAS | i915_ggtt_pin_bias(vma);
	flags = PIN_OFFSET_BIAS | i915_ggtt_pin_bias(vma);

	if (vma->obj->stolen)
		flags |= PIN_MAPPABLE;
	else
		flags |= PIN_HIGH;

	ret = i915_vma_pin(vma, 0, 0, flags);
	ret = i915_ggtt_pin(vma, 0, flags);
	if (unlikely(ret))
		goto err_unpin;

Loading