diff --git a/config/kalamammdrivers.conf b/config/kalamammdrivers.conf index 3df22e75d5..4f932958dd 100644 --- a/config/kalamammdrivers.conf +++ b/config/kalamammdrivers.conf @@ -3,3 +3,4 @@ # Copyright (c) 2020, The Linux Foundation. All rights reserved. export CONFIG_MSM_EXT_DISPLAY=y +export CONFIG_QCOM_SPEC_SYNC=y diff --git a/config/kalamammdriversconf.h b/config/kalamammdriversconf.h index 26ca25d02f..59c3a05b66 100644 --- a/config/kalamammdriversconf.h +++ b/config/kalamammdriversconf.h @@ -5,3 +5,4 @@ */ #define CONFIG_MSM_EXT_DISPLAY 1 +#define CONFIG_QCOM_SPEC_SYNC 1 diff --git a/sync_fence/Kbuild b/sync_fence/Kbuild index 48cb10624b..b91ec8c93c 100644 --- a/sync_fence/Kbuild +++ b/sync_fence/Kbuild @@ -3,8 +3,10 @@ KDIR := $(TOP)/kernel_platform/msm-kernel LINUXINCLUDE += -I$(SYNC_FENCE_ROOT)sync_fence/include/ +ifdef CONFIG_QCOM_SPEC_SYNC obj-m += sync_fence.o sync_fence-y := src/qcom_sync_file.o CDEFINES += -DBUILD_TIMESTAMP=\"$(shell date -u +'%Y-%m-%dT%H:%M:%SZ')\" +endif diff --git a/sync_fence/src/qcom_sync_file.c b/sync_fence/src/qcom_sync_file.c index 3cb2178412..b3ecf4eb1f 100644 --- a/sync_fence/src/qcom_sync_file.c +++ b/sync_fence/src/qcom_sync_file.c @@ -20,13 +20,13 @@ #include #include #include +#include #define CLASS_NAME "sync" #define DRV_NAME "spec_sync" #define DRV_VERSION 1 #define NAME_LEN 32 -#define SPEC_FENCE_FLAG_FENCE_ARRAY 0x10 /* user flags for debug */ #define FENCE_MIN 1 #define FENCE_MAX 32 @@ -44,6 +44,7 @@ struct sync_device { uint32_t version; struct mutex l_lock; struct list_head fence_array_list; + wait_queue_head_t wait_queue; }; struct fence_array_node { @@ -254,6 +255,34 @@ static int spec_sync_ioctl_create_fence(struct sync_device *obj, unsigned long _ return 0; } +int spec_sync_wait_bind_array(struct dma_fence_array *fence_array, u32 timeout_ms) +{ + int ret; + + /* Check if fence-array is a speculative fence */ + if (!fence_array || !test_bit(SPEC_FENCE_FLAG_FENCE_ARRAY, &fence_array->base.flags)) { + pr_err("invalid fence!\n"); + return -EINVAL; + } else if (test_bit(SPEC_FENCE_FLAG_FENCE_ARRAY_BOUND, &fence_array->base.flags)) { + /* This fence-array is already bound, just return success */ + return 0; + } + + /* Wait for the fence-array bind */ + ret = wait_event_timeout(sync_dev.wait_queue, + test_bit(SPEC_FENCE_FLAG_FENCE_ARRAY_BOUND, &fence_array->base.flags), + msecs_to_jiffies(timeout_ms)); + if (!ret) { + pr_err("timed out waiting for bind fence-array %d\n", timeout_ms); + ret = -ETIMEDOUT; + } else { + ret = 0; + } + + return ret; +} +EXPORT_SYMBOL(spec_sync_wait_bind_array); + static int spec_sync_bind_array(struct fence_bind_data *sync_bind_info) { struct dma_fence_array *fence_array; @@ -276,6 +305,13 @@ static int spec_sync_bind_array(struct fence_bind_data *sync_bind_info) ret = -EINVAL; goto end; } + + if (fence_array->fences) { + pr_err("fence array already populated, spec fd:%d status:%d flags:0x%x\n", + sync_bind_info->out_bind_fd, dma_fence_get_status(fence), fence->flags); + goto end; + } + num_fences = fence_array->num_fences; counter = num_fences; @@ -298,11 +334,12 @@ static int spec_sync_bind_array(struct fence_bind_data *sync_bind_info) goto out; } + spin_lock(fence->lock); fence_array->fences = fence_list; for (i = 0; i < num_fences; i++) { user_fence = sync_file_get_fence(user_fds[i]); if (!user_fence) { - pr_err("bind fences are invalid !! user_fd:%d out_bind_fd:%d\n", + pr_warn("bind fences are invalid !! user_fd:%d out_bind_fd:%d\n", user_fds[i], sync_bind_info->out_bind_fd); counter = i; ret = -EINVAL; @@ -314,11 +351,15 @@ static int spec_sync_bind_array(struct fence_bind_data *sync_bind_info) } clear_bit(DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT, &fence->flags); + spin_unlock(fence->lock); dma_fence_enable_sw_signaling(&fence_array->base); clear_fence_array_tracker(false); bind_invalid: + set_bit(SPEC_FENCE_FLAG_FENCE_ARRAY_BOUND, &fence_array->base.flags); + wake_up_all(&sync_dev.wait_queue); + if (ret) { for (i = counter - 1; i >= 0; i--) dma_fence_put(fence_array->fences[i]); @@ -327,6 +368,7 @@ bind_invalid: fence_array->fences = NULL; fence_array->num_fences = 0; dma_fence_set_error(fence, -EINVAL); + spin_unlock(fence->lock); dma_fence_signal(fence); clear_fence_array_tracker(false); } @@ -424,6 +466,7 @@ static int spec_sync_register_device(void) mutex_init(&sync_dev.lock); mutex_init(&sync_dev.l_lock); INIT_LIST_HEAD(&sync_dev.fence_array_list); + init_waitqueue_head(&sync_dev.wait_queue); return 0;