Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/drivers/dma-buf/selftest.c
26278 views
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
169