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
15enum {
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 },
22static 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) \
34module_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
39int __sanitycheck__(void)
40{
41 pr_debug("Hello World!\n");
42 return 0;
43}
44
45static char *__st_filter;
46
47static 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
90int
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
116static 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
128static 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
153static int __init st_init(void)
154{
155 return run_selftests(st: selftests, ARRAY_SIZE(selftests));
156}
157
158static void __exit st_exit(void)
159{
160}
161
162module_param_named(st_filter, __st_filter, charp, 0400);
163module_init(st_init);
164module_exit(st_exit);
165
166MODULE_DESCRIPTION("Self-test harness for dma-buf");
167MODULE_LICENSE("GPL and additional rights");
168

source code of linux/drivers/dma-buf/selftest.c