[PATCH 38/44] sync-gfp

Chris Wilson chris at chris-wilson.co.uk
Sat Jul 14 18:07:02 UTC 2018


---
 drivers/gpu/drm/i915/i915_syncmap.c           |  20 +--
 drivers/gpu/drm/i915/i915_syncmap.h           |   3 +-
 drivers/gpu/drm/i915/i915_timeline.h          |   2 +-
 drivers/gpu/drm/i915/selftests/i915_syncmap.c | 117 ++++++++++++++++--
 4 files changed, 125 insertions(+), 17 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_syncmap.c b/drivers/gpu/drm/i915/i915_syncmap.c
index 58f8d0cc125c..ae8c9d84b5dc 100644
--- a/drivers/gpu/drm/i915/i915_syncmap.c
+++ b/drivers/gpu/drm/i915/i915_syncmap.c
@@ -196,11 +196,11 @@ bool i915_syncmap_is_later(struct i915_syncmap **root, u64 id, u32 seqno)
 }
 
 static struct i915_syncmap *
-__sync_alloc_leaf(struct i915_syncmap *parent, u64 id)
+__sync_alloc_leaf(struct i915_syncmap *parent, u64 id, gfp_t gfp)
 {
 	struct i915_syncmap *p;
 
-	p = kmalloc(sizeof(*p) + KSYNCMAP * sizeof(u32), GFP_KERNEL);
+	p = kmalloc(sizeof(*p) + KSYNCMAP * sizeof(u32), gfp);
 	if (unlikely(!p))
 		return NULL;
 
@@ -227,13 +227,14 @@ static inline void __sync_set_child(struct i915_syncmap *p,
 	__sync_child(p)[idx] = child;
 }
 
-static noinline int __sync_set(struct i915_syncmap **root, u64 id, u32 seqno)
+static noinline int __sync_set(struct i915_syncmap **root,
+			       u64 id, u32 seqno, gfp_t gfp)
 {
 	struct i915_syncmap *p = *root;
 	unsigned int idx;
 
 	if (!p) {
-		p = __sync_alloc_leaf(NULL, id);
+		p = __sync_alloc_leaf(NULL, id, gfp);
 		if (unlikely(!p))
 			return -ENOMEM;
 
@@ -283,7 +284,7 @@ static noinline int __sync_set(struct i915_syncmap **root, u64 id, u32 seqno)
 
 			/* Insert a join above the current layer */
 			next = kzalloc(sizeof(*next) + KSYNCMAP * sizeof(next),
-				       GFP_KERNEL);
+				       gfp);
 			if (unlikely(!next))
 				return -ENOMEM;
 
@@ -318,7 +319,7 @@ static noinline int __sync_set(struct i915_syncmap **root, u64 id, u32 seqno)
 		idx = __sync_branch_idx(p, id);
 		next = __sync_child(p)[idx];
 		if (!next) {
-			next = __sync_alloc_leaf(p, id);
+			next = __sync_alloc_leaf(p, id, gfp);
 			if (unlikely(!next))
 				return -ENOMEM;
 
@@ -350,10 +351,13 @@ static noinline int __sync_set(struct i915_syncmap **root, u64 id, u32 seqno)
  *
  * Returns 0 on success, or a negative error code.
  */
-int i915_syncmap_set(struct i915_syncmap **root, u64 id, u32 seqno)
+int i915_syncmap_set(struct i915_syncmap **root,
+		     u64 id, u32 seqno, gfp_t gfp)
 {
 	struct i915_syncmap *p = *root;
 
+	might_sleep_if(gfpflags_allow_blocking(gfp));
+
 	/*
 	 * We expect to be called in sequence following is_later(id), which
 	 * should have preloaded the root for us.
@@ -363,7 +367,7 @@ int i915_syncmap_set(struct i915_syncmap **root, u64 id, u32 seqno)
 		return 0;
 	}
 
-	return __sync_set(root, id, seqno);
+	return __sync_set(root, id, seqno, gfp);
 }
 
 static void __sync_free(struct i915_syncmap *p)
diff --git a/drivers/gpu/drm/i915/i915_syncmap.h b/drivers/gpu/drm/i915/i915_syncmap.h
index 0653f70bee82..aacf5d9f0f5a 100644
--- a/drivers/gpu/drm/i915/i915_syncmap.h
+++ b/drivers/gpu/drm/i915/i915_syncmap.h
@@ -26,12 +26,13 @@
 #define __I915_SYNCMAP_H__
 
 #include <linux/types.h>
+#include <linux/gfp.h>
 
 struct i915_syncmap;
 #define KSYNCMAP 16 /* radix of the tree, how many slots in each layer */
 
 void i915_syncmap_init(struct i915_syncmap **root);
-int i915_syncmap_set(struct i915_syncmap **root, u64 id, u32 seqno);
+int i915_syncmap_set(struct i915_syncmap **root, u64 id, u32 seqno, gfp_t gfp);
 bool i915_syncmap_is_later(struct i915_syncmap **root, u64 id, u32 seqno);
 void i915_syncmap_free(struct i915_syncmap **root);
 
diff --git a/drivers/gpu/drm/i915/i915_timeline.h b/drivers/gpu/drm/i915/i915_timeline.h
index b5321dc2d5a5..8a50c6e599d8 100644
--- a/drivers/gpu/drm/i915/i915_timeline.h
+++ b/drivers/gpu/drm/i915/i915_timeline.h
@@ -103,7 +103,7 @@ static inline void i915_timeline_put(struct i915_timeline *timeline)
 static inline int __i915_timeline_sync_set(struct i915_timeline *tl,
 					   u64 context, u32 seqno)
 {
-	return i915_syncmap_set(&tl->sync, context, seqno);
+	return i915_syncmap_set(&tl->sync, context, seqno, GFP_KERNEL);
 }
 
 static inline int i915_timeline_sync_set(struct i915_timeline *tl,
diff --git a/drivers/gpu/drm/i915/selftests/i915_syncmap.c b/drivers/gpu/drm/i915/selftests/i915_syncmap.c
index 47f4ae18a1ef..0229b75f09cd 100644
--- a/drivers/gpu/drm/i915/selftests/i915_syncmap.c
+++ b/drivers/gpu/drm/i915/selftests/i915_syncmap.c
@@ -22,6 +22,8 @@
  *
  */
 
+#include <linux/sched/mm.h>
+
 #include "../i915_selftest.h"
 #include "i915_random.h"
 
@@ -164,7 +166,7 @@ static int check_one(struct i915_syncmap **sync, u64 context, u32 seqno)
 {
 	int err;
 
-	err = i915_syncmap_set(sync, context, seqno);
+	err = i915_syncmap_set(sync, context, seqno, GFP_KERNEL);
 	if (err)
 		return err;
 
@@ -239,7 +241,7 @@ static int check_leaf(struct i915_syncmap **sync, u64 context, u32 seqno)
 {
 	int err;
 
-	err = i915_syncmap_set(sync, context, seqno);
+	err = i915_syncmap_set(sync, context, seqno, GFP_KERNEL);
 	if (err)
 		return err;
 
@@ -345,7 +347,7 @@ static int igt_syncmap_join_below(void *arg)
 		for (order = 64 - SHIFT; order > 0; order -= SHIFT) {
 			u64 context = step * BIT_ULL(order);
 
-			err = i915_syncmap_set(&sync, context, 0);
+			err = i915_syncmap_set(&sync, context, 0, GFP_KERNEL);
 			if (err)
 				goto out;
 
@@ -418,7 +420,9 @@ static int igt_syncmap_neighbours(void *arg)
 			continue;
 
 		for (idx = 0; idx < KSYNCMAP; idx++) {
-			err = i915_syncmap_set(&sync, context + idx, 0);
+			err = i915_syncmap_set(&sync,
+					       context + idx, 0,
+					       GFP_KERNEL);
 			if (err)
 				goto out;
 
@@ -468,7 +472,7 @@ static int igt_syncmap_compact(void *arg)
 		for (idx = 0; idx < KSYNCMAP; idx++) {
 			u64 context = idx * BIT_ULL(order) + idx;
 
-			err = i915_syncmap_set(&sync, context, 0);
+			err = i915_syncmap_set(&sync, context, 0, GFP_KERNEL);
 			if (err)
 				goto out;
 
@@ -561,7 +565,7 @@ static int igt_syncmap_random(void *arg)
 	do {
 		u64 context = i915_prandom_u64_state(&prng);
 
-		err = i915_syncmap_set(&sync, context, 0);
+		err = i915_syncmap_set(&sync, context, 0, GFP_KERNEL);
 		if (err)
 			goto out;
 
@@ -588,7 +592,8 @@ static int igt_syncmap_random(void *arg)
 				goto out;
 			}
 
-			err = i915_syncmap_set(&sync, context, seqno);
+			err = i915_syncmap_set(&sync, context, seqno, 
+					       GFP_KERNEL);
 			if (err)
 				goto out;
 		}
@@ -600,6 +605,103 @@ static int igt_syncmap_random(void *arg)
 	return dump_syncmap(sync, err);
 }
 
+static void __normal_begin(void)
+{
+}
+
+static void __normal_end(void)
+{
+}
+
+static void __irqsoff_begin(void)
+{
+	local_irq_disable();
+}
+
+static void __irqsoff_end(void)
+{
+	local_irq_enable();
+}
+
+static void __preempt_begin(void)
+{
+	preempt_disable();
+}
+
+static void __preempt_end(void)
+{
+	preempt_enable();
+}
+
+static void __reclaim_begin(void)
+{
+	fs_reclaim_acquire(GFP_KERNEL);
+}
+
+static void __reclaim_end(void)
+{
+	fs_reclaim_release(GFP_KERNEL);
+}
+
+static int igt_syncmap_context(void *arg)
+{
+	static const struct {
+		const char *name;
+		void (*begin)(void);
+		void (*end)(void);
+		gfp_t gfp;
+	} contexts[] = {
+		{ "normal", __normal_begin, __normal_end, GFP_KERNEL },
+		{ "irqsoff", __irqsoff_begin, __irqsoff_end, GFP_ATOMIC },
+		{ "preempt", __preempt_begin, __preempt_end, GFP_NOWAIT },
+		{ "reclaim", __reclaim_begin, __reclaim_end, GFP_KERNEL & ~__GFP_RECLAIM },
+	};
+       	const typeof(*contexts) * const last = contexts + ARRAY_SIZE(contexts);
+	const typeof(*contexts) *c, *end;
+	I915_RND_STATE(prng);
+	int err = 0;
+
+	/*
+	 * Check that we can insert under different process contexts
+	 */
+
+	for (c = contexts, end = last; err == 0 && c != end; c++) {
+		struct i915_syncmap *sync;
+		u64 context = i915_prandom_u64_state(&prng);
+		u32 seqno = prandom_u32_state(&prng);
+
+		i915_syncmap_init(&sync);
+
+		c->begin();
+		err = i915_syncmap_set(&sync, context, seqno, c->gfp);
+		c->end();
+		if (err)
+			pr_err("Leaf allocation failed for '%s' (first)\n",
+			       c->name);
+
+		i915_syncmap_free(&sync);
+	}
+
+	for (c = last, end = contexts; err == 0 && c-- != end; ){
+		struct i915_syncmap *sync;
+		u64 context = i915_prandom_u64_state(&prng);
+		u32 seqno = prandom_u32_state(&prng);
+
+		i915_syncmap_init(&sync);
+
+		c->begin();
+		err = i915_syncmap_set(&sync, context, seqno, c->gfp);
+		c->end();
+		if (err)
+			pr_err("Leaf allocation failed for '%s' (second)\n",
+			       c->name);
+
+		i915_syncmap_free(&sync);
+	}
+
+	return err;
+}
+
 int i915_syncmap_mock_selftests(void)
 {
 	static const struct i915_subtest tests[] = {
@@ -610,6 +712,7 @@ int i915_syncmap_mock_selftests(void)
 		SUBTEST(igt_syncmap_neighbours),
 		SUBTEST(igt_syncmap_compact),
 		SUBTEST(igt_syncmap_random),
+		SUBTEST(igt_syncmap_context),
 	};
 
 	return i915_subtests(tests, NULL);
-- 
2.18.0



More information about the Intel-gfx-trybot mailing list