xref: /openbmc/linux/drivers/hwtracing/stm/ftrace.c (revision b8f8534b)
1ad0dfdfdSMathieu Poirier // SPDX-License-Identifier: GPL-2.0
2262e1f6eSChunyan Zhang /*
3262e1f6eSChunyan Zhang  * Simple kernel driver to link kernel Ftrace and an STM device
4262e1f6eSChunyan Zhang  * Copyright (c) 2016, Linaro Ltd.
5262e1f6eSChunyan Zhang  *
6262e1f6eSChunyan Zhang  * STM Ftrace will be registered as a trace_export.
7262e1f6eSChunyan Zhang  */
8262e1f6eSChunyan Zhang 
9262e1f6eSChunyan Zhang #include <linux/module.h>
10262e1f6eSChunyan Zhang #include <linux/stm.h>
11262e1f6eSChunyan Zhang #include <linux/trace.h>
12262e1f6eSChunyan Zhang 
13262e1f6eSChunyan Zhang #define STM_FTRACE_NR_CHANNELS 1
14262e1f6eSChunyan Zhang #define STM_FTRACE_CHAN 0
15262e1f6eSChunyan Zhang 
16262e1f6eSChunyan Zhang static int stm_ftrace_link(struct stm_source_data *data);
17262e1f6eSChunyan Zhang static void stm_ftrace_unlink(struct stm_source_data *data);
18262e1f6eSChunyan Zhang 
19262e1f6eSChunyan Zhang static struct stm_ftrace {
20262e1f6eSChunyan Zhang 	struct stm_source_data	data;
21262e1f6eSChunyan Zhang 	struct trace_export	ftrace;
22262e1f6eSChunyan Zhang } stm_ftrace = {
23262e1f6eSChunyan Zhang 	.data	= {
24262e1f6eSChunyan Zhang 		.name		= "ftrace",
25262e1f6eSChunyan Zhang 		.nr_chans	= STM_FTRACE_NR_CHANNELS,
26262e1f6eSChunyan Zhang 		.link		= stm_ftrace_link,
27262e1f6eSChunyan Zhang 		.unlink		= stm_ftrace_unlink,
28262e1f6eSChunyan Zhang 	},
29262e1f6eSChunyan Zhang };
30262e1f6eSChunyan Zhang 
31262e1f6eSChunyan Zhang /**
32262e1f6eSChunyan Zhang  * stm_ftrace_write() - write data to STM via 'stm_ftrace' source
33262e1f6eSChunyan Zhang  * @buf:	buffer containing the data packet
34262e1f6eSChunyan Zhang  * @len:	length of the data packet
35262e1f6eSChunyan Zhang  */
36262e1f6eSChunyan Zhang static void notrace
stm_ftrace_write(struct trace_export * export,const void * buf,unsigned int len)37a773d419SFelipe Balbi stm_ftrace_write(struct trace_export *export, const void *buf, unsigned int len)
38262e1f6eSChunyan Zhang {
39a773d419SFelipe Balbi 	struct stm_ftrace *stm = container_of(export, struct stm_ftrace, ftrace);
40b8f8534bSTingwei Zhang 	/* This is called from trace system with preemption disabled */
41b8f8534bSTingwei Zhang 	unsigned int cpu = smp_processor_id();
42a773d419SFelipe Balbi 
43b8f8534bSTingwei Zhang 	stm_source_write(&stm->data, STM_FTRACE_CHAN + cpu, buf, len);
44262e1f6eSChunyan Zhang }
45262e1f6eSChunyan Zhang 
stm_ftrace_link(struct stm_source_data * data)46262e1f6eSChunyan Zhang static int stm_ftrace_link(struct stm_source_data *data)
47262e1f6eSChunyan Zhang {
48262e1f6eSChunyan Zhang 	struct stm_ftrace *sf = container_of(data, struct stm_ftrace, data);
49262e1f6eSChunyan Zhang 
50262e1f6eSChunyan Zhang 	sf->ftrace.write = stm_ftrace_write;
51e8ecea30STingwei Zhang 	sf->ftrace.flags = TRACE_EXPORT_FUNCTION | TRACE_EXPORT_EVENT
52e8ecea30STingwei Zhang 			| TRACE_EXPORT_MARKER;
53262e1f6eSChunyan Zhang 
54262e1f6eSChunyan Zhang 	return register_ftrace_export(&sf->ftrace);
55262e1f6eSChunyan Zhang }
56262e1f6eSChunyan Zhang 
stm_ftrace_unlink(struct stm_source_data * data)57262e1f6eSChunyan Zhang static void stm_ftrace_unlink(struct stm_source_data *data)
58262e1f6eSChunyan Zhang {
59262e1f6eSChunyan Zhang 	struct stm_ftrace *sf = container_of(data, struct stm_ftrace, data);
60262e1f6eSChunyan Zhang 
61262e1f6eSChunyan Zhang 	unregister_ftrace_export(&sf->ftrace);
62262e1f6eSChunyan Zhang }
63262e1f6eSChunyan Zhang 
stm_ftrace_init(void)64262e1f6eSChunyan Zhang static int __init stm_ftrace_init(void)
65262e1f6eSChunyan Zhang {
66262e1f6eSChunyan Zhang 	int ret;
67262e1f6eSChunyan Zhang 
68b8f8534bSTingwei Zhang 	stm_ftrace.data.nr_chans = roundup_pow_of_two(num_possible_cpus());
69262e1f6eSChunyan Zhang 	ret = stm_source_register_device(NULL, &stm_ftrace.data);
70262e1f6eSChunyan Zhang 	if (ret)
71262e1f6eSChunyan Zhang 		pr_err("Failed to register stm_source - ftrace.\n");
72262e1f6eSChunyan Zhang 
73262e1f6eSChunyan Zhang 	return ret;
74262e1f6eSChunyan Zhang }
75262e1f6eSChunyan Zhang 
stm_ftrace_exit(void)76262e1f6eSChunyan Zhang static void __exit stm_ftrace_exit(void)
77262e1f6eSChunyan Zhang {
78262e1f6eSChunyan Zhang 	stm_source_unregister_device(&stm_ftrace.data);
79262e1f6eSChunyan Zhang }
80262e1f6eSChunyan Zhang 
81262e1f6eSChunyan Zhang module_init(stm_ftrace_init);
82262e1f6eSChunyan Zhang module_exit(stm_ftrace_exit);
83262e1f6eSChunyan Zhang 
84262e1f6eSChunyan Zhang MODULE_LICENSE("GPL v2");
85262e1f6eSChunyan Zhang MODULE_DESCRIPTION("stm_ftrace driver");
86262e1f6eSChunyan Zhang MODULE_AUTHOR("Chunyan Zhang <zhang.chunyan@linaro.org>");
87