Commit 39a2bd34 authored by Thomas Hellström's avatar Thomas Hellström
Browse files

drm/i915: Use the vma resource as argument for gtt binding / unbinding



When introducing asynchronous unbinding, the vma itself may no longer
be alive when the actual binding or unbinding takes place.

Update the gtt i915_vma_ops accordingly to take a struct i915_vma_resource
instead of a struct i915_vma for the bind_vma() and unbind_vma() ops.
Similarly change the insert_entries() op for struct i915_address_space.

Replace a couple of i915_vma_snapshot members with their newly introduced
i915_vma_resource counterparts, since they have the same lifetime.

Also make sure to avoid changing the struct i915_vma_flags (in particular
the bind flags) async. That should now only be done sync under the
vm mutex.

v2:
- Update the vma_res::bound_flags when binding to the aliased ggtt
v6:
- Remove I915_VMA_ALLOC_BIT (Matthew Auld)
- Change some members of struct i915_vma_resource from unsigned long to u64
  (Matthew Auld)
v7:
- Fix vma resource size parameters to be u64 rather than unsigned long
  (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-3-thomas.hellstrom@linux.intel.com
parent e1a4bbb6
Loading
Loading
Loading
Loading
+15 −12
Original line number Diff line number Diff line
@@ -48,7 +48,7 @@ static void dpt_insert_page(struct i915_address_space *vm,
}

static void dpt_insert_entries(struct i915_address_space *vm,
			       struct i915_vma *vma,
			       struct i915_vma_resource *vma_res,
			       enum i915_cache_level level,
			       u32 flags)
{
@@ -64,8 +64,8 @@ static void dpt_insert_entries(struct i915_address_space *vm,
	 * not to allow the user to override access to a read only page.
	 */

	i = vma->node.start / I915_GTT_PAGE_SIZE;
	for_each_sgt_daddr(addr, sgt_iter, vma->pages)
	i = vma_res->start / I915_GTT_PAGE_SIZE;
	for_each_sgt_daddr(addr, sgt_iter, vma_res->bi.pages)
		gen8_set_pte(&base[i++], pte_encode | addr);
}

@@ -76,35 +76,38 @@ static void dpt_clear_range(struct i915_address_space *vm,

static void dpt_bind_vma(struct i915_address_space *vm,
			 struct i915_vm_pt_stash *stash,
			 struct i915_vma *vma,
			 struct i915_vma_resource *vma_res,
			 enum i915_cache_level cache_level,
			 u32 flags)
{
	struct drm_i915_gem_object *obj = vma->obj;
	u32 pte_flags;

	if (vma_res->bound_flags)
		return;

	/* Applicable to VLV (gen8+ do not support RO in the GGTT) */
	pte_flags = 0;
	if (vma->vm->has_read_only && i915_gem_object_is_readonly(obj))
	if (vm->has_read_only && vma_res->bi.readonly)
		pte_flags |= PTE_READ_ONLY;
	if (i915_gem_object_is_lmem(obj))
	if (vma_res->bi.lmem)
		pte_flags |= PTE_LM;

	vma->vm->insert_entries(vma->vm, vma, cache_level, pte_flags);
	vm->insert_entries(vm, vma_res, cache_level, pte_flags);

	vma->page_sizes.gtt = I915_GTT_PAGE_SIZE;
	vma_res->page_sizes_gtt = I915_GTT_PAGE_SIZE;

	/*
	 * Without aliasing PPGTT there's no difference between
	 * GLOBAL/LOCAL_BIND, it's all the same ptes. Hence unconditionally
	 * upgrade to both bound if we bind either to avoid double-binding.
	 */
	atomic_or(I915_VMA_GLOBAL_BIND | I915_VMA_LOCAL_BIND, &vma->flags);
	vma_res->bound_flags = I915_VMA_GLOBAL_BIND | I915_VMA_LOCAL_BIND;
}

static void dpt_unbind_vma(struct i915_address_space *vm, struct i915_vma *vma)
static void dpt_unbind_vma(struct i915_address_space *vm,
			   struct i915_vma_resource *vma_res)
{
	vm->clear_range(vm, vma->node.start, vma->size);
	vm->clear_range(vm, vma_res->start, vma_res->vma_size);
}

static void dpt_cleanup(struct i915_address_space *vm)
+2 −25
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@

#include "i915_active.h"
#include "i915_selftest.h"
#include "i915_vma_resource.h"

struct drm_i915_gem_object;
struct intel_fronbuffer;
@@ -566,31 +567,7 @@ struct drm_i915_gem_object {
		struct sg_table *pages;
		void *mapping;

		struct i915_page_sizes {
			/**
			 * The sg mask of the pages sg_table. i.e the mask of
			 * of the lengths for each sg entry.
			 */
			unsigned int phys;

			/**
			 * The gtt page sizes we are allowed to use given the
			 * sg mask and the supported page sizes. This will
			 * express the smallest unit we can use for the whole
			 * object, as well as the larger sizes we may be able
			 * to use opportunistically.
			 */
			unsigned int sg;

			/**
			 * The actual gtt page size usage. Since we can have
			 * multiple vma associated with this object we need to
			 * prevent any trampling of state, hence a copy of this
			 * struct also lives in each vma, therefore the gtt
			 * value here should only be read/write through the vma.
			 */
			unsigned int gtt;
		} page_sizes;
		struct i915_page_sizes page_sizes;

		I915_SELFTEST_DECLARE(unsigned int page_mask);

+16 −21
Original line number Diff line number Diff line
@@ -370,9 +370,9 @@ static int igt_check_page_sizes(struct i915_vma *vma)
		err = -EINVAL;
	}

	if (!HAS_PAGE_SIZES(i915, vma->page_sizes.gtt)) {
	if (!HAS_PAGE_SIZES(i915, vma->resource->page_sizes_gtt)) {
		pr_err("unsupported page_sizes.gtt=%u, supported=%u\n",
		       vma->page_sizes.gtt & ~supported, supported);
		       vma->resource->page_sizes_gtt & ~supported, supported);
		err = -EINVAL;
	}

@@ -403,15 +403,9 @@ static int igt_check_page_sizes(struct i915_vma *vma)
	if (i915_gem_object_is_lmem(obj) &&
	    IS_ALIGNED(vma->node.start, SZ_2M) &&
	    vma->page_sizes.sg & SZ_2M &&
	    vma->page_sizes.gtt < SZ_2M) {
	    vma->resource->page_sizes_gtt < SZ_2M) {
		pr_err("gtt pages mismatch for LMEM, expected 2M GTT pages, sg(%u), gtt(%u)\n",
		       vma->page_sizes.sg, vma->page_sizes.gtt);
		err = -EINVAL;
	}

	if (obj->mm.page_sizes.gtt) {
		pr_err("obj->page_sizes.gtt(%u) should never be set\n",
		       obj->mm.page_sizes.gtt);
		       vma->page_sizes.sg, vma->resource->page_sizes_gtt);
		err = -EINVAL;
	}

@@ -547,9 +541,9 @@ static int igt_mock_memory_region_huge_pages(void *arg)
				goto out_unpin;
			}

			if (vma->page_sizes.gtt != page_size) {
			if (vma->resource->page_sizes_gtt != page_size) {
				pr_err("%s page_sizes.gtt=%u, expected=%u\n",
				       __func__, vma->page_sizes.gtt,
				       __func__, vma->resource->page_sizes_gtt,
				       page_size);
				err = -EINVAL;
				goto out_unpin;
@@ -630,9 +624,9 @@ static int igt_mock_ppgtt_misaligned_dma(void *arg)

		err = igt_check_page_sizes(vma);

		if (vma->page_sizes.gtt != page_size) {
		if (vma->resource->page_sizes_gtt != page_size) {
			pr_err("page_sizes.gtt=%u, expected %u\n",
			       vma->page_sizes.gtt, page_size);
			       vma->resource->page_sizes_gtt, page_size);
			err = -EINVAL;
		}

@@ -657,9 +651,10 @@ static int igt_mock_ppgtt_misaligned_dma(void *arg)

			err = igt_check_page_sizes(vma);

			if (vma->page_sizes.gtt != I915_GTT_PAGE_SIZE_4K) {
			if (vma->resource->page_sizes_gtt != I915_GTT_PAGE_SIZE_4K) {
				pr_err("page_sizes.gtt=%u, expected %llu\n",
				       vma->page_sizes.gtt, I915_GTT_PAGE_SIZE_4K);
				       vma->resource->page_sizes_gtt,
				       I915_GTT_PAGE_SIZE_4K);
				err = -EINVAL;
			}

@@ -805,9 +800,9 @@ static int igt_mock_ppgtt_huge_fill(void *arg)
			}
		}

		if (vma->page_sizes.gtt != expected_gtt) {
		if (vma->resource->page_sizes_gtt != expected_gtt) {
			pr_err("gtt=%u, expected=%u, size=%zd, single=%s\n",
			       vma->page_sizes.gtt, expected_gtt,
			       vma->resource->page_sizes_gtt, expected_gtt,
			       obj->base.size, yesno(!!single));
			err = -EINVAL;
			break;
@@ -961,10 +956,10 @@ static int igt_mock_ppgtt_64K(void *arg)
				}
			}

			if (vma->page_sizes.gtt != expected_gtt) {
			if (vma->resource->page_sizes_gtt != expected_gtt) {
				pr_err("gtt=%u, expected=%u, i=%d, single=%s\n",
				       vma->page_sizes.gtt, expected_gtt, i,
				       yesno(!!single));
				       vma->resource->page_sizes_gtt,
				       expected_gtt, i, yesno(!!single));
				err = -EINVAL;
				goto out_vma_unpin;
			}
+10 −9
Original line number Diff line number Diff line
@@ -104,17 +104,17 @@ static void gen6_ppgtt_clear_range(struct i915_address_space *vm,
}

static void gen6_ppgtt_insert_entries(struct i915_address_space *vm,
				      struct i915_vma *vma,
				      struct i915_vma_resource *vma_res,
				      enum i915_cache_level cache_level,
				      u32 flags)
{
	struct i915_ppgtt *ppgtt = i915_vm_to_ppgtt(vm);
	struct i915_page_directory * const pd = ppgtt->pd;
	unsigned int first_entry = vma->node.start / I915_GTT_PAGE_SIZE;
	unsigned int first_entry = vma_res->start / I915_GTT_PAGE_SIZE;
	unsigned int act_pt = first_entry / GEN6_PTES;
	unsigned int act_pte = first_entry % GEN6_PTES;
	const u32 pte_encode = vm->pte_encode(0, cache_level, flags);
	struct sgt_dma iter = sgt_dma(vma);
	struct sgt_dma iter = sgt_dma(vma_res);
	gen6_pte_t *vaddr;

	GEM_BUG_ON(!pd->entry[act_pt]);
@@ -140,7 +140,7 @@ static void gen6_ppgtt_insert_entries(struct i915_address_space *vm,
		}
	} while (1);

	vma->page_sizes.gtt = I915_GTT_PAGE_SIZE;
	vma_res->page_sizes_gtt = I915_GTT_PAGE_SIZE;
}

static void gen6_flush_pd(struct gen6_ppgtt *ppgtt, u64 start, u64 end)
@@ -271,13 +271,13 @@ static void gen6_ppgtt_cleanup(struct i915_address_space *vm)

static void pd_vma_bind(struct i915_address_space *vm,
			struct i915_vm_pt_stash *stash,
			struct i915_vma *vma,
			struct i915_vma_resource *vma_res,
			enum i915_cache_level cache_level,
			u32 unused)
{
	struct i915_ggtt *ggtt = i915_vm_to_ggtt(vm);
	struct gen6_ppgtt *ppgtt = vma->private;
	u32 ggtt_offset = i915_ggtt_offset(vma) / I915_GTT_PAGE_SIZE;
	struct gen6_ppgtt *ppgtt = vma_res->private;
	u32 ggtt_offset = vma_res->start / I915_GTT_PAGE_SIZE;

	ppgtt->pp_dir = ggtt_offset * sizeof(gen6_pte_t) << 10;
	ppgtt->pd_addr = (gen6_pte_t __iomem *)ggtt->gsm + ggtt_offset;
@@ -285,9 +285,10 @@ static void pd_vma_bind(struct i915_address_space *vm,
	gen6_flush_pd(ppgtt, 0, ppgtt->base.vm.total);
}

static void pd_vma_unbind(struct i915_address_space *vm, struct i915_vma *vma)
static void pd_vma_unbind(struct i915_address_space *vm,
			  struct i915_vma_resource *vma_res)
{
	struct gen6_ppgtt *ppgtt = vma->private;
	struct gen6_ppgtt *ppgtt = vma_res->private;
	struct i915_page_directory * const pd = ppgtt->base.pd;
	struct i915_page_table *pt;
	unsigned int pde;
+19 −18
Original line number Diff line number Diff line
@@ -453,20 +453,21 @@ gen8_ppgtt_insert_pte(struct i915_ppgtt *ppgtt,
	return idx;
}

static void gen8_ppgtt_insert_huge(struct i915_vma *vma,
static void gen8_ppgtt_insert_huge(struct i915_address_space *vm,
				   struct i915_vma_resource *vma_res,
				   struct sgt_dma *iter,
				   enum i915_cache_level cache_level,
				   u32 flags)
{
	const gen8_pte_t pte_encode = gen8_pte_encode(0, cache_level, flags);
	unsigned int rem = sg_dma_len(iter->sg);
	u64 start = vma->node.start;
	u64 start = vma_res->start;

	GEM_BUG_ON(!i915_vm_is_4lvl(vma->vm));
	GEM_BUG_ON(!i915_vm_is_4lvl(vm));

	do {
		struct i915_page_directory * const pdp =
			gen8_pdp_for_page_address(vma->vm, start);
			gen8_pdp_for_page_address(vm, start);
		struct i915_page_directory * const pd =
			i915_pd_entry(pdp, __gen8_pte_index(start, 2));
		gen8_pte_t encode = pte_encode;
@@ -475,7 +476,7 @@ static void gen8_ppgtt_insert_huge(struct i915_vma *vma,
		gen8_pte_t *vaddr;
		u16 index;

		if (vma->page_sizes.sg & I915_GTT_PAGE_SIZE_2M &&
		if (vma_res->bi.page_sizes.sg & I915_GTT_PAGE_SIZE_2M &&
		    IS_ALIGNED(iter->dma, I915_GTT_PAGE_SIZE_2M) &&
		    rem >= I915_GTT_PAGE_SIZE_2M &&
		    !__gen8_pte_index(start, 0)) {
@@ -492,7 +493,7 @@ static void gen8_ppgtt_insert_huge(struct i915_vma *vma,
			page_size = I915_GTT_PAGE_SIZE;

			if (!index &&
			    vma->page_sizes.sg & I915_GTT_PAGE_SIZE_64K &&
			    vma_res->bi.page_sizes.sg & I915_GTT_PAGE_SIZE_64K &&
			    IS_ALIGNED(iter->dma, I915_GTT_PAGE_SIZE_64K) &&
			    (IS_ALIGNED(rem, I915_GTT_PAGE_SIZE_64K) ||
			     rem >= (I915_PDES - index) * I915_GTT_PAGE_SIZE))
@@ -541,9 +542,9 @@ static void gen8_ppgtt_insert_huge(struct i915_vma *vma,
		 */
		if (maybe_64K != -1 &&
		    (index == I915_PDES ||
		     (i915_vm_has_scratch_64K(vma->vm) &&
		      !iter->sg && IS_ALIGNED(vma->node.start +
					      vma->node.size,
		     (i915_vm_has_scratch_64K(vm) &&
		      !iter->sg && IS_ALIGNED(vma_res->start +
					      vma_res->node_size,
					      I915_GTT_PAGE_SIZE_2M)))) {
			vaddr = px_vaddr(pd);
			vaddr[maybe_64K] |= GEN8_PDE_IPS_64K;
@@ -559,10 +560,10 @@ static void gen8_ppgtt_insert_huge(struct i915_vma *vma,
			 * instead - which we detect as missing results during
			 * selftests.
			 */
			if (I915_SELFTEST_ONLY(vma->vm->scrub_64K)) {
			if (I915_SELFTEST_ONLY(vm->scrub_64K)) {
				u16 i;

				encode = vma->vm->scratch[0]->encode;
				encode = vm->scratch[0]->encode;
				vaddr = px_vaddr(i915_pt_entry(pd, maybe_64K));

				for (i = 1; i < index; i += 16)
@@ -572,22 +573,22 @@ static void gen8_ppgtt_insert_huge(struct i915_vma *vma,
			}
		}

		vma->page_sizes.gtt |= page_size;
		vma_res->page_sizes_gtt |= page_size;
	} while (iter->sg && sg_dma_len(iter->sg));
}

static void gen8_ppgtt_insert(struct i915_address_space *vm,
			      struct i915_vma *vma,
			      struct i915_vma_resource *vma_res,
			      enum i915_cache_level cache_level,
			      u32 flags)
{
	struct i915_ppgtt * const ppgtt = i915_vm_to_ppgtt(vm);
	struct sgt_dma iter = sgt_dma(vma);
	struct sgt_dma iter = sgt_dma(vma_res);

	if (vma->page_sizes.sg > I915_GTT_PAGE_SIZE) {
		gen8_ppgtt_insert_huge(vma, &iter, cache_level, flags);
	if (vma_res->bi.page_sizes.sg > I915_GTT_PAGE_SIZE) {
		gen8_ppgtt_insert_huge(vm, vma_res, &iter, cache_level, flags);
	} else  {
		u64 idx = vma->node.start >> GEN8_PTE_SHIFT;
		u64 idx = vma_res->start >> GEN8_PTE_SHIFT;

		do {
			struct i915_page_directory * const pdp =
@@ -597,7 +598,7 @@ static void gen8_ppgtt_insert(struct i915_address_space *vm,
						    cache_level, flags);
		} while (idx);

		vma->page_sizes.gtt = I915_GTT_PAGE_SIZE;
		vma_res->page_sizes_gtt = I915_GTT_PAGE_SIZE;
	}
}

Loading