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