1 /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
2 /*
3 *
4 * (C) COPYRIGHT 2010-2023 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 #ifndef _KBASE_FENCE_H_
23 #define _KBASE_FENCE_H_
24
25 /*
26 * mali_kbase_fence.[hc] has fence code used only by
27 * - CONFIG_SYNC_FILE - explicit fences
28 */
29
30 #if IS_ENABLED(CONFIG_SYNC_FILE)
31
32 #include <linux/list.h>
33 #include "mali_kbase_fence_defs.h"
34 #include "mali_kbase.h"
35 #include "mali_kbase_refcount_defs.h"
36
37 #if MALI_USE_CSF
38 /* Maximum number of characters in DMA fence timeline name. */
39 #define MAX_TIMELINE_NAME (32)
40
41 /**
42 * struct kbase_kcpu_dma_fence_meta - Metadata structure for dma fence objects containing
43 * information about KCPU queue. One instance per KCPU
44 * queue.
45 *
46 * @refcount: Atomic value to keep track of number of references to an instance.
47 * An instance can outlive the KCPU queue itself.
48 * @kbdev: Pointer to Kbase device.
49 * @kctx_id: Kbase context ID.
50 * @timeline_name: String of timeline name for associated fence object.
51 */
52 struct kbase_kcpu_dma_fence_meta {
53 kbase_refcount_t refcount;
54 struct kbase_device *kbdev;
55 int kctx_id;
56 char timeline_name[MAX_TIMELINE_NAME];
57 };
58
59 /**
60 * struct kbase_kcpu_dma_fence - Structure which extends a dma fence object to include a
61 * reference to metadata containing more informaiton about it.
62 *
63 * @base: Fence object itself.
64 * @metadata: Pointer to metadata structure.
65 */
66 struct kbase_kcpu_dma_fence {
67 #if (KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE)
68 struct fence base;
69 #else
70 struct dma_fence base;
71 #endif /* LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0) */
72 struct kbase_kcpu_dma_fence_meta *metadata;
73 };
74 #endif
75
76 #if (KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE)
77 extern const struct fence_ops kbase_fence_ops;
78 #else
79 extern const struct dma_fence_ops kbase_fence_ops;
80 #endif
81
82 /**
83 * kbase_fence_out_new() - Creates a new output fence and puts it on the atom
84 * @katom: Atom to create an output fence for
85 *
86 * Return: A new fence object on success, NULL on failure.
87 */
88 #if (KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE)
89 struct fence *kbase_fence_out_new(struct kbase_jd_atom *katom);
90 #else
91 struct dma_fence *kbase_fence_out_new(struct kbase_jd_atom *katom);
92 #endif
93
94 #if IS_ENABLED(CONFIG_SYNC_FILE)
95 /**
96 * kbase_fence_fence_in_set() - Assign input fence to atom
97 * @katom: Atom to assign input fence to
98 * @fence: Input fence to assign to atom
99 *
100 * This function will take ownership of one fence reference!
101 */
102 #define kbase_fence_fence_in_set(katom, fence) \
103 do { \
104 WARN_ON((katom)->dma_fence.fence_in); \
105 (katom)->dma_fence.fence_in = fence; \
106 } while (0)
107 #endif
108
109
110 #if !MALI_USE_CSF
111 /**
112 * kbase_fence_out_remove() - Removes the output fence from atom
113 * @katom: Atom to remove output fence for
114 *
115 * This will also release the reference to this fence which the atom keeps
116 */
kbase_fence_out_remove(struct kbase_jd_atom * katom)117 static inline void kbase_fence_out_remove(struct kbase_jd_atom *katom)
118 {
119 if (katom->dma_fence.fence) {
120 dma_fence_put(katom->dma_fence.fence);
121 katom->dma_fence.fence = NULL;
122 }
123 }
124
125 #if IS_ENABLED(CONFIG_SYNC_FILE)
126 /**
127 * kbase_fence_in_remove() - Removes the input fence from atom
128 * @katom: Atom to remove input fence for
129 *
130 * This will also release the reference to this fence which the atom keeps
131 */
kbase_fence_in_remove(struct kbase_jd_atom * katom)132 static inline void kbase_fence_in_remove(struct kbase_jd_atom *katom)
133 {
134 if (katom->dma_fence.fence_in) {
135 dma_fence_put(katom->dma_fence.fence_in);
136 katom->dma_fence.fence_in = NULL;
137 }
138 }
139 #endif
140
141 /**
142 * kbase_fence_out_is_ours() - Check if atom has a valid fence created by us
143 * @katom: Atom to check output fence for
144 *
145 * Return: true if fence exists and is valid, otherwise false
146 */
kbase_fence_out_is_ours(struct kbase_jd_atom * katom)147 static inline bool kbase_fence_out_is_ours(struct kbase_jd_atom *katom)
148 {
149 return katom->dma_fence.fence &&
150 katom->dma_fence.fence->ops == &kbase_fence_ops;
151 }
152
153 /**
154 * kbase_fence_out_signal() - Signal output fence of atom
155 * @katom: Atom to signal output fence for
156 * @status: Status to signal with (0 for success, < 0 for error)
157 *
158 * Return: 0 on success, < 0 on error
159 */
kbase_fence_out_signal(struct kbase_jd_atom * katom,int status)160 static inline int kbase_fence_out_signal(struct kbase_jd_atom *katom,
161 int status)
162 {
163 if (status) {
164 #if (KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE && \
165 KERNEL_VERSION(4, 9, 68) <= LINUX_VERSION_CODE)
166 fence_set_error(katom->dma_fence.fence, status);
167 #elif (KERNEL_VERSION(4, 11, 0) <= LINUX_VERSION_CODE)
168 dma_fence_set_error(katom->dma_fence.fence, status);
169 #else
170 katom->dma_fence.fence->status = status;
171 #endif
172 }
173 return dma_fence_signal(katom->dma_fence.fence);
174 }
175
176 #if IS_ENABLED(CONFIG_SYNC_FILE)
177 /**
178 * kbase_fence_in_get() - Retrieve input fence for atom.
179 * @katom: Atom to get input fence from
180 *
181 * A ref will be taken for the fence, so use @kbase_fence_put() to release it
182 *
183 * Return: The fence, or NULL if there is no input fence for atom
184 */
185 #define kbase_fence_in_get(katom) dma_fence_get((katom)->dma_fence.fence_in)
186 #endif
187
188 /**
189 * kbase_fence_out_get() - Retrieve output fence for atom.
190 * @katom: Atom to get output fence from
191 *
192 * A ref will be taken for the fence, so use @kbase_fence_put() to release it
193 *
194 * Return: The fence, or NULL if there is no output fence for atom
195 */
196 #define kbase_fence_out_get(katom) dma_fence_get((katom)->dma_fence.fence)
197
198 #endif /* !MALI_USE_CSF */
199
200 /**
201 * kbase_fence_get() - Retrieve fence for a KCPUQ fence command.
202 * @fence_info: KCPUQ fence command
203 *
204 * A ref will be taken for the fence, so use @kbase_fence_put() to release it
205 *
206 * Return: The fence, or NULL if there is no fence for KCPUQ fence command
207 */
208 #define kbase_fence_get(fence_info) dma_fence_get((fence_info)->fence)
209
210 #if MALI_USE_CSF
211 #if (KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE)
kbase_kcpu_dma_fence_get(struct fence * fence)212 static inline struct kbase_kcpu_dma_fence *kbase_kcpu_dma_fence_get(struct fence *fence)
213 #else
214 static inline struct kbase_kcpu_dma_fence *kbase_kcpu_dma_fence_get(struct dma_fence *fence)
215 #endif
216 {
217 if (fence->ops == &kbase_fence_ops)
218 return (struct kbase_kcpu_dma_fence *)fence;
219
220 return NULL;
221 }
222
kbase_kcpu_dma_fence_meta_put(struct kbase_kcpu_dma_fence_meta * metadata)223 static inline void kbase_kcpu_dma_fence_meta_put(struct kbase_kcpu_dma_fence_meta *metadata)
224 {
225 if (kbase_refcount_dec_and_test(&metadata->refcount)) {
226 atomic_dec(&metadata->kbdev->live_fence_metadata);
227 kfree(metadata);
228 }
229 }
230
231 #if (KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE)
kbase_kcpu_dma_fence_put(struct fence * fence)232 static inline void kbase_kcpu_dma_fence_put(struct fence *fence)
233 #else
234 static inline void kbase_kcpu_dma_fence_put(struct dma_fence *fence)
235 #endif
236 {
237 struct kbase_kcpu_dma_fence *kcpu_fence = kbase_kcpu_dma_fence_get(fence);
238
239 if (kcpu_fence)
240 kbase_kcpu_dma_fence_meta_put(kcpu_fence->metadata);
241 }
242 #endif /* MALI_USE_CSF */
243
244 /**
245 * kbase_fence_put() - Releases a reference to a fence
246 * @fence: Fence to release reference for.
247 */
248 #if (KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE)
kbase_fence_put(struct fence * fence)249 static inline void kbase_fence_put(struct fence *fence)
250 #else
251 static inline void kbase_fence_put(struct dma_fence *fence)
252 #endif
253 {
254 dma_fence_put(fence);
255 }
256
257 #endif /* IS_ENABLED(CONFIG_SYNC_FILE) */
258
259 #endif /* _KBASE_FENCE_H_ */
260