selftest.c (3121B)
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");