diff options
Diffstat (limited to 'mali_kbase/mali_kbase_fence.h')
-rw-r--r-- | mali_kbase/mali_kbase_fence.h | 233 |
1 files changed, 101 insertions, 132 deletions
diff --git a/mali_kbase/mali_kbase_fence.h b/mali_kbase/mali_kbase_fence.h index 2842280..ea2ac34 100644 --- a/mali_kbase/mali_kbase_fence.h +++ b/mali_kbase/mali_kbase_fence.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ /* * - * (C) COPYRIGHT 2010-2018, 2020-2022 ARM Limited. All rights reserved. + * (C) COPYRIGHT 2010-2023 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the * GNU General Public License version 2 as published by the Free Software @@ -23,41 +23,62 @@ #define _KBASE_FENCE_H_ /* - * mali_kbase_fence.[hc] has common fence code used by both - * - CONFIG_MALI_DMA_FENCE - implicit DMA fences - * - CONFIG_SYNC_FILE - explicit fences beginning with 4.9 kernel + * mali_kbase_fence.[hc] has fence code used only by + * - CONFIG_SYNC_FILE - explicit fences */ -#if defined(CONFIG_MALI_DMA_FENCE) || defined(CONFIG_SYNC_FILE) +#if IS_ENABLED(CONFIG_SYNC_FILE) #include <linux/list.h> #include "mali_kbase_fence_defs.h" #include "mali_kbase.h" +#include "mali_kbase_refcount_defs.h" +#include <linux/version_compat_defs.h> +#if MALI_USE_CSF +/* Maximum number of characters in DMA fence timeline name. */ +#define MAX_TIMELINE_NAME (32) + +/** + * struct kbase_kcpu_dma_fence_meta - Metadata structure for dma fence objects containing + * information about KCPU queue. One instance per KCPU + * queue. + * + * @refcount: Atomic value to keep track of number of references to an instance. + * An instance can outlive the KCPU queue itself. + * @kbdev: Pointer to Kbase device. + * @kctx_id: Kbase context ID. + * @timeline_name: String of timeline name for associated fence object. + */ +struct kbase_kcpu_dma_fence_meta { + kbase_refcount_t refcount; + struct kbase_device *kbdev; + int kctx_id; + char timeline_name[MAX_TIMELINE_NAME]; +}; + +/** + * struct kbase_kcpu_dma_fence - Structure which extends a dma fence object to include a + * reference to metadata containing more informaiton about it. + * + * @base: Fence object itself. + * @metadata: Pointer to metadata structure. + */ +struct kbase_kcpu_dma_fence { #if (KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE) -extern const struct fence_ops kbase_fence_ops; + struct fence base; #else -extern const struct dma_fence_ops kbase_fence_ops; + struct dma_fence base; +#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0) */ + struct kbase_kcpu_dma_fence_meta *metadata; +}; #endif -/** - * struct kbase_fence_cb - Mali dma-fence callback data struct - * @fence_cb: Callback function - * @katom: Pointer to katom that is waiting on this callback - * @fence: Pointer to the fence object on which this callback is waiting - * @node: List head for linking this callback to the katom - */ -struct kbase_fence_cb { #if (KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE) - struct fence_cb fence_cb; - struct fence *fence; +extern const struct fence_ops kbase_fence_ops; #else - struct dma_fence_cb fence_cb; - struct dma_fence *fence; +extern const struct dma_fence_ops kbase_fence_ops; #endif - struct kbase_jd_atom *katom; - struct list_head node; -}; /** * kbase_fence_out_new() - Creates a new output fence and puts it on the atom @@ -71,7 +92,7 @@ struct fence *kbase_fence_out_new(struct kbase_jd_atom *katom); struct dma_fence *kbase_fence_out_new(struct kbase_jd_atom *katom); #endif -#if defined(CONFIG_SYNC_FILE) +#if IS_ENABLED(CONFIG_SYNC_FILE) /** * kbase_fence_fence_in_set() - Assign input fence to atom * @katom: Atom to assign input fence to @@ -102,9 +123,9 @@ static inline void kbase_fence_out_remove(struct kbase_jd_atom *katom) } } -#if defined(CONFIG_SYNC_FILE) +#if IS_ENABLED(CONFIG_SYNC_FILE) /** - * kbase_fence_out_remove() - Removes the input fence from atom + * kbase_fence_in_remove() - Removes the input fence from atom * @katom: Atom to remove input fence for * * This will also release the reference to this fence which the atom keeps @@ -140,144 +161,92 @@ static inline bool kbase_fence_out_is_ours(struct kbase_jd_atom *katom) static inline int kbase_fence_out_signal(struct kbase_jd_atom *katom, int status) { - if (status) { -#if (KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE && \ - KERNEL_VERSION(4, 9, 68) <= LINUX_VERSION_CODE) - fence_set_error(katom->dma_fence.fence, status); -#elif (KERNEL_VERSION(4, 11, 0) <= LINUX_VERSION_CODE) - dma_fence_set_error(katom->dma_fence.fence, status); -#else - katom->dma_fence.fence->status = status; -#endif - } + if (status) + dma_fence_set_error_helper(katom->dma_fence.fence, status); return dma_fence_signal(katom->dma_fence.fence); } +#if IS_ENABLED(CONFIG_SYNC_FILE) /** - * kbase_fence_add_callback() - Add callback on @fence to block @katom - * @katom: Pointer to katom that will be blocked by @fence - * @fence: Pointer to fence on which to set up the callback - * @callback: Pointer to function to be called when fence is signaled + * kbase_fence_in_get() - Retrieve input fence for atom. + * @katom: Atom to get input fence from * - * Caller needs to hold a reference to @fence when calling this function, and - * the caller is responsible for releasing that reference. An additional - * reference to @fence will be taken when the callback was successfully set up - * and @fence needs to be kept valid until the callback has been called and - * cleanup have been done. + * A ref will be taken for the fence, so use @kbase_fence_put() to release it * - * Return: 0 on success: fence was either already signaled, or callback was - * set up. Negative error code is returned on error. + * Return: The fence, or NULL if there is no input fence for atom */ -#if (KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE) -int kbase_fence_add_callback(struct kbase_jd_atom *katom, - struct fence *fence, - fence_func_t callback); -#else -int kbase_fence_add_callback(struct kbase_jd_atom *katom, - struct dma_fence *fence, - dma_fence_func_t callback); +#define kbase_fence_in_get(katom) dma_fence_get((katom)->dma_fence.fence_in) #endif /** - * kbase_fence_dep_count_set() - Set dep_count value on atom to specified value - * @katom: Atom to set dep_count for - * @val: value to set dep_count to - * - * The dep_count is available to the users of this module so that they can - * synchronize completion of the wait with cancellation and adding of more - * callbacks. For instance, a user could do the following: + * kbase_fence_out_get() - Retrieve output fence for atom. + * @katom: Atom to get output fence from * - * dep_count set to 1 - * callback #1 added, dep_count is increased to 2 - * callback #1 happens, dep_count decremented to 1 - * since dep_count > 0, no completion is done - * callback #2 is added, dep_count is increased to 2 - * dep_count decremented to 1 - * callback #2 happens, dep_count decremented to 0 - * since dep_count now is zero, completion executes + * A ref will be taken for the fence, so use @kbase_fence_put() to release it * - * The dep_count can also be used to make sure that the completion only - * executes once. This is typically done by setting dep_count to -1 for the - * thread that takes on this responsibility. + * Return: The fence, or NULL if there is no output fence for atom */ -static inline void -kbase_fence_dep_count_set(struct kbase_jd_atom *katom, int val) -{ - atomic_set(&katom->dma_fence.dep_count, val); -} +#define kbase_fence_out_get(katom) dma_fence_get((katom)->dma_fence.fence) + +#endif /* !MALI_USE_CSF */ /** - * kbase_fence_dep_count_dec_and_test() - Decrements dep_count - * @katom: Atom to decrement dep_count for + * kbase_fence_get() - Retrieve fence for a KCPUQ fence command. + * @fence_info: KCPUQ fence command * - * See @kbase_fence_dep_count_set for general description about dep_count + * A ref will be taken for the fence, so use @kbase_fence_put() to release it * - * Return: true if value was decremented to zero, otherwise false + * Return: The fence, or NULL if there is no fence for KCPUQ fence command */ -static inline bool -kbase_fence_dep_count_dec_and_test(struct kbase_jd_atom *katom) +#define kbase_fence_get(fence_info) dma_fence_get((fence_info)->fence) + +#if MALI_USE_CSF +#if (KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE) +static inline struct kbase_kcpu_dma_fence *kbase_kcpu_dma_fence_get(struct fence *fence) +#else +static inline struct kbase_kcpu_dma_fence *kbase_kcpu_dma_fence_get(struct dma_fence *fence) +#endif { - return atomic_dec_and_test(&katom->dma_fence.dep_count); + if (fence->ops == &kbase_fence_ops) + return (struct kbase_kcpu_dma_fence *)fence; + + return NULL; } -/** - * kbase_fence_dep_count_read() - Returns the current dep_count value - * @katom: Pointer to katom - * - * See @kbase_fence_dep_count_set for general description about dep_count - * - * Return: The current dep_count value - */ -static inline int kbase_fence_dep_count_read(struct kbase_jd_atom *katom) +static inline void kbase_kcpu_dma_fence_meta_put(struct kbase_kcpu_dma_fence_meta *metadata) { - return atomic_read(&katom->dma_fence.dep_count); + if (kbase_refcount_dec_and_test(&metadata->refcount)) { + atomic_dec(&metadata->kbdev->live_fence_metadata); + kfree(metadata); + } } -/** - * kbase_fence_free_callbacks() - Free dma-fence callbacks on a katom - * @katom: Pointer to katom - * - * This function will free all fence callbacks on the katom's list of - * callbacks. Callbacks that have not yet been called, because their fence - * hasn't yet signaled, will first be removed from the fence. - * - * Locking: katom->dma_fence.callbacks list assumes jctx.lock is held. - * - * Return: true if dep_count reached 0, otherwise false. - */ -bool kbase_fence_free_callbacks(struct kbase_jd_atom *katom); - -#if defined(CONFIG_SYNC_FILE) -/** - * kbase_fence_in_get() - Retrieve input fence for atom. - * @katom: Atom to get input fence from - * - * A ref will be taken for the fence, so use @kbase_fence_put() to release it - * - * Return: The fence, or NULL if there is no input fence for atom - */ -#define kbase_fence_in_get(katom) dma_fence_get((katom)->dma_fence.fence_in) +#if (KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE) +static inline void kbase_kcpu_dma_fence_put(struct fence *fence) +#else +static inline void kbase_kcpu_dma_fence_put(struct dma_fence *fence) #endif +{ + struct kbase_kcpu_dma_fence *kcpu_fence = kbase_kcpu_dma_fence_get(fence); -/** - * kbase_fence_out_get() - Retrieve output fence for atom. - * @katom: Atom to get output fence from - * - * A ref will be taken for the fence, so use @kbase_fence_put() to release it - * - * Return: The fence, or NULL if there is no output fence for atom - */ -#define kbase_fence_out_get(katom) dma_fence_get((katom)->dma_fence.fence) - -#endif /* !MALI_USE_CSF */ + if (kcpu_fence) + kbase_kcpu_dma_fence_meta_put(kcpu_fence->metadata); +} +#endif /* MALI_USE_CSF */ /** * kbase_fence_put() - Releases a reference to a fence * @fence: Fence to release reference for. */ -#define kbase_fence_put(fence) dma_fence_put(fence) - +#if (KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE) +static inline void kbase_fence_put(struct fence *fence) +#else +static inline void kbase_fence_put(struct dma_fence *fence) +#endif +{ + dma_fence_put(fence); +} -#endif /* CONFIG_MALI_DMA_FENCE || defined(CONFIG_SYNC_FILE */ +#endif /* IS_ENABLED(CONFIG_SYNC_FILE) */ #endif /* _KBASE_FENCE_H_ */ |