linux/drivers/hwtracing/stm/dummy_stm.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * A dummy STM device for stm/stm_source class testing.
   4 * Copyright (c) 2014, Intel Corporation.
   5 *
   6 * STM class implements generic infrastructure for  System Trace Module devices
   7 * as defined in MIPI STPv2 specification.
   8 */
   9
  10#undef DEBUG
  11#include <linux/kernel.h>
  12#include <linux/module.h>
  13#include <linux/slab.h>
  14#include <linux/stm.h>
  15#include <uapi/linux/stm.h>
  16
  17static ssize_t notrace
  18dummy_stm_packet(struct stm_data *stm_data, unsigned int master,
  19                 unsigned int channel, unsigned int packet, unsigned int flags,
  20                 unsigned int size, const unsigned char *payload)
  21{
  22#ifdef DEBUG
  23        u64 pl = 0;
  24
  25        if (payload)
  26                pl = *(u64 *)payload;
  27
  28        if (size < 8)
  29                pl &= (1ull << (size * 8)) - 1;
  30        trace_printk("[%u:%u] [pkt: %x/%x] (%llx)\n", master, channel,
  31                     packet, size, pl);
  32#endif
  33        return size;
  34}
  35
  36#define DUMMY_STM_MAX 32
  37
  38static struct stm_data dummy_stm[DUMMY_STM_MAX];
  39
  40static int nr_dummies = 4;
  41
  42module_param(nr_dummies, int, 0400);
  43
  44static unsigned int fail_mode;
  45
  46module_param(fail_mode, int, 0600);
  47
  48static unsigned int master_min;
  49
  50module_param(master_min, int, 0400);
  51
  52static unsigned int master_max = STP_MASTER_MAX;
  53
  54module_param(master_max, int, 0400);
  55
  56static unsigned int nr_channels = STP_CHANNEL_MAX;
  57
  58module_param(nr_channels, int, 0400);
  59
  60static int dummy_stm_link(struct stm_data *data, unsigned int master,
  61                          unsigned int channel)
  62{
  63        if (fail_mode && (channel & fail_mode))
  64                return -EINVAL;
  65
  66        return 0;
  67}
  68
  69static int dummy_stm_init(void)
  70{
  71        int i, ret = -ENOMEM;
  72
  73        if (nr_dummies < 0 || nr_dummies > DUMMY_STM_MAX)
  74                return -EINVAL;
  75
  76        if (master_min > master_max ||
  77            master_max > STP_MASTER_MAX ||
  78            nr_channels > STP_CHANNEL_MAX)
  79                return -EINVAL;
  80
  81        for (i = 0; i < nr_dummies; i++) {
  82                dummy_stm[i].name = kasprintf(GFP_KERNEL, "dummy_stm.%d", i);
  83                if (!dummy_stm[i].name)
  84                        goto fail_unregister;
  85
  86                dummy_stm[i].sw_start           = master_min;
  87                dummy_stm[i].sw_end             = master_max;
  88                dummy_stm[i].sw_nchannels       = nr_channels;
  89                dummy_stm[i].packet             = dummy_stm_packet;
  90                dummy_stm[i].link               = dummy_stm_link;
  91
  92                ret = stm_register_device(NULL, &dummy_stm[i], THIS_MODULE);
  93                if (ret)
  94                        goto fail_free;
  95        }
  96
  97        return 0;
  98
  99fail_unregister:
 100        for (i--; i >= 0; i--) {
 101                stm_unregister_device(&dummy_stm[i]);
 102fail_free:
 103                kfree(dummy_stm[i].name);
 104        }
 105
 106        return ret;
 107
 108}
 109
 110static void dummy_stm_exit(void)
 111{
 112        int i;
 113
 114        for (i = 0; i < nr_dummies; i++) {
 115                stm_unregister_device(&dummy_stm[i]);
 116                kfree(dummy_stm[i].name);
 117        }
 118}
 119
 120module_init(dummy_stm_init);
 121module_exit(dummy_stm_exit);
 122
 123MODULE_LICENSE("GPL v2");
 124MODULE_DESCRIPTION("dummy_stm device");
 125MODULE_AUTHOR("Alexander Shishkin <alexander.shishkin@linux.intel.com>");
 126