1 /* 2 * A dummy STM device for stm/stm_source class testing. 3 * Copyright (c) 2014, Intel Corporation. 4 * 5 * This program is free software; you can redistribute it and/or modify it 6 * under the terms and conditions of the GNU General Public License, 7 * version 2, as published by the Free Software Foundation. 8 * 9 * This program is distributed in the hope it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 12 * more details. 13 * 14 * STM class implements generic infrastructure for System Trace Module devices 15 * as defined in MIPI STPv2 specification. 16 */ 17 18 #undef DEBUG 19 #include <linux/kernel.h> 20 #include <linux/module.h> 21 #include <linux/slab.h> 22 #include <linux/stm.h> 23 24 static ssize_t 25 dummy_stm_packet(struct stm_data *stm_data, unsigned int master, 26 unsigned int channel, unsigned int packet, unsigned int flags, 27 unsigned int size, const unsigned char *payload) 28 { 29 #ifdef DEBUG 30 u64 pl = 0; 31 32 if (payload) 33 pl = *(u64 *)payload; 34 35 if (size < 8) 36 pl &= (1ull << (size * 8)) - 1; 37 trace_printk("[%u:%u] [pkt: %x/%x] (%llx)\n", master, channel, 38 packet, size, pl); 39 #endif 40 return size; 41 } 42 43 #define DUMMY_STM_MAX 32 44 45 static struct stm_data dummy_stm[DUMMY_STM_MAX]; 46 47 static int nr_dummies = 4; 48 49 module_param(nr_dummies, int, 0600); 50 51 static unsigned int dummy_stm_nr; 52 53 static unsigned int fail_mode; 54 55 module_param(fail_mode, int, 0600); 56 57 static int dummy_stm_link(struct stm_data *data, unsigned int master, 58 unsigned int channel) 59 { 60 if (fail_mode && (channel & fail_mode)) 61 return -EINVAL; 62 63 return 0; 64 } 65 66 static int dummy_stm_init(void) 67 { 68 int i, ret = -ENOMEM, __nr_dummies = ACCESS_ONCE(nr_dummies); 69 70 if (__nr_dummies < 0 || __nr_dummies > DUMMY_STM_MAX) 71 return -EINVAL; 72 73 for (i = 0; i < __nr_dummies; i++) { 74 dummy_stm[i].name = kasprintf(GFP_KERNEL, "dummy_stm.%d", i); 75 if (!dummy_stm[i].name) 76 goto fail_unregister; 77 78 dummy_stm[i].sw_start = 0x0000; 79 dummy_stm[i].sw_end = 0xffff; 80 dummy_stm[i].sw_nchannels = 0xffff; 81 dummy_stm[i].packet = dummy_stm_packet; 82 dummy_stm[i].link = dummy_stm_link; 83 84 ret = stm_register_device(NULL, &dummy_stm[i], THIS_MODULE); 85 if (ret) 86 goto fail_free; 87 } 88 89 dummy_stm_nr = __nr_dummies; 90 91 return 0; 92 93 fail_unregister: 94 for (i--; i >= 0; i--) { 95 stm_unregister_device(&dummy_stm[i]); 96 fail_free: 97 kfree(dummy_stm[i].name); 98 } 99 100 return ret; 101 102 } 103 104 static void dummy_stm_exit(void) 105 { 106 int i; 107 108 for (i = 0; i < dummy_stm_nr; i++) { 109 stm_unregister_device(&dummy_stm[i]); 110 kfree(dummy_stm[i].name); 111 } 112 } 113 114 module_init(dummy_stm_init); 115 module_exit(dummy_stm_exit); 116 117 MODULE_LICENSE("GPL v2"); 118 MODULE_DESCRIPTION("dummy_stm device"); 119 MODULE_AUTHOR("Alexander Shishkin <alexander.shishkin@linux.intel.com>"); 120