linux/drivers/hwtracing/stm/dummy_stm.c
Chunyan Zhang 9b5e3ff6b9 stm dummy: Mark dummy_stm_packet() with notrace
If CONFIG_STM_SOURCE_FTRACE is selected, Function trace data can be
writen to sink via STM, all functions that related to writing data
packets to STM should be marked 'notrace' to avoid being traced by
Ftrace, otherwise the program would stall into an endless loop.

Link: http://lkml.kernel.org/r/1479715043-6534-6-git-send-email-zhang.chunyan@linaro.org

Signed-off-by: Chunyan Zhang <zhang.chunyan@linaro.org>
Acked-by: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
2016-11-22 17:48:00 -05:00

116 lines
2.6 KiB
C

/*
* A dummy STM device for stm/stm_source class testing.
* Copyright (c) 2014, Intel Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* STM class implements generic infrastructure for System Trace Module devices
* as defined in MIPI STPv2 specification.
*/
#undef DEBUG
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/stm.h>
static ssize_t notrace
dummy_stm_packet(struct stm_data *stm_data, unsigned int master,
unsigned int channel, unsigned int packet, unsigned int flags,
unsigned int size, const unsigned char *payload)
{
#ifdef DEBUG
u64 pl = 0;
if (payload)
pl = *(u64 *)payload;
if (size < 8)
pl &= (1ull << (size * 8)) - 1;
trace_printk("[%u:%u] [pkt: %x/%x] (%llx)\n", master, channel,
packet, size, pl);
#endif
return size;
}
#define DUMMY_STM_MAX 32
static struct stm_data dummy_stm[DUMMY_STM_MAX];
static int nr_dummies = 4;
module_param(nr_dummies, int, 0400);
static unsigned int fail_mode;
module_param(fail_mode, int, 0600);
static int dummy_stm_link(struct stm_data *data, unsigned int master,
unsigned int channel)
{
if (fail_mode && (channel & fail_mode))
return -EINVAL;
return 0;
}
static int dummy_stm_init(void)
{
int i, ret = -ENOMEM;
if (nr_dummies < 0 || nr_dummies > DUMMY_STM_MAX)
return -EINVAL;
for (i = 0; i < nr_dummies; i++) {
dummy_stm[i].name = kasprintf(GFP_KERNEL, "dummy_stm.%d", i);
if (!dummy_stm[i].name)
goto fail_unregister;
dummy_stm[i].sw_start = 0x0000;
dummy_stm[i].sw_end = 0xffff;
dummy_stm[i].sw_nchannels = 0xffff;
dummy_stm[i].packet = dummy_stm_packet;
dummy_stm[i].link = dummy_stm_link;
ret = stm_register_device(NULL, &dummy_stm[i], THIS_MODULE);
if (ret)
goto fail_free;
}
return 0;
fail_unregister:
for (i--; i >= 0; i--) {
stm_unregister_device(&dummy_stm[i]);
fail_free:
kfree(dummy_stm[i].name);
}
return ret;
}
static void dummy_stm_exit(void)
{
int i;
for (i = 0; i < nr_dummies; i++) {
stm_unregister_device(&dummy_stm[i]);
kfree(dummy_stm[i].name);
}
}
module_init(dummy_stm_init);
module_exit(dummy_stm_exit);
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("dummy_stm device");
MODULE_AUTHOR("Alexander Shishkin <alexander.shishkin@linux.intel.com>");