Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 50f0033d authored by Chris Wilson's avatar Chris Wilson Committed by Daniel Vetter
Browse files

drm: Add some kselftests for the DRM range manager (struct drm_mm)



First we introduce a smattering of infrastructure for writing selftests.
The idea is that we have a test module that exercises a particular
portion of the exported API, and that module provides a set of tests
that can either be run as an ensemble via kselftest or individually via
an igt harness (in this case igt/drm_mm). To accommodate selecting
individual tests, we export a boolean parameter to control selection of
each test - that is hidden inside a bunch of reusable boilerplate macros
to keep writing the tests simple.

v2: Choose a random random_seed unless one is specified by the user.
v3: More parameters to control max_iterations and max_prime of the
tests.

Testcase: igt/drm_mm
Signed-off-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
Acked-by: default avatarChristian König <christian.koenig@amd.com>
Reviewed-by: default avatarJoonas Lahtinen <joonas.lahtinen@linux.intel.com>
Signed-off-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
Link: http://patchwork.freedesktop.org/patch/msgid/20161222083641.2691-7-chris@chris-wilson.co.uk
parent a33d42dd
Loading
Loading
Loading
Loading
+15 −0
Original line number Diff line number Diff line
@@ -48,6 +48,21 @@ config DRM_DEBUG_MM

	  If in doubt, say "N".

config DRM_DEBUG_MM_SELFTEST
	tristate "kselftests for DRM range manager (struct drm_mm)"
	depends on DRM
	depends on DEBUG_KERNEL
	select PRIME_NUMBERS
	select DRM_LIB_RANDOM
	default n
	help
	  This option provides a kernel module that can be used to test
	  the DRM range manager (drm_mm) and its API. This option is not
	  useful for distributions or general kernels, but only for kernel
	  developers working on DRM and associated drivers.

	  If in doubt, say "N".

config DRM_KMS_HELPER
	tristate
	depends on DRM
+1 −0
Original line number Diff line number Diff line
@@ -38,6 +38,7 @@ drm_kms_helper-$(CONFIG_DRM_KMS_CMA_HELPER) += drm_fb_cma_helper.o
drm_kms_helper-$(CONFIG_DRM_DP_AUX_CHARDEV) += drm_dp_aux_dev.o

obj-$(CONFIG_DRM_KMS_HELPER) += drm_kms_helper.o
obj-$(CONFIG_DRM_DEBUG_MM_SELFTEST) += selftests/test-drm_mm.o

CFLAGS_drm_trace_points.o := -I$(src)

+8 −0
Original line number Diff line number Diff line
/* List each unit test as selftest(name, function)
 *
 * The name is used as both an enum and expanded as igt__name to create
 * a module parameter. It must be unique and legal for a C identifier.
 *
 * Tests are executed in order by igt/drm_mm
 */
selftest(sanitycheck, igt_sanitycheck) /* keep first (selfcheck for igt) */
+109 −0
Original line number Diff line number Diff line
/*
 * Copyright © 2016 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 <linux/compiler.h>

#define selftest(name, func) __idx_##name,
enum {
#include TESTS
};
#undef selftest

#define selftest(n, f) [__idx_##n] = { .name = #n, .func = f },
static struct drm_selftest {
	bool enabled;
	const char *name;
	int (*func)(void *);
} selftests[] = {
#include TESTS
};
#undef selftest

/* Embed the line number into the parameter name so that we can order tests */
#define param(n) __PASTE(igt__, __PASTE(__PASTE(__LINE__, __), n))
#define selftest_0(n, func, id) \
module_param_named(id, selftests[__idx_##n].enabled, bool, 0400);
#define selftest(n, func) selftest_0(n, func, param(n))
#include TESTS
#undef selftest

static void set_default_test_all(struct drm_selftest *st, unsigned long count)
{
	unsigned long i;

	for (i = 0; i < count; i++)
		if (st[i].enabled)
			return;

	for (i = 0; i < count; i++)
		st[i].enabled = true;
}

static int run_selftests(struct drm_selftest *st,
			 unsigned long count,
			 void *data)
{
	int err = 0;

	set_default_test_all(st, count);

	/* Tests are listed in natural order in drm_*_selftests.h */
	for (; count--; st++) {
		if (!st->enabled)
			continue;

		pr_debug("drm: Running %s\n", st->name);
		err = st->func(data);
		if (err)
			break;
	}

	if (WARN(err > 0 || err == -ENOTTY,
		 "%s returned %d, conflicting with selftest's magic values!\n",
		 st->name, err))
		err = -1;

	rcu_barrier();
	return err;
}

static int __maybe_unused
__drm_subtests(const char *caller,
	       const struct drm_subtest *st,
	       int count,
	       void *data)
{
	int err;

	for (; count--; st++) {
		pr_debug("Running %s/%s\n", caller, st->name);
		err = st->func(data);
		if (err) {
			pr_err("%s: %s failed with error %d\n",
			       caller, st->name, err);
			return err;
		}
	}

	return 0;
}
+41 −0
Original line number Diff line number Diff line
/*
 * Copyright © 2016 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.
 */

#ifndef __DRM_SELFTEST_H__
#define __DRM_SELFTEST_H__

struct drm_subtest {
	int (*func)(void *data);
	const char *name;
};

static int __drm_subtests(const char *caller,
			  const struct drm_subtest *st,
			  int count,
			  void *data);
#define drm_subtests(T, data) \
	__drm_subtests(__func__, T, ARRAY_SIZE(T), data)

#define SUBTEST(x) { x, #x }

#endif /* __DRM_SELFTEST_H__ */
Loading