xref: /linux/drivers/hwtracing/stm/ftrace.c (revision 36ec807b627b4c0a0a382f0ae48eac7187d14b2b)
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,
26*07cf8356SMikhail Lappo 		.type		= STM_FTRACE,
27262e1f6eSChunyan Zhang 		.link		= stm_ftrace_link,
28262e1f6eSChunyan Zhang 		.unlink		= stm_ftrace_unlink,
29262e1f6eSChunyan Zhang 	},
30262e1f6eSChunyan Zhang };
31262e1f6eSChunyan Zhang 
32262e1f6eSChunyan Zhang /**
33262e1f6eSChunyan Zhang  * stm_ftrace_write() - write data to STM via 'stm_ftrace' source
34262e1f6eSChunyan Zhang  * @buf:	buffer containing the data packet
35262e1f6eSChunyan Zhang  * @len:	length of the data packet
36262e1f6eSChunyan Zhang  */
37262e1f6eSChunyan Zhang static void notrace
38a773d419SFelipe Balbi stm_ftrace_write(struct trace_export *export, const void *buf, unsigned int len)
39262e1f6eSChunyan Zhang {
40a773d419SFelipe Balbi 	struct stm_ftrace *stm = container_of(export, struct stm_ftrace, ftrace);
41b8f8534bSTingwei Zhang 	/* This is called from trace system with preemption disabled */
42b8f8534bSTingwei Zhang 	unsigned int cpu = smp_processor_id();
43a773d419SFelipe Balbi 
44b8f8534bSTingwei Zhang 	stm_source_write(&stm->data, STM_FTRACE_CHAN + cpu, buf, len);
45262e1f6eSChunyan Zhang }
46262e1f6eSChunyan Zhang 
47262e1f6eSChunyan Zhang static int stm_ftrace_link(struct stm_source_data *data)
48262e1f6eSChunyan Zhang {
49262e1f6eSChunyan Zhang 	struct stm_ftrace *sf = container_of(data, struct stm_ftrace, data);
50262e1f6eSChunyan Zhang 
51262e1f6eSChunyan Zhang 	sf->ftrace.write = stm_ftrace_write;
52e8ecea30STingwei Zhang 	sf->ftrace.flags = TRACE_EXPORT_FUNCTION | TRACE_EXPORT_EVENT
53e8ecea30STingwei Zhang 			| TRACE_EXPORT_MARKER;
54262e1f6eSChunyan Zhang 
55262e1f6eSChunyan Zhang 	return register_ftrace_export(&sf->ftrace);
56262e1f6eSChunyan Zhang }
57262e1f6eSChunyan Zhang 
58262e1f6eSChunyan Zhang static void stm_ftrace_unlink(struct stm_source_data *data)
59262e1f6eSChunyan Zhang {
60262e1f6eSChunyan Zhang 	struct stm_ftrace *sf = container_of(data, struct stm_ftrace, data);
61262e1f6eSChunyan Zhang 
62262e1f6eSChunyan Zhang 	unregister_ftrace_export(&sf->ftrace);
63262e1f6eSChunyan Zhang }
64262e1f6eSChunyan Zhang 
65262e1f6eSChunyan Zhang static int __init stm_ftrace_init(void)
66262e1f6eSChunyan Zhang {
67262e1f6eSChunyan Zhang 	int ret;
68262e1f6eSChunyan Zhang 
69b8f8534bSTingwei Zhang 	stm_ftrace.data.nr_chans = roundup_pow_of_two(num_possible_cpus());
70262e1f6eSChunyan Zhang 	ret = stm_source_register_device(NULL, &stm_ftrace.data);
71262e1f6eSChunyan Zhang 	if (ret)
72262e1f6eSChunyan Zhang 		pr_err("Failed to register stm_source - ftrace.\n");
73262e1f6eSChunyan Zhang 
74262e1f6eSChunyan Zhang 	return ret;
75262e1f6eSChunyan Zhang }
76262e1f6eSChunyan Zhang 
77262e1f6eSChunyan Zhang static void __exit stm_ftrace_exit(void)
78262e1f6eSChunyan Zhang {
79262e1f6eSChunyan Zhang 	stm_source_unregister_device(&stm_ftrace.data);
80262e1f6eSChunyan Zhang }
81262e1f6eSChunyan Zhang 
82262e1f6eSChunyan Zhang module_init(stm_ftrace_init);
83262e1f6eSChunyan Zhang module_exit(stm_ftrace_exit);
84262e1f6eSChunyan Zhang 
85262e1f6eSChunyan Zhang MODULE_LICENSE("GPL v2");
86262e1f6eSChunyan Zhang MODULE_DESCRIPTION("stm_ftrace driver");
87262e1f6eSChunyan Zhang MODULE_AUTHOR("Chunyan Zhang <zhang.chunyan@linaro.org>");
88