0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #undef DEBUG
0011 #include <linux/kernel.h>
0012 #include <linux/module.h>
0013 #include <linux/slab.h>
0014 #include <linux/stm.h>
0015 #include <uapi/linux/stm.h>
0016
0017 static ssize_t notrace
0018 dummy_stm_packet(struct stm_data *stm_data, unsigned int master,
0019 unsigned int channel, unsigned int packet, unsigned int flags,
0020 unsigned int size, const unsigned char *payload)
0021 {
0022 #ifdef DEBUG
0023 u64 pl = 0;
0024
0025 if (payload)
0026 pl = *(u64 *)payload;
0027
0028 if (size < 8)
0029 pl &= (1ull << (size * 8)) - 1;
0030 trace_printk("[%u:%u] [pkt: %x/%x] (%llx)\n", master, channel,
0031 packet, size, pl);
0032 #endif
0033 return size;
0034 }
0035
0036 #define DUMMY_STM_MAX 32
0037
0038 static struct stm_data dummy_stm[DUMMY_STM_MAX];
0039
0040 static int nr_dummies = 4;
0041
0042 module_param(nr_dummies, int, 0400);
0043
0044 static unsigned int fail_mode;
0045
0046 module_param(fail_mode, int, 0600);
0047
0048 static unsigned int master_min;
0049
0050 module_param(master_min, int, 0400);
0051
0052 static unsigned int master_max = STP_MASTER_MAX;
0053
0054 module_param(master_max, int, 0400);
0055
0056 static unsigned int nr_channels = STP_CHANNEL_MAX;
0057
0058 module_param(nr_channels, int, 0400);
0059
0060 static int dummy_stm_link(struct stm_data *data, unsigned int master,
0061 unsigned int channel)
0062 {
0063 if (fail_mode && (channel & fail_mode))
0064 return -EINVAL;
0065
0066 return 0;
0067 }
0068
0069 static int dummy_stm_init(void)
0070 {
0071 int i, ret = -ENOMEM;
0072
0073 if (nr_dummies < 0 || nr_dummies > DUMMY_STM_MAX)
0074 return -EINVAL;
0075
0076 if (master_min > master_max ||
0077 master_max > STP_MASTER_MAX ||
0078 nr_channels > STP_CHANNEL_MAX)
0079 return -EINVAL;
0080
0081 for (i = 0; i < nr_dummies; i++) {
0082 dummy_stm[i].name = kasprintf(GFP_KERNEL, "dummy_stm.%d", i);
0083 if (!dummy_stm[i].name)
0084 goto fail_unregister;
0085
0086 dummy_stm[i].sw_start = master_min;
0087 dummy_stm[i].sw_end = master_max;
0088 dummy_stm[i].sw_nchannels = nr_channels;
0089 dummy_stm[i].packet = dummy_stm_packet;
0090 dummy_stm[i].link = dummy_stm_link;
0091
0092 ret = stm_register_device(NULL, &dummy_stm[i], THIS_MODULE);
0093 if (ret)
0094 goto fail_free;
0095 }
0096
0097 return 0;
0098
0099 fail_unregister:
0100 for (i--; i >= 0; i--) {
0101 stm_unregister_device(&dummy_stm[i]);
0102 fail_free:
0103 kfree(dummy_stm[i].name);
0104 }
0105
0106 return ret;
0107
0108 }
0109
0110 static void dummy_stm_exit(void)
0111 {
0112 int i;
0113
0114 for (i = 0; i < nr_dummies; i++) {
0115 stm_unregister_device(&dummy_stm[i]);
0116 kfree(dummy_stm[i].name);
0117 }
0118 }
0119
0120 module_init(dummy_stm_init);
0121 module_exit(dummy_stm_exit);
0122
0123 MODULE_LICENSE("GPL v2");
0124 MODULE_DESCRIPTION("dummy_stm device");
0125 MODULE_AUTHOR("Alexander Shishkin <alexander.shishkin@linux.intel.com>");