linux/drivers/dma-buf/selftest.c
<<
>>
Prefs
   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");
 168