diff options
author | Alexander Shishkin <alexander.shishkin@linux.intel.com> | 2016-02-15 12:12:04 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2016-02-20 17:09:14 -0500 |
commit | 1192918530381b5cfc0e5da51233fa94f783b221 (patch) | |
tree | c0f85d2050633c84eb8c1f11a0c7677f52418bee /drivers/hwtracing | |
parent | bcfdf8afdebe63a2217fa632ae94f8aeecf9126f (diff) |
stm class: Add heartbeat stm source device
Heartbeat stm source may have multiple instances (for connecting to
different stm devices). Each instance will send a periodic test message
over its stm device when it is linked. This can be used for testing stm
class framework, stm device drivers or as a heartbeat over the stm link.
Signed-off-by: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/hwtracing')
-rw-r--r-- | drivers/hwtracing/stm/Kconfig | 11 | ||||
-rw-r--r-- | drivers/hwtracing/stm/Makefile | 2 | ||||
-rw-r--r-- | drivers/hwtracing/stm/heartbeat.c | 130 |
3 files changed, 143 insertions, 0 deletions
diff --git a/drivers/hwtracing/stm/Kconfig b/drivers/hwtracing/stm/Kconfig index e0ac75395526..847a39b35307 100644 --- a/drivers/hwtracing/stm/Kconfig +++ b/drivers/hwtracing/stm/Kconfig | |||
@@ -28,4 +28,15 @@ config STM_SOURCE_CONSOLE | |||
28 | If you want to send kernel console messages over STM devices, | 28 | If you want to send kernel console messages over STM devices, |
29 | say Y. | 29 | say Y. |
30 | 30 | ||
31 | config STM_SOURCE_HEARTBEAT | ||
32 | tristate "Heartbeat over STM devices" | ||
33 | help | ||
34 | This is a kernel space trace source that sends periodic | ||
35 | heartbeat messages to trace hosts over STM devices. It is | ||
36 | also useful for testing stm class drivers and the stm class | ||
37 | framework itself. | ||
38 | |||
39 | If you want to send heartbeat messages over STM devices, | ||
40 | say Y. | ||
41 | |||
31 | endif | 42 | endif |
diff --git a/drivers/hwtracing/stm/Makefile b/drivers/hwtracing/stm/Makefile index f9312c38dd7a..a9ce3d487e57 100644 --- a/drivers/hwtracing/stm/Makefile +++ b/drivers/hwtracing/stm/Makefile | |||
@@ -5,5 +5,7 @@ stm_core-y := core.o policy.o | |||
5 | obj-$(CONFIG_STM_DUMMY) += dummy_stm.o | 5 | obj-$(CONFIG_STM_DUMMY) += dummy_stm.o |
6 | 6 | ||
7 | obj-$(CONFIG_STM_SOURCE_CONSOLE) += stm_console.o | 7 | obj-$(CONFIG_STM_SOURCE_CONSOLE) += stm_console.o |
8 | obj-$(CONFIG_STM_SOURCE_HEARTBEAT) += stm_heartbeat.o | ||
8 | 9 | ||
9 | stm_console-y := console.o | 10 | stm_console-y := console.o |
11 | stm_heartbeat-y := heartbeat.o | ||
diff --git a/drivers/hwtracing/stm/heartbeat.c b/drivers/hwtracing/stm/heartbeat.c new file mode 100644 index 000000000000..0133571b506f --- /dev/null +++ b/drivers/hwtracing/stm/heartbeat.c | |||
@@ -0,0 +1,130 @@ | |||
1 | /* | ||
2 | * Simple heartbeat STM source driver | ||
3 | * Copyright (c) 2016, 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 | * Heartbeat STM source will send repetitive messages over STM devices to a | ||
15 | * trace host. | ||
16 | */ | ||
17 | |||
18 | #include <linux/kernel.h> | ||
19 | #include <linux/module.h> | ||
20 | #include <linux/hrtimer.h> | ||
21 | #include <linux/slab.h> | ||
22 | #include <linux/stm.h> | ||
23 | |||
24 | #define STM_HEARTBEAT_MAX 32 | ||
25 | |||
26 | static int nr_devs = 4; | ||
27 | static int interval_ms = 10; | ||
28 | |||
29 | module_param(nr_devs, int, 0600); | ||
30 | module_param(interval_ms, int, 0600); | ||
31 | |||
32 | static struct stm_heartbeat { | ||
33 | struct stm_source_data data; | ||
34 | struct hrtimer hrtimer; | ||
35 | unsigned int active; | ||
36 | } stm_heartbeat[STM_HEARTBEAT_MAX]; | ||
37 | |||
38 | static unsigned int nr_instances; | ||
39 | |||
40 | static const char str[] = "heartbeat stm source driver is here to serve you"; | ||
41 | |||
42 | static enum hrtimer_restart stm_heartbeat_hrtimer_handler(struct hrtimer *hr) | ||
43 | { | ||
44 | struct stm_heartbeat *heartbeat = container_of(hr, struct stm_heartbeat, | ||
45 | hrtimer); | ||
46 | |||
47 | stm_source_write(&heartbeat->data, 0, str, sizeof str); | ||
48 | if (heartbeat->active) | ||
49 | hrtimer_forward_now(hr, ms_to_ktime(interval_ms)); | ||
50 | |||
51 | return heartbeat->active ? HRTIMER_RESTART : HRTIMER_NORESTART; | ||
52 | } | ||
53 | |||
54 | static int stm_heartbeat_link(struct stm_source_data *data) | ||
55 | { | ||
56 | struct stm_heartbeat *heartbeat = | ||
57 | container_of(data, struct stm_heartbeat, data); | ||
58 | |||
59 | heartbeat->active = 1; | ||
60 | hrtimer_start(&heartbeat->hrtimer, ms_to_ktime(interval_ms), | ||
61 | HRTIMER_MODE_ABS); | ||
62 | |||
63 | return 0; | ||
64 | } | ||
65 | |||
66 | static void stm_heartbeat_unlink(struct stm_source_data *data) | ||
67 | { | ||
68 | struct stm_heartbeat *heartbeat = | ||
69 | container_of(data, struct stm_heartbeat, data); | ||
70 | |||
71 | heartbeat->active = 0; | ||
72 | hrtimer_cancel(&heartbeat->hrtimer); | ||
73 | } | ||
74 | |||
75 | static int stm_heartbeat_init(void) | ||
76 | { | ||
77 | int i, ret = -ENOMEM, __nr_instances = ACCESS_ONCE(nr_devs); | ||
78 | |||
79 | if (__nr_instances < 0 || __nr_instances > STM_HEARTBEAT_MAX) | ||
80 | return -EINVAL; | ||
81 | |||
82 | for (i = 0; i < __nr_instances; i++) { | ||
83 | stm_heartbeat[i].data.name = | ||
84 | kasprintf(GFP_KERNEL, "heartbeat.%d", i); | ||
85 | if (!stm_heartbeat[i].data.name) | ||
86 | goto fail_unregister; | ||
87 | |||
88 | stm_heartbeat[i].data.nr_chans = 1; | ||
89 | stm_heartbeat[i].data.link = stm_heartbeat_link; | ||
90 | stm_heartbeat[i].data.unlink = stm_heartbeat_unlink; | ||
91 | hrtimer_init(&stm_heartbeat[i].hrtimer, CLOCK_MONOTONIC, | ||
92 | HRTIMER_MODE_ABS); | ||
93 | stm_heartbeat[i].hrtimer.function = | ||
94 | stm_heartbeat_hrtimer_handler; | ||
95 | |||
96 | ret = stm_source_register_device(NULL, &stm_heartbeat[i].data); | ||
97 | if (ret) | ||
98 | goto fail_free; | ||
99 | } | ||
100 | |||
101 | nr_instances = __nr_instances; | ||
102 | |||
103 | return 0; | ||
104 | |||
105 | fail_unregister: | ||
106 | for (i--; i >= 0; i--) { | ||
107 | stm_source_unregister_device(&stm_heartbeat[i].data); | ||
108 | fail_free: | ||
109 | kfree(stm_heartbeat[i].data.name); | ||
110 | } | ||
111 | |||
112 | return ret; | ||
113 | } | ||
114 | |||
115 | static void stm_heartbeat_exit(void) | ||
116 | { | ||
117 | int i; | ||
118 | |||
119 | for (i = 0; i < nr_instances; i++) { | ||
120 | stm_source_unregister_device(&stm_heartbeat[i].data); | ||
121 | kfree(stm_heartbeat[i].data.name); | ||
122 | } | ||
123 | } | ||
124 | |||
125 | module_init(stm_heartbeat_init); | ||
126 | module_exit(stm_heartbeat_exit); | ||
127 | |||
128 | MODULE_LICENSE("GPL v2"); | ||
129 | MODULE_DESCRIPTION("stm_heartbeat driver"); | ||
130 | MODULE_AUTHOR("Alexander Shishkin <alexander.shishkin@linux.intel.com>"); | ||