xref: /OK3568_Linux_fs/kernel/drivers/gpu/arm/bifrost/mali_kbase_fence.h (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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