* [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.