xref: /OK3568_Linux_fs/kernel/drivers/gpu/arm/bifrost/mali_kbase_kinstr_jm.h (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
2 /*
3  *
4  * (C) COPYRIGHT 2019-2022 ARM Limited. All rights reserved.
5  *
6  * This program is free software and is provided to you under the terms of the
7  * GNU General Public License version 2 as published by the Free Software
8  * Foundation, and any use by you of this program is subject to the terms
9  * of such GNU license.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, you can access it online at
18  * http://www.gnu.org/licenses/gpl-2.0.html.
19  *
20  */
21 
22 /*
23  * mali_kbase_kinstr_jm.h
24  * Kernel driver public interface to job manager atom tracing. This API provides
25  * a method to get the atom state changes into user space.
26  *
27  * The flow of operation is:
28  *
29  * | kernel                              | user                                |
30  * | ----------------------------------- | ----------------------------------- |
31  * | Initialize API with                 |                                     |
32  * | kbase_kinstr_jm_init()              |                                     |
33  * |                                     |                                     |
34  * | Kernel code injects states with     |                                     |
35  * | kbase_kinstr_jm_atom_state_*() APIs |                                     |
36  * |                                     | Call ioctl() to get file descriptor |
37  * |                                     | via KBASE_IOCTL_KINSTR_JM_FD        |
38  * | Allocates a reader attached to FD   |                                     |
39  * | Allocates circular buffer and       |                                     |
40  * | patches, via ASM goto, the          |                                     |
41  * | kbase_kinstr_jm_atom_state_*()      |                                     |
42  * |                                     | loop:                               |
43  * |                                     |   Call poll() on FD for POLLIN      |
44  * |   When threshold of changes is hit, |                                     |
45  * |   the poll is interrupted with      |                                     |
46  * |   POLLIN. If circular buffer is     |                                     |
47  * |   full then store the missed count  |                                     |
48  * |   and interrupt poll                |   Call read() to get data from      |
49  * |                                     |   circular buffer via the fd        |
50  * |   Kernel advances tail of circular  |                                     |
51  * |   buffer                            |                                     |
52  * |                                     | Close file descriptor               |
53  * | Deallocates circular buffer         |                                     |
54  * |                                     |                                     |
55  * | Terminate API with                  |                                     |
56  * | kbase_kinstr_jm_term()              |                                     |
57  *
58  * All tracepoints are guarded on a static key. The static key is activated when
59  * a user space reader gets created. This means that there is negligible cost
60  * inserting the tracepoints into code when there are no readers.
61  */
62 
63 #ifndef _KBASE_KINSTR_JM_H_
64 #define _KBASE_KINSTR_JM_H_
65 
66 #include <uapi/gpu/arm/bifrost/mali_kbase_kinstr_jm_reader.h>
67 
68 #ifdef __KERNEL__
69 #include <linux/version.h>
70 #include <linux/static_key.h>
71 #else
72 /* empty wrapper macros for userspace */
73 #define static_branch_unlikely(key) (1)
74 #endif /* __KERNEL__ */
75 
76 /* Forward declarations */
77 struct kbase_context;
78 struct kbase_kinstr_jm;
79 struct kbase_jd_atom;
80 union kbase_kinstr_jm_fd;
81 
82 /**
83  * kbase_kinstr_jm_init() - Initialise an instrumentation job manager context.
84  * @ctx: Non-NULL pointer to where the pointer to the created context will
85  *       be stored on success.
86  *
87  * Return: 0 on success, else error code.
88  */
89 int kbase_kinstr_jm_init(struct kbase_kinstr_jm **ctx);
90 
91 /**
92  * kbase_kinstr_jm_term() - Terminate an instrumentation job manager context.
93  * @ctx: Pointer to context to be terminated.
94  */
95 void kbase_kinstr_jm_term(struct kbase_kinstr_jm *ctx);
96 
97 /**
98  * kbase_kinstr_jm_get_fd() - Retrieves a file descriptor that can be used to
99  * read the atom state changes from userspace
100  *
101  * @ctx: Pointer to the initialized context
102  * @jm_fd_arg: Pointer to the union containing the in/out params
103  * Return: -1 on failure, valid file descriptor on success
104  */
105 int kbase_kinstr_jm_get_fd(struct kbase_kinstr_jm *const ctx,
106 			   union kbase_kinstr_jm_fd *jm_fd_arg);
107 
108 /**
109  * kbasep_kinstr_jm_atom_state() - Signifies that an atom has changed state
110  * @atom: The atom that has changed state
111  * @state: The new state of the atom
112  *
113  * This performs the actual storage of the state ready for user space to
114  * read the data. It is only called when the static key is enabled from
115  * kbase_kinstr_jm_atom_state(). There is almost never a need to invoke this
116  * function directly.
117  */
118 void kbasep_kinstr_jm_atom_state(
119 	struct kbase_jd_atom *const atom,
120 	const enum kbase_kinstr_jm_reader_atom_state state);
121 
122 /* Allows ASM goto patching to reduce tracing overhead. This is
123  * incremented/decremented when readers are created and terminated. This really
124  * shouldn't be changed externally, but if you do, make sure you use
125  * a static_key_inc()/static_key_dec() pair.
126  */
127 extern struct static_key_false basep_kinstr_jm_reader_static_key;
128 
129 /**
130  * kbase_kinstr_jm_atom_state() - Signifies that an atom has changed state
131  * @atom: The atom that has changed state
132  * @state: The new state of the atom
133  *
134  * This uses a static key to reduce overhead when tracing is disabled
135  */
kbase_kinstr_jm_atom_state(struct kbase_jd_atom * const atom,const enum kbase_kinstr_jm_reader_atom_state state)136 static inline void kbase_kinstr_jm_atom_state(
137 	struct kbase_jd_atom *const atom,
138 	const enum kbase_kinstr_jm_reader_atom_state state)
139 {
140 	if (static_branch_unlikely(&basep_kinstr_jm_reader_static_key))
141 		kbasep_kinstr_jm_atom_state(atom, state);
142 }
143 
144 /**
145  * kbase_kinstr_jm_atom_state_queue() - Signifies that an atom has entered a
146  *                                      hardware or software queue.
147  * @atom: The atom that has changed state
148  */
kbase_kinstr_jm_atom_state_queue(struct kbase_jd_atom * const atom)149 static inline void kbase_kinstr_jm_atom_state_queue(
150 	struct kbase_jd_atom *const atom)
151 {
152 	kbase_kinstr_jm_atom_state(
153 		atom, KBASE_KINSTR_JM_READER_ATOM_STATE_QUEUE);
154 }
155 
156 /**
157  * kbase_kinstr_jm_atom_state_start() - Signifies that work has started on an
158  *                                      atom
159  * @atom: The atom that has changed state
160  */
kbase_kinstr_jm_atom_state_start(struct kbase_jd_atom * const atom)161 static inline void kbase_kinstr_jm_atom_state_start(
162 	struct kbase_jd_atom *const atom)
163 {
164 	kbase_kinstr_jm_atom_state(
165 		atom, KBASE_KINSTR_JM_READER_ATOM_STATE_START);
166 }
167 
168 /**
169  * kbase_kinstr_jm_atom_state_stop() - Signifies that work has stopped on an
170  *                                     atom
171  * @atom: The atom that has changed state
172  */
kbase_kinstr_jm_atom_state_stop(struct kbase_jd_atom * const atom)173 static inline void kbase_kinstr_jm_atom_state_stop(
174 	struct kbase_jd_atom *const atom)
175 {
176 	kbase_kinstr_jm_atom_state(
177 		atom, KBASE_KINSTR_JM_READER_ATOM_STATE_STOP);
178 }
179 
180 /**
181  * kbase_kinstr_jm_atom_state_complete() - Signifies that all work has completed
182  *                                         on an atom
183  * @atom: The atom that has changed state
184  */
kbase_kinstr_jm_atom_state_complete(struct kbase_jd_atom * const atom)185 static inline void kbase_kinstr_jm_atom_state_complete(
186 	struct kbase_jd_atom *const atom)
187 {
188 	kbase_kinstr_jm_atom_state(
189 		atom, KBASE_KINSTR_JM_READER_ATOM_STATE_COMPLETE);
190 }
191 
192 /**
193  * kbase_kinstr_jm_atom_queue() - A software *or* hardware atom is queued for
194  *                                execution
195  * @atom: The atom that has changed state
196  */
kbase_kinstr_jm_atom_queue(struct kbase_jd_atom * const atom)197 static inline void kbase_kinstr_jm_atom_queue(struct kbase_jd_atom *const atom)
198 {
199 	kbase_kinstr_jm_atom_state_queue(atom);
200 }
201 
202 /**
203  * kbase_kinstr_jm_atom_complete() - A software *or* hardware atom is fully
204  *                                   completed
205  * @atom: The atom that has changed state
206  */
kbase_kinstr_jm_atom_complete(struct kbase_jd_atom * const atom)207 static inline void kbase_kinstr_jm_atom_complete(
208 	struct kbase_jd_atom *const atom)
209 {
210 	kbase_kinstr_jm_atom_state_complete(atom);
211 }
212 
213 /**
214  * kbase_kinstr_jm_atom_sw_start() - A software atom has started work
215  * @atom: The atom that has changed state
216  */
kbase_kinstr_jm_atom_sw_start(struct kbase_jd_atom * const atom)217 static inline void kbase_kinstr_jm_atom_sw_start(
218 	struct kbase_jd_atom *const atom)
219 {
220 	kbase_kinstr_jm_atom_state_start(atom);
221 }
222 
223 /**
224  * kbase_kinstr_jm_atom_sw_stop() - A software atom has stopped work
225  * @atom: The atom that has changed state
226  */
kbase_kinstr_jm_atom_sw_stop(struct kbase_jd_atom * const atom)227 static inline void kbase_kinstr_jm_atom_sw_stop(
228 	struct kbase_jd_atom *const atom)
229 {
230 	kbase_kinstr_jm_atom_state_stop(atom);
231 }
232 
233 /**
234  * kbasep_kinstr_jm_atom_hw_submit() - A hardware atom has been submitted
235  * @atom: The atom that has been submitted
236  *
237  * This private implementation should not be called directly, it is protected
238  * by a static key in kbase_kinstr_jm_atom_hw_submit(). Use that instead.
239  */
240 void kbasep_kinstr_jm_atom_hw_submit(struct kbase_jd_atom *const atom);
241 
242 /**
243  * kbase_kinstr_jm_atom_hw_submit() - A hardware atom has been submitted
244  * @atom: The atom that has been submitted
245  */
kbase_kinstr_jm_atom_hw_submit(struct kbase_jd_atom * const atom)246 static inline void kbase_kinstr_jm_atom_hw_submit(
247 	struct kbase_jd_atom *const atom)
248 {
249 	if (static_branch_unlikely(&basep_kinstr_jm_reader_static_key))
250 		kbasep_kinstr_jm_atom_hw_submit(atom);
251 }
252 
253 /**
254  * kbasep_kinstr_jm_atom_hw_release() - A hardware atom has been released
255  * @atom: The atom that has been released
256  *
257  * This private implementation should not be called directly, it is protected
258  * by a static key in kbase_kinstr_jm_atom_hw_release(). Use that instead.
259  */
260 void kbasep_kinstr_jm_atom_hw_release(struct kbase_jd_atom *const atom);
261 
262 /**
263  * kbase_kinstr_jm_atom_hw_release() - A hardware atom has been released
264  * @atom: The atom that has been released
265  */
kbase_kinstr_jm_atom_hw_release(struct kbase_jd_atom * const atom)266 static inline void kbase_kinstr_jm_atom_hw_release(
267 	struct kbase_jd_atom *const atom)
268 {
269 	if (static_branch_unlikely(&basep_kinstr_jm_reader_static_key))
270 		kbasep_kinstr_jm_atom_hw_release(atom);
271 }
272 
273 #endif /* _KBASE_KINSTR_JM_H_ */
274