All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 1/3] drm/i915: Fix eviction when the GGTT is idle but full
@ 2017-10-12 12:57 Chris Wilson
  2017-10-12 12:57 ` [PATCH v3 2/3] drm/i915/selftests: Wrap a timer into a i915_sw_fence Chris Wilson
                   ` (3 more replies)
  0 siblings, 4 replies; 8+ messages in thread
From: Chris Wilson @ 2017-10-12 12:57 UTC (permalink / raw)
  To: intel-gfx

In the full-ppgtt world, we can fill the GGTT full of context objects.
These context objects are currently implicitly tracked by the requests
that pin them i.e. they are only unpinned when the request is completed
and retired, but we do not have the link from the vma to the request
(anymore). In order to unpin those contexts, we have to issue another
request and wait upon the switch to the kernel context.

The bug during eviction was that we assumed that a full GGTT meant we
would have requests on the GGTT timeline, and so we missed situations
where those requests where merely in flight (and when even they have not
yet been submitted to hw yet). The fix employed here is to change the
already-is-idle test to no look at the execution timeline, but count the
outstanding requests and then check that we have switched to the kernel
context. Erring on the side of overkill here just means that we stall a
little longer than may be strictly required, but we only expect to hit
this path in extreme corner cases where returning an erroneous error is
worse than the delay.

v2: Logical inversion when swapping over branches.

Fixes: 80b204bce8f2 ("drm/i915: Enable multiple timelines")
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
---
 drivers/gpu/drm/i915/i915_gem_evict.c | 63 ++++++++++++++++++++++-------------
 1 file changed, 39 insertions(+), 24 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_gem_evict.c b/drivers/gpu/drm/i915/i915_gem_evict.c
index a5a5b7e6daae..ee4811ffb7aa 100644
--- a/drivers/gpu/drm/i915/i915_gem_evict.c
+++ b/drivers/gpu/drm/i915/i915_gem_evict.c
@@ -33,21 +33,20 @@
 #include "intel_drv.h"
 #include "i915_trace.h"
 
-static bool ggtt_is_idle(struct drm_i915_private *dev_priv)
+static bool ggtt_is_idle(struct drm_i915_private *i915)
 {
-	struct i915_ggtt *ggtt = &dev_priv->ggtt;
-	struct intel_engine_cs *engine;
-	enum intel_engine_id id;
+       struct intel_engine_cs *engine;
+       enum intel_engine_id id;
 
-	for_each_engine(engine, dev_priv, id) {
-		struct intel_timeline *tl;
+       if (i915->gt.active_requests)
+	       return false;
 
-		tl = &ggtt->base.timeline.engine[engine->id];
-		if (i915_gem_active_isset(&tl->last_request))
-			return false;
-	}
+       for_each_engine(engine, i915, id) {
+	       if (engine->last_retired_context != i915->kernel_context)
+		       return false;
+       }
 
-	return true;
+       return true;
 }
 
 static int ggtt_flush(struct drm_i915_private *i915)
@@ -157,7 +156,8 @@ i915_gem_evict_something(struct i915_address_space *vm,
 				    min_size, alignment, cache_level,
 				    start, end, mode);
 
-	/* Retire before we search the active list. Although we have
+	/*
+	 * Retire before we search the active list. Although we have
 	 * reasonable accuracy in our retirement lists, we may have
 	 * a stray pin (preventing eviction) that can only be resolved by
 	 * retiring.
@@ -182,7 +182,8 @@ i915_gem_evict_something(struct i915_address_space *vm,
 		BUG_ON(ret);
 	}
 
-	/* Can we unpin some objects such as idle hw contents,
+	/*
+	 * Can we unpin some objects such as idle hw contents,
 	 * or pending flips? But since only the GGTT has global entries
 	 * such as scanouts, rinbuffers and contexts, we can skip the
 	 * purge when inspecting per-process local address spaces.
@@ -190,19 +191,33 @@ i915_gem_evict_something(struct i915_address_space *vm,
 	if (!i915_is_ggtt(vm) || flags & PIN_NONBLOCK)
 		return -ENOSPC;
 
-	if (ggtt_is_idle(dev_priv)) {
-		/* If we still have pending pageflip completions, drop
-		 * back to userspace to give our workqueues time to
-		 * acquire our locks and unpin the old scanouts.
-		 */
-		return intel_has_pending_fb_unpin(dev_priv) ? -EAGAIN : -ENOSPC;
-	}
+	/*
+	 * Not everything in the GGTT is tracked via VMA using
+	 * i915_vma_move_to_active(), otherwise we could evict as required
+	 * with minimal stalling. Instead we are forced to idle the GPU and
+	 * explicitly retire outstanding requests which will then remove
+	 * the pinning for active objects such as contexts and ring,
+	 * enabling us to evict them on the next iteration.
+	 *
+	 * To ensure that all user contexts are evictable, we perform
+	 * a switch to the perma-pinned kernel context. This all also gives
+	 * us a termination condition, when the last retired context is
+	 * the kernel's there is no more we can evict.
+	 */
+	if (!ggtt_is_idle(dev_priv)) {
+		ret = ggtt_flush(dev_priv);
+		if (ret)
+			return ret;
 
-	ret = ggtt_flush(dev_priv);
-	if (ret)
-		return ret;
+		goto search_again;
+	}
 
-	goto search_again;
+	/*
+	 * If we still have pending pageflip completions, drop
+	 * back to userspace to give our workqueues time to
+	 * acquire our locks and unpin the old scanouts.
+	 */
+	return intel_has_pending_fb_unpin(dev_priv) ? -EAGAIN : -ENOSPC;
 
 found:
 	/* drm_mm doesn't allow any other other operations while
-- 
2.15.0.rc0

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH v3 2/3] drm/i915/selftests: Wrap a timer into a i915_sw_fence
  2017-10-12 12:57 [PATCH v3 1/3] drm/i915: Fix eviction when the GGTT is idle but full Chris Wilson
@ 2017-10-12 12:57 ` Chris Wilson
  2017-10-12 15:06   ` Tvrtko Ursulin
  2017-10-12 12:57 ` [PATCH v3 3/3] drm/i915/selftests: Exercise adding requests to a full GGTT Chris Wilson
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 8+ messages in thread
From: Chris Wilson @ 2017-10-12 12:57 UTC (permalink / raw)
  To: intel-gfx

For some selftests, we want to issue requests but delay them going to
hardware. Furthermore, we don't want those requests to block
indefinitely (or else we may hang the driver and block testing) so we
want to employ a timeout. So naturally we want a fence that is
automatically signaled by a timer.

v2: Add kselftests.
v3: Limit the API available to selftests; there isn't an overwhelming
reason to export it universally.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
---
 drivers/gpu/drm/i915/i915_sw_fence.c           | 10 ++++
 drivers/gpu/drm/i915/selftests/i915_sw_fence.c | 42 ++++++++++++++
 drivers/gpu/drm/i915/selftests/lib_sw_fence.c  | 78 ++++++++++++++++++++++++++
 drivers/gpu/drm/i915/selftests/lib_sw_fence.h  | 42 ++++++++++++++
 4 files changed, 172 insertions(+)
 create mode 100644 drivers/gpu/drm/i915/selftests/lib_sw_fence.c
 create mode 100644 drivers/gpu/drm/i915/selftests/lib_sw_fence.h

diff --git a/drivers/gpu/drm/i915/i915_sw_fence.c b/drivers/gpu/drm/i915/i915_sw_fence.c
index 808ea4d5b962..ca33cc08cb07 100644
--- a/drivers/gpu/drm/i915/i915_sw_fence.c
+++ b/drivers/gpu/drm/i915/i915_sw_fence.c
@@ -41,6 +41,11 @@ static inline void debug_fence_init(struct i915_sw_fence *fence)
 	debug_object_init(fence, &i915_sw_fence_debug_descr);
 }
 
+static inline void debug_fence_init_onstack(struct i915_sw_fence *fence)
+{
+	debug_object_init_on_stack(fence, &i915_sw_fence_debug_descr);
+}
+
 static inline void debug_fence_activate(struct i915_sw_fence *fence)
 {
 	debug_object_activate(fence, &i915_sw_fence_debug_descr);
@@ -79,6 +84,10 @@ static inline void debug_fence_init(struct i915_sw_fence *fence)
 {
 }
 
+static inline void debug_fence_init_onstack(struct i915_sw_fence *fence)
+{
+}
+
 static inline void debug_fence_activate(struct i915_sw_fence *fence)
 {
 }
@@ -507,5 +516,6 @@ int i915_sw_fence_await_reservation(struct i915_sw_fence *fence,
 }
 
 #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
+#include "selftests/lib_sw_fence.c"
 #include "selftests/i915_sw_fence.c"
 #endif
diff --git a/drivers/gpu/drm/i915/selftests/i915_sw_fence.c b/drivers/gpu/drm/i915/selftests/i915_sw_fence.c
index 19d145d6bf52..ea01d0fe3ace 100644
--- a/drivers/gpu/drm/i915/selftests/i915_sw_fence.c
+++ b/drivers/gpu/drm/i915/selftests/i915_sw_fence.c
@@ -24,6 +24,7 @@
 
 #include <linux/completion.h>
 #include <linux/delay.h>
+#include <linux/prime_numbers.h>
 
 #include "../i915_selftest.h"
 
@@ -565,6 +566,46 @@ static int test_ipc(void *arg)
 	return ret;
 }
 
+static int test_timer(void *arg)
+{
+	unsigned long target, delay;
+	struct timed_fence tf;
+
+	timed_fence_init(&tf, target = jiffies);
+	if (!i915_sw_fence_done(&tf.fence)) {
+		pr_err("Fence with immediate expiration not signaled\n");
+		goto err;
+	}
+	timed_fence_fini(&tf);
+
+	for_each_prime_number(delay, i915_selftest.timeout_jiffies/2) {
+		timed_fence_init(&tf, target = jiffies + delay);
+		if (i915_sw_fence_done(&tf.fence)) {
+			pr_err("Fence with future expiration (%lu jiffies) already signaled\n", delay);
+			goto err;
+		}
+
+		i915_sw_fence_wait(&tf.fence);
+		if (!i915_sw_fence_done(&tf.fence)) {
+			pr_err("Fence not signaled after wait\n");
+			goto err;
+		}
+		if (time_before(jiffies, target)) {
+			pr_err("Fence signaled too early, target=%lu, now=%lu\n",
+			       target, jiffies);
+			goto err;
+		}
+
+		timed_fence_fini(&tf);
+	}
+
+	return 0;
+
+err:
+	timed_fence_fini(&tf);
+	return -EINVAL;
+}
+
 int i915_sw_fence_mock_selftests(void)
 {
 	static const struct i915_subtest tests[] = {
@@ -576,6 +617,7 @@ int i915_sw_fence_mock_selftests(void)
 		SUBTEST(test_C_AB),
 		SUBTEST(test_chain),
 		SUBTEST(test_ipc),
+		SUBTEST(test_timer),
 	};
 
 	return i915_subtests(tests, NULL);
diff --git a/drivers/gpu/drm/i915/selftests/lib_sw_fence.c b/drivers/gpu/drm/i915/selftests/lib_sw_fence.c
new file mode 100644
index 000000000000..3790fdf44a1a
--- /dev/null
+++ b/drivers/gpu/drm/i915/selftests/lib_sw_fence.c
@@ -0,0 +1,78 @@
+/*
+ * Copyright © 2017 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ */
+
+#include "lib_sw_fence.h"
+
+/* Small library of different fence types useful for writing tests */
+
+static int __i915_sw_fence_call
+nop_fence_notify(struct i915_sw_fence *fence, enum i915_sw_fence_notify state)
+{
+	return NOTIFY_DONE;
+}
+
+void __onstack_fence_init(struct i915_sw_fence *fence,
+			  const char *name,
+			  struct lock_class_key *key)
+{
+	debug_fence_init_onstack(fence);
+
+	__init_waitqueue_head(&fence->wait, name, key);
+	atomic_set(&fence->pending, 1);
+	fence->flags = (unsigned long)nop_fence_notify;
+}
+
+void onstack_fence_fini(struct i915_sw_fence *fence)
+{
+	i915_sw_fence_commit(fence);
+	i915_sw_fence_fini(fence);
+}
+
+static void timed_fence_wake(unsigned long data)
+{
+	struct timed_fence *tf = (struct timed_fence *)data;
+
+	i915_sw_fence_commit(&tf->fence);
+}
+
+void timed_fence_init(struct timed_fence *tf, unsigned long expires)
+{
+	onstack_fence_init(&tf->fence);
+
+	setup_timer_on_stack(&tf->timer, timed_fence_wake, (unsigned long)tf);
+
+	if (time_after(expires, jiffies))
+		mod_timer(&tf->timer, expires);
+	else
+		i915_sw_fence_commit(&tf->fence);
+}
+
+void timed_fence_fini(struct timed_fence *tf)
+{
+	if (del_timer_sync(&tf->timer))
+		i915_sw_fence_commit(&tf->fence);
+
+	destroy_timer_on_stack(&tf->timer);
+	i915_sw_fence_fini(&tf->fence);
+}
diff --git a/drivers/gpu/drm/i915/selftests/lib_sw_fence.h b/drivers/gpu/drm/i915/selftests/lib_sw_fence.h
new file mode 100644
index 000000000000..474aafb92ae1
--- /dev/null
+++ b/drivers/gpu/drm/i915/selftests/lib_sw_fence.h
@@ -0,0 +1,42 @@
+/*
+ * lib_sw_fence.h - library routines for testing N:M synchronisation points
+ *
+ * Copyright (C) 2017 Intel Corporation
+ *
+ * This file is released under the GPLv2.
+ *
+ */
+
+#ifndef _LIB_SW_FENCE_H_
+#define _LIB_SW_FENCE_H_
+
+#include <linux/timer.h>
+
+#include "../i915_sw_fence.h"
+
+#ifdef CONFIG_LOCKDEP
+#define onstack_fence_init(fence)				\
+do {								\
+	static struct lock_class_key __key;			\
+								\
+	__onstack_fence_init((fence), #fence, &__key);	\
+} while (0)
+#else
+#define onstack_fence_init(fence)				\
+	__onstack_fence_init((fence), NULL, NULL)
+#endif
+
+void __onstack_fence_init(struct i915_sw_fence *fence,
+			  const char *name,
+			  struct lock_class_key *key);
+void onstack_fence_fini(struct i915_sw_fence *fence);
+
+struct timed_fence {
+	struct i915_sw_fence fence;
+	struct timer_list timer;
+};
+
+void timed_fence_init(struct timed_fence *tf, unsigned long expires);
+void timed_fence_fini(struct timed_fence *tf);
+
+#endif /* _LIB_SW_FENCE_H_ */
-- 
2.15.0.rc0

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH v3 3/3] drm/i915/selftests: Exercise adding requests to a full GGTT
  2017-10-12 12:57 [PATCH v3 1/3] drm/i915: Fix eviction when the GGTT is idle but full Chris Wilson
  2017-10-12 12:57 ` [PATCH v3 2/3] drm/i915/selftests: Wrap a timer into a i915_sw_fence Chris Wilson
@ 2017-10-12 12:57 ` Chris Wilson
  2017-10-12 14:40   ` Chris Wilson
  2017-10-12 15:12   ` Tvrtko Ursulin
  2017-10-12 13:29 ` ✓ Fi.CI.BAT: success for series starting with [v3,1/3] drm/i915: Fix eviction when the GGTT is idle but full Patchwork
  2017-10-12 17:48 ` ✗ Fi.CI.IGT: failure " Patchwork
  3 siblings, 2 replies; 8+ messages in thread
From: Chris Wilson @ 2017-10-12 12:57 UTC (permalink / raw)
  To: intel-gfx

A bug recently encountered involved the issue where are we were
submitting requests to different ppGTT, each would pin a segment of the
GGTT for its logical context and ring. However, this is invisible to
eviction as we do not tie the context/ring VMA to a request and so do
not automatically wait upon it them (instead they are marked as pinned,
preventing eviction entirely). Instead the eviction code must flush those
contexts by switching to the kernel context. This selftest tries to
fill the GGTT with contexts to exercise a path where the
switch-to-kernel-context failed to make forward progress and we fail
with ENOSPC.

v2: Make the hole in the filled GGTT explicit.
v3: Swap out the arbitrary timeout for a private notification from
i915_gem_evict_something()

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
---
 drivers/gpu/drm/i915/i915_gem_evict.c              |   7 +
 drivers/gpu/drm/i915/selftests/i915_gem_evict.c    | 153 +++++++++++++++++++++
 .../gpu/drm/i915/selftests/i915_live_selftests.h   |   1 +
 drivers/gpu/drm/i915/selftests/mock_context.c      |   6 +-
 4 files changed, 162 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_gem_evict.c b/drivers/gpu/drm/i915/i915_gem_evict.c
index ee4811ffb7aa..8daa8a78cdc0 100644
--- a/drivers/gpu/drm/i915/i915_gem_evict.c
+++ b/drivers/gpu/drm/i915/i915_gem_evict.c
@@ -33,6 +33,10 @@
 #include "intel_drv.h"
 #include "i915_trace.h"
 
+I915_SELFTEST_DECLARE(static struct igt_evict_ctl {
+	bool fail_if_busy:1;
+} igt_evict_ctl;)
+
 static bool ggtt_is_idle(struct drm_i915_private *i915)
 {
        struct intel_engine_cs *engine;
@@ -205,6 +209,9 @@ i915_gem_evict_something(struct i915_address_space *vm,
 	 * the kernel's there is no more we can evict.
 	 */
 	if (!ggtt_is_idle(dev_priv)) {
+		if (I915_SELFTEST_ONLY(igt_evict_ctl.fail_if_busy))
+			return -EBUSY;
+
 		ret = ggtt_flush(dev_priv);
 		if (ret)
 			return ret;
diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_evict.c b/drivers/gpu/drm/i915/selftests/i915_gem_evict.c
index 5ea373221f49..869262c3f15e 100644
--- a/drivers/gpu/drm/i915/selftests/i915_gem_evict.c
+++ b/drivers/gpu/drm/i915/selftests/i915_gem_evict.c
@@ -24,6 +24,9 @@
 
 #include "../i915_selftest.h"
 
+#include "lib_sw_fence.h"
+#include "mock_context.h"
+#include "mock_drm.h"
 #include "mock_gem_device.h"
 
 static int populate_ggtt(struct drm_i915_private *i915)
@@ -325,6 +328,147 @@ static int igt_evict_vm(void *arg)
 	return err;
 }
 
+static int igt_evict_contexts(void *arg)
+{
+	const u64 PRETEND_GGTT_SIZE = 16ull << 20;
+	struct drm_i915_private *i915 = arg;
+	struct intel_engine_cs *engine;
+	enum intel_engine_id id;
+	struct reserved {
+		struct drm_mm_node node;
+		struct reserved *next;
+	} *reserved = NULL;
+	struct drm_mm_node hole;
+	unsigned long count;
+	int err;
+
+	/*
+	 * The purpose of this test is to verify that we will trigger an
+	 * eviction in the GGTT when constructing a request that requires
+	 * additional space in the GGTT for pinning the context. This space
+	 * is not directly tied to the request so reclaiming it requires
+	 * extra work.
+	 *
+	 * As such this test is only meaningful for full-ppgtt environments
+	 * where the GTT space of the request is separate from the GGTT
+	 * allocation required to build the request.
+	 */
+	if (!USES_FULL_PPGTT(i915))
+		return 0;
+
+	mutex_lock(&i915->drm.struct_mutex);
+
+	/* Reserve a block so that we know we have enough to fit a few rq */
+	memset(&hole, 0, sizeof(hole));
+	err = i915_gem_gtt_insert(&i915->ggtt.base, &hole,
+				  PRETEND_GGTT_SIZE, 0, I915_COLOR_UNEVICTABLE,
+				  0, i915->ggtt.base.total,
+				  PIN_NOEVICT);
+	if (err)
+		goto out_locked;
+
+	/* Make the GGTT appear small by filling it with unevictable nodes */
+	count = 0;
+	do {
+		struct reserved *r;
+
+		r = kcalloc(1, sizeof(*r), GFP_KERNEL);
+		if (!r) {
+			err = -ENOMEM;
+			goto out_locked;
+		}
+
+		if (i915_gem_gtt_insert(&i915->ggtt.base, &r->node,
+					1ul << 20, 0, I915_COLOR_UNEVICTABLE,
+					0, i915->ggtt.base.total,
+					PIN_NOEVICT)) {
+			kfree(r);
+			break;
+		}
+
+		r->next = reserved;
+		reserved = r;
+
+		count++;
+	} while (1);
+	drm_mm_remove_node(&hole);
+	mutex_unlock(&i915->drm.struct_mutex);
+	pr_info("Filled GGTT with %lu 1MiB nodes\n", count);
+
+	/* Overfill the GGTT with context objects and so try to evict one. */
+	for_each_engine(engine, i915, id) {
+		struct i915_sw_fence fence;
+		struct drm_file *file;
+
+		file = mock_file(i915);
+		if (IS_ERR(file))
+			return PTR_ERR(file);
+
+		count = 0;
+		mutex_lock(&i915->drm.struct_mutex);
+		onstack_fence_init(&fence);
+		do {
+			struct drm_i915_gem_request *rq;
+			struct i915_gem_context *ctx;
+
+			ctx = live_context(i915, file);
+			if (!ctx)
+				break;
+
+			igt_evict_ctl.fail_if_busy = true;
+			rq = i915_gem_request_alloc(engine, ctx);
+			igt_evict_ctl.fail_if_busy = false;
+
+			if (IS_ERR(rq)) {
+				/* When full, fail_if_busy will trigger -EBUSY */
+				if (PTR_ERR(rq) != -EBUSY) {
+					pr_err("Unexpected error from request alloc (ctx hw id %u, on %s): %d\n",
+					       ctx->hw_id, engine->name,
+					       (int)PTR_ERR(rq));
+					err = PTR_ERR(rq);
+				}
+				break;
+			}
+
+			/* Keep every request busy until we are full */
+			err = i915_sw_fence_await_sw_fence_gfp(&rq->submit,
+							       &fence,
+							       GFP_KERNEL);
+			if (err < 0)
+				break;
+
+			i915_add_request(rq);
+			count++;
+			err = 0;
+		} while(!i915_sw_fence_done(&fence));
+		mutex_unlock(&i915->drm.struct_mutex);
+
+		onstack_fence_fini(&fence);
+		pr_info("Submitted %lu contexts/requests on %s\n",
+			count, engine->name);
+
+		mock_file_free(i915, file);
+		if (err)
+			break;
+	}
+
+	mutex_lock(&i915->drm.struct_mutex);
+out_locked:
+	while (reserved) {
+		struct reserved *next = reserved->next;
+
+		drm_mm_remove_node(&reserved->node);
+		kfree(reserved);
+
+		reserved = next;
+	}
+	if (drm_mm_node_allocated(&hole))
+		drm_mm_remove_node(&hole);
+	mutex_unlock(&i915->drm.struct_mutex);
+
+	return err;
+}
+
 int i915_gem_evict_mock_selftests(void)
 {
 	static const struct i915_subtest tests[] = {
@@ -348,3 +492,12 @@ int i915_gem_evict_mock_selftests(void)
 	drm_dev_unref(&i915->drm);
 	return err;
 }
+
+int i915_gem_evict_live_selftests(struct drm_i915_private *i915)
+{
+	static const struct i915_subtest tests[] = {
+		SUBTEST(igt_evict_contexts),
+	};
+
+	return i915_subtests(tests, i915);
+}
diff --git a/drivers/gpu/drm/i915/selftests/i915_live_selftests.h b/drivers/gpu/drm/i915/selftests/i915_live_selftests.h
index 64acd7eccc5c..54a73534b37e 100644
--- a/drivers/gpu/drm/i915/selftests/i915_live_selftests.h
+++ b/drivers/gpu/drm/i915/selftests/i915_live_selftests.h
@@ -15,6 +15,7 @@ selftest(objects, i915_gem_object_live_selftests)
 selftest(dmabuf, i915_gem_dmabuf_live_selftests)
 selftest(coherency, i915_gem_coherency_live_selftests)
 selftest(gtt, i915_gem_gtt_live_selftests)
+selftest(evict, i915_gem_evict_live_selftests)
 selftest(hugepages, i915_gem_huge_page_live_selftests)
 selftest(contexts, i915_gem_context_live_selftests)
 selftest(hangcheck, intel_hangcheck_live_selftests)
diff --git a/drivers/gpu/drm/i915/selftests/mock_context.c b/drivers/gpu/drm/i915/selftests/mock_context.c
index 098ce643ad07..bbf80d42e793 100644
--- a/drivers/gpu/drm/i915/selftests/mock_context.c
+++ b/drivers/gpu/drm/i915/selftests/mock_context.c
@@ -73,11 +73,7 @@ mock_context(struct drm_i915_private *i915,
 
 void mock_context_close(struct i915_gem_context *ctx)
 {
-	i915_gem_context_set_closed(ctx);
-
-	i915_ppgtt_close(&ctx->ppgtt->base);
-
-	i915_gem_context_put(ctx);
+	context_close(ctx);
 }
 
 void mock_init_contexts(struct drm_i915_private *i915)
-- 
2.15.0.rc0

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* ✓ Fi.CI.BAT: success for series starting with [v3,1/3] drm/i915: Fix eviction when the GGTT is idle but full
  2017-10-12 12:57 [PATCH v3 1/3] drm/i915: Fix eviction when the GGTT is idle but full Chris Wilson
  2017-10-12 12:57 ` [PATCH v3 2/3] drm/i915/selftests: Wrap a timer into a i915_sw_fence Chris Wilson
  2017-10-12 12:57 ` [PATCH v3 3/3] drm/i915/selftests: Exercise adding requests to a full GGTT Chris Wilson
@ 2017-10-12 13:29 ` Patchwork
  2017-10-12 17:48 ` ✗ Fi.CI.IGT: failure " Patchwork
  3 siblings, 0 replies; 8+ messages in thread
From: Patchwork @ 2017-10-12 13:29 UTC (permalink / raw)
  To: Chris Wilson; +Cc: intel-gfx

== Series Details ==

Series: series starting with [v3,1/3] drm/i915: Fix eviction when the GGTT is idle but full
URL   : https://patchwork.freedesktop.org/series/31815/
State : success

== Summary ==

Series 31815v1 series starting with [v3,1/3] drm/i915: Fix eviction when the GGTT is idle but full
https://patchwork.freedesktop.org/api/1.0/series/31815/revisions/1/mbox/

fi-bdw-5557u     total:289  pass:268  dwarn:0   dfail:0   fail:0   skip:21  time:457s
fi-bdw-gvtdvm    total:289  pass:265  dwarn:0   dfail:0   fail:0   skip:24  time:468s
fi-blb-e6850     total:289  pass:223  dwarn:1   dfail:0   fail:0   skip:65  time:393s
fi-bsw-n3050     total:289  pass:243  dwarn:0   dfail:0   fail:0   skip:46  time:574s
fi-bwr-2160      total:289  pass:183  dwarn:0   dfail:0   fail:0   skip:106 time:285s
fi-bxt-dsi       total:289  pass:259  dwarn:0   dfail:0   fail:0   skip:30  time:525s
fi-bxt-j4205     total:289  pass:260  dwarn:0   dfail:0   fail:0   skip:29  time:524s
fi-byt-j1900     total:289  pass:253  dwarn:1   dfail:0   fail:0   skip:35  time:541s
fi-byt-n2820     total:289  pass:249  dwarn:1   dfail:0   fail:0   skip:39  time:520s
fi-cfl-s         total:289  pass:253  dwarn:4   dfail:0   fail:0   skip:32  time:567s
fi-elk-e7500     total:289  pass:229  dwarn:0   dfail:0   fail:0   skip:60  time:435s
fi-gdg-551       total:289  pass:178  dwarn:1   dfail:0   fail:1   skip:109 time:274s
fi-glk-1         total:289  pass:261  dwarn:0   dfail:0   fail:0   skip:28  time:606s
fi-hsw-4770r     total:289  pass:262  dwarn:0   dfail:0   fail:0   skip:27  time:442s
fi-ilk-650       total:289  pass:228  dwarn:0   dfail:0   fail:0   skip:61  time:469s
fi-ivb-3520m     total:289  pass:260  dwarn:0   dfail:0   fail:0   skip:29  time:507s
fi-ivb-3770      total:289  pass:260  dwarn:0   dfail:0   fail:0   skip:29  time:477s
fi-kbl-7500u     total:289  pass:264  dwarn:1   dfail:0   fail:0   skip:24  time:503s
fi-kbl-7567u     total:289  pass:265  dwarn:4   dfail:0   fail:0   skip:20  time:488s
fi-kbl-r         total:289  pass:262  dwarn:0   dfail:0   fail:0   skip:27  time:593s
fi-pnv-d510      total:289  pass:222  dwarn:1   dfail:0   fail:0   skip:66  time:665s
fi-skl-6260u     total:289  pass:269  dwarn:0   dfail:0   fail:0   skip:20  time:460s
fi-skl-6700hq    total:289  pass:263  dwarn:0   dfail:0   fail:0   skip:26  time:654s
fi-skl-6770hq    total:289  pass:269  dwarn:0   dfail:0   fail:0   skip:20  time:516s
fi-skl-gvtdvm    total:289  pass:266  dwarn:0   dfail:0   fail:0   skip:23  time:469s
fi-snb-2520m     total:289  pass:250  dwarn:0   dfail:0   fail:0   skip:39  time:586s
fi-snb-2600      total:289  pass:249  dwarn:0   dfail:0   fail:0   skip:40  time:440s
fi-skl-6700k failed to connect after reboot

a869721e93a51c2bf425f322514527b4dc3944c8 drm-tip: 2017y-10m-12d-08h-30m-31s UTC integration manifest
6f2b0f98253d drm/i915/selftests: Exercise adding requests to a full GGTT
58246bf63737 drm/i915/selftests: Wrap a timer into a i915_sw_fence
412ef957b56f drm/i915: Fix eviction when the GGTT is idle but full

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_6007/
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH v3 3/3] drm/i915/selftests: Exercise adding requests to a full GGTT
  2017-10-12 12:57 ` [PATCH v3 3/3] drm/i915/selftests: Exercise adding requests to a full GGTT Chris Wilson
@ 2017-10-12 14:40   ` Chris Wilson
  2017-10-12 15:12   ` Tvrtko Ursulin
  1 sibling, 0 replies; 8+ messages in thread
From: Chris Wilson @ 2017-10-12 14:40 UTC (permalink / raw)
  To: intel-gfx

Quoting Chris Wilson (2017-10-12 13:57:26)
> +               count = 0;
> +               mutex_lock(&i915->drm.struct_mutex);
> +               onstack_fence_init(&fence);
> +               do {
> +                       struct drm_i915_gem_request *rq;
> +                       struct i915_gem_context *ctx;
> +
> +                       ctx = live_context(i915, file);
> +                       if (!ctx)
> +                               break;
> +
> +                       igt_evict_ctl.fail_if_busy = true;
> +                       rq = i915_gem_request_alloc(engine, ctx);
> +                       igt_evict_ctl.fail_if_busy = false;
> +
> +                       if (IS_ERR(rq)) {
> +                               /* When full, fail_if_busy will trigger -EBUSY */
> +                               if (PTR_ERR(rq) != -EBUSY) {
> +                                       pr_err("Unexpected error from request alloc (ctx hw id %u, on %s): %d\n",
> +                                              ctx->hw_id, engine->name,
> +                                              (int)PTR_ERR(rq));
> +                                       err = PTR_ERR(rq);
> +                               }
> +                               break;
> +                       }
> +
> +                       /* Keep every request busy until we are full */
> +                       err = i915_sw_fence_await_sw_fence_gfp(&rq->submit,
> +                                                              &fence,
> +                                                              GFP_KERNEL);
> +                       if (err < 0)
> +                               break;
> +
> +                       i915_add_request(rq);
> +                       count++;
> +                       err = 0;
> +               } while(!i915_sw_fence_done(&fence));

This should now just be 
	} while (1);
The only escape is when we hit EBUSY upon filling the GGTT.
-Chris
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH v3 2/3] drm/i915/selftests: Wrap a timer into a i915_sw_fence
  2017-10-12 12:57 ` [PATCH v3 2/3] drm/i915/selftests: Wrap a timer into a i915_sw_fence Chris Wilson
@ 2017-10-12 15:06   ` Tvrtko Ursulin
  0 siblings, 0 replies; 8+ messages in thread
From: Tvrtko Ursulin @ 2017-10-12 15:06 UTC (permalink / raw)
  To: Chris Wilson, intel-gfx


On 12/10/2017 13:57, Chris Wilson wrote:
> For some selftests, we want to issue requests but delay them going to
> hardware. Furthermore, we don't want those requests to block
> indefinitely (or else we may hang the driver and block testing) so we
> want to employ a timeout. So naturally we want a fence that is
> automatically signaled by a timer.
> 
> v2: Add kselftests.
> v3: Limit the API available to selftests; there isn't an overwhelming
> reason to export it universally.

v4: Added support for debug objects and rewrote everything? :) More on 
stack business, when a debug feature becomes to intrusive for normal use..

> 
> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
> Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
> ---
>   drivers/gpu/drm/i915/i915_sw_fence.c           | 10 ++++
>   drivers/gpu/drm/i915/selftests/i915_sw_fence.c | 42 ++++++++++++++
>   drivers/gpu/drm/i915/selftests/lib_sw_fence.c  | 78 ++++++++++++++++++++++++++
>   drivers/gpu/drm/i915/selftests/lib_sw_fence.h  | 42 ++++++++++++++
>   4 files changed, 172 insertions(+)
>   create mode 100644 drivers/gpu/drm/i915/selftests/lib_sw_fence.c
>   create mode 100644 drivers/gpu/drm/i915/selftests/lib_sw_fence.h
> 
> diff --git a/drivers/gpu/drm/i915/i915_sw_fence.c b/drivers/gpu/drm/i915/i915_sw_fence.c
> index 808ea4d5b962..ca33cc08cb07 100644
> --- a/drivers/gpu/drm/i915/i915_sw_fence.c
> +++ b/drivers/gpu/drm/i915/i915_sw_fence.c
> @@ -41,6 +41,11 @@ static inline void debug_fence_init(struct i915_sw_fence *fence)
>   	debug_object_init(fence, &i915_sw_fence_debug_descr);
>   }
>   
> +static inline void debug_fence_init_onstack(struct i915_sw_fence *fence)
> +{
> +	debug_object_init_on_stack(fence, &i915_sw_fence_debug_descr);
> +}
> +
>   static inline void debug_fence_activate(struct i915_sw_fence *fence)
>   {
>   	debug_object_activate(fence, &i915_sw_fence_debug_descr);
> @@ -79,6 +84,10 @@ static inline void debug_fence_init(struct i915_sw_fence *fence)
>   {
>   }
>   
> +static inline void debug_fence_init_onstack(struct i915_sw_fence *fence)
> +{
> +}
> +
>   static inline void debug_fence_activate(struct i915_sw_fence *fence)
>   {
>   }
> @@ -507,5 +516,6 @@ int i915_sw_fence_await_reservation(struct i915_sw_fence *fence,
>   }
>   
>   #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
> +#include "selftests/lib_sw_fence.c"
>   #include "selftests/i915_sw_fence.c"
>   #endif
> diff --git a/drivers/gpu/drm/i915/selftests/i915_sw_fence.c b/drivers/gpu/drm/i915/selftests/i915_sw_fence.c
> index 19d145d6bf52..ea01d0fe3ace 100644
> --- a/drivers/gpu/drm/i915/selftests/i915_sw_fence.c
> +++ b/drivers/gpu/drm/i915/selftests/i915_sw_fence.c
> @@ -24,6 +24,7 @@
>   
>   #include <linux/completion.h>
>   #include <linux/delay.h>
> +#include <linux/prime_numbers.h>
>   
>   #include "../i915_selftest.h"
>   
> @@ -565,6 +566,46 @@ static int test_ipc(void *arg)
>   	return ret;
>   }
>   
> +static int test_timer(void *arg)
> +{
> +	unsigned long target, delay;
> +	struct timed_fence tf;
> +
> +	timed_fence_init(&tf, target = jiffies);
> +	if (!i915_sw_fence_done(&tf.fence)) {
> +		pr_err("Fence with immediate expiration not signaled\n");
> +		goto err;
> +	}
> +	timed_fence_fini(&tf);
> +
> +	for_each_prime_number(delay, i915_selftest.timeout_jiffies/2) {
> +		timed_fence_init(&tf, target = jiffies + delay);
> +		if (i915_sw_fence_done(&tf.fence)) {
> +			pr_err("Fence with future expiration (%lu jiffies) already signaled\n", delay);
> +			goto err;
> +		}
> +
> +		i915_sw_fence_wait(&tf.fence);
> +		if (!i915_sw_fence_done(&tf.fence)) {
> +			pr_err("Fence not signaled after wait\n");
> +			goto err;
> +		}
> +		if (time_before(jiffies, target)) {
> +			pr_err("Fence signaled too early, target=%lu, now=%lu\n",
> +			       target, jiffies);
> +			goto err;
> +		}
> +
> +		timed_fence_fini(&tf);
> +	}
> +
> +	return 0;
> +
> +err:
> +	timed_fence_fini(&tf);
> +	return -EINVAL;
> +}
> +
>   int i915_sw_fence_mock_selftests(void)
>   {
>   	static const struct i915_subtest tests[] = {
> @@ -576,6 +617,7 @@ int i915_sw_fence_mock_selftests(void)
>   		SUBTEST(test_C_AB),
>   		SUBTEST(test_chain),
>   		SUBTEST(test_ipc),
> +		SUBTEST(test_timer),
>   	};
>   
>   	return i915_subtests(tests, NULL);
> diff --git a/drivers/gpu/drm/i915/selftests/lib_sw_fence.c b/drivers/gpu/drm/i915/selftests/lib_sw_fence.c
> new file mode 100644
> index 000000000000..3790fdf44a1a
> --- /dev/null
> +++ b/drivers/gpu/drm/i915/selftests/lib_sw_fence.c
> @@ -0,0 +1,78 @@
> +/*
> + * Copyright © 2017 Intel Corporation
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a
> + * copy of this software and associated documentation files (the "Software"),
> + * to deal in the Software without restriction, including without limitation
> + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
> + * and/or sell copies of the Software, and to permit persons to whom the
> + * Software is furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice (including the next
> + * paragraph) shall be included in all copies or substantial portions of the
> + * Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
> + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
> + * IN THE SOFTWARE.
> + *
> + */
> +
> +#include "lib_sw_fence.h"
> +
> +/* Small library of different fence types useful for writing tests */
> +
> +static int __i915_sw_fence_call
> +nop_fence_notify(struct i915_sw_fence *fence, enum i915_sw_fence_notify state)
> +{
> +	return NOTIFY_DONE;
> +}
> +
> +void __onstack_fence_init(struct i915_sw_fence *fence,
> +			  const char *name,
> +			  struct lock_class_key *key)
> +{
> +	debug_fence_init_onstack(fence);
> +
> +	__init_waitqueue_head(&fence->wait, name, key);
> +	atomic_set(&fence->pending, 1);
> +	fence->flags = (unsigned long)nop_fence_notify;
> +}
> +
> +void onstack_fence_fini(struct i915_sw_fence *fence)
> +{
> +	i915_sw_fence_commit(fence);
> +	i915_sw_fence_fini(fence);
> +}
> +
> +static void timed_fence_wake(unsigned long data)
> +{
> +	struct timed_fence *tf = (struct timed_fence *)data;
> +
> +	i915_sw_fence_commit(&tf->fence);
> +}
> +
> +void timed_fence_init(struct timed_fence *tf, unsigned long expires)
> +{
> +	onstack_fence_init(&tf->fence);
> +
> +	setup_timer_on_stack(&tf->timer, timed_fence_wake, (unsigned long)tf);
> +
> +	if (time_after(expires, jiffies))
> +		mod_timer(&tf->timer, expires);
> +	else
> +		i915_sw_fence_commit(&tf->fence);
> +}
> +
> +void timed_fence_fini(struct timed_fence *tf)
> +{
> +	if (del_timer_sync(&tf->timer))
> +		i915_sw_fence_commit(&tf->fence);
> +
> +	destroy_timer_on_stack(&tf->timer);
> +	i915_sw_fence_fini(&tf->fence);
> +}
> diff --git a/drivers/gpu/drm/i915/selftests/lib_sw_fence.h b/drivers/gpu/drm/i915/selftests/lib_sw_fence.h
> new file mode 100644
> index 000000000000..474aafb92ae1
> --- /dev/null
> +++ b/drivers/gpu/drm/i915/selftests/lib_sw_fence.h
> @@ -0,0 +1,42 @@
> +/*
> + * lib_sw_fence.h - library routines for testing N:M synchronisation points
> + *
> + * Copyright (C) 2017 Intel Corporation
> + *
> + * This file is released under the GPLv2.
> + *
> + */
> +
> +#ifndef _LIB_SW_FENCE_H_
> +#define _LIB_SW_FENCE_H_
> +
> +#include <linux/timer.h>
> +
> +#include "../i915_sw_fence.h"
> +
> +#ifdef CONFIG_LOCKDEP
> +#define onstack_fence_init(fence)				\
> +do {								\
> +	static struct lock_class_key __key;			\
> +								\
> +	__onstack_fence_init((fence), #fence, &__key);	\
> +} while (0)
> +#else
> +#define onstack_fence_init(fence)				\
> +	__onstack_fence_init((fence), NULL, NULL)
> +#endif
> +
> +void __onstack_fence_init(struct i915_sw_fence *fence,
> +			  const char *name,
> +			  struct lock_class_key *key);
> +void onstack_fence_fini(struct i915_sw_fence *fence);
> +
> +struct timed_fence {
> +	struct i915_sw_fence fence;
> +	struct timer_list timer;
> +};
> +
> +void timed_fence_init(struct timed_fence *tf, unsigned long expires);
> +void timed_fence_fini(struct timed_fence *tf);
> +
> +#endif /* _LIB_SW_FENCE_H_ */
> 

Trusting that the lockdep onstack business builds in both cases. The 
rest looks ok to me.

Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>

Regards,

Tvrtko
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH v3 3/3] drm/i915/selftests: Exercise adding requests to a full GGTT
  2017-10-12 12:57 ` [PATCH v3 3/3] drm/i915/selftests: Exercise adding requests to a full GGTT Chris Wilson
  2017-10-12 14:40   ` Chris Wilson
@ 2017-10-12 15:12   ` Tvrtko Ursulin
  1 sibling, 0 replies; 8+ messages in thread
From: Tvrtko Ursulin @ 2017-10-12 15:12 UTC (permalink / raw)
  To: Chris Wilson, intel-gfx


On 12/10/2017 13:57, Chris Wilson wrote:
> A bug recently encountered involved the issue where are we were
> submitting requests to different ppGTT, each would pin a segment of the
> GGTT for its logical context and ring. However, this is invisible to
> eviction as we do not tie the context/ring VMA to a request and so do
> not automatically wait upon it them (instead they are marked as pinned,
> preventing eviction entirely). Instead the eviction code must flush those
> contexts by switching to the kernel context. This selftest tries to
> fill the GGTT with contexts to exercise a path where the
> switch-to-kernel-context failed to make forward progress and we fail
> with ENOSPC.
> 
> v2: Make the hole in the filled GGTT explicit.
> v3: Swap out the arbitrary timeout for a private notification from
> i915_gem_evict_something()
> 
> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
> Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
> ---
>   drivers/gpu/drm/i915/i915_gem_evict.c              |   7 +
>   drivers/gpu/drm/i915/selftests/i915_gem_evict.c    | 153 +++++++++++++++++++++
>   .../gpu/drm/i915/selftests/i915_live_selftests.h   |   1 +
>   drivers/gpu/drm/i915/selftests/mock_context.c      |   6 +-
>   4 files changed, 162 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_gem_evict.c b/drivers/gpu/drm/i915/i915_gem_evict.c
> index ee4811ffb7aa..8daa8a78cdc0 100644
> --- a/drivers/gpu/drm/i915/i915_gem_evict.c
> +++ b/drivers/gpu/drm/i915/i915_gem_evict.c
> @@ -33,6 +33,10 @@
>   #include "intel_drv.h"
>   #include "i915_trace.h"
>   
> +I915_SELFTEST_DECLARE(static struct igt_evict_ctl {
> +	bool fail_if_busy:1;
> +} igt_evict_ctl;)
> +
>   static bool ggtt_is_idle(struct drm_i915_private *i915)
>   {
>          struct intel_engine_cs *engine;
> @@ -205,6 +209,9 @@ i915_gem_evict_something(struct i915_address_space *vm,
>   	 * the kernel's there is no more we can evict.
>   	 */
>   	if (!ggtt_is_idle(dev_priv)) {
> +		if (I915_SELFTEST_ONLY(igt_evict_ctl.fail_if_busy))
> +			return -EBUSY;
> +
>   		ret = ggtt_flush(dev_priv);
>   		if (ret)
>   			return ret;
> diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_evict.c b/drivers/gpu/drm/i915/selftests/i915_gem_evict.c
> index 5ea373221f49..869262c3f15e 100644
> --- a/drivers/gpu/drm/i915/selftests/i915_gem_evict.c
> +++ b/drivers/gpu/drm/i915/selftests/i915_gem_evict.c
> @@ -24,6 +24,9 @@
>   
>   #include "../i915_selftest.h"
>   
> +#include "lib_sw_fence.h"
> +#include "mock_context.h"
> +#include "mock_drm.h"
>   #include "mock_gem_device.h"
>   
>   static int populate_ggtt(struct drm_i915_private *i915)
> @@ -325,6 +328,147 @@ static int igt_evict_vm(void *arg)
>   	return err;
>   }
>   
> +static int igt_evict_contexts(void *arg)
> +{
> +	const u64 PRETEND_GGTT_SIZE = 16ull << 20;
> +	struct drm_i915_private *i915 = arg;
> +	struct intel_engine_cs *engine;
> +	enum intel_engine_id id;
> +	struct reserved {
> +		struct drm_mm_node node;
> +		struct reserved *next;
> +	} *reserved = NULL;
> +	struct drm_mm_node hole;
> +	unsigned long count;
> +	int err;
> +
> +	/*
> +	 * The purpose of this test is to verify that we will trigger an
> +	 * eviction in the GGTT when constructing a request that requires
> +	 * additional space in the GGTT for pinning the context. This space
> +	 * is not directly tied to the request so reclaiming it requires
> +	 * extra work.
> +	 *
> +	 * As such this test is only meaningful for full-ppgtt environments
> +	 * where the GTT space of the request is separate from the GGTT
> +	 * allocation required to build the request.
> +	 */
> +	if (!USES_FULL_PPGTT(i915))
> +		return 0;
> +
> +	mutex_lock(&i915->drm.struct_mutex);
> +
> +	/* Reserve a block so that we know we have enough to fit a few rq */
> +	memset(&hole, 0, sizeof(hole));
> +	err = i915_gem_gtt_insert(&i915->ggtt.base, &hole,
> +				  PRETEND_GGTT_SIZE, 0, I915_COLOR_UNEVICTABLE,
> +				  0, i915->ggtt.base.total,
> +				  PIN_NOEVICT);
> +	if (err)
> +		goto out_locked;
> +
> +	/* Make the GGTT appear small by filling it with unevictable nodes */
> +	count = 0;
> +	do {
> +		struct reserved *r;
> +
> +		r = kcalloc(1, sizeof(*r), GFP_KERNEL);
> +		if (!r) {
> +			err = -ENOMEM;
> +			goto out_locked;
> +		}
> +
> +		if (i915_gem_gtt_insert(&i915->ggtt.base, &r->node,
> +					1ul << 20, 0, I915_COLOR_UNEVICTABLE,
> +					0, i915->ggtt.base.total,
> +					PIN_NOEVICT)) {
> +			kfree(r);
> +			break;
> +		}
> +
> +		r->next = reserved;
> +		reserved = r;
> +
> +		count++;
> +	} while (1);
> +	drm_mm_remove_node(&hole);
> +	mutex_unlock(&i915->drm.struct_mutex);
> +	pr_info("Filled GGTT with %lu 1MiB nodes\n", count);
> +
> +	/* Overfill the GGTT with context objects and so try to evict one. */
> +	for_each_engine(engine, i915, id) {
> +		struct i915_sw_fence fence;
> +		struct drm_file *file;
> +
> +		file = mock_file(i915);
> +		if (IS_ERR(file))
> +			return PTR_ERR(file);
> +
> +		count = 0;
> +		mutex_lock(&i915->drm.struct_mutex);
> +		onstack_fence_init(&fence);
> +		do {
> +			struct drm_i915_gem_request *rq;
> +			struct i915_gem_context *ctx;
> +
> +			ctx = live_context(i915, file);
> +			if (!ctx)
> +				break;
> +
> +			igt_evict_ctl.fail_if_busy = true;
> +			rq = i915_gem_request_alloc(engine, ctx);
> +			igt_evict_ctl.fail_if_busy = false;
> +
> +			if (IS_ERR(rq)) {
> +				/* When full, fail_if_busy will trigger -EBUSY */
> +				if (PTR_ERR(rq) != -EBUSY) {
> +					pr_err("Unexpected error from request alloc (ctx hw id %u, on %s): %d\n",
> +					       ctx->hw_id, engine->name,
> +					       (int)PTR_ERR(rq));
> +					err = PTR_ERR(rq);
> +				}
> +				break;
> +			}
> +
> +			/* Keep every request busy until we are full */
> +			err = i915_sw_fence_await_sw_fence_gfp(&rq->submit,
> +							       &fence,
> +							       GFP_KERNEL);
> +			if (err < 0)
> +				break;
> +
> +			i915_add_request(rq);
> +			count++;
> +			err = 0;
> +		} while(!i915_sw_fence_done(&fence));
> +		mutex_unlock(&i915->drm.struct_mutex);
> +
> +		onstack_fence_fini(&fence);
> +		pr_info("Submitted %lu contexts/requests on %s\n",
> +			count, engine->name);
> +
> +		mock_file_free(i915, file);
> +		if (err)
> +			break;
> +	}
> +
> +	mutex_lock(&i915->drm.struct_mutex);
> +out_locked:
> +	while (reserved) {
> +		struct reserved *next = reserved->next;
> +
> +		drm_mm_remove_node(&reserved->node);
> +		kfree(reserved);
> +
> +		reserved = next;
> +	}
> +	if (drm_mm_node_allocated(&hole))
> +		drm_mm_remove_node(&hole);
> +	mutex_unlock(&i915->drm.struct_mutex);
> +
> +	return err;
> +}
> +
>   int i915_gem_evict_mock_selftests(void)
>   {
>   	static const struct i915_subtest tests[] = {
> @@ -348,3 +492,12 @@ int i915_gem_evict_mock_selftests(void)
>   	drm_dev_unref(&i915->drm);
>   	return err;
>   }
> +
> +int i915_gem_evict_live_selftests(struct drm_i915_private *i915)
> +{
> +	static const struct i915_subtest tests[] = {
> +		SUBTEST(igt_evict_contexts),
> +	};
> +
> +	return i915_subtests(tests, i915);
> +}
> diff --git a/drivers/gpu/drm/i915/selftests/i915_live_selftests.h b/drivers/gpu/drm/i915/selftests/i915_live_selftests.h
> index 64acd7eccc5c..54a73534b37e 100644
> --- a/drivers/gpu/drm/i915/selftests/i915_live_selftests.h
> +++ b/drivers/gpu/drm/i915/selftests/i915_live_selftests.h
> @@ -15,6 +15,7 @@ selftest(objects, i915_gem_object_live_selftests)
>   selftest(dmabuf, i915_gem_dmabuf_live_selftests)
>   selftest(coherency, i915_gem_coherency_live_selftests)
>   selftest(gtt, i915_gem_gtt_live_selftests)
> +selftest(evict, i915_gem_evict_live_selftests)
>   selftest(hugepages, i915_gem_huge_page_live_selftests)
>   selftest(contexts, i915_gem_context_live_selftests)
>   selftest(hangcheck, intel_hangcheck_live_selftests)
> diff --git a/drivers/gpu/drm/i915/selftests/mock_context.c b/drivers/gpu/drm/i915/selftests/mock_context.c
> index 098ce643ad07..bbf80d42e793 100644
> --- a/drivers/gpu/drm/i915/selftests/mock_context.c
> +++ b/drivers/gpu/drm/i915/selftests/mock_context.c
> @@ -73,11 +73,7 @@ mock_context(struct drm_i915_private *i915,
>   
>   void mock_context_close(struct i915_gem_context *ctx)
>   {
> -	i915_gem_context_set_closed(ctx);
> -
> -	i915_ppgtt_close(&ctx->ppgtt->base);
> -
> -	i915_gem_context_put(ctx);
> +	context_close(ctx);
>   }
>   
>   void mock_init_contexts(struct drm_i915_private *i915)
> 

Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>

Regards,

Tvrtko

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 8+ messages in thread

* ✗ Fi.CI.IGT: failure for series starting with [v3,1/3] drm/i915: Fix eviction when the GGTT is idle but full
  2017-10-12 12:57 [PATCH v3 1/3] drm/i915: Fix eviction when the GGTT is idle but full Chris Wilson
                   ` (2 preceding siblings ...)
  2017-10-12 13:29 ` ✓ Fi.CI.BAT: success for series starting with [v3,1/3] drm/i915: Fix eviction when the GGTT is idle but full Patchwork
@ 2017-10-12 17:48 ` Patchwork
  3 siblings, 0 replies; 8+ messages in thread
From: Patchwork @ 2017-10-12 17:48 UTC (permalink / raw)
  To: Chris Wilson; +Cc: intel-gfx

== Series Details ==

Series: series starting with [v3,1/3] drm/i915: Fix eviction when the GGTT is idle but full
URL   : https://patchwork.freedesktop.org/series/31815/
State : failure

== Summary ==

Test prime_self_import:
        Subgroup reimport-vs-gem_close-race:
                fail       -> PASS       (shard-hsw) fdo#102655
Test kms_atomic_transition:
        Subgroup plane-primary-toggle-with-vblank-wait:
                pass       -> SKIP       (shard-hsw)
        Subgroup 1x-modeset-transitions-nonblocking-fencing:
                pass       -> SKIP       (shard-hsw)
Test kms_universal_plane:
        Subgroup universal-plane-pipe-A-sanity:
                pass       -> SKIP       (shard-hsw)
Test kms_busy:
        Subgroup basic-modeset-C:
                pass       -> SKIP       (shard-hsw)
        Subgroup extended-modeset-hang-newfb-with-reset-render-A:
                pass       -> SKIP       (shard-hsw)
Test kms_cursor_crc:
        Subgroup cursor-64x21-sliding:
                pass       -> SKIP       (shard-hsw)
Test kms_cursor_legacy:
        Subgroup flip-vs-cursor-varying-size:
                pass       -> FAIL       (shard-hsw)
Test kms_force_connector_basic:
        Subgroup force-connector-state:
                skip       -> PASS       (shard-hsw)
Test kms_chv_cursor_fail:
        Subgroup pipe-C-256x256-bottom-edge:
                pass       -> SKIP       (shard-hsw)
Test kms_frontbuffer_tracking:
        Subgroup fbc-1p-offscren-pri-shrfb-draw-mmap-wc:
                dmesg-warn -> PASS       (shard-hsw) fdo#102614

fdo#102655 https://bugs.freedesktop.org/show_bug.cgi?id=102655
fdo#102614 https://bugs.freedesktop.org/show_bug.cgi?id=102614

shard-hsw        total:2551 pass:1433 dwarn:0   dfail:0   fail:9   skip:1109 time:9494s

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_6007/shards.html
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2017-10-12 17:48 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-10-12 12:57 [PATCH v3 1/3] drm/i915: Fix eviction when the GGTT is idle but full Chris Wilson
2017-10-12 12:57 ` [PATCH v3 2/3] drm/i915/selftests: Wrap a timer into a i915_sw_fence Chris Wilson
2017-10-12 15:06   ` Tvrtko Ursulin
2017-10-12 12:57 ` [PATCH v3 3/3] drm/i915/selftests: Exercise adding requests to a full GGTT Chris Wilson
2017-10-12 14:40   ` Chris Wilson
2017-10-12 15:12   ` Tvrtko Ursulin
2017-10-12 13:29 ` ✓ Fi.CI.BAT: success for series starting with [v3,1/3] drm/i915: Fix eviction when the GGTT is idle but full Patchwork
2017-10-12 17:48 ` ✗ Fi.CI.IGT: failure " Patchwork

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.