summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2019-08-19 05:59:26 -0400
committerChris Wilson <chris@chris-wilson.co.uk>2019-08-19 13:01:34 -0400
commit9536b64ac0d6e3151963a11441dde7ade045fb29 (patch)
treefa992f4f91d0b5052157727c9ef5ebe0e4c356e0
parentaa4fffec310da5eb6d6ef09509b03e780bdf248a (diff)
dma-buf: Introduce selftesting framework
In light of recent review slip ups, the absence of a suite of tests for dma-buf became apparent. Given the current plethora of testing frameworks, opt for one already in use by Intel's CI and so allow easy hook up into igt. We introduce a new module that when loaded will execute the list of selftests and their subtest. The names of the selftests are put into the modinfo as parameters so that igt can identify each, and run them independently, principally for ease of error reporting. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Cc: Daniel Vetter <daniel.vetter@ffwll.ch> Cc: Tomi Sarvela <tomi.p.sarvela@intel.com> Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch> Link: https://patchwork.freedesktop.org/patch/msgid/20190819095928.32091-1-chris@chris-wilson.co.uk
-rw-r--r--drivers/dma-buf/Kconfig5
-rw-r--r--drivers/dma-buf/Makefile3
-rw-r--r--drivers/dma-buf/selftest.c167
-rw-r--r--drivers/dma-buf/selftest.h30
-rw-r--r--drivers/dma-buf/selftests.h12
5 files changed, 217 insertions, 0 deletions
diff --git a/drivers/dma-buf/Kconfig b/drivers/dma-buf/Kconfig
index b6a9c2f1bc41..a23b6752d11a 100644
--- a/drivers/dma-buf/Kconfig
+++ b/drivers/dma-buf/Kconfig
@@ -39,4 +39,9 @@ config UDMABUF
39 A driver to let userspace turn memfd regions into dma-bufs. 39 A driver to let userspace turn memfd regions into dma-bufs.
40 Qemu can use this to create host dmabufs for guest framebuffers. 40 Qemu can use this to create host dmabufs for guest framebuffers.
41 41
42config DMABUF_SELFTESTS
43 tristate "Selftests for the dma-buf interfaces"
44 default n
45 depends on DMA_SHARED_BUFFER
46
42endmenu 47endmenu
diff --git a/drivers/dma-buf/Makefile b/drivers/dma-buf/Makefile
index dcfb01e7c6f4..b5ae122a9349 100644
--- a/drivers/dma-buf/Makefile
+++ b/drivers/dma-buf/Makefile
@@ -4,3 +4,6 @@ obj-y := dma-buf.o dma-fence.o dma-fence-array.o dma-fence-chain.o \
4obj-$(CONFIG_SYNC_FILE) += sync_file.o 4obj-$(CONFIG_SYNC_FILE) += sync_file.o
5obj-$(CONFIG_SW_SYNC) += sw_sync.o sync_debug.o 5obj-$(CONFIG_SW_SYNC) += sw_sync.o sync_debug.o
6obj-$(CONFIG_UDMABUF) += udmabuf.o 6obj-$(CONFIG_UDMABUF) += udmabuf.o
7
8dmabuf_selftests-y := selftest.o
9obj-$(CONFIG_DMABUF_SELFTESTS) += dmabuf_selftests.o
diff --git a/drivers/dma-buf/selftest.c b/drivers/dma-buf/selftest.c
new file mode 100644
index 000000000000..c60b6944b4bd
--- /dev/null
+++ b/drivers/dma-buf/selftest.c
@@ -0,0 +1,167 @@
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(__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
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, 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(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");
diff --git a/drivers/dma-buf/selftest.h b/drivers/dma-buf/selftest.h
new file mode 100644
index 000000000000..45793aff6142
--- /dev/null
+++ b/drivers/dma-buf/selftest.h
@@ -0,0 +1,30 @@
1// SPDX-License-Identifier: MIT
2
3/*
4 * Copyright © 2019 Intel Corporation
5 */
6
7#ifndef __SELFTEST_H__
8#define __SELFTEST_H__
9
10#include <linux/compiler.h>
11
12#define selftest(name, func) int func(void);
13#include "selftests.h"
14#undef selftest
15
16struct subtest {
17 int (*func)(void *data);
18 const char *name;
19};
20
21int __subtests(const char *caller,
22 const struct subtest *st,
23 int count,
24 void *data);
25#define subtests(T, data) \
26 __subtests(__func__, T, ARRAY_SIZE(T), data)
27
28#define SUBTEST(x) { x, #x }
29
30#endif /* __SELFTEST_H__ */
diff --git a/drivers/dma-buf/selftests.h b/drivers/dma-buf/selftests.h
new file mode 100644
index 000000000000..44b44390d23a
--- /dev/null
+++ b/drivers/dma-buf/selftests.h
@@ -0,0 +1,12 @@
1/* SPDX-License-Identifier: MIT */
2/* List each unit test as selftest(name, function)
3 *
4 * The name is used as both an enum and expanded as subtest__name to create
5 * a module parameter. It must be unique and legal for a C identifier.
6 *
7 * The function should be of type int function(void). It may be conditionally
8 * compiled using #if IS_ENABLED(DRM_I915_SELFTEST).
9 *
10 * Tests are executed in order by igt/dmabuf_selftest
11 */
12selftest(sanitycheck, __sanitycheck__) /* keep first (igt selfcheck) */