From 03173f7cc81b11d359203f7ece6f3e41e7b91dc7 Mon Sep 17 00:00:00 2001 From: Narendra Muppalla Date: Wed, 30 Mar 2022 12:14:59 -0700 Subject: [PATCH 1/2] mm-drivers: sync-fence: add changes to serialize fence operations This change acquires fence_lock to serialize the enable_sw signalling operation on dma_fence_array. It bails out safely if the bind operation is called twice on the spec fence. The error level for bind failure with invalid user fd is changed to warning as this case can be treated non fatal. Change-Id: I688cbc84ba3cfb49c54de9b5e1bf8a9ec9d8da3a Signed-off-by: Narendra Muppalla --- sync_fence/src/qcom_sync_file.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/sync_fence/src/qcom_sync_file.c b/sync_fence/src/qcom_sync_file.c index 3cb2178412..3c006cc35b 100644 --- a/sync_fence/src/qcom_sync_file.c +++ b/sync_fence/src/qcom_sync_file.c @@ -276,6 +276,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 +305,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,6 +322,7 @@ 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); @@ -327,6 +336,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); } From 7deaa672388e7433d849acca267e517fbc8f69d6 Mon Sep 17 00:00:00 2001 From: Ingrid Gallardo Date: Fri, 4 Feb 2022 14:14:18 -0800 Subject: [PATCH 2/2] mm-drivers: sync: add api to wait for sync fence bind This change adds an api to check if a given speculative fence is bound. If fence is not bound, it will wait for the speculative fence ioctl to bind the fence, or else timeout. Change-Id: I9a86d09df410e89137264be47763ae39f06eea2b Signed-off-by: Ingrid Gallardo --- config/kalamammdrivers.conf | 1 + config/kalamammdriversconf.h | 1 + sync_fence/Kbuild | 2 ++ sync_fence/src/qcom_sync_file.c | 35 ++++++++++++++++++++++++++++++++- 4 files changed, 38 insertions(+), 1 deletion(-) 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 3c006cc35b..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; @@ -328,6 +357,9 @@ static int spec_sync_bind_array(struct fence_bind_data *sync_bind_info) 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]); @@ -434,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;