| .. | .. |
|---|
| 1 | 1 | /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ |
|---|
| 2 | 2 | /* |
|---|
| 3 | 3 | * |
|---|
| 4 | | - * (C) COPYRIGHT 2010-2018, 2020-2021 ARM Limited. All rights reserved. |
|---|
| 4 | + * (C) COPYRIGHT 2010-2023 ARM Limited. All rights reserved. |
|---|
| 5 | 5 | * |
|---|
| 6 | 6 | * This program is free software and is provided to you under the terms of the |
|---|
| 7 | 7 | * GNU General Public License version 2 as published by the Free Software |
|---|
| .. | .. |
|---|
| 23 | 23 | #define _KBASE_FENCE_H_ |
|---|
| 24 | 24 | |
|---|
| 25 | 25 | /* |
|---|
| 26 | | - * mali_kbase_fence.[hc] has common fence code used by both |
|---|
| 27 | | - * - CONFIG_MALI_BIFROST_DMA_FENCE - implicit DMA fences |
|---|
| 28 | | - * - CONFIG_SYNC_FILE - explicit fences beginning with 4.9 kernel |
|---|
| 26 | + * mali_kbase_fence.[hc] has fence code used only by |
|---|
| 27 | + * - CONFIG_SYNC_FILE - explicit fences |
|---|
| 29 | 28 | */ |
|---|
| 30 | 29 | |
|---|
| 31 | | -#if defined(CONFIG_MALI_BIFROST_DMA_FENCE) || defined(CONFIG_SYNC_FILE) |
|---|
| 30 | +#if IS_ENABLED(CONFIG_SYNC_FILE) |
|---|
| 32 | 31 | |
|---|
| 33 | 32 | #include <linux/list.h> |
|---|
| 34 | 33 | #include "mali_kbase_fence_defs.h" |
|---|
| 35 | 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 |
|---|
| 36 | 75 | |
|---|
| 37 | 76 | #if (KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE) |
|---|
| 38 | 77 | extern const struct fence_ops kbase_fence_ops; |
|---|
| .. | .. |
|---|
| 41 | 80 | #endif |
|---|
| 42 | 81 | |
|---|
| 43 | 82 | /** |
|---|
| 44 | | -* struct kbase_fence_cb - Mali dma-fence callback data struct |
|---|
| 45 | | -* @fence_cb: Callback function |
|---|
| 46 | | -* @katom: Pointer to katom that is waiting on this callback |
|---|
| 47 | | -* @fence: Pointer to the fence object on which this callback is waiting |
|---|
| 48 | | -* @node: List head for linking this callback to the katom |
|---|
| 49 | | -*/ |
|---|
| 50 | | -struct kbase_fence_cb { |
|---|
| 51 | | -#if (KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE) |
|---|
| 52 | | - struct fence_cb fence_cb; |
|---|
| 53 | | - struct fence *fence; |
|---|
| 54 | | -#else |
|---|
| 55 | | - struct dma_fence_cb fence_cb; |
|---|
| 56 | | - struct dma_fence *fence; |
|---|
| 57 | | -#endif |
|---|
| 58 | | - struct kbase_jd_atom *katom; |
|---|
| 59 | | - struct list_head node; |
|---|
| 60 | | -}; |
|---|
| 61 | | - |
|---|
| 62 | | -/** |
|---|
| 63 | 83 | * kbase_fence_out_new() - Creates a new output fence and puts it on the atom |
|---|
| 64 | 84 | * @katom: Atom to create an output fence for |
|---|
| 65 | 85 | * |
|---|
| 66 | | - * return: A new fence object on success, NULL on failure. |
|---|
| 86 | + * Return: A new fence object on success, NULL on failure. |
|---|
| 67 | 87 | */ |
|---|
| 68 | 88 | #if (KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE) |
|---|
| 69 | 89 | struct fence *kbase_fence_out_new(struct kbase_jd_atom *katom); |
|---|
| .. | .. |
|---|
| 71 | 91 | struct dma_fence *kbase_fence_out_new(struct kbase_jd_atom *katom); |
|---|
| 72 | 92 | #endif |
|---|
| 73 | 93 | |
|---|
| 74 | | -#if defined(CONFIG_SYNC_FILE) |
|---|
| 94 | +#if IS_ENABLED(CONFIG_SYNC_FILE) |
|---|
| 75 | 95 | /** |
|---|
| 76 | 96 | * kbase_fence_fence_in_set() - Assign input fence to atom |
|---|
| 77 | 97 | * @katom: Atom to assign input fence to |
|---|
| .. | .. |
|---|
| 102 | 122 | } |
|---|
| 103 | 123 | } |
|---|
| 104 | 124 | |
|---|
| 105 | | -#if defined(CONFIG_SYNC_FILE) |
|---|
| 125 | +#if IS_ENABLED(CONFIG_SYNC_FILE) |
|---|
| 106 | 126 | /** |
|---|
| 107 | | - * kbase_fence_out_remove() - Removes the input fence from atom |
|---|
| 127 | + * kbase_fence_in_remove() - Removes the input fence from atom |
|---|
| 108 | 128 | * @katom: Atom to remove input fence for |
|---|
| 109 | 129 | * |
|---|
| 110 | 130 | * This will also release the reference to this fence which the atom keeps |
|---|
| .. | .. |
|---|
| 153 | 173 | return dma_fence_signal(katom->dma_fence.fence); |
|---|
| 154 | 174 | } |
|---|
| 155 | 175 | |
|---|
| 156 | | -/** |
|---|
| 157 | | - * kbase_fence_add_callback() - Add callback on @fence to block @katom |
|---|
| 158 | | - * @katom: Pointer to katom that will be blocked by @fence |
|---|
| 159 | | - * @fence: Pointer to fence on which to set up the callback |
|---|
| 160 | | - * @callback: Pointer to function to be called when fence is signaled |
|---|
| 161 | | - * |
|---|
| 162 | | - * Caller needs to hold a reference to @fence when calling this function, and |
|---|
| 163 | | - * the caller is responsible for releasing that reference. An additional |
|---|
| 164 | | - * reference to @fence will be taken when the callback was successfully set up |
|---|
| 165 | | - * and @fence needs to be kept valid until the callback has been called and |
|---|
| 166 | | - * cleanup have been done. |
|---|
| 167 | | - * |
|---|
| 168 | | - * Return: 0 on success: fence was either already signaled, or callback was |
|---|
| 169 | | - * set up. Negative error code is returned on error. |
|---|
| 170 | | - */ |
|---|
| 171 | | -#if (KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE) |
|---|
| 172 | | -int kbase_fence_add_callback(struct kbase_jd_atom *katom, |
|---|
| 173 | | - struct fence *fence, |
|---|
| 174 | | - fence_func_t callback); |
|---|
| 175 | | -#else |
|---|
| 176 | | -int kbase_fence_add_callback(struct kbase_jd_atom *katom, |
|---|
| 177 | | - struct dma_fence *fence, |
|---|
| 178 | | - dma_fence_func_t callback); |
|---|
| 179 | | -#endif |
|---|
| 180 | | - |
|---|
| 181 | | -/** |
|---|
| 182 | | - * kbase_fence_dep_count_set() - Set dep_count value on atom to specified value |
|---|
| 183 | | - * @katom: Atom to set dep_count for |
|---|
| 184 | | - * @val: value to set dep_count to |
|---|
| 185 | | - * |
|---|
| 186 | | - * The dep_count is available to the users of this module so that they can |
|---|
| 187 | | - * synchronize completion of the wait with cancellation and adding of more |
|---|
| 188 | | - * callbacks. For instance, a user could do the following: |
|---|
| 189 | | - * |
|---|
| 190 | | - * dep_count set to 1 |
|---|
| 191 | | - * callback #1 added, dep_count is increased to 2 |
|---|
| 192 | | - * callback #1 happens, dep_count decremented to 1 |
|---|
| 193 | | - * since dep_count > 0, no completion is done |
|---|
| 194 | | - * callback #2 is added, dep_count is increased to 2 |
|---|
| 195 | | - * dep_count decremented to 1 |
|---|
| 196 | | - * callback #2 happens, dep_count decremented to 0 |
|---|
| 197 | | - * since dep_count now is zero, completion executes |
|---|
| 198 | | - * |
|---|
| 199 | | - * The dep_count can also be used to make sure that the completion only |
|---|
| 200 | | - * executes once. This is typically done by setting dep_count to -1 for the |
|---|
| 201 | | - * thread that takes on this responsibility. |
|---|
| 202 | | - */ |
|---|
| 203 | | -static inline void |
|---|
| 204 | | -kbase_fence_dep_count_set(struct kbase_jd_atom *katom, int val) |
|---|
| 205 | | -{ |
|---|
| 206 | | - atomic_set(&katom->dma_fence.dep_count, val); |
|---|
| 207 | | -} |
|---|
| 208 | | - |
|---|
| 209 | | -/** |
|---|
| 210 | | - * kbase_fence_dep_count_dec_and_test() - Decrements dep_count |
|---|
| 211 | | - * @katom: Atom to decrement dep_count for |
|---|
| 212 | | - * |
|---|
| 213 | | - * See @kbase_fence_dep_count_set for general description about dep_count |
|---|
| 214 | | - * |
|---|
| 215 | | - * Return: true if value was decremented to zero, otherwise false |
|---|
| 216 | | - */ |
|---|
| 217 | | -static inline bool |
|---|
| 218 | | -kbase_fence_dep_count_dec_and_test(struct kbase_jd_atom *katom) |
|---|
| 219 | | -{ |
|---|
| 220 | | - return atomic_dec_and_test(&katom->dma_fence.dep_count); |
|---|
| 221 | | -} |
|---|
| 222 | | - |
|---|
| 223 | | -/** |
|---|
| 224 | | - * kbase_fence_dep_count_read() - Returns the current dep_count value |
|---|
| 225 | | - * @katom: Pointer to katom |
|---|
| 226 | | - * |
|---|
| 227 | | - * See @kbase_fence_dep_count_set for general description about dep_count |
|---|
| 228 | | - * |
|---|
| 229 | | - * Return: The current dep_count value |
|---|
| 230 | | - */ |
|---|
| 231 | | -static inline int kbase_fence_dep_count_read(struct kbase_jd_atom *katom) |
|---|
| 232 | | -{ |
|---|
| 233 | | - return atomic_read(&katom->dma_fence.dep_count); |
|---|
| 234 | | -} |
|---|
| 235 | | - |
|---|
| 236 | | -/** |
|---|
| 237 | | - * kbase_fence_free_callbacks() - Free dma-fence callbacks on a katom |
|---|
| 238 | | - * @katom: Pointer to katom |
|---|
| 239 | | - * |
|---|
| 240 | | - * This function will free all fence callbacks on the katom's list of |
|---|
| 241 | | - * callbacks. Callbacks that have not yet been called, because their fence |
|---|
| 242 | | - * hasn't yet signaled, will first be removed from the fence. |
|---|
| 243 | | - * |
|---|
| 244 | | - * Locking: katom->dma_fence.callbacks list assumes jctx.lock is held. |
|---|
| 245 | | - * |
|---|
| 246 | | - * Return: true if dep_count reached 0, otherwise false. |
|---|
| 247 | | - */ |
|---|
| 248 | | -bool kbase_fence_free_callbacks(struct kbase_jd_atom *katom); |
|---|
| 249 | | - |
|---|
| 250 | | -#if defined(CONFIG_SYNC_FILE) |
|---|
| 176 | +#if IS_ENABLED(CONFIG_SYNC_FILE) |
|---|
| 251 | 177 | /** |
|---|
| 252 | 178 | * kbase_fence_in_get() - Retrieve input fence for atom. |
|---|
| 253 | 179 | * @katom: Atom to get input fence from |
|---|
| .. | .. |
|---|
| 272 | 198 | #endif /* !MALI_USE_CSF */ |
|---|
| 273 | 199 | |
|---|
| 274 | 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) |
|---|
| 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 | + |
|---|
| 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) |
|---|
| 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 | +/** |
|---|
| 275 | 245 | * kbase_fence_put() - Releases a reference to a fence |
|---|
| 276 | 246 | * @fence: Fence to release reference for. |
|---|
| 277 | 247 | */ |
|---|
| 278 | | -#define kbase_fence_put(fence) dma_fence_put(fence) |
|---|
| 248 | +#if (KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE) |
|---|
| 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 | +} |
|---|
| 279 | 256 | |
|---|
| 280 | | - |
|---|
| 281 | | -#endif /* CONFIG_MALI_BIFROST_DMA_FENCE || defined(CONFIG_SYNC_FILE */ |
|---|
| 257 | +#endif /* IS_ENABLED(CONFIG_SYNC_FILE) */ |
|---|
| 282 | 258 | |
|---|
| 283 | 259 | #endif /* _KBASE_FENCE_H_ */ |
|---|