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(s: __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(objp: 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, name: 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(st: 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 | |