168 строки
3.0 KiB
C
168 строки
3.0 KiB
C
/* SPDX-License-Identifier: MIT */
|
|
|
|
/*
|
|
* Copyright © 2019 Intel Corporation
|
|
*/
|
|
|
|
#include <linux/compiler.h>
|
|
#include <linux/kernel.h>
|
|
#include <linux/module.h>
|
|
#include <linux/sched/signal.h>
|
|
#include <linux/slab.h>
|
|
|
|
#include "selftest.h"
|
|
|
|
enum {
|
|
#define selftest(n, func) __idx_##n,
|
|
#include "selftests.h"
|
|
#undef selftest
|
|
};
|
|
|
|
#define selftest(n, f) [__idx_##n] = { .name = #n, .func = f },
|
|
static struct selftest {
|
|
bool enabled;
|
|
const char *name;
|
|
int (*func)(void);
|
|
} selftests[] = {
|
|
#include "selftests.h"
|
|
};
|
|
#undef selftest
|
|
|
|
/* Embed the line number into the parameter name so that we can order tests */
|
|
#define param(n) __PASTE(igt__, __PASTE(__PASTE(__LINE__, __), n))
|
|
#define selftest_0(n, func, id) \
|
|
module_param_named(id, selftests[__idx_##n].enabled, bool, 0400);
|
|
#define selftest(n, func) selftest_0(n, func, param(n))
|
|
#include "selftests.h"
|
|
#undef selftest
|
|
|
|
int __sanitycheck__(void)
|
|
{
|
|
pr_debug("Hello World!\n");
|
|
return 0;
|
|
}
|
|
|
|
static char *__st_filter;
|
|
|
|
static bool apply_subtest_filter(const char *caller, const char *name)
|
|
{
|
|
char *filter, *sep, *tok;
|
|
bool result = true;
|
|
|
|
filter = kstrdup(__st_filter, GFP_KERNEL);
|
|
for (sep = filter; (tok = strsep(&sep, ","));) {
|
|
bool allow = true;
|
|
char *sl;
|
|
|
|
if (*tok == '!') {
|
|
allow = false;
|
|
tok++;
|
|
}
|
|
|
|
if (*tok == '\0')
|
|
continue;
|
|
|
|
sl = strchr(tok, '/');
|
|
if (sl) {
|
|
*sl++ = '\0';
|
|
if (strcmp(tok, caller)) {
|
|
if (allow)
|
|
result = false;
|
|
continue;
|
|
}
|
|
tok = sl;
|
|
}
|
|
|
|
if (strcmp(tok, name)) {
|
|
if (allow)
|
|
result = false;
|
|
continue;
|
|
}
|
|
|
|
result = allow;
|
|
break;
|
|
}
|
|
kfree(filter);
|
|
|
|
return result;
|
|
}
|
|
|
|
int
|
|
__subtests(const char *caller, const struct subtest *st, int count, void *data)
|
|
{
|
|
int err;
|
|
|
|
for (; count--; st++) {
|
|
cond_resched();
|
|
if (signal_pending(current))
|
|
return -EINTR;
|
|
|
|
if (!apply_subtest_filter(caller, st->name))
|
|
continue;
|
|
|
|
pr_info("dma-buf: Running %s/%s\n", caller, st->name);
|
|
|
|
err = st->func(data);
|
|
if (err && err != -EINTR) {
|
|
pr_err("dma-buf/%s: %s failed with error %d\n",
|
|
caller, st->name, err);
|
|
return err;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void set_default_test_all(struct selftest *st, unsigned long count)
|
|
{
|
|
unsigned long i;
|
|
|
|
for (i = 0; i < count; i++)
|
|
if (st[i].enabled)
|
|
return;
|
|
|
|
for (i = 0; i < count; i++)
|
|
st[i].enabled = true;
|
|
}
|
|
|
|
static int run_selftests(struct selftest *st, unsigned long count)
|
|
{
|
|
int err = 0;
|
|
|
|
set_default_test_all(st, count);
|
|
|
|
/* Tests are listed in natural order in selftests.h */
|
|
for (; count--; st++) {
|
|
if (!st->enabled)
|
|
continue;
|
|
|
|
pr_info("dma-buf: Running %s\n", st->name);
|
|
err = st->func();
|
|
if (err)
|
|
break;
|
|
}
|
|
|
|
if (WARN(err > 0 || err == -ENOTTY,
|
|
"%s returned %d, conflicting with selftest's magic values!\n",
|
|
st->name, err))
|
|
err = -1;
|
|
|
|
return err;
|
|
}
|
|
|
|
static int __init st_init(void)
|
|
{
|
|
return run_selftests(selftests, ARRAY_SIZE(selftests));
|
|
}
|
|
|
|
static void __exit st_exit(void)
|
|
{
|
|
}
|
|
|
|
module_param_named(st_filter, __st_filter, charp, 0400);
|
|
module_init(st_init);
|
|
module_exit(st_exit);
|
|
|
|
MODULE_DESCRIPTION("Self-test harness for dma-buf");
|
|
MODULE_LICENSE("GPL and additional rights");
|