[PATCH 61/61] drm/i915/gem: Improve coordination of page domains

Chris Wilson chris at chris-wilson.co.uk
Tue Jun 23 20:02:23 UTC 2020


Explicitly control which read/write domains we serialise when acquiring
the pages for internal temporary access, and use this information to
coordinate with outstanding and future fences without waiting, or
performing the clflushing, underneath the reservation_ww_class lock.
In particular, we take the opportunity to restore the ability to
concurrently read from multiple contexts, previously lost by the
installation of the exclusive fence.

Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
---
 drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c    |  26 +--
 drivers/gpu/drm/i915/gem/i915_gem_domain.c    | 204 ++----------------
 drivers/gpu/drm/i915/gem/i915_gem_fence.c     | 178 +++++++++++++--
 drivers/gpu/drm/i915/gem/i915_gem_object.h    |  30 +--
 drivers/gpu/drm/i915/gem/i915_gem_pages.c     |   2 +-
 drivers/gpu/drm/i915/gem/i915_gem_pm.c        |   3 +-
 .../gpu/drm/i915/gem/selftests/huge_pages.c   |  22 +-
 .../i915/gem/selftests/i915_gem_coherency.c   |  87 +++++---
 .../drm/i915/gem/selftests/i915_gem_context.c |  45 ++--
 .../drm/i915/gem/selftests/i915_gem_mman.c    |  26 +--
 .../drm/i915/gem/selftests/i915_gem_phys.c    |  11 +-
 drivers/gpu/drm/i915/i915_gem.c               | 108 ++++------
 drivers/gpu/drm/i915/selftests/i915_vma.c     |  10 +-
 13 files changed, 349 insertions(+), 403 deletions(-)

diff --git a/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c b/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
index 049a15e6b496..4c2dc8677e1f 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
@@ -121,30 +121,24 @@ static int i915_gem_dmabuf_mmap(struct dma_buf *dma_buf, struct vm_area_struct *
 static int i915_gem_begin_cpu_access(struct dma_buf *dma_buf, enum dma_data_direction direction)
 {
 	struct drm_i915_gem_object *obj = dma_buf_to_obj(dma_buf);
-	bool write = (direction == DMA_BIDIRECTIONAL || direction == DMA_TO_DEVICE);
-	int err;
+	unsigned int write;
 
-	err = i915_gem_object_lock_interruptible(obj);
-	if (err)
-		return err;
+	write = 0;
+	if (direction == DMA_BIDIRECTIONAL || direction == DMA_TO_DEVICE)
+		write = I915_GEM_DOMAIN_CPU;
 
-	err = i915_gem_object_set_to_cpu_domain(obj, write);
-	i915_gem_object_unlock(obj);
-	return err;
+	return i915_gem_object_acquire_pages_barrier(obj,
+						     I915_GEM_DOMAIN_CPU,
+						     write);
 }
 
 static int i915_gem_end_cpu_access(struct dma_buf *dma_buf, enum dma_data_direction direction)
 {
 	struct drm_i915_gem_object *obj = dma_buf_to_obj(dma_buf);
-	int err;
 
-	err = i915_gem_object_lock_interruptible(obj);
-	if (err)
-		return err;
-
-	err = i915_gem_object_set_to_gtt_domain(obj, false);
-	i915_gem_object_unlock(obj);
-	return err;
+	return i915_gem_object_acquire_pages_barrier(obj,
+						     I915_GEM_DOMAIN_GTT,
+						     0);
 }
 
 static const struct dma_buf_ops i915_dmabuf_ops =  {
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_domain.c b/drivers/gpu/drm/i915/gem/i915_gem_domain.c
index 2ee42a58bfee..d11ffc102dcc 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_domain.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_domain.c
@@ -97,24 +97,16 @@ void i915_gem_object_flush_if_display(struct drm_i915_gem_object *obj)
  * This function returns when the move is complete, including waiting on
  * flushes to occur.
  */
-int
+void
 i915_gem_object_set_to_wc_domain(struct drm_i915_gem_object *obj, bool write)
 {
-	int ret;
-
 	assert_object_held(obj);
 
-	ret = i915_gem_object_wait(obj,
-				   I915_WAIT_INTERRUPTIBLE |
-				   (write ? I915_WAIT_ALL : 0),
-				   MAX_SCHEDULE_TIMEOUT);
-	if (ret)
-		return ret;
-
 	if (obj->write_domain == I915_GEM_DOMAIN_WC)
-		return 0;
+		return;
 
-	/* Flush and acquire obj->pages so that we are coherent through
+	/*
+	 * Flush and acquire obj->pages so that we are coherent through
 	 * direct access in memory with previous cached writes through
 	 * shmemfs and that our cache domain tracking remains valid.
 	 * For example, if the obj->filp was moved to swap without us
@@ -122,20 +114,18 @@ i915_gem_object_set_to_wc_domain(struct drm_i915_gem_object *obj, bool write)
 	 * continue to assume that the obj remained out of the CPU cached
 	 * domain.
 	 */
-	ret = __i915_gem_object_get_pages_locked(obj);
-	if (ret)
-		return ret;
-
 	flush_write_domains(obj, ~I915_GEM_DOMAIN_WC);
 
-	/* Serialise direct access to this object with the barriers for
+	/*
+	 * Serialise direct access to this object with the barriers for
 	 * coherent writes from the GPU, by effectively invalidating the
 	 * WC domain upon first access.
 	 */
 	if ((obj->read_domains & I915_GEM_DOMAIN_WC) == 0)
 		mb();
 
-	/* It should now be out of any other write domains, and we can update
+	/*
+	 * It should now be out of any other write domains, and we can update
 	 * the domain values for our changes.
 	 */
 	GEM_BUG_ON((obj->write_domain & ~I915_GEM_DOMAIN_WC) != 0);
@@ -145,9 +135,6 @@ i915_gem_object_set_to_wc_domain(struct drm_i915_gem_object *obj, bool write)
 		obj->write_domain = I915_GEM_DOMAIN_WC;
 		obj->mm.dirty = true;
 	}
-
-	i915_gem_object_unpin_pages(obj);
-	return 0;
 }
 
 /**
@@ -158,34 +145,13 @@ i915_gem_object_set_to_wc_domain(struct drm_i915_gem_object *obj, bool write)
  * This function returns when the move is complete, including waiting on
  * flushes to occur.
  */
-int
+void
 i915_gem_object_set_to_gtt_domain(struct drm_i915_gem_object *obj, bool write)
 {
-	int ret;
-
 	assert_object_held(obj);
 
-	ret = i915_gem_object_wait(obj,
-				   I915_WAIT_INTERRUPTIBLE |
-				   (write ? I915_WAIT_ALL : 0),
-				   MAX_SCHEDULE_TIMEOUT);
-	if (ret)
-		return ret;
-
 	if (obj->write_domain == I915_GEM_DOMAIN_GTT)
-		return 0;
-
-	/* Flush and acquire obj->pages so that we are coherent through
-	 * direct access in memory with previous cached writes through
-	 * shmemfs and that our cache domain tracking remains valid.
-	 * For example, if the obj->filp was moved to swap without us
-	 * being notified and releasing the pages, we would mistakenly
-	 * continue to assume that the obj remained out of the CPU cached
-	 * domain.
-	 */
-	ret = __i915_gem_object_get_pages_locked(obj);
-	if (ret)
-		return ret;
+		return;
 
 	flush_write_domains(obj, ~I915_GEM_DOMAIN_GTT);
 
@@ -214,9 +180,6 @@ i915_gem_object_set_to_gtt_domain(struct drm_i915_gem_object *obj, bool write)
 				i915_vma_set_ggtt_write(vma);
 		spin_unlock(&obj->vma.lock);
 	}
-
-	i915_gem_object_unpin_pages(obj);
-	return 0;
 }
 
 /**
@@ -465,20 +428,11 @@ i915_gem_object_unpin_from_display_plane(struct i915_vma *vma)
  * This function returns when the move is complete, including waiting on
  * flushes to occur.
  */
-int
+void
 i915_gem_object_set_to_cpu_domain(struct drm_i915_gem_object *obj, bool write)
 {
-	int ret;
-
 	assert_object_held(obj);
 
-	ret = i915_gem_object_wait(obj,
-				   I915_WAIT_INTERRUPTIBLE |
-				   (write ? I915_WAIT_ALL : 0),
-				   MAX_SCHEDULE_TIMEOUT);
-	if (ret)
-		return ret;
-
 	flush_write_domains(obj, ~I915_GEM_DOMAIN_CPU);
 
 	/* Flush the CPU cache if it's still invalid. */
@@ -497,8 +451,6 @@ i915_gem_object_set_to_cpu_domain(struct drm_i915_gem_object *obj, bool write)
 	 */
 	if (write)
 		__start_cpu_write(obj);
-
-	return 0;
 }
 
 /**
@@ -584,141 +536,13 @@ i915_gem_set_domain_ioctl(struct drm_device *dev, void *data,
 	 * continue to assume that the obj remained out of the CPU cached
 	 * domain.
 	 */
-	err = i915_gem_object_lock_interruptible(obj);
-	if (err)
-		goto out;
-
-	if (read_domains & I915_GEM_DOMAIN_WC)
-		err = i915_gem_object_set_to_wc_domain(obj, write_domain);
-	else if (read_domains & I915_GEM_DOMAIN_GTT)
-		err = i915_gem_object_set_to_gtt_domain(obj, write_domain);
-	else
-		err = i915_gem_object_set_to_cpu_domain(obj, write_domain);
-
+	err = i915_gem_object_acquire_pages_barrier(obj,
+						    read_domains,
+						    write_domain);
 	/* And bump the LRU for this access */
 	i915_gem_object_bump_inactive_ggtt(obj);
 
-	i915_gem_object_unlock(obj);
-
-	if (write_domain)
-		i915_gem_object_invalidate_frontbuffer(obj, ORIGIN_CPU);
-
 out:
 	i915_gem_object_put(obj);
 	return err;
 }
-
-/*
- * Pins the specified object's pages and synchronizes the object with
- * GPU accesses. Sets needs_clflush to non-zero if the caller should
- * flush the object from the CPU cache.
- */
-int i915_gem_object_prepare_read(struct drm_i915_gem_object *obj,
-				 unsigned int *needs_clflush)
-{
-	int ret;
-
-	assert_object_held(obj);
-
-	*needs_clflush = 0;
-	if (!i915_gem_object_has_struct_page(obj))
-		return -ENODEV;
-
-	ret = __i915_gem_object_get_pages_locked(obj);
-	if (ret)
-		return ret;
-
-	ret = i915_gem_object_wait(obj,
-				   I915_WAIT_INTERRUPTIBLE,
-				   MAX_SCHEDULE_TIMEOUT);
-	if (ret)
-		goto err_unpin;
-
-	if (obj->cache_coherent & I915_BO_CACHE_COHERENT_FOR_READ ||
-	    !static_cpu_has(X86_FEATURE_CLFLUSH)) {
-		ret = i915_gem_object_set_to_cpu_domain(obj, false);
-		if (ret)
-			goto err_unpin;
-		else
-			goto out;
-	}
-
-	flush_write_domains(obj, ~I915_GEM_DOMAIN_CPU);
-
-	/* If we're not in the cpu read domain, set ourself into the gtt
-	 * read domain and manually flush cachelines (if required). This
-	 * optimizes for the case when the gpu will dirty the data
-	 * anyway again before the next pread happens.
-	 */
-	if (!obj->cache_dirty &&
-	    !(obj->read_domains & I915_GEM_DOMAIN_CPU))
-		*needs_clflush = CLFLUSH_BEFORE;
-
-out:
-	/* return with the pages pinned */
-	return 0;
-
-err_unpin:
-	i915_gem_object_unpin_pages(obj);
-	return ret;
-}
-
-int i915_gem_object_prepare_write(struct drm_i915_gem_object *obj,
-				  unsigned int *needs_clflush)
-{
-	int ret;
-
-	assert_object_held(obj);
-
-	*needs_clflush = 0;
-	if (!i915_gem_object_has_struct_page(obj))
-		return -ENODEV;
-
-	ret = __i915_gem_object_get_pages_locked(obj);
-	if (ret)
-		return ret;
-
-	ret = i915_gem_object_wait(obj,
-				   I915_WAIT_INTERRUPTIBLE |
-				   I915_WAIT_ALL,
-				   MAX_SCHEDULE_TIMEOUT);
-	if (ret)
-		goto err_unpin;
-
-	if (obj->cache_coherent & I915_BO_CACHE_COHERENT_FOR_WRITE ||
-	    !static_cpu_has(X86_FEATURE_CLFLUSH)) {
-		ret = i915_gem_object_set_to_cpu_domain(obj, true);
-		if (ret)
-			goto err_unpin;
-		else
-			goto out;
-	}
-
-	flush_write_domains(obj, ~I915_GEM_DOMAIN_CPU);
-
-	/* If we're not in the cpu write domain, set ourself into the
-	 * gtt write domain and manually flush cachelines (as required).
-	 * This optimizes for the case when the gpu will use the data
-	 * right away and we therefore have to clflush anyway.
-	 */
-	if (!obj->cache_dirty) {
-		*needs_clflush |= CLFLUSH_AFTER;
-
-		/*
-		 * Same trick applies to invalidate partially written
-		 * cachelines read before writing.
-		 */
-		if (!(obj->read_domains & I915_GEM_DOMAIN_CPU))
-			*needs_clflush |= CLFLUSH_BEFORE;
-	}
-
-out:
-	i915_gem_object_invalidate_frontbuffer(obj, ORIGIN_CPU);
-	obj->mm.dirty = true;
-	/* return with the pages pinned */
-	return 0;
-
-err_unpin:
-	i915_gem_object_unpin_pages(obj);
-	return ret;
-}
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_fence.c b/drivers/gpu/drm/i915/gem/i915_gem_fence.c
index 8ab842c80f99..b752d62b13ae 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_fence.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_fence.c
@@ -4,12 +4,15 @@
  * Copyright © 2019 Intel Corporation
  */
 
+#include "gt/intel_gt.h"
+
 #include "i915_drv.h"
 #include "i915_gem_object.h"
 
 struct stub_fence {
 	struct dma_fence dma;
 	struct i915_sw_fence chain;
+	unsigned int flush_domain;
 };
 
 static int __i915_sw_fence_call
@@ -19,7 +22,6 @@ stub_notify(struct i915_sw_fence *fence, enum i915_sw_fence_notify state)
 
 	switch (state) {
 	case FENCE_COMPLETE:
-		dma_fence_signal(&stub->dma);
 		break;
 
 	case FENCE_FREE:
@@ -56,40 +58,186 @@ static const struct dma_fence_ops stub_fence_ops = {
 	.release = stub_release,
 };
 
+static bool gpu_write_needs_clflush(struct drm_i915_gem_object *obj)
+{
+	if (obj->write_domain != I915_GEM_DOMAIN_RENDER)
+		return false;
+
+	return !(obj->cache_level == I915_CACHE_NONE ||
+		 obj->cache_level == I915_CACHE_WT);
+}
+
 struct dma_fence *
-i915_gem_object_lock_fence(struct drm_i915_gem_object *obj)
+i915_gem_object_acquire_pages_fence(struct drm_i915_gem_object *obj,
+				    unsigned int read_domains,
+				    unsigned int write_domain,
+				    unsigned int *needs_clflush)
 {
 	struct stub_fence *stub;
-
-	assert_object_held(obj);
+	struct i915_vma *vma;
+	unsigned int old = 0;
+	bool clflush = false;
+	int err;
+
+	if (needs_clflush) {
+		*needs_clflush = 0;
+		if (!static_cpu_has(X86_FEATURE_CLFLUSH))
+			needs_clflush = NULL;
+	}
 
 	stub = kmalloc(sizeof(*stub), GFP_KERNEL);
 	if (!stub)
-		return NULL;
+		return ERR_PTR(-ENOMEM);
 
 	i915_sw_fence_init(&stub->chain, stub_notify);
 	dma_fence_init(&stub->dma, &stub_fence_ops, &stub->chain.wait.lock,
 		       0, 0);
+	dma_fence_get(&stub->dma);
+
+	i915_gem_object_lock(obj);
+
+	err = dma_resv_reserve_shared(obj->base.resv, 1);
+	if (err)
+		goto err;
+
+	err = ____i915_gem_object_get_pages_async(obj);
+	if (err)
+		goto err;
+
+	err = i915_sw_fence_await_active(&stub->chain,
+					 &obj->mm.active,
+					 I915_ACTIVE_AWAIT_EXCL);
+	if (err)
+		goto err;
 
-	if (i915_sw_fence_await_reservation(&stub->chain,
-					    obj->base.resv, NULL, true,
-					    i915_fence_timeout(to_i915(obj->base.dev)),
-					    I915_FENCE_GFP) < 0)
+	err = i915_sw_fence_await_reservation(&stub->chain,
+					      obj->base.resv, NULL,
+					      write_domain,
+					      i915_fence_timeout(to_i915(obj->base.dev)),
+					      I915_FENCE_GFP);
+	if (err < 0)
 		goto err;
 
-	dma_resv_add_excl_fence(obj->base.resv, &stub->dma);
+	err = i915_active_ref(&obj->mm.active, 0, &stub->dma);
+	if (err)
+		goto err;
+
+	if (gpu_write_needs_clflush(obj))
+		obj->cache_dirty = true;
+
+	if (obj->write_domain != read_domains) {
+		old = obj->write_domain;
+		obj->write_domain = 0;
+	}
+
+	if (!needs_clflush || read_domains & ~I915_GEM_DOMAIN_CPU) {
+		if(read_domains & ~obj->read_domains & I915_GEM_DOMAIN_CPU) {
+			clflush = obj->cache_dirty;
+			obj->cache_dirty = false;
+		}
+		if (write_domain) {
+			obj->read_domains = 0;
+			obj->write_domain = write_domain;
+			if (write_domain & I915_GEM_DOMAIN_CPU)
+				obj->cache_dirty = true;
+		}
+		obj->read_domains |= read_domains;
+	} else if (!obj->cache_dirty) {
+		if (!(obj->read_domains & I915_GEM_DOMAIN_CPU) &&
+		    !(obj->cache_coherent & I915_BO_CACHE_COHERENT_FOR_READ))
+			*needs_clflush |= CLFLUSH_BEFORE;
+
+		if (write_domain & I915_GEM_DOMAIN_CPU &&
+		    !(obj->cache_coherent & I915_BO_CACHE_COHERENT_FOR_WRITE))
+			*needs_clflush |= CLFLUSH_AFTER;
+	}
+
+	if (write_domain)
+		dma_resv_add_excl_fence(obj->base.resv, &stub->dma);
+	else
+		dma_resv_add_shared_fence(obj->base.resv, &stub->dma);
+
+	stub->flush_domain = write_domain;
+	obj->mm.dirty |= write_domain;
+
+	i915_gem_object_unlock(obj);
+
+	i915_sw_fence_commit(&stub->chain);
+
+	if (wait_event_interruptible(stub->chain.wait,
+				     i915_sw_fence_done(&stub->chain))) {
+		dma_fence_put(&stub->dma);
+		return ERR_PTR(-EINTR);
+	}
+
+	if (stub->chain.error) {
+		dma_fence_signal(&stub->dma);
+		dma_fence_put(&stub->dma);
+		return ERR_PTR(stub->chain.error);
+	}
+
+	if (old & I915_GEM_DOMAIN_GTT) {
+		spin_lock(&obj->vma.lock);
+		for_each_ggtt_vma(vma, obj) {
+			if (i915_vma_unset_ggtt_write(vma))
+				intel_gt_flush_ggtt_writes(vma->vm->gt);
+		}
+		spin_unlock(&obj->vma.lock);
+	}
+	if (clflush || old & I915_GEM_DOMAIN_CPU)
+		drm_clflush_sg(obj->mm.pages);
+	rmb();
+
+	if (write_domain)
+		i915_gem_object_invalidate_frontbuffer(obj, ORIGIN_CPU);
 
 	return &stub->dma;
 
 err:
-	stub_release(&stub->dma);
-	return NULL;
+	i915_gem_object_unlock(obj);
+	i915_sw_fence_commit(&stub->chain);
+	dma_fence_signal(&stub->dma);
+	dma_fence_put(&stub->dma);
+	return ERR_PTR(err);
 }
 
-void i915_gem_object_unlock_fence(struct drm_i915_gem_object *obj,
-				  struct dma_fence *fence)
+void i915_gem_object_release_pages_fence(struct drm_i915_gem_object *obj,
+					 struct dma_fence *fence)
 {
 	struct stub_fence *stub = container_of(fence, typeof(*stub), dma);
+	struct i915_vma *vma;
 
-	i915_sw_fence_commit(&stub->chain);
+	wmb();
+
+	if (stub->flush_domain & I915_GEM_DOMAIN_GTT) {
+		spin_lock(&obj->vma.lock);
+		for_each_ggtt_vma(vma, obj)
+			if (i915_vma_is_bound(vma, I915_VMA_GLOBAL_BIND))
+				i915_vma_set_ggtt_write(vma);
+		spin_unlock(&obj->vma.lock);
+	}
+
+	if (stub->flush_domain)
+		i915_gem_object_flush_frontbuffer(obj, ORIGIN_CPU);
+
+	dma_fence_signal(fence);
+	dma_fence_put(fence);
+}
+
+int
+i915_gem_object_acquire_pages_barrier(struct drm_i915_gem_object *obj,
+				      unsigned int read_domains,
+				      unsigned int write_domain)
+{
+	struct dma_fence *fence;
+
+	fence = i915_gem_object_acquire_pages_fence(obj,
+						    read_domains,
+						    write_domain,
+						    NULL);
+	if (IS_ERR(fence))
+		return PTR_ERR(fence);
+
+	i915_gem_object_release_pages_fence(obj, fence);
+	return 0;
 }
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.h b/drivers/gpu/drm/i915/gem/i915_gem_object.h
index fdfecbb3346f..549a413fbd2d 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_object.h
+++ b/drivers/gpu/drm/i915/gem/i915_gem_object.h
@@ -132,9 +132,19 @@ static inline void i915_gem_object_unlock(struct drm_i915_gem_object *obj)
 }
 
 struct dma_fence *
-i915_gem_object_lock_fence(struct drm_i915_gem_object *obj);
-void i915_gem_object_unlock_fence(struct drm_i915_gem_object *obj,
-				  struct dma_fence *fence);
+i915_gem_object_acquire_pages_fence(struct drm_i915_gem_object *obj,
+				    unsigned int read_domains,
+				    unsigned int write_domain,
+				    unsigned int *needs_clflush);
+#define CLFLUSH_BEFORE	BIT(0)
+#define CLFLUSH_AFTER	BIT(1)
+void i915_gem_object_release_pages_fence(struct drm_i915_gem_object *obj,
+					 struct dma_fence *fence);
+
+int
+i915_gem_object_acquire_pages_barrier(struct drm_i915_gem_object *obj,
+				      unsigned int read_domains,
+				      unsigned int write_domain);
 
 static inline void
 i915_gem_object_set_readonly(struct drm_i915_gem_object *obj)
@@ -392,14 +402,6 @@ void
 i915_gem_object_flush_write_domain(struct drm_i915_gem_object *obj,
 				   unsigned int flush_domains);
 
-int i915_gem_object_prepare_read(struct drm_i915_gem_object *obj,
-				 unsigned int *needs_clflush);
-int i915_gem_object_prepare_write(struct drm_i915_gem_object *obj,
-				  unsigned int *needs_clflush);
-#define CLFLUSH_BEFORE	BIT(0)
-#define CLFLUSH_AFTER	BIT(1)
-#define CLFLUSH_FLAGS	(CLFLUSH_BEFORE | CLFLUSH_AFTER)
-
 static inline void
 i915_gem_object_finish_access(struct drm_i915_gem_object *obj)
 {
@@ -427,11 +429,11 @@ void i915_gem_object_set_cache_coherency(struct drm_i915_gem_object *obj,
 					 unsigned int cache_level);
 void i915_gem_object_flush_if_display(struct drm_i915_gem_object *obj);
 
-int __must_check
+void
 i915_gem_object_set_to_wc_domain(struct drm_i915_gem_object *obj, bool write);
-int __must_check
+void
 i915_gem_object_set_to_gtt_domain(struct drm_i915_gem_object *obj, bool write);
-int __must_check
+void
 i915_gem_object_set_to_cpu_domain(struct drm_i915_gem_object *obj, bool write);
 struct i915_vma * __must_check
 i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj,
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_pages.c b/drivers/gpu/drm/i915/gem/i915_gem_pages.c
index 1dd31527ffe0..4f07743d979f 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_pages.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_pages.c
@@ -483,7 +483,7 @@ i915_gem_object_get_sg(struct drm_i915_gem_object *obj,
 
 	might_sleep();
 	GEM_BUG_ON(n >= obj->base.size >> PAGE_SHIFT);
-	GEM_BUG_ON(!i915_gem_object_has_pinned_pages(obj));
+	GEM_BUG_ON(!i915_gem_object_has_pages(obj));
 
 	/* As we iterate forward through the sg, we record each entry in a
 	 * radixtree for quick repeated (backwards) lookups. If we have seen
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_pm.c b/drivers/gpu/drm/i915/gem/i915_gem_pm.c
index 3d215164dd5a..43b0b967ef6a 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_pm.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_pm.c
@@ -85,8 +85,7 @@ void i915_gem_suspend_late(struct drm_i915_private *i915)
 			spin_unlock_irqrestore(&i915->mm.obj_lock, flags);
 
 			i915_gem_object_lock(obj);
-			drm_WARN_ON(&i915->drm,
-			    i915_gem_object_set_to_gtt_domain(obj, false));
+			i915_gem_object_set_to_gtt_domain(obj, false);
 			i915_gem_object_unlock(obj);
 			i915_gem_object_put(obj);
 
diff --git a/drivers/gpu/drm/i915/gem/selftests/huge_pages.c b/drivers/gpu/drm/i915/gem/selftests/huge_pages.c
index 6ff7c402556e..120670df1519 100644
--- a/drivers/gpu/drm/i915/gem/selftests/huge_pages.c
+++ b/drivers/gpu/drm/i915/gem/selftests/huge_pages.c
@@ -950,13 +950,9 @@ static int gpu_write(struct intel_context *ce,
 		     u32 dw,
 		     u32 val)
 {
-	int err;
-
 	i915_gem_object_lock(vma->obj);
-	err = i915_gem_object_set_to_gtt_domain(vma->obj, true);
+	i915_gem_object_set_to_gtt_domain(vma->obj, true);
 	i915_gem_object_unlock(vma->obj);
-	if (err)
-		return err;
 
 	return igt_gpu_fill_dw(ce, vma, dw * sizeof(u32),
 			       vma->size >> PAGE_SHIFT, val);
@@ -966,13 +962,15 @@ static int
 __cpu_check_shmem(struct drm_i915_gem_object *obj, u32 dword, u32 val)
 {
 	unsigned int needs_flush;
+	struct dma_fence *fence;
 	unsigned long n;
-	int err;
+	int err = 0;
 
-	i915_gem_object_lock(obj);
-	err = i915_gem_object_prepare_read(obj, &needs_flush);
-	if (err)
-		goto unlock;
+	fence = i915_gem_object_acquire_pages_fence(obj,
+						    I915_GEM_DOMAIN_CPU, 0,
+						    &needs_flush);
+	if (IS_ERR(fence))
+		return PTR_ERR(fence);
 
 	for (n = 0; n < obj->base.size >> PAGE_SHIFT; ++n) {
 		u32 *ptr = kmap_atomic(i915_gem_object_get_page(obj, n));
@@ -991,9 +989,7 @@ __cpu_check_shmem(struct drm_i915_gem_object *obj, u32 dword, u32 val)
 		kunmap_atomic(ptr);
 	}
 
-	i915_gem_object_finish_access(obj);
-unlock:
-	i915_gem_object_unlock(obj);
+	i915_gem_object_release_pages_fence(obj, fence);
 	return err;
 }
 
diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_coherency.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_coherency.c
index 58e9f68b815f..cf478ea1e548 100644
--- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_coherency.c
+++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_coherency.c
@@ -22,15 +22,17 @@ struct context {
 static int cpu_set(struct context *ctx, unsigned long offset, u32 v)
 {
 	unsigned int needs_clflush;
+	struct dma_fence *fence;
 	struct page *page;
 	void *map;
 	u32 *cpu;
-	int err;
 
-	i915_gem_object_lock(ctx->obj);
-	err = i915_gem_object_prepare_write(ctx->obj, &needs_clflush);
-	if (err)
-		goto unlock;
+	fence = i915_gem_object_acquire_pages_fence(ctx->obj,
+						    I915_GEM_DOMAIN_CPU,
+						    I915_GEM_DOMAIN_CPU,
+						    &needs_clflush);
+	if (IS_ERR(fence))
+		return PTR_ERR(fence);
 
 	page = i915_gem_object_get_page(ctx->obj, offset >> PAGE_SHIFT);
 	map = kmap_atomic(page);
@@ -45,25 +47,24 @@ static int cpu_set(struct context *ctx, unsigned long offset, u32 v)
 		drm_clflush_virt_range(cpu, sizeof(*cpu));
 
 	kunmap_atomic(map);
-	i915_gem_object_finish_access(ctx->obj);
 
-unlock:
-	i915_gem_object_unlock(ctx->obj);
-	return err;
+	i915_gem_object_release_pages_fence(ctx->obj, fence);
+	return 0;
 }
 
 static int cpu_get(struct context *ctx, unsigned long offset, u32 *v)
 {
 	unsigned int needs_clflush;
+	struct dma_fence *fence;
 	struct page *page;
 	void *map;
 	u32 *cpu;
-	int err;
 
-	i915_gem_object_lock(ctx->obj);
-	err = i915_gem_object_prepare_read(ctx->obj, &needs_clflush);
-	if (err)
-		goto unlock;
+	fence = i915_gem_object_acquire_pages_fence(ctx->obj,
+						    I915_GEM_DOMAIN_CPU, 0,
+						    &needs_clflush);
+	if (IS_ERR(fence))
+		return PTR_ERR(fence);
 
 	page = i915_gem_object_get_page(ctx->obj, offset >> PAGE_SHIFT);
 	map = kmap_atomic(page);
@@ -75,24 +76,24 @@ static int cpu_get(struct context *ctx, unsigned long offset, u32 *v)
 	*v = *cpu;
 
 	kunmap_atomic(map);
-	i915_gem_object_finish_access(ctx->obj);
 
-unlock:
-	i915_gem_object_unlock(ctx->obj);
-	return err;
+	i915_gem_object_release_pages_fence(ctx->obj, fence);
+	return 0;
 }
 
 static int gtt_set(struct context *ctx, unsigned long offset, u32 v)
 {
+	struct dma_fence *fence;
 	struct i915_vma *vma;
 	u32 __iomem *map;
 	int err = 0;
 
-	i915_gem_object_lock(ctx->obj);
-	err = i915_gem_object_set_to_gtt_domain(ctx->obj, true);
-	i915_gem_object_unlock(ctx->obj);
-	if (err)
-		return err;
+	fence = i915_gem_object_acquire_pages_fence(ctx->obj,
+						    I915_GEM_DOMAIN_GTT,
+						    I915_GEM_DOMAIN_GTT,
+						    NULL);
+	if (IS_ERR(fence))
+		return PTR_ERR(fence);
 
 	vma = i915_gem_object_ggtt_pin(ctx->obj, NULL, 0, 0, PIN_MAPPABLE);
 	if (IS_ERR(vma))
@@ -112,20 +113,22 @@ static int gtt_set(struct context *ctx, unsigned long offset, u32 v)
 
 out_rpm:
 	intel_gt_pm_put(vma->vm->gt);
+	i915_gem_object_release_pages_fence(ctx->obj, fence);
 	return err;
 }
 
 static int gtt_get(struct context *ctx, unsigned long offset, u32 *v)
 {
+	struct dma_fence *fence;
 	struct i915_vma *vma;
 	u32 __iomem *map;
 	int err = 0;
 
-	i915_gem_object_lock(ctx->obj);
-	err = i915_gem_object_set_to_gtt_domain(ctx->obj, false);
-	i915_gem_object_unlock(ctx->obj);
-	if (err)
-		return err;
+	fence = i915_gem_object_acquire_pages_fence(ctx->obj,
+						    I915_GEM_DOMAIN_GTT, 0,
+						    NULL);
+	if (IS_ERR(fence))
+		return PTR_ERR(fence);
 
 	vma = i915_gem_object_ggtt_pin(ctx->obj, NULL, 0, 0, PIN_MAPPABLE);
 	if (IS_ERR(vma))
@@ -145,13 +148,22 @@ static int gtt_get(struct context *ctx, unsigned long offset, u32 *v)
 
 out_rpm:
 	intel_gt_pm_put(vma->vm->gt);
+	i915_gem_object_release_pages_fence(ctx->obj, fence);
 	return err;
 }
 
 static int map_set(struct context *ctx, unsigned long offset, u32 v)
 {
+	struct dma_fence *fence;
 	u32 *map;
 
+	fence = i915_gem_object_acquire_pages_fence(ctx->obj,
+						    I915_GEM_DOMAIN_WC,
+						    I915_GEM_DOMAIN_WC,
+						    NULL);
+	if (IS_ERR(fence))
+		return PTR_ERR(fence);
+
 	map = i915_gem_object_pin_map(ctx->obj, I915_MAP_WC);
 	if (IS_ERR(map))
 		return PTR_ERR(map);
@@ -160,14 +172,22 @@ static int map_set(struct context *ctx, unsigned long offset, u32 v)
 	__i915_gem_object_flush_map(ctx->obj, offset, sizeof(*map));
 
 	i915_gem_object_unpin_map(ctx->obj);
+	i915_gem_object_release_pages_fence(ctx->obj, fence);
 
 	return 0;
 }
 
 static int map_get(struct context *ctx, unsigned long offset, u32 *v)
 {
+	struct dma_fence *fence;
 	u32 *map;
 
+	fence = i915_gem_object_acquire_pages_fence(ctx->obj,
+						    I915_GEM_DOMAIN_WC, 0,
+						    NULL);
+	if (IS_ERR(fence))
+		return PTR_ERR(fence);
+
 	map = i915_gem_object_pin_map(ctx->obj, I915_MAP_WC);
 	if (IS_ERR(map))
 		return PTR_ERR(map);
@@ -176,6 +196,7 @@ static int map_get(struct context *ctx, unsigned long offset, u32 *v)
 	*v = map[offset / sizeof(*map)];
 
 	i915_gem_object_unpin_map(ctx->obj);
+	i915_gem_object_release_pages_fence(ctx->obj, fence);
 
 	return 0;
 }
@@ -187,16 +208,14 @@ static int gpu_set(struct context *ctx, unsigned long offset, u32 v)
 	u32 *cs;
 	int err;
 
-	i915_gem_object_lock(ctx->obj);
-	err = i915_gem_object_set_to_gtt_domain(ctx->obj, true);
-	i915_gem_object_unlock(ctx->obj);
-	if (err)
-		return err;
-
 	vma = i915_gem_object_ggtt_pin(ctx->obj, NULL, 0, 0, 0);
 	if (IS_ERR(vma))
 		return PTR_ERR(vma);
 
+	i915_gem_object_lock(ctx->obj);
+	i915_gem_object_set_to_gtt_domain(ctx->obj, true);
+	i915_gem_object_unlock(ctx->obj);
+
 	rq = intel_engine_create_kernel_request(ctx->engine);
 	if (IS_ERR(rq)) {
 		i915_vma_unpin(vma);
diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c
index 6abf36e076eb..1ff829d04e73 100644
--- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c
+++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c
@@ -458,13 +458,15 @@ static int gpu_fill(struct intel_context *ce,
 static int cpu_fill(struct drm_i915_gem_object *obj, u32 value)
 {
 	const bool has_llc = HAS_LLC(to_i915(obj->base.dev));
-	unsigned int n, m, need_flush;
-	int err;
+	struct dma_fence *fence;
+	unsigned int n, m;
 
-	i915_gem_object_lock(obj);
-	err = i915_gem_object_prepare_write(obj, &need_flush);
-	if (err)
-		goto unlock;
+	fence = i915_gem_object_acquire_pages_fence(obj,
+						    I915_GEM_DOMAIN_CPU,
+						    I915_GEM_DOMAIN_CPU,
+						    NULL);
+	if (IS_ERR(fence))
+		return PTR_ERR(fence);
 
 	for (n = 0; n < real_page_count(obj); n++) {
 		u32 *map;
@@ -477,11 +479,10 @@ static int cpu_fill(struct drm_i915_gem_object *obj, u32 value)
 		kunmap_atomic(map);
 	}
 
-	i915_gem_object_finish_access(obj);
 	obj->read_domains = I915_GEM_DOMAIN_GTT | I915_GEM_DOMAIN_CPU;
 	obj->write_domain = 0;
-unlock:
-	i915_gem_object_unlock(obj);
+
+	i915_gem_object_release_pages_fence(obj, fence);
 	return 0;
 }
 
@@ -489,12 +490,14 @@ static noinline int cpu_check(struct drm_i915_gem_object *obj,
 			      unsigned int idx, unsigned int max)
 {
 	unsigned int n, m, needs_flush;
-	int err;
+	struct dma_fence *fence;
+	int err = 0;
 
-	i915_gem_object_lock(obj);
-	err = i915_gem_object_prepare_read(obj, &needs_flush);
-	if (err)
-		goto unlock;
+	fence = i915_gem_object_acquire_pages_fence(obj,
+						    I915_GEM_DOMAIN_CPU, 0,
+						    &needs_flush);
+	if (IS_ERR(fence))
+		return PTR_ERR(fence);
 
 	for (n = 0; n < real_page_count(obj); n++) {
 		u32 *map;
@@ -530,9 +533,7 @@ static noinline int cpu_check(struct drm_i915_gem_object *obj,
 			break;
 	}
 
-	i915_gem_object_finish_access(obj);
-unlock:
-	i915_gem_object_unlock(obj);
+	i915_gem_object_release_pages_fence(obj, fence);
 	return err;
 }
 
@@ -956,16 +957,14 @@ emit_rpcs_query(struct drm_i915_gem_object *obj,
 	if (IS_ERR(vma))
 		return PTR_ERR(vma);
 
-	i915_gem_object_lock(obj);
-	err = i915_gem_object_set_to_gtt_domain(obj, false);
-	i915_gem_object_unlock(obj);
-	if (err)
-		return err;
-
 	err = i915_vma_pin(vma, 0, 0, PIN_USER);
 	if (err)
 		return err;
 
+	i915_gem_object_lock(obj);
+	i915_gem_object_set_to_gtt_domain(obj, false);
+	i915_gem_object_unlock(obj);
+
 	batch = rpcs_query_batch(vma);
 	if (IS_ERR(batch)) {
 		err = PTR_ERR(batch);
diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c
index 11f734fea3ab..36d545d67d87 100644
--- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c
+++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c
@@ -84,6 +84,7 @@ static int check_partial_mapping(struct drm_i915_gem_object *obj,
 {
 	const unsigned long npages = obj->base.size / PAGE_SIZE;
 	struct i915_ggtt_view view;
+	struct dma_fence *fence;
 	struct i915_vma *vma;
 	unsigned long page;
 	u32 __iomem *io;
@@ -103,12 +104,14 @@ static int check_partial_mapping(struct drm_i915_gem_object *obj,
 	GEM_BUG_ON(i915_gem_object_get_tiling(obj) != tile->tiling);
 	GEM_BUG_ON(i915_gem_object_get_stride(obj) != tile->stride);
 
-	i915_gem_object_lock(obj);
-	err = i915_gem_object_set_to_gtt_domain(obj, true);
-	i915_gem_object_unlock(obj);
-	if (err) {
-		pr_err("Failed to flush to GTT write domain; err=%d\n", err);
-		return err;
+	fence = i915_gem_object_acquire_pages_fence(obj,
+						    I915_GEM_DOMAIN_GTT,
+						    I915_GEM_DOMAIN_GTT,
+						    NULL);
+	if (IS_ERR(fence)) {
+		pr_err("Failed to flush to GTT write domain; err=%ld\n",
+		       PTR_ERR(fence));
+		return PTR_ERR(fence);
 	}
 
 	page = i915_prandom_u32_max_state(npages, prng);
@@ -118,7 +121,8 @@ static int check_partial_mapping(struct drm_i915_gem_object *obj,
 	if (IS_ERR(vma)) {
 		pr_err("Failed to pin partial view: offset=%lu; err=%d\n",
 		       page, (int)PTR_ERR(vma));
-		return PTR_ERR(vma);
+		err = PTR_ERR(vma);
+		goto out_fence;
 	}
 
 	n = page - view.partial.offset;
@@ -165,6 +169,8 @@ static int check_partial_mapping(struct drm_i915_gem_object *obj,
 
 out:
 	__i915_vma_put(vma);
+out_fence:
+	i915_gem_object_release_pages_fence(obj, fence);
 	return err;
 }
 
@@ -189,12 +195,8 @@ static int check_partial_mappings(struct drm_i915_gem_object *obj,
 	GEM_BUG_ON(i915_gem_object_get_stride(obj) != tile->stride);
 
 	i915_gem_object_lock(obj);
-	err = i915_gem_object_set_to_gtt_domain(obj, true);
+	i915_gem_object_set_to_gtt_domain(obj, true);
 	i915_gem_object_unlock(obj);
-	if (err) {
-		pr_err("Failed to flush to GTT write domain; err=%d\n", err);
-		return err;
-	}
 
 	for_each_prime_number_from(page, 1, npages) {
 		struct i915_ggtt_view view =
diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_phys.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_phys.c
index 34932871b3a5..1e46969f491e 100644
--- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_phys.c
+++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_phys.c
@@ -44,14 +44,9 @@ static int mock_phys_object(void *arg)
 	}
 
 	/* Make the object dirty so that put_pages must do copy back the data */
-	i915_gem_object_lock(obj);
-	err = i915_gem_object_set_to_gtt_domain(obj, true);
-	i915_gem_object_unlock(obj);
-	if (err) {
-		pr_err("i915_gem_object_set_to_gtt_domain failed with err=%d\n",
-		       err);
-		goto out_obj;
-	}
+	err = i915_gem_object_acquire_pages_barrier(obj,
+						    I915_GEM_DOMAIN_GTT,
+						    I915_GEM_DOMAIN_GTT);
 
 out_obj:
 	i915_gem_object_put(obj);
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 0fbe438c4523..cac61956725f 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -307,7 +307,7 @@ i915_gem_create_ioctl(struct drm_device *dev, void *data,
 
 static int
 shmem_pread(struct page *page, int offset, int len, char __user *user_data,
-	    bool needs_clflush)
+	    unsigned int needs_clflush)
 {
 	char *vaddr;
 	int ret;
@@ -328,25 +328,20 @@ static int
 i915_gem_shmem_pread(struct drm_i915_gem_object *obj,
 		     struct drm_i915_gem_pread *args)
 {
-	unsigned int needs_clflush;
-	unsigned int idx, offset;
+	unsigned int idx, offset, needs_clflush;
 	struct dma_fence *fence;
 	char __user *user_data;
+	int ret = 0;
 	u64 remain;
-	int ret;
 
-	i915_gem_object_lock(obj);
-	ret = i915_gem_object_prepare_read(obj, &needs_clflush);
-	if (ret) {
-		i915_gem_object_unlock(obj);
-		return ret;
-	}
+	if (!i915_gem_object_has_struct_page(obj))
+		return -ENODEV;
 
-	fence = i915_gem_object_lock_fence(obj);
-	i915_gem_object_finish_access(obj);
-	i915_gem_object_unlock(obj);
-	if (!fence)
-		return -ENOMEM;
+	fence = i915_gem_object_acquire_pages_fence(obj,
+						    I915_GEM_DOMAIN_CPU, 0,
+						    &needs_clflush);
+	if (IS_ERR(fence))
+		return PTR_ERR(fence);
 
 	remain = args->size;
 	user_data = u64_to_user_ptr(args->data_ptr);
@@ -365,7 +360,7 @@ i915_gem_shmem_pread(struct drm_i915_gem_object *obj,
 		offset = 0;
 	}
 
-	i915_gem_object_unlock_fence(obj, fence);
+	i915_gem_object_release_pages_fence(obj, fence);
 	return ret;
 }
 
@@ -405,7 +400,7 @@ i915_gem_gtt_pread(struct drm_i915_gem_object *obj,
 	void __user *user_data;
 	struct i915_vma *vma;
 	u64 remain, offset;
-	int ret;
+	int ret = 0;
 
 	wakeref = intel_runtime_pm_get(&i915->runtime_pm);
 	vma = ERR_PTR(-ENODEV);
@@ -424,20 +419,11 @@ i915_gem_gtt_pread(struct drm_i915_gem_object *obj,
 		GEM_BUG_ON(!drm_mm_node_allocated(&node));
 	}
 
-	ret = i915_gem_object_lock_interruptible(obj);
-	if (ret)
-		goto out_unpin;
-
-	ret = i915_gem_object_set_to_gtt_domain(obj, false);
-	if (ret) {
-		i915_gem_object_unlock(obj);
-		goto out_unpin;
-	}
-
-	fence = i915_gem_object_lock_fence(obj);
-	i915_gem_object_unlock(obj);
-	if (!fence) {
-		ret = -ENOMEM;
+	fence = i915_gem_object_acquire_pages_fence(obj,
+						    I915_GEM_DOMAIN_GTT, 0,
+						    NULL);
+	if (IS_ERR(fence)) {
+		ret = PTR_ERR(fence);
 		goto out_unpin;
 	}
 
@@ -475,7 +461,7 @@ i915_gem_gtt_pread(struct drm_i915_gem_object *obj,
 		offset += page_length;
 	}
 
-	i915_gem_object_unlock_fence(obj, fence);
+	i915_gem_object_release_pages_fence(obj, fence);
 out_unpin:
 	if (drm_mm_node_allocated(&node)) {
 		ggtt->vm.clear_range(&ggtt->vm, node.start, node.size);
@@ -589,7 +575,7 @@ i915_gem_gtt_pwrite_fast(struct drm_i915_gem_object *obj,
 	struct i915_vma *vma;
 	u64 remain, offset;
 	void __user *user_data;
-	int ret;
+	int ret = 0;
 
 	if (i915_gem_object_has_struct_page(obj)) {
 		/*
@@ -623,20 +609,12 @@ i915_gem_gtt_pwrite_fast(struct drm_i915_gem_object *obj,
 		GEM_BUG_ON(!drm_mm_node_allocated(&node));
 	}
 
-	ret = i915_gem_object_lock_interruptible(obj);
-	if (ret)
-		goto out_unpin;
-
-	ret = i915_gem_object_set_to_gtt_domain(obj, true);
-	if (ret) {
-		i915_gem_object_unlock(obj);
-		goto out_unpin;
-	}
-
-	fence = i915_gem_object_lock_fence(obj);
-	i915_gem_object_unlock(obj);
-	if (!fence) {
-		ret = -ENOMEM;
+	fence = i915_gem_object_acquire_pages_fence(obj,
+						    I915_GEM_DOMAIN_GTT,
+						    I915_GEM_DOMAIN_GTT,
+						    NULL);
+	if (IS_ERR(fence)) {
+		ret = PTR_ERR(fence);
 		goto out_unpin;
 	}
 
@@ -683,10 +661,7 @@ i915_gem_gtt_pwrite_fast(struct drm_i915_gem_object *obj,
 		offset += page_length;
 	}
 
-	intel_gt_flush_ggtt_writes(ggtt->vm.gt);
-	i915_gem_object_flush_frontbuffer(obj, ORIGIN_CPU);
-
-	i915_gem_object_unlock_fence(obj, fence);
+	i915_gem_object_release_pages_fence(obj, fence);
 out_unpin:
 	if (drm_mm_node_allocated(&node)) {
 		ggtt->vm.clear_range(&ggtt->vm, node.start, node.size);
@@ -735,23 +710,21 @@ i915_gem_shmem_pwrite(struct drm_i915_gem_object *obj,
 	unsigned int offset, idx;
 	struct dma_fence *fence;
 	void __user *user_data;
+	int ret = 0;
 	u64 remain;
-	int ret;
 
-	i915_gem_object_lock(obj);
-	ret = i915_gem_object_prepare_write(obj, &needs_clflush);
-	if (ret) {
-		i915_gem_object_unlock(obj);
-		return ret;
-	}
+	if (!i915_gem_object_has_struct_page(obj))
+		return -ENODEV;
 
-	fence = i915_gem_object_lock_fence(obj);
-	i915_gem_object_finish_access(obj);
-	i915_gem_object_unlock(obj);
-	if (!fence)
-		return -ENOMEM;
+	fence = i915_gem_object_acquire_pages_fence(obj,
+						    I915_GEM_DOMAIN_CPU,
+						    I915_GEM_DOMAIN_CPU,
+						    &needs_clflush);
+	if (IS_ERR(fence))
+		return PTR_ERR(fence);
 
-	/* If we don't overwrite a cacheline completely we need to be
+	/*
+	 * If we don't overwrite a cacheline completely we need to be
 	 * careful to have up-to-date data by first clflushing. Don't
 	 * overcomplicate things and flush the entire patch.
 	 */
@@ -777,9 +750,7 @@ i915_gem_shmem_pwrite(struct drm_i915_gem_object *obj,
 		offset = 0;
 	}
 
-	i915_gem_object_flush_frontbuffer(obj, ORIGIN_CPU);
-	i915_gem_object_unlock_fence(obj, fence);
-
+	i915_gem_object_release_pages_fence(obj, fence);
 	return ret;
 }
 
@@ -1306,8 +1277,7 @@ int i915_gem_freeze_late(struct drm_i915_private *i915)
 
 	list_for_each_entry(obj, &i915->mm.shrink_list, mm.link) {
 		i915_gem_object_lock(obj);
-		drm_WARN_ON(&i915->drm,
-			    i915_gem_object_set_to_cpu_domain(obj, true));
+		i915_gem_object_set_to_cpu_domain(obj, true);
 		i915_gem_object_unlock(obj);
 	}
 
diff --git a/drivers/gpu/drm/i915/selftests/i915_vma.c b/drivers/gpu/drm/i915/selftests/i915_vma.c
index af89c7fc8f59..c41e978eb293 100644
--- a/drivers/gpu/drm/i915/selftests/i915_vma.c
+++ b/drivers/gpu/drm/i915/selftests/i915_vma.c
@@ -892,12 +892,6 @@ static int igt_vma_remapped_gtt(void *arg)
 			unsigned int x, y;
 			int err;
 
-			i915_gem_object_lock(obj);
-			err = i915_gem_object_set_to_gtt_domain(obj, true);
-			i915_gem_object_unlock(obj);
-			if (err)
-				goto out;
-
 			vma = i915_gem_object_ggtt_pin(obj, &view, 0, 0, PIN_MAPPABLE);
 			if (IS_ERR(vma)) {
 				err = PTR_ERR(vma);
@@ -913,6 +907,10 @@ static int igt_vma_remapped_gtt(void *arg)
 				goto out;
 			}
 
+			i915_gem_object_lock(obj);
+			i915_gem_object_set_to_gtt_domain(obj, true);
+			i915_gem_object_unlock(obj);
+
 			for (y = 0 ; y < p->height; y++) {
 				for (x = 0 ; x < p->width; x++) {
 					unsigned int offset;
-- 
2.20.1



More information about the Intel-gfx-trybot mailing list