[PATCH 18/21] drm/i915: Add an implementation for i915_gem_ww_ctx locking, v2.

Chris Wilson chris at chris-wilson.co.uk
Sat Jul 4 22:37:48 UTC 2020


From: Maarten Lankhorst <maarten.lankhorst at linux.intel.com>

i915_gem_ww_ctx is used to lock all gem bo's for pinning and memory
eviction. We don't use it yet, but lets start adding the definition
first.

To use it, we have to pass a non-NULL ww to gem_object_lock, and don't
unlock directly. It is done in i915_gem_ww_ctx_fini.

Changes since v1:
- Change ww_ctx and obj order in locking functions (Jonas Lahtinen)

Signed-off-by: Maarten Lankhorst <maarten.lankhorst at linux.intel.com>
---
 drivers/gpu/drm/i915/Makefile                 |   4 +
 drivers/gpu/drm/i915/gem/i915_gem_object.h    |   8 +-
 .../gpu/drm/i915/gem/i915_gem_object_types.h  |   9 ++
 drivers/gpu/drm/i915/mm/i915_acquire_ctx.c    | 108 ++++++++++++++++++
 drivers/gpu/drm/i915/mm/i915_acquire_ctx.h    |  34 ++++++
 5 files changed, 159 insertions(+), 4 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/mm/i915_acquire_ctx.c
 create mode 100644 drivers/gpu/drm/i915/mm/i915_acquire_ctx.h

diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index 41a27fd5dbc7..33c85b4ff3ed 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -124,6 +124,10 @@ gt-y += \
 	gt/gen9_renderstate.o
 i915-y += $(gt-y)
 
+# Memory + DMA management
+i915-y += \
+	mm/i915_acquire_ctx.o
+
 # GEM (Graphics Execution Management) code
 gem-y += \
 	gem/i915_gem_busy.o \
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.h b/drivers/gpu/drm/i915/gem/i915_gem_object.h
index 25714bf70b6a..450fa51570de 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_object.h
+++ b/drivers/gpu/drm/i915/gem/i915_gem_object.h
@@ -110,14 +110,14 @@ i915_gem_object_put(struct drm_i915_gem_object *obj)
 
 #define assert_object_held(obj) dma_resv_assert_held((obj)->base.resv)
 
-static inline void i915_gem_object_lock(struct drm_i915_gem_object *obj)
+static inline bool i915_gem_object_trylock(struct drm_i915_gem_object *obj)
 {
-	dma_resv_lock(obj->base.resv, NULL);
+	return dma_resv_trylock(obj->base.resv);
 }
 
-static inline bool i915_gem_object_trylock(struct drm_i915_gem_object *obj)
+static inline void i915_gem_object_lock(struct drm_i915_gem_object *obj)
 {
-	return dma_resv_trylock(obj->base.resv);
+	dma_resv_lock(obj->base.resv, NULL);
 }
 
 static inline int
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 d0847d7896f9..80b2cdd3875f 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_object_types.h
+++ b/drivers/gpu/drm/i915/gem/i915_gem_object_types.h
@@ -206,6 +206,15 @@ struct drm_i915_gem_object {
 		 */
 		struct list_head region_link;
 
+		/**
+		 * @acquire_link: Link into @i915_acquire_ctx.list
+		 *
+		 * When we lock this object through i915_gem_object_lock() with a
+		 * context, we add it to the list to ensure we can unlock everything
+		 * when i915_gem_ww_ctx_backoff() or i915_gem_ww_ctx_fini() are called.
+		 */
+		struct list_head acquire_link;
+
 		struct sg_table *pages;
 		void *mapping;
 
diff --git a/drivers/gpu/drm/i915/mm/i915_acquire_ctx.c b/drivers/gpu/drm/i915/mm/i915_acquire_ctx.c
new file mode 100644
index 000000000000..180a04874125
--- /dev/null
+++ b/drivers/gpu/drm/i915/mm/i915_acquire_ctx.c
@@ -0,0 +1,108 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2020 Intel Corporation
+ */
+
+#include <linux/dma-resv.h>
+
+#include "gem/i915_gem_object.h"
+
+#include "i915_acquire_ctx.h"
+
+void i915_acquire_ctx_init(struct i915_acquire_ctx *ctx)
+{
+	ww_acquire_init(&ctx->ctx, &reservation_ww_class);
+	INIT_LIST_HEAD(&ctx->acquire_list);
+}
+
+int i915_acquire_ctx_lock(struct i915_acquire_ctx *ctx,
+			  struct drm_i915_gem_object *obj)
+{
+	int err;
+
+	err = dma_resv_lock_interruptible(obj->base.resv, &ctx->ctx);
+	if (!err) {
+		list_add_tail(&obj->mm.acquire_link, &ctx->acquire_list);
+		i915_gem_object_get(obj);
+	}
+	if (err == -EALREADY)
+		err = 0;
+
+	return err;
+}
+
+static void i915_acquire_ctx_unlock_all(struct i915_acquire_ctx *ctx)
+{
+	struct drm_i915_gem_object *obj, *on;
+
+	list_for_each_entry_safe(obj, on, &ctx->acquire_list, mm.acquire_link) {
+		i915_gem_object_unlock(obj);
+		i915_gem_object_put(obj);
+	}
+	INIT_LIST_HEAD(&ctx->acquire_list);
+}
+
+int i915_acquire_ctx_backoff(struct i915_acquire_ctx *ctx,
+			     struct drm_i915_gem_object *obj)
+{
+	int err;
+
+	i915_acquire_ctx_unlock_all(ctx);
+
+	err = dma_resv_lock_slow_interruptible(obj->base.resv, &ctx->ctx);
+	if (!err) {
+		list_add_tail(&obj->mm.acquire_link, &ctx->acquire_list);
+		i915_gem_object_get(obj);
+	}
+
+	return err;
+}
+
+void i915_acquire_ctx_fini(struct i915_acquire_ctx *ctx)
+{
+	i915_acquire_ctx_unlock_all(ctx);
+	ww_acquire_fini(&ctx->ctx);
+}
+
+#if 0
+static int igt_acquire_ctx(void *arg)
+{
+	struct drm_i915_private *i915 = arg;
+	struct drm_i915_gem_object *obj, *obj2;
+	struct i915_acquire_ctx acquire;
+	int err = 0;
+
+	obj = i915_gem_object_create_internal(i915, PAGE_SIZE);
+	if (IS_ERR(obj))
+		return PTR_ERR(obj);
+
+	obj2 = i915_gem_object_create_internal(i915, PAGE_SIZE);
+	if (IS_ERR(obj)) {
+		err = PTR_ERR(obj);
+		goto put1;
+	}
+
+	i915_acquire_ctx_init(&acquire, true);
+retry:
+	/* Lock the objects, twice for good measure (-EALREADY handling) */
+	err = i915_gem_object_lock(obj, &acquire);
+	if (!err)
+		err = i915_gem_object_lock_interruptible(obj, &acquire);
+	if (!err)
+		err = i915_gem_object_lock_interruptible(obj2, &acquire);
+	if (!err)
+		err = i915_gem_object_lock(obj2, &acquire);
+
+	if (err == -EDEADLK) {
+		err = i915_acquire_ctx_backoff(&acquire);
+		if (!err)
+			goto retry;
+	}
+	i915_acquire_ctx_fini(&acquire);
+	i915_gem_object_put(obj2);
+put1:
+	i915_gem_object_put(obj);
+	return err;
+}
+
+#endif
diff --git a/drivers/gpu/drm/i915/mm/i915_acquire_ctx.h b/drivers/gpu/drm/i915/mm/i915_acquire_ctx.h
new file mode 100644
index 000000000000..8f3d7d4ab9c2
--- /dev/null
+++ b/drivers/gpu/drm/i915/mm/i915_acquire_ctx.h
@@ -0,0 +1,34 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2020 Intel Corporation
+ */
+
+#ifndef __I915_ACQIURE_CTX_H__
+#define __I915_ACQUIRE_CTX_H__
+
+#include <linux/list.h>
+#include <linux/ww_mutex.h>
+
+struct drm_i915_gem_object;
+
+struct i915_acquire_ctx {
+	struct ww_acquire_ctx ctx;
+	struct list_head acquire_list;
+};
+
+void i915_acquire_ctx_init(struct i915_acquire_ctx *acquire);
+
+static inline void i915_acquire_ctx_done(struct i915_acquire_ctx *acquire)
+{
+	ww_acquire_done(&acquire->ctx);
+}
+
+void i915_acquire_ctx_fini(struct i915_acquire_ctx *acquire);
+
+int __must_check i915_acquire_ctx_lock(struct i915_acquire_ctx *acquire,
+				       struct drm_i915_gem_object *obj);
+
+int __must_check i915_acquire_ctx_backoff(struct i915_acquire_ctx *ctx,
+					  struct drm_i915_gem_object *obj);
+
+#endif /* __I915_ACQUIRE_CTX_H__ */
-- 
2.20.1



More information about the Intel-gfx-trybot mailing list