[PATCH 71/75] drm/i915/selftests: Reimplement mock engine using a tasklet
Chris Wilson
chris at chris-wilson.co.uk
Tue Feb 2 11:38:28 UTC 2021
Switch the mock_engine to using the scheduler as its basic primitive.
Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
---
drivers/gpu/drm/i915/gt/mock_engine.c | 223 +++++++++---------
drivers/gpu/drm/i915/gt/mock_engine.h | 15 +-
drivers/gpu/drm/i915/selftests/i915_request.c | 68 ------
drivers/gpu/drm/i915/selftests/mock_request.c | 17 --
drivers/gpu/drm/i915/selftests/mock_request.h | 2 -
5 files changed, 109 insertions(+), 216 deletions(-)
diff --git a/drivers/gpu/drm/i915/gt/mock_engine.c b/drivers/gpu/drm/i915/gt/mock_engine.c
index d2a4221a8b9e..3a5bd4f23f7f 100644
--- a/drivers/gpu/drm/i915/gt/mock_engine.c
+++ b/drivers/gpu/drm/i915/gt/mock_engine.c
@@ -3,6 +3,8 @@
* Copyright © 2016 Intel Corporation
*/
+#include <linux/timer.h>
+
#include "gem/i915_gem_context.h"
#include "gt/intel_ring.h"
@@ -13,6 +15,12 @@
#include "mock_engine.h"
#include "selftests/mock_request.h"
+struct mock_sched {
+ struct i915_sched sched;
+
+ struct timer_list hw_delay;
+};
+
static void mock_timeline_pin(struct intel_timeline *tl)
{
atomic_inc(&tl->pin_count);
@@ -62,51 +70,62 @@ static void mock_ring_free(struct intel_ring *ring)
kfree(ring);
}
-static struct i915_request *first_request(struct mock_engine *engine)
+static void dequeue(struct mock_sched *mock)
{
- return list_first_entry_or_null(&engine->hw_queue,
- struct i915_request,
- mock.link);
+ struct i915_request *rq, *rn;
+ struct i915_priolist *pl;
+
+ for_each_priolist(pl, &mock->sched.queue) {
+ priolist_for_each_request_safe(rq, rn, pl) {
+ __i915_request_submit(rq, mock->sched.priv);
+ if (rq->mock.delay && !rq->fence.error) {
+ mod_timer(&mock->hw_delay,
+ jiffies + rq->mock.delay);
+ return;
+ }
+ list_del_init(&rq->sched.link);
+ i915_request_mark_complete(rq);
+ }
+
+ i915_priolist_advance(&mock->sched.queue, pl);
+ }
}
-static void advance(struct i915_request *request,
- struct mock_engine *engine)
+static void advance(struct mock_sched *mock)
{
- list_del_init(&request->mock.link);
- i915_request_mark_complete(request);
- GEM_BUG_ON(!i915_request_completed(request));
+ struct i915_request *rq;
- intel_engine_signal_breadcrumbs(&engine->base);
+ if (list_empty(&mock->sched.requests))
+ return;
+
+ rq = list_first_entry(&mock->sched.requests, typeof(*rq), sched.link);
+ list_del_init(&rq->sched.link);
+ i915_request_mark_complete(rq);
+ intel_engine_signal_breadcrumbs(mock->sched.priv);
+
+ GEM_BUG_ON(!list_empty(&mock->sched.requests));
+}
+
+static void submission_tasklet(struct tasklet_struct *t)
+{
+ struct mock_sched *mock = from_tasklet(mock, t, sched.tasklet);
+
+ spin_lock_irq(&mock->sched.lock);
+
+ if (timer_expired(&mock->hw_delay))
+ advance(mock);
+
+ if (list_empty(&mock->sched.requests))
+ dequeue(mock);
+
+ spin_unlock_irq(&mock->sched.lock);
}
static void hw_delay_complete(struct timer_list *t)
{
- struct mock_engine *engine = from_timer(engine, t, hw_delay);
- struct i915_request *request;
- unsigned long flags;
+ struct mock_sched *mock = from_timer(mock, t, hw_delay);
- spin_lock_irqsave(&engine->hw_lock, flags);
-
- /* Timer fired, first request is complete */
- request = first_request(engine);
- if (request)
- advance(request, engine);
-
- /*
- * Also immediately signal any subsequent 0-delay requests, but
- * requeue the timer for the next delayed request.
- */
- while ((request = first_request(engine))) {
- if (request->mock.delay) {
- mod_timer(&engine->hw_delay,
- jiffies + request->mock.delay);
- break;
- }
-
- advance(request, engine);
- }
-
- spin_unlock_irqrestore(&engine->hw_lock, flags);
+ i915_sched_kick(&mock->sched);
}
static void mock_context_unpin(struct intel_context *ce)
@@ -167,9 +186,7 @@ static void mock_context_reset(struct intel_context *ce)
static int
mock_context_request(struct intel_context *ce, struct i915_request *rq)
{
- INIT_LIST_HEAD(&rq->mock.link);
rq->mock.delay = 0;
-
return 0;
}
@@ -203,28 +220,6 @@ static u32 *mock_emit_breadcrumb(const struct intel_engine_cs *engine,
return cs;
}
-static void mock_submit_request(struct i915_request *request)
-{
- struct mock_engine *engine =
- container_of(i915_request_get_engine(request),
- typeof(*engine),
- base);
- unsigned long flags;
-
- i915_request_submit(request, &engine->base);
-
- spin_lock_irqsave(&engine->hw_lock, flags);
- list_add_tail(&request->mock.link, &engine->hw_queue);
- if (list_is_first(&request->mock.link, &engine->hw_queue)) {
- if (request->mock.delay)
- mod_timer(&engine->hw_delay,
- jiffies + request->mock.delay);
- else
- advance(request, engine);
- }
- spin_unlock_irqrestore(&engine->hw_lock, flags);
-}
-
static void mock_reset_prepare(struct intel_engine_cs *engine)
{
}
@@ -236,14 +231,11 @@ static void mock_reset_rewind(struct intel_engine_cs *engine, bool stalled)
static void mock_reset_cancel(struct intel_engine_cs *engine)
{
- struct mock_engine *mock =
- container_of(engine, typeof(*mock), base);
struct i915_sched *se = intel_engine_get_scheduler(engine);
- struct i915_request *rq;
+ struct i915_request *rq, *rn;
+ struct i915_priolist *pl;
unsigned long flags;
- del_timer_sync(&mock->hw_delay);
-
spin_lock_irqsave(&se->lock, flags);
/* Mark all submitted requests as skipped. */
@@ -252,13 +244,15 @@ static void mock_reset_cancel(struct intel_engine_cs *engine)
intel_engine_signal_breadcrumbs(engine);
/* Cancel and submit all pending requests. */
- list_for_each_entry(rq, &mock->hw_queue, mock.link) {
- if (i915_request_mark_eio(rq)) {
- __i915_request_submit(rq, engine);
- i915_request_put(rq);
+ for_each_priolist(pl, &se->queue) {
+ priolist_for_each_request_safe(rq, rn, pl) {
+ if (i915_request_mark_eio(rq)) {
+ __i915_request_submit(rq, engine);
+ i915_request_put(rq);
+ }
}
+ i915_priolist_advance(&se->queue, pl);
}
- INIT_LIST_HEAD(&mock->hw_queue);
spin_unlock_irqrestore(&se->lock, flags);
}
@@ -269,12 +263,12 @@ static void mock_reset_finish(struct intel_engine_cs *engine)
static void mock_engine_release(struct intel_engine_cs *engine)
{
- struct mock_engine *mock =
- container_of(engine, typeof(*mock), base);
+ struct mock_sched *mock =
+ container_of(engine->sched, typeof(*mock), sched);
- GEM_BUG_ON(timer_pending(&mock->hw_delay));
+ del_timer_sync(&mock->hw_delay);
+ i915_sched_put(&mock->sched);
- i915_sched_put(engine->sched);
intel_breadcrumbs_free(engine->breadcrumbs);
intel_context_unpin(engine->kernel_context);
@@ -287,7 +281,7 @@ struct intel_engine_cs *mock_engine(struct drm_i915_private *i915,
const char *name,
int id)
{
- struct mock_engine *engine;
+ struct intel_engine_cs *engine;
GEM_BUG_ON(id >= I915_NUM_ENGINES);
GEM_BUG_ON(!i915->gt.uncore);
@@ -297,54 +291,54 @@ struct intel_engine_cs *mock_engine(struct drm_i915_private *i915,
return NULL;
/* minimal engine setup for requests */
- engine->base.i915 = i915;
- engine->base.gt = &i915->gt;
- engine->base.uncore = i915->gt.uncore;
- snprintf(engine->base.name, sizeof(engine->base.name), "%s", name);
- engine->base.id = id;
- engine->base.mask = BIT(id);
- engine->base.legacy_idx = INVALID_ENGINE;
- engine->base.instance = id;
- engine->base.status_page.addr = (void *)(engine + 1);
+ engine->i915 = i915;
+ engine->gt = &i915->gt;
+ engine->uncore = i915->gt.uncore;
+ snprintf(engine->name, sizeof(engine->name), "%s", name);
+ engine->id = id;
+ engine->mask = BIT(id);
+ engine->legacy_idx = INVALID_ENGINE;
+ engine->instance = id;
+ engine->status_page.addr = (void *)(engine + 1);
- engine->base.cops = &mock_context_ops;
- engine->base.emit_flush = mock_emit_flush;
- engine->base.emit_fini_breadcrumb = mock_emit_breadcrumb;
+ engine->cops = &mock_context_ops;
+ engine->emit_flush = mock_emit_flush;
+ engine->emit_fini_breadcrumb = mock_emit_breadcrumb;
- engine->base.reset.prepare = mock_reset_prepare;
- engine->base.reset.rewind = mock_reset_rewind;
- engine->base.reset.cancel = mock_reset_cancel;
- engine->base.reset.finish = mock_reset_finish;
+ engine->reset.prepare = mock_reset_prepare;
+ engine->reset.rewind = mock_reset_rewind;
+ engine->reset.cancel = mock_reset_cancel;
+ engine->reset.finish = mock_reset_finish;
- engine->base.release = mock_engine_release;
+ engine->release = mock_engine_release;
- i915->gt.engine[id] = &engine->base;
- i915->gt.engine_class[0][id] = &engine->base;
+ i915->gt.engine[id] = engine;
+ i915->gt.engine_class[0][id] = engine;
- /* fake hw queue */
- spin_lock_init(&engine->hw_lock);
- timer_setup(&engine->hw_delay, hw_delay_complete, 0);
- INIT_LIST_HEAD(&engine->hw_queue);
+ intel_engine_add_user(engine);
- intel_engine_add_user(&engine->base);
-
- return &engine->base;
+ return engine;
}
int mock_engine_init(struct intel_engine_cs *engine)
{
struct intel_context *ce;
+ struct mock_sched *se;
- engine->sched =
- i915_sched_create(engine->i915->drm.dev,
- engine->name,
- engine->mask,
- NULL, engine,
- ENGINE_MOCK);
- if (!engine->sched)
+ se = kzalloc(sizeof(*se), GFP_KERNEL);
+ if (!se)
return -ENOMEM;
- engine->sched->submit_request = mock_submit_request;
+ timer_setup(&se->hw_delay, hw_delay_complete, 0);
+
+ i915_sched_init(&se->sched,
+ engine->i915->drm.dev,
+ engine->name,
+ engine->mask,
+ submission_tasklet, engine,
+ ENGINE_MOCK);
+
+ engine->sched = &se->sched;
intel_engine_init__pm(engine);
intel_engine_init_retire(engine);
@@ -372,16 +366,13 @@ int mock_engine_init(struct intel_engine_cs *engine)
void mock_engine_flush(struct intel_engine_cs *engine)
{
- struct mock_engine *mock =
- container_of(engine, typeof(*mock), base);
- struct i915_request *request, *rn;
+ struct mock_sched *mock =
+ container_of(engine->sched, typeof(*mock), sched);
+
+ mock_reset_cancel(engine);
del_timer_sync(&mock->hw_delay);
-
- spin_lock_irq(&mock->hw_lock);
- list_for_each_entry_safe(request, rn, &mock->hw_queue, mock.link)
- advance(request, mock);
- spin_unlock_irq(&mock->hw_lock);
+ i915_sched_flush(&mock->sched);
}
void mock_engine_reset(struct intel_engine_cs *engine)
diff --git a/drivers/gpu/drm/i915/gt/mock_engine.h b/drivers/gpu/drm/i915/gt/mock_engine.h
index cc5ab6e1f37e..fdcb9eab3f4f 100644
--- a/drivers/gpu/drm/i915/gt/mock_engine.h
+++ b/drivers/gpu/drm/i915/gt/mock_engine.h
@@ -6,19 +6,8 @@
#ifndef __MOCK_ENGINE_H__
#define __MOCK_ENGINE_H__
-#include <linux/list.h>
-#include <linux/spinlock.h>
-#include <linux/timer.h>
-
-#include "gt/intel_engine.h"
-
-struct mock_engine {
- struct intel_engine_cs base;
-
- spinlock_t hw_lock;
- struct list_head hw_queue;
- struct timer_list hw_delay;
-};
+struct drm_i915_private;
+struct intel_engine_cs;
struct intel_engine_cs *mock_engine(struct drm_i915_private *i915,
const char *name,
diff --git a/drivers/gpu/drm/i915/selftests/i915_request.c b/drivers/gpu/drm/i915/selftests/i915_request.c
index 5d747c2d937b..8c9d60359324 100644
--- a/drivers/gpu/drm/i915/selftests/i915_request.c
+++ b/drivers/gpu/drm/i915/selftests/i915_request.c
@@ -200,73 +200,6 @@ static int igt_fence_wait(void *arg)
return err;
}
-static int igt_request_rewind(void *arg)
-{
- struct drm_i915_private *i915 = arg;
- struct i915_request *request, *vip;
- struct i915_gem_context *ctx[2];
- struct intel_context *ce;
- int err = -EINVAL;
-
- ctx[0] = mock_context(i915, "A");
-
- ce = i915_gem_context_get_engine(ctx[0], RCS0);
- GEM_BUG_ON(IS_ERR(ce));
- request = mock_request(ce, 2 * HZ);
- intel_context_put(ce);
- if (!request) {
- err = -ENOMEM;
- goto err_context_0;
- }
-
- i915_request_get(request);
- i915_request_add(request);
-
- ctx[1] = mock_context(i915, "B");
-
- ce = i915_gem_context_get_engine(ctx[1], RCS0);
- GEM_BUG_ON(IS_ERR(ce));
- vip = mock_request(ce, 0);
- intel_context_put(ce);
- if (!vip) {
- err = -ENOMEM;
- goto err_context_1;
- }
-
- /* Simulate preemption by manual reordering */
- if (!mock_cancel_request(request)) {
- pr_err("failed to cancel request (already executed)!\n");
- i915_request_add(vip);
- goto err_context_1;
- }
- i915_request_get(vip);
- i915_request_add(vip);
- rcu_read_lock();
- i915_request_get_scheduler(request)->submit_request(request);
- rcu_read_unlock();
-
- if (i915_request_wait(vip, 0, HZ) == -ETIME) {
- pr_err("timed out waiting for high priority request\n");
- goto err;
- }
-
- if (i915_request_completed(request)) {
- pr_err("low priority request already completed\n");
- goto err;
- }
-
- err = 0;
-err:
- i915_request_put(vip);
-err_context_1:
- mock_context_close(ctx[1]);
- i915_request_put(request);
-err_context_0:
- mock_context_close(ctx[0]);
- mock_device_flush(i915);
- return err;
-}
-
struct smoketest {
struct intel_engine_cs *engine;
struct i915_gem_context **contexts;
@@ -513,7 +446,6 @@ int i915_request_mock_selftests(void)
SUBTEST(igt_add_request),
SUBTEST(igt_wait_request),
SUBTEST(igt_fence_wait),
- SUBTEST(igt_request_rewind),
SUBTEST(mock_breadcrumbs_smoketest),
};
struct drm_i915_private *i915;
diff --git a/drivers/gpu/drm/i915/selftests/mock_request.c b/drivers/gpu/drm/i915/selftests/mock_request.c
index 49f3bddfcb95..8aa28e8d1c89 100644
--- a/drivers/gpu/drm/i915/selftests/mock_request.c
+++ b/drivers/gpu/drm/i915/selftests/mock_request.c
@@ -40,20 +40,3 @@ mock_request(struct intel_context *ce, unsigned long delay)
request->mock.delay = delay;
return request;
}
-
-bool mock_cancel_request(struct i915_request *request)
-{
- struct mock_engine *engine =
- container_of(i915_request_get_engine(request), typeof(*engine), base);
- bool was_queued;
-
- spin_lock_irq(&engine->hw_lock);
- was_queued = !list_empty(&request->mock.link);
- list_del_init(&request->mock.link);
- spin_unlock_irq(&engine->hw_lock);
-
- if (was_queued)
- i915_request_unsubmit(request);
-
- return was_queued;
-}
diff --git a/drivers/gpu/drm/i915/selftests/mock_request.h b/drivers/gpu/drm/i915/selftests/mock_request.h
index 8907b60c290d..3d4bac9bcfe2 100644
--- a/drivers/gpu/drm/i915/selftests/mock_request.h
+++ b/drivers/gpu/drm/i915/selftests/mock_request.h
@@ -32,6 +32,4 @@
struct i915_request *
mock_request(struct intel_context *ce, unsigned long delay);
-bool mock_cancel_request(struct i915_request *request);
-
#endif /* !__MOCK_REQUEST__ */
--
2.20.1
More information about the Intel-gfx-trybot
mailing list