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