xref: /linux/drivers/dma-buf/selftest.c (revision 24bce201d79807b668bf9d9e0aca801c5c0d5f78)
1 /* SPDX-License-Identifier: MIT */
2 
3 /*
4  * Copyright © 2019 Intel Corporation
5  */
6 
7 #include <linux/compiler.h>
8 #include <linux/kernel.h>
9 #include <linux/module.h>
10 #include <linux/sched/signal.h>
11 #include <linux/slab.h>
12 
13 #include "selftest.h"
14 
15 enum {
16 #define selftest(n, func) __idx_##n,
17 #include "selftests.h"
18 #undef selftest
19 };
20 
21 #define selftest(n, f) [__idx_##n] = { .name = #n, .func = f },
22 static struct selftest {
23 	bool enabled;
24 	const char *name;
25 	int (*func)(void);
26 } selftests[] = {
27 #include "selftests.h"
28 };
29 #undef selftest
30 
31 /* Embed the line number into the parameter name so that we can order tests */
32 #define param(n) __PASTE(igt__, __PASTE(__PASTE(__LINE__, __), n))
33 #define selftest_0(n, func, id) \
34 module_param_named(id, selftests[__idx_##n].enabled, bool, 0400);
35 #define selftest(n, func) selftest_0(n, func, param(n))
36 #include "selftests.h"
37 #undef selftest
38 
39 int __sanitycheck__(void)
40 {
41 	pr_debug("Hello World!\n");
42 	return 0;
43 }
44 
45 static char *__st_filter;
46 
47 static bool apply_subtest_filter(const char *caller, const char *name)
48 {
49 	char *filter, *sep, *tok;
50 	bool result = true;
51 
52 	filter = kstrdup(__st_filter, GFP_KERNEL);
53 	for (sep = filter; (tok = strsep(&sep, ","));) {
54 		bool allow = true;
55 		char *sl;
56 
57 		if (*tok == '!') {
58 			allow = false;
59 			tok++;
60 		}
61 
62 		if (*tok == '\0')
63 			continue;
64 
65 		sl = strchr(tok, '/');
66 		if (sl) {
67 			*sl++ = '\0';
68 			if (strcmp(tok, caller)) {
69 				if (allow)
70 					result = false;
71 				continue;
72 			}
73 			tok = sl;
74 		}
75 
76 		if (strcmp(tok, name)) {
77 			if (allow)
78 				result = false;
79 			continue;
80 		}
81 
82 		result = allow;
83 		break;
84 	}
85 	kfree(filter);
86 
87 	return result;
88 }
89 
90 int
91 __subtests(const char *caller, const struct subtest *st, int count, void *data)
92 {
93 	int err;
94 
95 	for (; count--; st++) {
96 		cond_resched();
97 		if (signal_pending(current))
98 			return -EINTR;
99 
100 		if (!apply_subtest_filter(caller, st->name))
101 			continue;
102 
103 		pr_info("dma-buf: Running %s/%s\n", caller, st->name);
104 
105 		err = st->func(data);
106 		if (err && err != -EINTR) {
107 			pr_err("dma-buf/%s: %s failed with error %d\n",
108 			       caller, st->name, err);
109 			return err;
110 		}
111 	}
112 
113 	return 0;
114 }
115 
116 static void set_default_test_all(struct selftest *st, unsigned long count)
117 {
118 	unsigned long i;
119 
120 	for (i = 0; i < count; i++)
121 		if (st[i].enabled)
122 			return;
123 
124 	for (i = 0; i < count; i++)
125 		st[i].enabled = true;
126 }
127 
128 static int run_selftests(struct selftest *st, unsigned long count)
129 {
130 	int err = 0;
131 
132 	set_default_test_all(st, count);
133 
134 	/* Tests are listed in natural order in selftests.h */
135 	for (; count--; st++) {
136 		if (!st->enabled)
137 			continue;
138 
139 		pr_info("dma-buf: Running %s\n", st->name);
140 		err = st->func();
141 		if (err)
142 			break;
143 	}
144 
145 	if (WARN(err > 0 || err == -ENOTTY,
146 		 "%s returned %d, conflicting with selftest's magic values!\n",
147 		 st->name, err))
148 		err = -1;
149 
150 	return err;
151 }
152 
153 static int __init st_init(void)
154 {
155 	return run_selftests(selftests, ARRAY_SIZE(selftests));
156 }
157 
158 static void __exit st_exit(void)
159 {
160 }
161 
162 module_param_named(st_filter, __st_filter, charp, 0400);
163 module_init(st_init);
164 module_exit(st_exit);
165 
166 MODULE_DESCRIPTION("Self-test harness for dma-buf");
167 MODULE_LICENSE("GPL and additional rights");
168