mirror of https://github.com/Qortal/Brooklyn
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
120 lines
2.8 KiB
120 lines
2.8 KiB
// SPDX-License-Identifier: GPL-2.0 |
|
/* |
|
* Simple heartbeat STM source driver |
|
* Copyright (c) 2016, Intel Corporation. |
|
* |
|
* Heartbeat STM source will send repetitive messages over STM devices to a |
|
* trace host. |
|
*/ |
|
|
|
#include <linux/kernel.h> |
|
#include <linux/module.h> |
|
#include <linux/hrtimer.h> |
|
#include <linux/slab.h> |
|
#include <linux/stm.h> |
|
|
|
#define STM_HEARTBEAT_MAX 32 |
|
|
|
static int nr_devs = 4; |
|
static int interval_ms = 10; |
|
|
|
module_param(nr_devs, int, 0400); |
|
module_param(interval_ms, int, 0600); |
|
|
|
static struct stm_heartbeat { |
|
struct stm_source_data data; |
|
struct hrtimer hrtimer; |
|
unsigned int active; |
|
} stm_heartbeat[STM_HEARTBEAT_MAX]; |
|
|
|
static const char str[] = "heartbeat stm source driver is here to serve you"; |
|
|
|
static enum hrtimer_restart stm_heartbeat_hrtimer_handler(struct hrtimer *hr) |
|
{ |
|
struct stm_heartbeat *heartbeat = container_of(hr, struct stm_heartbeat, |
|
hrtimer); |
|
|
|
stm_source_write(&heartbeat->data, 0, str, sizeof str); |
|
if (heartbeat->active) |
|
hrtimer_forward_now(hr, ms_to_ktime(interval_ms)); |
|
|
|
return heartbeat->active ? HRTIMER_RESTART : HRTIMER_NORESTART; |
|
} |
|
|
|
static int stm_heartbeat_link(struct stm_source_data *data) |
|
{ |
|
struct stm_heartbeat *heartbeat = |
|
container_of(data, struct stm_heartbeat, data); |
|
|
|
heartbeat->active = 1; |
|
hrtimer_start(&heartbeat->hrtimer, ms_to_ktime(interval_ms), |
|
HRTIMER_MODE_ABS); |
|
|
|
return 0; |
|
} |
|
|
|
static void stm_heartbeat_unlink(struct stm_source_data *data) |
|
{ |
|
struct stm_heartbeat *heartbeat = |
|
container_of(data, struct stm_heartbeat, data); |
|
|
|
heartbeat->active = 0; |
|
hrtimer_cancel(&heartbeat->hrtimer); |
|
} |
|
|
|
static int stm_heartbeat_init(void) |
|
{ |
|
int i, ret; |
|
|
|
if (nr_devs < 0 || nr_devs > STM_HEARTBEAT_MAX) |
|
return -EINVAL; |
|
|
|
for (i = 0; i < nr_devs; i++) { |
|
stm_heartbeat[i].data.name = |
|
kasprintf(GFP_KERNEL, "heartbeat.%d", i); |
|
if (!stm_heartbeat[i].data.name) { |
|
ret = -ENOMEM; |
|
goto fail_unregister; |
|
} |
|
|
|
stm_heartbeat[i].data.nr_chans = 1; |
|
stm_heartbeat[i].data.link = stm_heartbeat_link; |
|
stm_heartbeat[i].data.unlink = stm_heartbeat_unlink; |
|
hrtimer_init(&stm_heartbeat[i].hrtimer, CLOCK_MONOTONIC, |
|
HRTIMER_MODE_ABS); |
|
stm_heartbeat[i].hrtimer.function = |
|
stm_heartbeat_hrtimer_handler; |
|
|
|
ret = stm_source_register_device(NULL, &stm_heartbeat[i].data); |
|
if (ret) |
|
goto fail_free; |
|
} |
|
|
|
return 0; |
|
|
|
fail_unregister: |
|
for (i--; i >= 0; i--) { |
|
stm_source_unregister_device(&stm_heartbeat[i].data); |
|
fail_free: |
|
kfree(stm_heartbeat[i].data.name); |
|
} |
|
|
|
return ret; |
|
} |
|
|
|
static void stm_heartbeat_exit(void) |
|
{ |
|
int i; |
|
|
|
for (i = 0; i < nr_devs; i++) { |
|
stm_source_unregister_device(&stm_heartbeat[i].data); |
|
kfree(stm_heartbeat[i].data.name); |
|
} |
|
} |
|
|
|
module_init(stm_heartbeat_init); |
|
module_exit(stm_heartbeat_exit); |
|
|
|
MODULE_LICENSE("GPL v2"); |
|
MODULE_DESCRIPTION("stm_heartbeat driver"); |
|
MODULE_AUTHOR("Alexander Shishkin <[email protected]>");
|
|
|