xref: /OK3568_Linux_fs/kernel/drivers/gpu/arm/midgard/mali_kbase_fence.h (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  *
3*4882a593Smuzhiyun  * (C) COPYRIGHT 2010-2017 ARM Limited. All rights reserved.
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * This program is free software and is provided to you under the terms of the
6*4882a593Smuzhiyun  * GNU General Public License version 2 as published by the Free Software
7*4882a593Smuzhiyun  * Foundation, and any use by you of this program is subject to the terms
8*4882a593Smuzhiyun  * of such GNU licence.
9*4882a593Smuzhiyun  *
10*4882a593Smuzhiyun  * A copy of the licence is included with the program, and can also be obtained
11*4882a593Smuzhiyun  * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
12*4882a593Smuzhiyun  * Boston, MA  02110-1301, USA.
13*4882a593Smuzhiyun  *
14*4882a593Smuzhiyun  */
15*4882a593Smuzhiyun 
16*4882a593Smuzhiyun 
17*4882a593Smuzhiyun 
18*4882a593Smuzhiyun #ifndef _KBASE_FENCE_H_
19*4882a593Smuzhiyun #define _KBASE_FENCE_H_
20*4882a593Smuzhiyun 
21*4882a593Smuzhiyun /*
22*4882a593Smuzhiyun  * mali_kbase_fence.[hc] has common fence code used by both
23*4882a593Smuzhiyun  * - CONFIG_MALI_DMA_FENCE - implicit DMA fences
24*4882a593Smuzhiyun  * - CONFIG_SYNC_FILE      - explicit fences beginning with 4.9 kernel
25*4882a593Smuzhiyun  */
26*4882a593Smuzhiyun 
27*4882a593Smuzhiyun #if defined(CONFIG_MALI_DMA_FENCE) || defined(CONFIG_SYNC_FILE)
28*4882a593Smuzhiyun 
29*4882a593Smuzhiyun #include <linux/list.h>
30*4882a593Smuzhiyun #include "mali_kbase_fence_defs.h"
31*4882a593Smuzhiyun #include "mali_kbase.h"
32*4882a593Smuzhiyun 
33*4882a593Smuzhiyun #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0))
34*4882a593Smuzhiyun extern const struct fence_ops kbase_fence_ops;
35*4882a593Smuzhiyun #else
36*4882a593Smuzhiyun extern const struct dma_fence_ops kbase_fence_ops;
37*4882a593Smuzhiyun #endif
38*4882a593Smuzhiyun 
39*4882a593Smuzhiyun /**
40*4882a593Smuzhiyun * struct kbase_fence_cb - Mali dma-fence callback data struct
41*4882a593Smuzhiyun * @fence_cb: Callback function
42*4882a593Smuzhiyun * @katom:    Pointer to katom that is waiting on this callback
43*4882a593Smuzhiyun * @fence:    Pointer to the fence object on which this callback is waiting
44*4882a593Smuzhiyun * @node:     List head for linking this callback to the katom
45*4882a593Smuzhiyun */
46*4882a593Smuzhiyun struct kbase_fence_cb {
47*4882a593Smuzhiyun #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0))
48*4882a593Smuzhiyun 	struct fence_cb fence_cb;
49*4882a593Smuzhiyun 	struct fence *fence;
50*4882a593Smuzhiyun #else
51*4882a593Smuzhiyun 	struct dma_fence_cb fence_cb;
52*4882a593Smuzhiyun 	struct dma_fence *fence;
53*4882a593Smuzhiyun #endif
54*4882a593Smuzhiyun 	struct kbase_jd_atom *katom;
55*4882a593Smuzhiyun 	struct list_head node;
56*4882a593Smuzhiyun };
57*4882a593Smuzhiyun 
58*4882a593Smuzhiyun /**
59*4882a593Smuzhiyun  * kbase_fence_out_new() - Creates a new output fence and puts it on the atom
60*4882a593Smuzhiyun  * @katom: Atom to create an output fence for
61*4882a593Smuzhiyun  *
62*4882a593Smuzhiyun  * return: A new fence object on success, NULL on failure.
63*4882a593Smuzhiyun  */
64*4882a593Smuzhiyun #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0))
65*4882a593Smuzhiyun struct fence *kbase_fence_out_new(struct kbase_jd_atom *katom);
66*4882a593Smuzhiyun #else
67*4882a593Smuzhiyun struct dma_fence *kbase_fence_out_new(struct kbase_jd_atom *katom);
68*4882a593Smuzhiyun #endif
69*4882a593Smuzhiyun 
70*4882a593Smuzhiyun #if defined(CONFIG_SYNC_FILE)
71*4882a593Smuzhiyun /**
72*4882a593Smuzhiyun  * kbase_fence_fence_in_set() - Assign input fence to atom
73*4882a593Smuzhiyun  * @katom: Atom to assign input fence to
74*4882a593Smuzhiyun  * @fence: Input fence to assign to atom
75*4882a593Smuzhiyun  *
76*4882a593Smuzhiyun  * This function will take ownership of one fence reference!
77*4882a593Smuzhiyun  */
78*4882a593Smuzhiyun #define kbase_fence_fence_in_set(katom, fence) \
79*4882a593Smuzhiyun 	do { \
80*4882a593Smuzhiyun 		WARN_ON((katom)->dma_fence.fence_in); \
81*4882a593Smuzhiyun 		(katom)->dma_fence.fence_in = fence; \
82*4882a593Smuzhiyun 	} while (0)
83*4882a593Smuzhiyun #endif
84*4882a593Smuzhiyun 
85*4882a593Smuzhiyun /**
86*4882a593Smuzhiyun  * kbase_fence_out_remove() - Removes the output fence from atom
87*4882a593Smuzhiyun  * @katom: Atom to remove output fence for
88*4882a593Smuzhiyun  *
89*4882a593Smuzhiyun  * This will also release the reference to this fence which the atom keeps
90*4882a593Smuzhiyun  */
kbase_fence_out_remove(struct kbase_jd_atom * katom)91*4882a593Smuzhiyun static inline void kbase_fence_out_remove(struct kbase_jd_atom *katom)
92*4882a593Smuzhiyun {
93*4882a593Smuzhiyun 	if (katom->dma_fence.fence) {
94*4882a593Smuzhiyun 		dma_fence_put(katom->dma_fence.fence);
95*4882a593Smuzhiyun 		katom->dma_fence.fence = NULL;
96*4882a593Smuzhiyun 	}
97*4882a593Smuzhiyun }
98*4882a593Smuzhiyun 
99*4882a593Smuzhiyun #if defined(CONFIG_SYNC_FILE)
100*4882a593Smuzhiyun /**
101*4882a593Smuzhiyun  * kbase_fence_out_remove() - Removes the input fence from atom
102*4882a593Smuzhiyun  * @katom: Atom to remove input fence for
103*4882a593Smuzhiyun  *
104*4882a593Smuzhiyun  * This will also release the reference to this fence which the atom keeps
105*4882a593Smuzhiyun  */
kbase_fence_in_remove(struct kbase_jd_atom * katom)106*4882a593Smuzhiyun static inline void kbase_fence_in_remove(struct kbase_jd_atom *katom)
107*4882a593Smuzhiyun {
108*4882a593Smuzhiyun 	if (katom->dma_fence.fence_in) {
109*4882a593Smuzhiyun 		dma_fence_put(katom->dma_fence.fence_in);
110*4882a593Smuzhiyun 		katom->dma_fence.fence_in = NULL;
111*4882a593Smuzhiyun 	}
112*4882a593Smuzhiyun }
113*4882a593Smuzhiyun #endif
114*4882a593Smuzhiyun 
115*4882a593Smuzhiyun /**
116*4882a593Smuzhiyun  * kbase_fence_out_is_ours() - Check if atom has a valid fence created by us
117*4882a593Smuzhiyun  * @katom: Atom to check output fence for
118*4882a593Smuzhiyun  *
119*4882a593Smuzhiyun  * Return: true if fence exists and is valid, otherwise false
120*4882a593Smuzhiyun  */
kbase_fence_out_is_ours(struct kbase_jd_atom * katom)121*4882a593Smuzhiyun static inline bool kbase_fence_out_is_ours(struct kbase_jd_atom *katom)
122*4882a593Smuzhiyun {
123*4882a593Smuzhiyun 	return katom->dma_fence.fence &&
124*4882a593Smuzhiyun 				katom->dma_fence.fence->ops == &kbase_fence_ops;
125*4882a593Smuzhiyun }
126*4882a593Smuzhiyun 
127*4882a593Smuzhiyun /**
128*4882a593Smuzhiyun  * kbase_fence_out_signal() - Signal output fence of atom
129*4882a593Smuzhiyun  * @katom: Atom to signal output fence for
130*4882a593Smuzhiyun  * @status: Status to signal with (0 for success, < 0 for error)
131*4882a593Smuzhiyun  *
132*4882a593Smuzhiyun  * Return: 0 on success, < 0 on error
133*4882a593Smuzhiyun  */
kbase_fence_out_signal(struct kbase_jd_atom * katom,int status)134*4882a593Smuzhiyun static inline int kbase_fence_out_signal(struct kbase_jd_atom *katom,
135*4882a593Smuzhiyun 					 int status)
136*4882a593Smuzhiyun {
137*4882a593Smuzhiyun 	if (status) {
138*4882a593Smuzhiyun #if (KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE && \
139*4882a593Smuzhiyun 	  KERNEL_VERSION(4, 9, 68) <= LINUX_VERSION_CODE)
140*4882a593Smuzhiyun 		fence_set_error(katom->dma_fence.fence, status);
141*4882a593Smuzhiyun #elif (KERNEL_VERSION(4, 11, 0) <= LINUX_VERSION_CODE)
142*4882a593Smuzhiyun 		dma_fence_set_error(katom->dma_fence.fence, status);
143*4882a593Smuzhiyun #else
144*4882a593Smuzhiyun 		katom->dma_fence.fence->status = status;
145*4882a593Smuzhiyun #endif
146*4882a593Smuzhiyun 	}
147*4882a593Smuzhiyun 	return dma_fence_signal(katom->dma_fence.fence);
148*4882a593Smuzhiyun }
149*4882a593Smuzhiyun 
150*4882a593Smuzhiyun /**
151*4882a593Smuzhiyun  * kbase_fence_add_callback() - Add callback on @fence to block @katom
152*4882a593Smuzhiyun  * @katom: Pointer to katom that will be blocked by @fence
153*4882a593Smuzhiyun  * @fence: Pointer to fence on which to set up the callback
154*4882a593Smuzhiyun  * @callback: Pointer to function to be called when fence is signaled
155*4882a593Smuzhiyun  *
156*4882a593Smuzhiyun  * Caller needs to hold a reference to @fence when calling this function, and
157*4882a593Smuzhiyun  * the caller is responsible for releasing that reference.  An additional
158*4882a593Smuzhiyun  * reference to @fence will be taken when the callback was successfully set up
159*4882a593Smuzhiyun  * and @fence needs to be kept valid until the callback has been called and
160*4882a593Smuzhiyun  * cleanup have been done.
161*4882a593Smuzhiyun  *
162*4882a593Smuzhiyun  * Return: 0 on success: fence was either already signaled, or callback was
163*4882a593Smuzhiyun  * set up. Negative error code is returned on error.
164*4882a593Smuzhiyun  */
165*4882a593Smuzhiyun #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0))
166*4882a593Smuzhiyun int kbase_fence_add_callback(struct kbase_jd_atom *katom,
167*4882a593Smuzhiyun 			     struct fence *fence,
168*4882a593Smuzhiyun 			     fence_func_t callback);
169*4882a593Smuzhiyun #else
170*4882a593Smuzhiyun int kbase_fence_add_callback(struct kbase_jd_atom *katom,
171*4882a593Smuzhiyun 			     struct dma_fence *fence,
172*4882a593Smuzhiyun 			     dma_fence_func_t callback);
173*4882a593Smuzhiyun #endif
174*4882a593Smuzhiyun 
175*4882a593Smuzhiyun /**
176*4882a593Smuzhiyun  * kbase_fence_dep_count_set() - Set dep_count value on atom to specified value
177*4882a593Smuzhiyun  * @katom: Atom to set dep_count for
178*4882a593Smuzhiyun  * @val: value to set dep_count to
179*4882a593Smuzhiyun  *
180*4882a593Smuzhiyun  * The dep_count is available to the users of this module so that they can
181*4882a593Smuzhiyun  * synchronize completion of the wait with cancellation and adding of more
182*4882a593Smuzhiyun  * callbacks. For instance, a user could do the following:
183*4882a593Smuzhiyun  *
184*4882a593Smuzhiyun  * dep_count set to 1
185*4882a593Smuzhiyun  * callback #1 added, dep_count is increased to 2
186*4882a593Smuzhiyun  *                             callback #1 happens, dep_count decremented to 1
187*4882a593Smuzhiyun  *                             since dep_count > 0, no completion is done
188*4882a593Smuzhiyun  * callback #2 is added, dep_count is increased to 2
189*4882a593Smuzhiyun  * dep_count decremented to 1
190*4882a593Smuzhiyun  *                             callback #2 happens, dep_count decremented to 0
191*4882a593Smuzhiyun  *                             since dep_count now is zero, completion executes
192*4882a593Smuzhiyun  *
193*4882a593Smuzhiyun  * The dep_count can also be used to make sure that the completion only
194*4882a593Smuzhiyun  * executes once. This is typically done by setting dep_count to -1 for the
195*4882a593Smuzhiyun  * thread that takes on this responsibility.
196*4882a593Smuzhiyun  */
197*4882a593Smuzhiyun static inline void
kbase_fence_dep_count_set(struct kbase_jd_atom * katom,int val)198*4882a593Smuzhiyun kbase_fence_dep_count_set(struct kbase_jd_atom *katom, int val)
199*4882a593Smuzhiyun {
200*4882a593Smuzhiyun 	atomic_set(&katom->dma_fence.dep_count, val);
201*4882a593Smuzhiyun }
202*4882a593Smuzhiyun 
203*4882a593Smuzhiyun /**
204*4882a593Smuzhiyun  * kbase_fence_dep_count_dec_and_test() - Decrements dep_count
205*4882a593Smuzhiyun  * @katom: Atom to decrement dep_count for
206*4882a593Smuzhiyun  *
207*4882a593Smuzhiyun  * See @kbase_fence_dep_count_set for general description about dep_count
208*4882a593Smuzhiyun  *
209*4882a593Smuzhiyun  * Return: true if value was decremented to zero, otherwise false
210*4882a593Smuzhiyun  */
211*4882a593Smuzhiyun static inline bool
kbase_fence_dep_count_dec_and_test(struct kbase_jd_atom * katom)212*4882a593Smuzhiyun kbase_fence_dep_count_dec_and_test(struct kbase_jd_atom *katom)
213*4882a593Smuzhiyun {
214*4882a593Smuzhiyun 	return atomic_dec_and_test(&katom->dma_fence.dep_count);
215*4882a593Smuzhiyun }
216*4882a593Smuzhiyun 
217*4882a593Smuzhiyun /**
218*4882a593Smuzhiyun  * kbase_fence_dep_count_read() - Returns the current dep_count value
219*4882a593Smuzhiyun  * @katom: Pointer to katom
220*4882a593Smuzhiyun  *
221*4882a593Smuzhiyun  * See @kbase_fence_dep_count_set for general description about dep_count
222*4882a593Smuzhiyun  *
223*4882a593Smuzhiyun  * Return: The current dep_count value
224*4882a593Smuzhiyun  */
kbase_fence_dep_count_read(struct kbase_jd_atom * katom)225*4882a593Smuzhiyun static inline int kbase_fence_dep_count_read(struct kbase_jd_atom *katom)
226*4882a593Smuzhiyun {
227*4882a593Smuzhiyun 	return atomic_read(&katom->dma_fence.dep_count);
228*4882a593Smuzhiyun }
229*4882a593Smuzhiyun 
230*4882a593Smuzhiyun /**
231*4882a593Smuzhiyun  * kbase_fence_free_callbacks() - Free dma-fence callbacks on a katom
232*4882a593Smuzhiyun  * @katom: Pointer to katom
233*4882a593Smuzhiyun  *
234*4882a593Smuzhiyun  * This function will free all fence callbacks on the katom's list of
235*4882a593Smuzhiyun  * callbacks. Callbacks that have not yet been called, because their fence
236*4882a593Smuzhiyun  * hasn't yet signaled, will first be removed from the fence.
237*4882a593Smuzhiyun  *
238*4882a593Smuzhiyun  * Locking: katom->dma_fence.callbacks list assumes jctx.lock is held.
239*4882a593Smuzhiyun  *
240*4882a593Smuzhiyun  * Return: true if dep_count reached 0, otherwise false.
241*4882a593Smuzhiyun  */
242*4882a593Smuzhiyun bool kbase_fence_free_callbacks(struct kbase_jd_atom *katom);
243*4882a593Smuzhiyun 
244*4882a593Smuzhiyun #if defined(CONFIG_SYNC_FILE)
245*4882a593Smuzhiyun /**
246*4882a593Smuzhiyun  * kbase_fence_in_get() - Retrieve input fence for atom.
247*4882a593Smuzhiyun  * @katom: Atom to get input fence from
248*4882a593Smuzhiyun  *
249*4882a593Smuzhiyun  * A ref will be taken for the fence, so use @kbase_fence_put() to release it
250*4882a593Smuzhiyun  *
251*4882a593Smuzhiyun  * Return: The fence, or NULL if there is no input fence for atom
252*4882a593Smuzhiyun  */
253*4882a593Smuzhiyun #define kbase_fence_in_get(katom) dma_fence_get((katom)->dma_fence.fence_in)
254*4882a593Smuzhiyun #endif
255*4882a593Smuzhiyun 
256*4882a593Smuzhiyun /**
257*4882a593Smuzhiyun  * kbase_fence_out_get() - Retrieve output fence for atom.
258*4882a593Smuzhiyun  * @katom: Atom to get output fence from
259*4882a593Smuzhiyun  *
260*4882a593Smuzhiyun  * A ref will be taken for the fence, so use @kbase_fence_put() to release it
261*4882a593Smuzhiyun  *
262*4882a593Smuzhiyun  * Return: The fence, or NULL if there is no output fence for atom
263*4882a593Smuzhiyun  */
264*4882a593Smuzhiyun #define kbase_fence_out_get(katom) dma_fence_get((katom)->dma_fence.fence)
265*4882a593Smuzhiyun 
266*4882a593Smuzhiyun /**
267*4882a593Smuzhiyun  * kbase_fence_put() - Releases a reference to a fence
268*4882a593Smuzhiyun  * @fence: Fence to release reference for.
269*4882a593Smuzhiyun  */
270*4882a593Smuzhiyun #define kbase_fence_put(fence) dma_fence_put(fence)
271*4882a593Smuzhiyun 
272*4882a593Smuzhiyun 
273*4882a593Smuzhiyun #endif /* CONFIG_MALI_DMA_FENCE || defined(CONFIG_SYNC_FILE */
274*4882a593Smuzhiyun 
275*4882a593Smuzhiyun #endif /* _KBASE_FENCE_H_ */
276