[PATCH 55/56] mm-active
Chris Wilson
chris at chris-wilson.co.uk
Sat Jun 20 18:31:25 UTC 2020
---
drivers/gpu/drm/i915/gem/i915_gem_object.c | 23 +++++++++++++
.../gpu/drm/i915/gem/i915_gem_object_types.h | 2 ++
drivers/gpu/drm/i915/gem/i915_gem_pages.c | 33 +++++++++++++++++--
drivers/gpu/drm/i915/i915_active.c | 18 ++++++++++
drivers/gpu/drm/i915/i915_active.h | 7 ++++
drivers/gpu/drm/i915/i915_vma.c | 8 +++++
6 files changed, 88 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.c b/drivers/gpu/drm/i915/gem/i915_gem_object.c
index 37b3fb0eb943..b7fc0da239f5 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_object.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_object.c
@@ -26,6 +26,7 @@
#include "display/intel_frontbuffer.h"
#include "gt/intel_gt.h"
+#include "i915_active.h"
#include "i915_drv.h"
#include "i915_gem_clflush.h"
#include "i915_gem_context.h"
@@ -49,6 +50,24 @@ void i915_gem_object_free(struct drm_i915_gem_object *obj)
return kmem_cache_free(global.slab_objects, obj);
}
+static int i915_mm_active(struct i915_active *ref)
+{
+ struct drm_i915_gem_object *obj =
+ container_of(ref, typeof(*obj), mm.active);
+
+ i915_gem_object_get(obj);
+ return 0;
+}
+
+__i915_active_call
+static void i915_mm_retire(struct i915_active *ref)
+{
+ struct drm_i915_gem_object *obj =
+ container_of(ref, typeof(*obj), mm.active);
+
+ i915_gem_object_put(obj);
+}
+
void i915_gem_object_init(struct drm_i915_gem_object *obj,
const struct drm_i915_gem_object_ops *ops,
struct lock_class_key *key)
@@ -70,6 +89,8 @@ void i915_gem_object_init(struct drm_i915_gem_object *obj,
obj->mm.madv = I915_MADV_WILLNEED;
INIT_RADIX_TREE(&obj->mm.get_page.radix, GFP_KERNEL | __GFP_NOWARN);
mutex_init(&obj->mm.get_page.lock);
+
+ i915_active_init(&obj->mm.active, i915_mm_active, i915_mm_retire);
}
/**
@@ -149,6 +170,8 @@ static void __i915_gem_free_object_rcu(struct rcu_head *head)
container_of(head, typeof(*obj), rcu);
struct drm_i915_private *i915 = to_i915(obj->base.dev);
+ i915_active_fini(&obj->mm.active);
+
dma_resv_fini(&obj->base._resv);
i915_gem_object_free(obj);
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object_types.h b/drivers/gpu/drm/i915/gem/i915_gem_object_types.h
index dbb33aac7828..668b249fd109 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_object_types.h
+++ b/drivers/gpu/drm/i915/gem/i915_gem_object_types.h
@@ -189,6 +189,8 @@ struct drm_i915_gem_object {
atomic_t pages_pin_count;
atomic_t shrink_pin;
+ struct i915_active active;
+
/**
* Memory region for this object.
*/
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_pages.c b/drivers/gpu/drm/i915/gem/i915_gem_pages.c
index be051239e0ac..cfc29043cbf0 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_pages.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_pages.c
@@ -81,6 +81,20 @@ void __i915_gem_object_set_pages(struct drm_i915_gem_object *obj,
}
}
+static int __i915_gem_object_wait_for_pages(struct drm_i915_gem_object *obj)
+{
+ int err;
+
+ err = i915_active_wait_for_exclusive(&obj->mm.active);
+ if (err)
+ return err;
+
+ if (IS_ERR(obj->mm.pages))
+ return PTR_ERR(obj->mm.pages);
+
+ return 0;
+}
+
int ____i915_gem_object_get_pages(struct drm_i915_gem_object *obj)
{
struct drm_i915_private *i915 = to_i915(obj->base.dev);
@@ -92,10 +106,18 @@ int ____i915_gem_object_get_pages(struct drm_i915_gem_object *obj)
return -EFAULT;
}
- err = obj->ops->get_pages(obj);
- GEM_BUG_ON(!err && !i915_gem_object_has_pages(obj));
+ if (!i915_active_has_exclusive(&obj->mm.active)) {
+ err = i915_active_acquire(&obj->mm.active);
+ if (err)
+ return err;
- return err;
+ err = obj->ops->get_pages(obj);
+ i915_active_release(&obj->mm.active);
+ if (err)
+ return err;
+ }
+
+ return __i915_gem_object_wait_for_pages(obj);
}
/* Ensure that the associated pages are gathered from the backing storage
@@ -201,6 +223,7 @@ __i915_gem_object_unset_pages(struct drm_i915_gem_object *obj)
int __i915_gem_object_put_pages(struct drm_i915_gem_object *obj)
{
struct sg_table *pages;
+ int err;
/* May be called by shrinker from within get_pages() (on another bo) */
lockdep_assert_held(&obj->base.resv->lock.base);
@@ -211,6 +234,10 @@ int __i915_gem_object_put_pages(struct drm_i915_gem_object *obj)
if (unlikely(atomic_read(&obj->mm.pages_pin_count)))
return -EBUSY;
+ err = i915_active_wait(&obj->mm.active);
+ if (err)
+ return err;
+
i915_gem_object_release_mmap_offset(obj);
/*
diff --git a/drivers/gpu/drm/i915/i915_active.c b/drivers/gpu/drm/i915/i915_active.c
index 71ad0d452680..a0dd8fc20b8e 100644
--- a/drivers/gpu/drm/i915/i915_active.c
+++ b/drivers/gpu/drm/i915/i915_active.c
@@ -1077,6 +1077,24 @@ int i915_active_fence_set(struct i915_active_fence *active,
return err;
}
+int i915_active_fence_wait(struct i915_active_fence *active)
+{
+ struct dma_fence *fence;
+ int err;
+
+ if (GEM_WARN_ON(is_barrier(active)))
+ return -EBUSY;
+
+ fence = i915_active_fence_get(active);
+ if (!fence)
+ return 0;
+
+ err = dma_fence_wait(fence, true);
+ dma_fence_put(fence);
+
+ return err;
+}
+
void i915_active_noop(struct dma_fence *fence, struct dma_fence_cb *cb)
{
active_fence_cb(fence, cb);
diff --git a/drivers/gpu/drm/i915/i915_active.h b/drivers/gpu/drm/i915/i915_active.h
index 042502abefe5..923ed27497d8 100644
--- a/drivers/gpu/drm/i915/i915_active.h
+++ b/drivers/gpu/drm/i915/i915_active.h
@@ -123,6 +123,8 @@ i915_active_fence_isset(const struct i915_active_fence *active)
return rcu_access_pointer(active->fence);
}
+int i915_active_fence_wait(struct i915_active_fence *active);
+
/*
* GPU activity tracking
*
@@ -190,6 +192,11 @@ static inline int i915_active_wait(struct i915_active *ref)
return __i915_active_wait(ref, TASK_INTERRUPTIBLE);
}
+static inline int i915_active_wait_for_exclusive(struct i915_active *ref)
+{
+ return i915_active_fence_wait(&ref->excl);
+}
+
int i915_sw_fence_await_active(struct i915_sw_fence *fence,
struct i915_active *ref,
unsigned int flags);
diff --git a/drivers/gpu/drm/i915/i915_vma.c b/drivers/gpu/drm/i915/i915_vma.c
index efb9eacf59b9..9717a8f05c63 100644
--- a/drivers/gpu/drm/i915/i915_vma.c
+++ b/drivers/gpu/drm/i915/i915_vma.c
@@ -435,6 +435,8 @@ int i915_vma_bind(struct i915_vma *vma,
* execution and not content or object's backing store lifetime.
*/
prev = i915_active_set_exclusive(&vma->active, &work->base.dma);
+ if (!prev && vma->obj)
+ prev = i915_active_fence_get(&vma->obj->mm.active.excl);
if (prev) {
__i915_sw_fence_await_dma_fence(&work->base.chain,
prev,
@@ -449,6 +451,12 @@ int i915_vma_bind(struct i915_vma *vma,
work->pinned = vma->obj;
}
} else {
+ if (vma->obj) {
+ ret = i915_active_wait_for_exclusive(&vma->obj->mm.active);
+ if (ret)
+ return ret;
+ }
+
ret = vma->ops->bind_vma(vma, cache_level, bind_flags);
if (ret)
return ret;
--
2.20.1
More information about the Intel-gfx-trybot
mailing list