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: Chris Wilson <chris@chris-wilson.co.uk> Acked-by: Christian König <christian.koenig@amd.com> Reviewed-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch> Link: http://patchwork.freedesktop.org/patch/msgid/20161222083641.2691-7-chris@chris-wilson.co.uk
This commit is contained in:
		
							parent
							
								
									a33d42dd03
								
							
						
					
					
						commit
						50f0033d1a
					
				| @ -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 | ||||
|  | ||||
| @ -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
									
								
								drivers/gpu/drm/selftests/drm_mm_selftests.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								drivers/gpu/drm/selftests/drm_mm_selftests.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,8 @@ | ||||
| /* 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
									
								
								drivers/gpu/drm/selftests/drm_selftest.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										109
									
								
								drivers/gpu/drm/selftests/drm_selftest.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,109 @@ | ||||
| /*
 | ||||
|  * 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
									
								
								drivers/gpu/drm/selftests/drm_selftest.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								drivers/gpu/drm/selftests/drm_selftest.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,41 @@ | ||||
| /*
 | ||||
|  * 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__ */ | ||||
							
								
								
									
										58
									
								
								drivers/gpu/drm/selftests/test-drm_mm.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								drivers/gpu/drm/selftests/test-drm_mm.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,58 @@ | ||||
| /*
 | ||||
|  * Test cases for the drm_mm range manager | ||||
|  */ | ||||
| 
 | ||||
| #define pr_fmt(fmt) "drm_mm: " fmt | ||||
| 
 | ||||
| #include <linux/module.h> | ||||
| #include <linux/prime_numbers.h> | ||||
| #include <linux/slab.h> | ||||
| #include <linux/random.h> | ||||
| #include <linux/vmalloc.h> | ||||
| 
 | ||||
| #include <drm/drm_mm.h> | ||||
| 
 | ||||
| #include "../lib/drm_random.h" | ||||
| 
 | ||||
| #define TESTS "drm_mm_selftests.h" | ||||
| #include "drm_selftest.h" | ||||
| 
 | ||||
| static unsigned int random_seed; | ||||
| static unsigned int max_iterations = 8192; | ||||
| static unsigned int max_prime = 128; | ||||
| 
 | ||||
| static int igt_sanitycheck(void *ignored) | ||||
| { | ||||
| 	pr_info("%s - ok!\n", __func__); | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| #include "drm_selftest.c" | ||||
| 
 | ||||
| static int __init test_drm_mm_init(void) | ||||
| { | ||||
| 	int err; | ||||
| 
 | ||||
| 	while (!random_seed) | ||||
| 		random_seed = get_random_int(); | ||||
| 
 | ||||
| 	pr_info("Testing DRM range manger (struct drm_mm), with random_seed=0x%x max_iterations=%u max_prime=%u\n", | ||||
| 		random_seed, max_iterations, max_prime); | ||||
| 	err = run_selftests(selftests, ARRAY_SIZE(selftests), NULL); | ||||
| 
 | ||||
| 	return err > 0 ? 0 : err; | ||||
| } | ||||
| 
 | ||||
| static void __exit test_drm_mm_exit(void) | ||||
| { | ||||
| } | ||||
| 
 | ||||
| module_init(test_drm_mm_init); | ||||
| module_exit(test_drm_mm_exit); | ||||
| 
 | ||||
| module_param(random_seed, uint, 0400); | ||||
| module_param(max_iterations, uint, 0400); | ||||
| module_param(max_prime, uint, 0400); | ||||
| 
 | ||||
| MODULE_AUTHOR("Intel Corporation"); | ||||
| MODULE_LICENSE("GPL"); | ||||
							
								
								
									
										15
									
								
								tools/testing/selftests/drivers/gpu/drm_mm.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										15
									
								
								tools/testing/selftests/drivers/gpu/drm_mm.sh
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,15 @@ | ||||
| #!/bin/sh | ||||
| # Runs API tests for struct drm_mm (DRM range manager) | ||||
| 
 | ||||
| if ! /sbin/modprobe -n -q test-drm_mm; then | ||||
|        echo "drivers/gpu/drm_mm: [skip]" | ||||
|        exit 77 | ||||
| fi | ||||
| 
 | ||||
| if /sbin/modprobe -q test-drm_mm; then | ||||
|        /sbin/modprobe -q -r test-drm_mm | ||||
|        echo "drivers/gpu/drm_mm: ok" | ||||
| else | ||||
|        echo "drivers/gpu/drm_mm: [FAIL]" | ||||
|        exit 1 | ||||
| fi | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user