Commit b348090d authored by Chris Wilson's avatar Chris Wilson

drm/i915: Simple selftest to exercise live requests

Just create several batches of requests and expect it to not fall over!
Signed-off-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: default avatarJoonas Lahtinen <joonas.lahtinen@linux.intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/20170213171558.20942-13-chris@chris-wilson.co.uk
parent 5fd4d112
......@@ -22,6 +22,8 @@
*
*/
#include <linux/prime_numbers.h>
#include "../i915_selftest.h"
#include "mock_gem_device.h"
......@@ -198,3 +200,148 @@ int i915_gem_request_mock_selftests(void)
return err;
}
struct live_test {
struct drm_i915_private *i915;
const char *func;
const char *name;
unsigned int reset_count;
};
static int begin_live_test(struct live_test *t,
struct drm_i915_private *i915,
const char *func,
const char *name)
{
int err;
t->i915 = i915;
t->func = func;
t->name = name;
err = i915_gem_wait_for_idle(i915, I915_WAIT_LOCKED);
if (err) {
pr_err("%s(%s): failed to idle before, with err=%d!",
func, name, err);
return err;
}
i915_gem_retire_requests(i915);
i915->gpu_error.missed_irq_rings = 0;
t->reset_count = i915_reset_count(&i915->gpu_error);
return 0;
}
static int end_live_test(struct live_test *t)
{
struct drm_i915_private *i915 = t->i915;
if (wait_for(intel_execlists_idle(i915), 1)) {
pr_err("%s(%s): GPU not idle\n", t->func, t->name);
return -EIO;
}
if (t->reset_count != i915_reset_count(&i915->gpu_error)) {
pr_err("%s(%s): GPU was reset %d times!\n",
t->func, t->name,
i915_reset_count(&i915->gpu_error) - t->reset_count);
return -EIO;
}
if (i915->gpu_error.missed_irq_rings) {
pr_err("%s(%s): Missed interrupts on engines %lx\n",
t->func, t->name, i915->gpu_error.missed_irq_rings);
return -EIO;
}
return 0;
}
static int live_nop_request(void *arg)
{
struct drm_i915_private *i915 = arg;
struct intel_engine_cs *engine;
struct live_test t;
unsigned int id;
int err;
/* Submit various sized batches of empty requests, to each engine
* (individually), and wait for the batch to complete. We can check
* the overhead of submitting requests to the hardware.
*/
mutex_lock(&i915->drm.struct_mutex);
for_each_engine(engine, i915, id) {
IGT_TIMEOUT(end_time);
struct drm_i915_gem_request *request;
unsigned long n, prime;
ktime_t times[2] = {};
err = begin_live_test(&t, i915, __func__, engine->name);
if (err)
goto out_unlock;
for_each_prime_number_from(prime, 1, 8192) {
times[1] = ktime_get_raw();
for (n = 0; n < prime; n++) {
request = i915_gem_request_alloc(engine,
i915->kernel_context);
if (IS_ERR(request)) {
err = PTR_ERR(request);
goto out_unlock;
}
/* This space is left intentionally blank.
*
* We do not actually want to perform any
* action with this request, we just want
* to measure the latency in allocation
* and submission of our breadcrumbs -
* ensuring that the bare request is sufficient
* for the system to work (i.e. proper HEAD
* tracking of the rings, interrupt handling,
* etc). It also gives us the lowest bounds
* for latency.
*/
i915_add_request(request);
}
i915_wait_request(request,
I915_WAIT_LOCKED,
MAX_SCHEDULE_TIMEOUT);
times[1] = ktime_sub(ktime_get_raw(), times[1]);
if (prime == 1)
times[0] = times[1];
if (__igt_timeout(end_time, NULL))
break;
}
err = end_live_test(&t);
if (err)
goto out_unlock;
pr_info("Request latencies on %s: 1 = %lluns, %lu = %lluns\n",
engine->name,
ktime_to_ns(times[0]),
prime, div64_u64(ktime_to_ns(times[1]), prime));
}
out_unlock:
mutex_unlock(&i915->drm.struct_mutex);
return err;
}
int i915_gem_request_live_selftests(struct drm_i915_private *i915)
{
static const struct i915_subtest tests[] = {
SUBTEST(live_nop_request),
};
return i915_subtests(tests, i915);
}
......@@ -9,3 +9,4 @@
* Tests are executed in order by igt/drv_selftest
*/
selftest(sanitycheck, i915_live_sanitycheck) /* keep first (igt selfcheck) */
selftest(requests, i915_gem_request_live_selftests)
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment