[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