| /* |
| * Copyright (C) 2012-2016 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 Foundation, and any use by you of this program is subject to the terms of such GNU licence. |
| * |
| * A copy of the licence is included with the program, and can also be obtained from Free Software |
| * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
| */ |
| |
| #include "mali_sync.h" |
| |
| #include "mali_osk.h" |
| #include "mali_kernel_common.h" |
| #include "mali_timeline.h" |
| #include "mali_executor.h" |
| |
| #include <linux/file.h> |
| #include <linux/seq_file.h> |
| #include <linux/module.h> |
| #include <asm-generic/fcntl.h> |
| |
| struct mali_sync_pt { |
| #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 6, 0) |
| struct sync_pt sync_pt; |
| #else |
| struct mali_internal_sync_point sync_pt; |
| #endif |
| struct mali_sync_flag *flag; |
| #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 6, 0) |
| struct sync_timeline *sync_tl; /**< Sync timeline this pt is connected to. */ |
| #else |
| struct mali_internal_sync_timeline *sync_tl; /**< Sync timeline this pt is connected to. */ |
| #endif |
| }; |
| |
| /** |
| * The sync flag is used to connect sync fences to the Mali Timeline system. Sync fences can be |
| * created from a sync flag, and when the flag is signaled, the sync fences will also be signaled. |
| */ |
| struct mali_sync_flag { |
| #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 6, 0) |
| struct sync_timeline *sync_tl; /**< Sync timeline this flag is connected to. */ |
| #else |
| struct mali_internal_sync_timeline *sync_tl; /**< Sync timeline this flag is connected to. */ |
| #endif |
| u32 point; /**< Point on timeline. */ |
| int status; /**< 0 if unsignaled, 1 if signaled without error or negative if signaled with error. */ |
| struct kref refcount; /**< Reference count. */ |
| }; |
| |
| /** |
| * Mali sync timeline is used to connect mali timeline to sync_timeline. |
| * When fence timeout can print more detailed mali timeline system info. |
| */ |
| struct mali_sync_timeline_container { |
| #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 6, 0) |
| struct sync_timeline sync_timeline; |
| #else |
| struct mali_internal_sync_timeline sync_timeline; |
| #endif |
| struct mali_timeline *timeline; |
| }; |
| |
| #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 6, 0) |
| MALI_STATIC_INLINE struct mali_sync_pt *to_mali_sync_pt(struct sync_pt *pt) |
| #else |
| MALI_STATIC_INLINE struct mali_sync_pt *to_mali_sync_pt(struct mali_internal_sync_point *pt) |
| #endif |
| { |
| return container_of(pt, struct mali_sync_pt, sync_pt); |
| } |
| |
| #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 6, 0) |
| MALI_STATIC_INLINE struct mali_sync_timeline_container *to_mali_sync_tl_container(struct sync_timeline *sync_tl) |
| #else |
| MALI_STATIC_INLINE struct mali_sync_timeline_container *to_mali_sync_tl_container(struct mali_internal_sync_timeline *sync_tl) |
| #endif |
| { |
| return container_of(sync_tl, struct mali_sync_timeline_container, sync_timeline); |
| } |
| |
| #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 6, 0) |
| static int timeline_has_signaled(struct sync_pt *pt) |
| #else |
| static int timeline_has_signaled(struct mali_internal_sync_point *pt) |
| #endif |
| { |
| struct mali_sync_pt *mpt; |
| |
| MALI_DEBUG_ASSERT_POINTER(pt); |
| mpt = to_mali_sync_pt(pt); |
| |
| MALI_DEBUG_ASSERT_POINTER(mpt->flag); |
| |
| return mpt->flag->status; |
| } |
| |
| #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 6, 0) |
| static void timeline_free_pt(struct sync_pt *pt) |
| #else |
| static void timeline_free_pt(struct mali_internal_sync_point *pt) |
| #endif |
| { |
| struct mali_sync_pt *mpt; |
| |
| MALI_DEBUG_ASSERT_POINTER(pt); |
| mpt = to_mali_sync_pt(pt); |
| |
| mali_sync_flag_put(mpt->flag); |
| } |
| |
| #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 6, 0) |
| static void timeline_release(struct sync_timeline *sync_timeline) |
| #else |
| static void timeline_release(struct mali_internal_sync_timeline *sync_timeline) |
| #endif |
| { |
| struct mali_sync_timeline_container *mali_sync_tl = NULL; |
| struct mali_timeline *mali_tl = NULL; |
| |
| MALI_DEBUG_ASSERT_POINTER(sync_timeline); |
| |
| mali_sync_tl = to_mali_sync_tl_container(sync_timeline); |
| MALI_DEBUG_ASSERT_POINTER(mali_sync_tl); |
| |
| mali_tl = mali_sync_tl->timeline; |
| |
| /* always signaled timeline didn't have mali container */ |
| if (mali_tl) { |
| if (NULL != mali_tl->spinlock) { |
| mali_spinlock_reentrant_term(mali_tl->spinlock); |
| } |
| _mali_osk_free(mali_tl); |
| } |
| |
| module_put(THIS_MODULE); |
| } |
| |
| #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 6, 0) |
| static struct sync_pt *timeline_dup(struct sync_pt *pt) |
| { |
| struct mali_sync_pt *mpt, *new_mpt; |
| struct sync_pt *new_pt; |
| MALI_DEBUG_ASSERT_POINTER(pt); |
| |
| mpt = to_mali_sync_pt(pt); |
| |
| new_pt = sync_pt_create(mpt->sync_tl, sizeof(struct mali_sync_pt)); |
| if (NULL == new_pt) return NULL; |
| |
| new_mpt = to_mali_sync_pt(new_pt); |
| |
| mali_sync_flag_get(mpt->flag); |
| new_mpt->flag = mpt->flag; |
| new_mpt->sync_tl = mpt->sync_tl; |
| |
| return new_pt; |
| } |
| |
| static int timeline_compare(struct sync_pt *pta, struct sync_pt *ptb) |
| { |
| struct mali_sync_pt *mpta; |
| struct mali_sync_pt *mptb; |
| u32 a, b; |
| |
| MALI_DEBUG_ASSERT_POINTER(pta); |
| MALI_DEBUG_ASSERT_POINTER(ptb); |
| mpta = to_mali_sync_pt(pta); |
| mptb = to_mali_sync_pt(ptb); |
| |
| MALI_DEBUG_ASSERT_POINTER(mpta->flag); |
| MALI_DEBUG_ASSERT_POINTER(mptb->flag); |
| |
| a = mpta->flag->point; |
| b = mptb->flag->point; |
| |
| if (a == b) return 0; |
| |
| return ((b - a) < (a - b) ? -1 : 1); |
| } |
| #endif |
| |
| #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0) |
| static void timeline_print_pt(struct seq_file *s, struct sync_pt *sync_pt) |
| { |
| struct mali_sync_pt *mpt; |
| |
| MALI_DEBUG_ASSERT_POINTER(s); |
| MALI_DEBUG_ASSERT_POINTER(sync_pt); |
| |
| mpt = to_mali_sync_pt(sync_pt); |
| |
| /* It is possible this sync point is just under construct, |
| * make sure the flag is valid before accessing it |
| */ |
| if (mpt->flag) { |
| seq_printf(s, "%u", mpt->flag->point); |
| } else { |
| seq_printf(s, "uninitialized"); |
| } |
| } |
| |
| static void timeline_print_obj(struct seq_file *s, struct sync_timeline *sync_tl) |
| { |
| struct mali_sync_timeline_container *mali_sync_tl = NULL; |
| struct mali_timeline *mali_tl = NULL; |
| |
| MALI_DEBUG_ASSERT_POINTER(sync_tl); |
| |
| mali_sync_tl = to_mali_sync_tl_container(sync_tl); |
| MALI_DEBUG_ASSERT_POINTER(mali_sync_tl); |
| |
| mali_tl = mali_sync_tl->timeline; |
| |
| if (NULL != mali_tl) { |
| seq_printf(s, "oldest (%u) ", mali_tl->point_oldest); |
| seq_printf(s, "next (%u)", mali_tl->point_next); |
| seq_printf(s, "\n"); |
| |
| #if defined(MALI_TIMELINE_DEBUG_FUNCTIONS) |
| { |
| u32 tid = _mali_osk_get_tid(); |
| struct mali_timeline_system *system = mali_tl->system; |
| |
| mali_spinlock_reentrant_wait(mali_tl->spinlock, tid); |
| if (!mali_tl->destroyed) { |
| mali_spinlock_reentrant_wait(system->spinlock, tid); |
| mali_timeline_debug_print_timeline(mali_tl, s); |
| mali_spinlock_reentrant_signal(system->spinlock, tid); |
| } |
| mali_spinlock_reentrant_signal(mali_tl->spinlock, tid); |
| |
| /* dump job queue status and group running status */ |
| mali_executor_status_dump(); |
| } |
| #endif |
| } |
| } |
| #elif LINUX_VERSION_CODE < KERNEL_VERSION(4, 6, 0) |
| static void timeline_pt_value_str(struct sync_pt *pt, char *str, int size) |
| { |
| struct mali_sync_pt *mpt; |
| |
| MALI_DEBUG_ASSERT_POINTER(str); |
| MALI_DEBUG_ASSERT_POINTER(pt); |
| |
| mpt = to_mali_sync_pt(pt); |
| |
| /* It is possible this sync point is just under construct, |
| * make sure the flag is valid before accessing it |
| */ |
| if (mpt->flag) { |
| _mali_osk_snprintf(str, size, "%u", mpt->flag->point); |
| } else { |
| _mali_osk_snprintf(str, size, "uninitialized"); |
| } |
| } |
| |
| static void timeline_value_str(struct sync_timeline *timeline, char *str, int size) |
| { |
| struct mali_sync_timeline_container *mali_sync_tl = NULL; |
| struct mali_timeline *mali_tl = NULL; |
| |
| MALI_DEBUG_ASSERT_POINTER(timeline); |
| |
| mali_sync_tl = to_mali_sync_tl_container(timeline); |
| MALI_DEBUG_ASSERT_POINTER(mali_sync_tl); |
| |
| mali_tl = mali_sync_tl->timeline; |
| |
| if (NULL != mali_tl) { |
| _mali_osk_snprintf(str, size, "oldest (%u) ", mali_tl->point_oldest); |
| _mali_osk_snprintf(str, size, "next (%u)", mali_tl->point_next); |
| _mali_osk_snprintf(str, size, "\n"); |
| |
| #if defined(MALI_TIMELINE_DEBUG_FUNCTIONS) |
| { |
| u32 tid = _mali_osk_get_tid(); |
| struct mali_timeline_system *system = mali_tl->system; |
| |
| mali_spinlock_reentrant_wait(mali_tl->spinlock, tid); |
| if (!mali_tl->destroyed) { |
| mali_spinlock_reentrant_wait(system->spinlock, tid); |
| mali_timeline_debug_direct_print_timeline(mali_tl); |
| mali_spinlock_reentrant_signal(system->spinlock, tid); |
| } |
| mali_spinlock_reentrant_signal(mali_tl->spinlock, tid); |
| |
| /* dump job queue status and group running status */ |
| mali_executor_status_dump(); |
| } |
| #endif |
| } |
| } |
| #else |
| static void timeline_print_sync_pt(struct mali_internal_sync_point *sync_pt) |
| { |
| struct mali_sync_pt *mpt; |
| |
| MALI_DEBUG_ASSERT_POINTER(sync_pt); |
| |
| mpt = to_mali_sync_pt(sync_pt); |
| |
| if (mpt->flag) { |
| MALI_DEBUG_PRINT(2, ("mali_internal_sync_pt: %u\n", mpt->flag->point)); |
| } else { |
| MALI_DEBUG_PRINT(2, ("uninitialized\n", mpt->flag->point)); |
| } |
| } |
| #endif |
| |
| #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 6, 0) |
| static struct sync_timeline_ops mali_timeline_ops = { |
| .driver_name = "Mali", |
| .dup = timeline_dup, |
| .has_signaled = timeline_has_signaled, |
| .compare = timeline_compare, |
| .free_pt = timeline_free_pt, |
| .release_obj = timeline_release, |
| #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0) |
| .print_pt = timeline_print_pt, |
| .print_obj = timeline_print_obj, |
| #else |
| .pt_value_str = timeline_pt_value_str, |
| .timeline_value_str = timeline_value_str, |
| #endif |
| }; |
| |
| struct sync_timeline *mali_sync_timeline_create(struct mali_timeline *timeline, const char *name) |
| { |
| struct sync_timeline *sync_tl; |
| struct mali_sync_timeline_container *mali_sync_tl; |
| |
| sync_tl = sync_timeline_create(&mali_timeline_ops, sizeof(struct mali_sync_timeline_container), name); |
| if (NULL == sync_tl) return NULL; |
| |
| mali_sync_tl = to_mali_sync_tl_container(sync_tl); |
| mali_sync_tl->timeline = timeline; |
| |
| /* Grab a reference on the module to ensure the callbacks are present |
| * as long some timeline exists. The reference is released when the |
| * timeline is freed. |
| * Since this function is called from a ioctl on an open file we know |
| * we already have a reference, so using __module_get is safe. */ |
| __module_get(THIS_MODULE); |
| |
| return sync_tl; |
| } |
| |
| s32 mali_sync_fence_fd_alloc(struct sync_fence *sync_fence) |
| { |
| s32 fd = -1; |
| |
| #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 19, 0) |
| fd = get_unused_fd(); |
| #else |
| fd = get_unused_fd_flags(O_CLOEXEC); |
| #endif |
| |
| if (fd < 0) { |
| sync_fence_put(sync_fence); |
| return -1; |
| } |
| sync_fence_install(sync_fence, fd); |
| |
| return fd; |
| } |
| |
| struct sync_fence *mali_sync_fence_merge(struct sync_fence *sync_fence1, struct sync_fence *sync_fence2) |
| { |
| struct sync_fence *sync_fence; |
| |
| MALI_DEBUG_ASSERT_POINTER(sync_fence1); |
| MALI_DEBUG_ASSERT_POINTER(sync_fence1); |
| |
| sync_fence = sync_fence_merge("mali_merge_fence", sync_fence1, sync_fence2); |
| sync_fence_put(sync_fence1); |
| sync_fence_put(sync_fence2); |
| |
| return sync_fence; |
| } |
| |
| struct sync_fence *mali_sync_timeline_create_signaled_fence(struct sync_timeline *sync_tl) |
| { |
| struct mali_sync_flag *flag; |
| struct sync_fence *sync_fence; |
| |
| MALI_DEBUG_ASSERT_POINTER(sync_tl); |
| |
| flag = mali_sync_flag_create(sync_tl, 0); |
| if (NULL == flag) return NULL; |
| |
| sync_fence = mali_sync_flag_create_fence(flag); |
| |
| mali_sync_flag_signal(flag, 0); |
| mali_sync_flag_put(flag); |
| |
| return sync_fence; |
| } |
| |
| struct mali_sync_flag *mali_sync_flag_create(struct sync_timeline *sync_tl, mali_timeline_point point) |
| { |
| struct mali_sync_flag *flag; |
| |
| if (NULL == sync_tl) return NULL; |
| |
| flag = _mali_osk_calloc(1, sizeof(*flag)); |
| if (NULL == flag) return NULL; |
| |
| flag->sync_tl = sync_tl; |
| flag->point = point; |
| |
| flag->status = 0; |
| kref_init(&flag->refcount); |
| |
| return flag; |
| } |
| |
| /** |
| * Create a sync point attached to given sync flag. |
| * |
| * @note Sync points must be triggered in *exactly* the same order as they are created. |
| * |
| * @param flag Sync flag. |
| * @return New sync point if successful, NULL if not. |
| */ |
| static struct sync_pt *mali_sync_flag_create_pt(struct mali_sync_flag *flag) |
| { |
| struct sync_pt *pt; |
| struct mali_sync_pt *mpt; |
| |
| MALI_DEBUG_ASSERT_POINTER(flag); |
| MALI_DEBUG_ASSERT_POINTER(flag->sync_tl); |
| |
| pt = sync_pt_create(flag->sync_tl, sizeof(struct mali_sync_pt)); |
| if (NULL == pt) return NULL; |
| |
| mali_sync_flag_get(flag); |
| |
| mpt = to_mali_sync_pt(pt); |
| mpt->flag = flag; |
| mpt->sync_tl = flag->sync_tl; |
| |
| return pt; |
| } |
| |
| struct sync_fence *mali_sync_flag_create_fence(struct mali_sync_flag *flag) |
| { |
| struct sync_pt *sync_pt; |
| struct sync_fence *sync_fence; |
| |
| MALI_DEBUG_ASSERT_POINTER(flag); |
| MALI_DEBUG_ASSERT_POINTER(flag->sync_tl); |
| |
| sync_pt = mali_sync_flag_create_pt(flag); |
| if (NULL == sync_pt) return NULL; |
| |
| sync_fence = sync_fence_create("mali_flag_fence", sync_pt); |
| if (NULL == sync_fence) { |
| sync_pt_free(sync_pt); |
| return NULL; |
| } |
| |
| return sync_fence; |
| } |
| #else |
| static struct mali_internal_sync_timeline_ops mali_timeline_ops = { |
| .driver_name = "Mali", |
| .has_signaled = timeline_has_signaled, |
| .free_pt = timeline_free_pt, |
| .release_obj = timeline_release, |
| .print_sync_pt = timeline_print_sync_pt, |
| }; |
| |
| struct mali_internal_sync_timeline *mali_sync_timeline_create(struct mali_timeline *timeline, const char *name) |
| { |
| struct mali_internal_sync_timeline *sync_tl; |
| struct mali_sync_timeline_container *mali_sync_tl; |
| |
| sync_tl = mali_internal_sync_timeline_create(&mali_timeline_ops, sizeof(struct mali_sync_timeline_container), name); |
| if (NULL == sync_tl) return NULL; |
| |
| mali_sync_tl = to_mali_sync_tl_container(sync_tl); |
| mali_sync_tl->timeline = timeline; |
| |
| /* Grab a reference on the module to ensure the callbacks are present |
| * as long some timeline exists. The reference is released when the |
| * timeline is freed. |
| * Since this function is called from a ioctl on an open file we know |
| * we already have a reference, so using __module_get is safe. */ |
| __module_get(THIS_MODULE); |
| |
| return sync_tl; |
| } |
| |
| s32 mali_sync_fence_fd_alloc(struct mali_internal_sync_fence *sync_fence) |
| { |
| s32 fd = -1; |
| |
| fd = get_unused_fd_flags(0); |
| |
| if (fd < 0) { |
| fput(sync_fence->file); |
| return -1; |
| } |
| fd_install(fd, sync_fence->file); |
| return fd; |
| } |
| |
| struct mali_internal_sync_fence *mali_sync_fence_merge(struct mali_internal_sync_fence *sync_fence1, struct mali_internal_sync_fence *sync_fence2) |
| { |
| struct mali_internal_sync_fence *sync_fence; |
| |
| MALI_DEBUG_ASSERT_POINTER(sync_fence1); |
| MALI_DEBUG_ASSERT_POINTER(sync_fence1); |
| |
| sync_fence = mali_internal_sync_fence_merge(sync_fence1, sync_fence2); |
| fput(sync_fence1->file); |
| fput(sync_fence2->file); |
| |
| return sync_fence; |
| } |
| |
| struct mali_internal_sync_fence *mali_sync_timeline_create_signaled_fence(struct mali_internal_sync_timeline *sync_tl) |
| { |
| struct mali_sync_flag *flag; |
| struct mali_internal_sync_fence *sync_fence; |
| |
| MALI_DEBUG_ASSERT_POINTER(sync_tl); |
| |
| flag = mali_sync_flag_create(sync_tl, 0); |
| if (NULL == flag) return NULL; |
| |
| sync_fence = mali_sync_flag_create_fence(flag); |
| |
| mali_sync_flag_signal(flag, 0); |
| mali_sync_flag_put(flag); |
| |
| return sync_fence; |
| } |
| |
| struct mali_sync_flag *mali_sync_flag_create(struct mali_internal_sync_timeline *sync_tl, mali_timeline_point point) |
| { |
| struct mali_sync_flag *flag; |
| |
| if (NULL == sync_tl) return NULL; |
| |
| flag = _mali_osk_calloc(1, sizeof(*flag)); |
| if (NULL == flag) return NULL; |
| |
| flag->sync_tl = sync_tl; |
| flag->point = point; |
| |
| flag->status = 0; |
| kref_init(&flag->refcount); |
| |
| return flag; |
| } |
| |
| /** |
| * Create a sync point attached to given sync flag. |
| * |
| * @note Sync points must be triggered in *exactly* the same order as they are created. |
| * |
| * @param flag Sync flag. |
| * @return New sync point if successful, NULL if not. |
| */ |
| static struct mali_internal_sync_point *mali_sync_flag_create_pt(struct mali_sync_flag *flag) |
| { |
| struct mali_internal_sync_point *pt; |
| struct mali_sync_pt *mpt; |
| |
| MALI_DEBUG_ASSERT_POINTER(flag); |
| MALI_DEBUG_ASSERT_POINTER(flag->sync_tl); |
| |
| pt = mali_internal_sync_point_create(flag->sync_tl, sizeof(struct mali_sync_pt)); |
| |
| if (pt == NULL) { |
| MALI_PRINT_ERROR(("Mali sync: sync_pt creation failed\n")); |
| return NULL; |
| } |
| mali_sync_flag_get(flag); |
| |
| mpt = to_mali_sync_pt(pt); |
| mpt->flag = flag; |
| mpt->sync_tl = flag->sync_tl; |
| |
| return pt; |
| } |
| |
| struct mali_internal_sync_fence *mali_sync_flag_create_fence(struct mali_sync_flag *flag) |
| { |
| struct mali_internal_sync_point *sync_pt; |
| struct mali_internal_sync_fence *sync_fence; |
| |
| MALI_DEBUG_ASSERT_POINTER(flag); |
| MALI_DEBUG_ASSERT_POINTER(flag->sync_tl); |
| |
| sync_pt = mali_sync_flag_create_pt(flag); |
| if (NULL == sync_pt) { |
| MALI_PRINT_ERROR(("Mali sync: sync_pt creation failed\n")); |
| return NULL; |
| } |
| sync_fence = (struct mali_internal_sync_fence *)sync_file_create(&sync_pt->base); |
| if (NULL == sync_fence) { |
| MALI_PRINT_ERROR(("Mali sync: sync_fence creation failed\n")); |
| #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0) |
| dma_fence_put(&sync_pt->base); |
| #else |
| fence_put(&sync_pt->base); |
| #endif |
| return NULL; |
| } |
| |
| #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0) |
| fence_put(&sync_pt->base); |
| #else |
| dma_fence_put(&sync_pt->base); |
| #endif |
| |
| return sync_fence; |
| } |
| #endif |
| |
| void mali_sync_flag_get(struct mali_sync_flag *flag) |
| { |
| MALI_DEBUG_ASSERT_POINTER(flag); |
| kref_get(&flag->refcount); |
| } |
| |
| /** |
| * Free sync flag. |
| * |
| * @param ref kref object embedded in sync flag that should be freed. |
| */ |
| static void mali_sync_flag_free(struct kref *ref) |
| { |
| struct mali_sync_flag *flag; |
| |
| MALI_DEBUG_ASSERT_POINTER(ref); |
| flag = container_of(ref, struct mali_sync_flag, refcount); |
| |
| _mali_osk_free(flag); |
| } |
| |
| void mali_sync_flag_put(struct mali_sync_flag *flag) |
| { |
| MALI_DEBUG_ASSERT_POINTER(flag); |
| kref_put(&flag->refcount, mali_sync_flag_free); |
| } |
| |
| void mali_sync_flag_signal(struct mali_sync_flag *flag, int error) |
| { |
| MALI_DEBUG_ASSERT_POINTER(flag); |
| |
| MALI_DEBUG_ASSERT(0 == flag->status); |
| flag->status = (0 > error) ? error : 1; |
| |
| _mali_osk_write_mem_barrier(); |
| #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 6, 0) |
| sync_timeline_signal(flag->sync_tl); |
| #else |
| mali_internal_sync_timeline_signal(flag->sync_tl); |
| #endif |
| } |
| |
| |