From f22f48c91fb57e8bee4a48cb8d21d095767838b9 Mon Sep 17 00:00:00 2001 From: Petar Nedev Date: Fri, 7 Oct 2022 08:06:30 -0700 Subject: [PATCH] msm: camera: sync: Add support for synx objects Add support to create, release, signal and import a synx object using the existing generic fence operations. Handle signaling of underlying synx object when a sync object is signaled & vice versa. CRs-Fixed: 3317280 Change-Id: Ia6fac6eb732ed7091ec62f04875bdb30d88c8676 Signed-off-by: Petar Nedev --- Kbuild | 2 + drivers/cam_sync/cam_sync.c | 793 +++++++++++++++++++++++++++- drivers/cam_sync/cam_sync_private.h | 22 +- drivers/cam_sync/cam_sync_synx.c | 638 ++++++++++++++++++++++ drivers/cam_sync/cam_sync_synx.h | 157 ++++++ drivers/cam_sync/cam_sync_util.c | 16 +- drivers/cam_sync/cam_sync_util.h | 28 +- drivers/cam_utils/cam_debug_util.h | 5 +- 8 files changed, 1629 insertions(+), 32 deletions(-) create mode 100644 drivers/cam_sync/cam_sync_synx.c create mode 100644 drivers/cam_sync/cam_sync_synx.h diff --git a/Kbuild b/Kbuild index cc173ea5bb..6043d135ff 100644 --- a/Kbuild +++ b/Kbuild @@ -72,6 +72,7 @@ LINUXINCLUDE += \ -I$(CAMERA_KERNEL_ROOT)/ # Optional include directories ccflags-$(CONFIG_MSM_GLOBAL_SYNX) += -I$(KERNEL_ROOT)/drivers/media/platform/msm/synx +ccflags-$(CONFIG_MSM_GLOBAL_SYNX_V2) += -I$(KERNEL_ROOT)/drivers/media/platform/msm/synx # After creating lists, add content of 'ccflags-m' variable to 'ccflags-y' one. ccflags-y += ${ccflags-m} @@ -120,6 +121,7 @@ else ccflags-y += -DCONFIG_CAM_PRESIL=1 endif +camera-$(CONFIG_MSM_GLOBAL_SYNX_V2) += drivers/cam_sync/cam_sync_synx.o camera-$(CONFIG_QCOM_CX_IPEAK) += drivers/cam_utils/cam_cx_ipeak.o camera-$(CONFIG_QCOM_BUS_SCALING) += drivers/cam_utils/cam_soc_bus.o camera-$(CONFIG_INTERCONNECT_QCOM) += drivers/cam_utils/cam_soc_icc.o diff --git a/drivers/cam_sync/cam_sync.c b/drivers/cam_sync/cam_sync.c index 71ede7b16a..e35c68bf10 100644 --- a/drivers/cam_sync/cam_sync.c +++ b/drivers/cam_sync/cam_sync.c @@ -10,7 +10,7 @@ #include #include #include -#if IS_REACHABLE(CONFIG_MSM_GLOBAL_SYNX) +#if IS_REACHABLE(CONFIG_MSM_GLOBAL_SYNX) || IS_REACHABLE(CONFIG_MSM_GLOBAL_SYNX_V2) #include #endif #include "cam_sync_util.h" @@ -49,7 +49,8 @@ static void cam_sync_print_fence_table(void) static int cam_sync_create_util( int32_t *sync_obj, const char *name, - struct cam_dma_fence_create_sync_obj_payload *dma_sync_create_info) + struct cam_dma_fence_create_sync_obj_payload *dma_sync_create_info, + struct sync_synx_obj_info *synx_obj_sync_create_info) { int rc; long idx; @@ -84,6 +85,21 @@ static int cam_sync_create_util( *sync_obj = idx; + /* Associate sync obj with synx if any holding sync lock */ + if (synx_obj_sync_create_info) { + row = sync_dev->sync_table + idx; + row->synx_obj_info.synx_obj_row_idx = + synx_obj_sync_create_info->synx_obj_row_idx; + row->synx_obj_info.sync_created_with_synx = + synx_obj_sync_create_info->sync_created_with_synx; + row->synx_obj_info.synx_obj = synx_obj_sync_create_info->synx_obj; + + set_bit(CAM_GENERIC_FENCE_TYPE_SYNX_OBJ, &row->ext_fence_mask); + + CAM_DBG(CAM_SYNC, "sync_obj: %s[%d] associated with synx_obj: %d", + name, *sync_obj, row->synx_obj_info.synx_obj); + } + /* Associate sync obj with dma fence if any holding sync lock */ if (dma_sync_create_info) { row = sync_dev->sync_table + idx; @@ -119,7 +135,7 @@ end: int cam_sync_create(int32_t *sync_obj, const char *name) { - return cam_sync_create_util(sync_obj, name, NULL); + return cam_sync_create_util(sync_obj, name, NULL, NULL); } int cam_sync_register_callback(sync_callback cb_func, @@ -341,6 +357,9 @@ int cam_sync_signal(int32_t sync_obj, uint32_t status, uint32_t event_cause) struct sync_table_row *row = NULL; struct list_head parents_list; int rc = 0; +#if IS_REACHABLE(CONFIG_MSM_GLOBAL_SYNX_V2) + struct cam_synx_obj_signal signal_synx_obj; +#endif if (sync_obj >= CAM_SYNC_MAX_OBJS || sync_obj <= 0) { CAM_ERR(CAM_SYNC, "Error: Out of range sync obj (0 <= %d < %d)", @@ -378,6 +397,22 @@ int cam_sync_signal(int32_t sync_obj, uint32_t status, uint32_t event_cause) row->dma_fence_info.dma_fence_fd, row->name, sync_obj); } +#if IS_REACHABLE(CONFIG_MSM_GLOBAL_SYNX_V2) + /* + * Signal associated synx obj + */ + if (test_bit(CAM_GENERIC_FENCE_TYPE_SYNX_OBJ, &row->ext_fence_mask)) { + signal_synx_obj.status = status; + signal_synx_obj.synx_obj = row->synx_obj_info.synx_obj; + rc = cam_synx_obj_internal_signal( + row->synx_obj_info.synx_obj_row_idx, &signal_synx_obj); + if (rc) + CAM_ERR(CAM_SYNC, + "Error: Failed to signal associated synx obj = %d for sync_obj = %s[%d]", + row->synx_obj_info.synx_obj, row->name, sync_obj); + } +#endif + cam_sync_util_dispatch_signaled_cb(sync_obj, status, event_cause); /* copy parent list to local and release child lock */ @@ -492,7 +527,7 @@ int cam_sync_put_obj_ref(int32_t sync_obj) int cam_sync_destroy(int32_t sync_obj) { - return cam_sync_deinit_object(sync_dev->sync_table, sync_obj, NULL); + return cam_sync_deinit_object(sync_dev->sync_table, sync_obj, NULL, NULL); } int cam_sync_check_valid(int32_t sync_obj) @@ -939,6 +974,87 @@ end: return rc; } +#if IS_REACHABLE(CONFIG_MSM_GLOBAL_SYNX_V2) +static int cam_sync_synx_obj_cb(int32_t sync_obj, + struct cam_synx_obj_signal_sync_obj *signal_sync_obj) +{ + int32_t rc = 0; + struct sync_table_row *row = NULL; + struct list_head parents_list; + + if (!signal_sync_obj) { + CAM_ERR(CAM_SYNC, "Invalid signal info args"); + return -EINVAL; + } + + /* Validate sync object range */ + if (!(sync_obj > 0 && sync_obj < CAM_SYNC_MAX_OBJS)) { + CAM_ERR(CAM_SYNC, "Invalid sync obj: %d", sync_obj); + return -EINVAL; + } + + spin_lock_bh(&sync_dev->row_spinlocks[sync_obj]); + row = sync_dev->sync_table + sync_obj; + + /* Validate if sync obj has a synx obj association */ + if (!test_bit(CAM_GENERIC_FENCE_TYPE_SYNX_OBJ, &row->ext_fence_mask)) { + CAM_ERR(CAM_SYNC, + "sync obj = %d[%s] has no associated synx obj ext_fence_mask = 0x%x", + sync_obj, row->name, row->ext_fence_mask); + rc = -EINVAL; + goto end; + } + + /* Validate if we are signaling the right sync obj based on synx handle */ + if (row->synx_obj_info.synx_obj != signal_sync_obj->synx_obj) { + CAM_ERR(CAM_SYNC, + "sync obj: %d[%s] is associated with a different synx obj: %d, signaling for synx obj: %d", + sync_obj, row->name, row->synx_obj_info.synx_obj, + signal_sync_obj->synx_obj); + rc = -EINVAL; + goto end; + } + + rc = cam_sync_signal_validate_util(sync_obj, signal_sync_obj->status); + if (rc) { + CAM_ERR(CAM_SYNC, + "Error: Failed to validate signal info for sync_obj = %d[%s] with status = %d rc = %d", + sync_obj, row->name, signal_sync_obj->status, rc); + goto end; + } + + /* Adding synx reference on sync */ + atomic_inc(&row->ref_cnt); + if (!atomic_dec_and_test(&row->ref_cnt)) { + CAM_DBG(CAM_SYNC, "Sync = %d[%s] fence still has references, synx_hdl = %d", + sync_obj, row->name, signal_sync_obj->synx_obj); + goto end; + } + + row->state = signal_sync_obj->status; + + cam_sync_util_dispatch_signaled_cb(sync_obj, signal_sync_obj->status, 0); + + INIT_LIST_HEAD(&parents_list); + list_splice_init(&row->parents_list, &parents_list); + spin_unlock_bh(&sync_dev->row_spinlocks[sync_obj]); + + if (list_empty(&parents_list)) + return 0; + + cam_sync_signal_parent_util(signal_sync_obj->status, 0x0, &parents_list); + CAM_DBG(CAM_SYNC, + "Successfully signaled sync obj = %d with status = %d via synx obj = %d signal callback", + sync_obj, signal_sync_obj->status, signal_sync_obj->synx_obj); + + return 0; + +end: + spin_unlock_bh(&sync_dev->row_spinlocks[sync_obj]); + return rc; +} +#endif + static int cam_generic_fence_alloc_validate_input_info_util( struct cam_generic_fence_cmd_args *fence_cmd_args, struct cam_generic_fence_input_info **fence_input_info) @@ -1148,7 +1264,7 @@ static int cam_generic_fence_handle_dma_import( /* Create new sync object and associate dma fence */ rc = cam_sync_create_util(&fence_cfg->sync_obj, fence_cfg->name, - &dma_sync_create); + &dma_sync_create, NULL); if (rc) { fence_cfg->reason_code = rc; @@ -1164,7 +1280,8 @@ static int cam_generic_fence_handle_dma_import( CAM_ERR(CAM_DMA_FENCE, "Failed to register cb for dma fence fd: %d sync_obj: %d rc: %d", fence_cfg->dma_fence_fd, fence_cfg->sync_obj, rc); - cam_sync_deinit_object(sync_dev->sync_table, fence_cfg->sync_obj, NULL); + cam_sync_deinit_object(sync_dev->sync_table, fence_cfg->sync_obj, + NULL, NULL); fence_cfg->reason_code = rc; goto out_copy; } @@ -1234,6 +1351,472 @@ static int cam_generic_fence_process_dma_fence_cmd( return rc; } +#if IS_REACHABLE(CONFIG_MSM_GLOBAL_SYNX_V2) +static int cam_generic_fence_validate_signal_input_info_util( + int32_t fence_type, + struct cam_generic_fence_cmd_args *fence_cmd_args, + struct cam_generic_fence_signal_info **fence_signal_info, + void **fence_signal_data) +{ + int rc = 0; + struct cam_generic_fence_signal_info *signal_info = NULL; + void *signal_data; + uint32_t num_fences; + size_t expected_size; + + *fence_signal_info = NULL; + *fence_signal_data = NULL; + + if (fence_cmd_args->input_data_size < + sizeof(struct cam_generic_fence_signal_info)) { + CAM_ERR(CAM_SYNC, "Size is invalid expected: 0x%llx actual: 0x%llx", + sizeof(struct cam_generic_fence_signal_info), + fence_cmd_args->input_data_size); + return -EINVAL; + } + + signal_info = memdup_user(u64_to_user_ptr(fence_cmd_args->input_handle), + fence_cmd_args->input_data_size); + if (IS_ERR_OR_NULL(signal_info)) { + CAM_ERR(CAM_SYNC, "memdup failed for hdl: %d size: 0x%x", + fence_cmd_args->input_handle, fence_cmd_args->input_data_size); + return -ENOMEM; + } + + /* Validate num fences */ + num_fences = signal_info->num_fences_requested; + if ((num_fences == 0) || (num_fences > CAM_GENERIC_FENCE_BATCH_MAX)) { + CAM_ERR(CAM_SYNC, "Invalid number of fences: %u for batching", + num_fences); + rc = -EINVAL; + goto free_mem; + } + + if (signal_info->fence_handle_type != CAM_HANDLE_USER_POINTER) { + CAM_ERR(CAM_SYNC, "Invalid signal handle type: %d", + signal_info->fence_handle_type); + rc = -EINVAL; + goto free_mem; + } + + /* Validate sizes */ + switch (fence_type) { + case CAM_GENERIC_FENCE_TYPE_SYNC_OBJ: + expected_size = sizeof(struct cam_sync_signal); + break; + case CAM_GENERIC_FENCE_TYPE_SYNX_OBJ: + expected_size = sizeof(struct cam_synx_obj_signal); + break; + case CAM_GENERIC_FENCE_TYPE_DMA_FENCE: + expected_size = sizeof(struct cam_dma_fence_signal); + break; + default: + CAM_ERR(CAM_SYNC, "Unsupported fence type: %u", fence_type); + rc = -EINVAL; + goto free_mem; + } + + if ((signal_info->fence_data_size) < (expected_size * num_fences)) { + CAM_ERR(CAM_SYNC, "Invalid input size expected: 0x%x actual: 0x%x for fences: %u", + (expected_size * num_fences), signal_info->fence_data_size, num_fences); + rc = -EINVAL; + goto free_mem; + } + + signal_data = memdup_user(u64_to_user_ptr(signal_info->fence_info_hdl), + signal_info->fence_data_size); + if (IS_ERR_OR_NULL(signal_data)) { + CAM_ERR(CAM_SYNC, "memdup failed for hdl: %d size: 0x%x", + signal_info->fence_info_hdl, signal_info->fence_data_size); + rc = -ENOMEM; + goto free_mem; + } + + *fence_signal_info = signal_info; + *fence_signal_data = signal_data; + return rc; + +free_mem: + kfree(signal_info); + return rc; +} + +static void cam_generic_fence_free_signal_input_info_util( + struct cam_generic_fence_signal_info **fence_signal_info, + void **fence_signal_data) +{ + void *signal_data = *fence_signal_data; + struct cam_generic_fence_signal_info *fence_input = *fence_signal_info; + + kfree(signal_data); + kfree(fence_input); + + *fence_signal_info = NULL; + *fence_signal_data = NULL; +} + +static int cam_generic_fence_config_parse_params( + struct cam_generic_fence_config *fence_cfg, + int32_t requested_param_mask, int32_t *result) +{ + uint32_t index = 0, num_entries; + + if (!result) { + CAM_ERR(CAM_SYNC, "Invalid result hdl : %p", result); + return -EINVAL; + } + + /* Assign to 0 by default */ + *result = 0; + + if (!fence_cfg->num_valid_params || !requested_param_mask) { + CAM_DBG(CAM_SYNC, + "No params configured num_valid = %d requested_mask = 0x%x", + fence_cfg->num_valid_params, requested_param_mask); + return 0; + } + + if (!(fence_cfg->valid_param_mask & requested_param_mask)) { + CAM_DBG(CAM_SYNC, + "Requested parameter not set in additional param mask expecting: 0x%x actual: 0x%x", + requested_param_mask, fence_cfg->valid_param_mask); + return 0; + } + + index = ffs(requested_param_mask) - 1; + num_entries = ARRAY_SIZE(fence_cfg->params); + if (index >= num_entries) { + CAM_DBG(CAM_SYNC, + "Obtained index %u from mask: 0x%x num_param_entries: %u, index exceeding max", + index, requested_param_mask, num_entries); + return 0; + } + + *result = fence_cfg->params[index]; + return 0; +} + +static int cam_generic_fence_handle_synx_create( + struct cam_generic_fence_cmd_args *fence_cmd_args) +{ + int rc = 0, i; + int32_t row_idx, fence_flag; + struct cam_generic_fence_input_info *fence_input_info = NULL; + struct cam_generic_fence_config *fence_cfg = NULL; + + rc = cam_generic_fence_alloc_validate_input_info_util(fence_cmd_args, &fence_input_info); + if (rc || !fence_input_info) { + CAM_ERR(CAM_SYNX, + "Fence input info validation failed rc: %d fence_input_info: %pK", + rc, fence_input_info); + return -EINVAL; + } + + for (i = 0; i < fence_input_info->num_fences_requested; i++) { + fence_cfg = &fence_input_info->fence_cfg[i]; + fence_input_info->num_fences_processed++; + fence_cfg->reason_code = 0; + fence_flag = 0; + + cam_generic_fence_config_parse_params(fence_cfg, + CAM_GENERIC_FENCE_CONFIG_FLAG_PARAM_INDEX, &fence_flag); + + rc = cam_synx_obj_create(fence_cfg->name, + fence_flag, &fence_cfg->synx_obj, &row_idx); + if (rc) { + CAM_ERR(CAM_SYNX, + "Failed to create synx fence at index: %d rc: %d num fences [requested: %u processed: %u]", + i, rc, fence_input_info->num_fences_requested, + fence_input_info->num_fences_processed); + fence_cfg->reason_code = rc; + goto out_copy; + } + + CAM_DBG(CAM_SYNX, + "Created synx fence @ i: %d synx_obj: %d[%s] num fences [requested: %u processed: %u] ", + i, fence_cfg->synx_obj, fence_cfg->name, + fence_input_info->num_fences_requested, + fence_input_info->num_fences_processed); + } + +out_copy: + if (copy_to_user(u64_to_user_ptr(fence_cmd_args->input_handle), + fence_input_info, fence_cmd_args->input_data_size)) { + CAM_ERR(CAM_SYNX, "copy to user failed hdl: %d size: 0x%x", + fence_cmd_args->input_handle, fence_cmd_args->input_data_size); + rc = -EFAULT; + } + + cam_generic_fence_free_input_info_util(&fence_input_info); + return rc; +} + +static int cam_generic_fence_handle_synx_release( + struct cam_generic_fence_cmd_args *fence_cmd_args) +{ + int rc = 0, i; + bool failed = false; + struct cam_generic_fence_input_info *fence_input_info = NULL; + struct cam_generic_fence_config *fence_cfg = NULL; + struct cam_synx_obj_release_params synx_release_params; + + rc = cam_generic_fence_alloc_validate_input_info_util(fence_cmd_args, &fence_input_info); + if (rc || !fence_input_info) { + CAM_ERR(CAM_SYNX, + "Fence input info validation failed rc: %d fence_input_info: %pK", + rc, fence_input_info); + return -EINVAL; + } + + for (i = 0; i < fence_input_info->num_fences_requested; i++) { + fence_cfg = &fence_input_info->fence_cfg[i]; + fence_input_info->num_fences_processed++; + fence_cfg->reason_code = 0; + + synx_release_params.use_row_idx = false; + synx_release_params.u.synx_obj = fence_cfg->synx_obj; + + rc = cam_synx_obj_release(&synx_release_params); + if (rc) { + CAM_ERR(CAM_SYNX, + "Failed to release synx object at index: %d rc: %d num fences [requested: %u processed: %u]", + i, rc, fence_input_info->num_fences_requested, + fence_input_info->num_fences_processed); + fence_cfg->reason_code = rc; + /* Continue to release other fences, but mark the call as failed */ + failed = true; + continue; + } + + CAM_DBG(CAM_SYNX, + "Released synx object @ i: %d handle: %d num fences [requested: %u processed: %u]", + i, fence_cfg->synx_obj, + fence_input_info->num_fences_requested, + fence_input_info->num_fences_processed); + } + + if (failed) + rc = -ENOMSG; + + if (copy_to_user(u64_to_user_ptr(fence_cmd_args->input_handle), + fence_input_info, fence_cmd_args->input_data_size)) { + CAM_ERR(CAM_SYNX, "copy to user failed hdl: %d size: 0x%x", + fence_cmd_args->input_handle, fence_cmd_args->input_data_size); + rc = -EFAULT; + } + + cam_generic_fence_free_input_info_util(&fence_input_info); + return rc; +} + +static int cam_sync_synx_associate_obj(int32_t sync_obj, uint32_t synx_obj, + int32_t synx_obj_row_idx, bool *is_sync_obj_signaled) +{ + int rc = 0; + struct sync_table_row *row = NULL; + struct cam_synx_obj_signal signal_synx_obj; + + rc = cam_sync_check_valid(sync_obj); + if (rc) + return rc; + + row = sync_dev->sync_table + sync_obj; + spin_lock(&sync_dev->row_spinlocks[sync_obj]); + if (row->state != CAM_SYNC_STATE_ACTIVE) { + signal_synx_obj.status = row->state; + signal_synx_obj.synx_obj = synx_obj; + *is_sync_obj_signaled = true; + rc = cam_synx_obj_signal_obj(&signal_synx_obj); + } else { + row->synx_obj_info.synx_obj_row_idx = synx_obj_row_idx; + row->synx_obj_info.sync_created_with_synx = false; + row->synx_obj_info.synx_obj = synx_obj; + set_bit(CAM_GENERIC_FENCE_TYPE_SYNX_OBJ, &row->ext_fence_mask); + CAM_DBG(CAM_SYNX, "sync_obj: %s[%d] associated with synx_obj: %d", + row->name, sync_obj, row->synx_obj_info.synx_obj); + } + + spin_unlock(&sync_dev->row_spinlocks[sync_obj]); + + return rc; +} + +static int cam_generic_fence_handle_synx_import( + struct cam_generic_fence_cmd_args *fence_cmd_args) +{ + int32_t rc = 0, i, synx_obj_row_idx; + struct sync_synx_obj_info synx_sync_create; + struct cam_generic_fence_input_info *fence_input_info = NULL; + struct cam_generic_fence_config *fence_cfg = NULL; + bool is_sync_obj_signaled = false; + bool is_sync_obj_created = false; + + rc = cam_generic_fence_alloc_validate_input_info_util(fence_cmd_args, &fence_input_info); + if (rc || !fence_input_info) { + CAM_ERR(CAM_SYNX, + "Fence input info validation failed rc: %d fence_input_info: %pK", + rc, fence_input_info); + return -EINVAL; + } + + for (i = 0; i < fence_input_info->num_fences_requested; i++) { + fence_cfg = &fence_input_info->fence_cfg[i]; + fence_input_info->num_fences_processed++; + fence_cfg->reason_code = 0; + is_sync_obj_signaled = false; + is_sync_obj_created = false; + + /* Check if synx handle is for a valid synx obj */ + rc = cam_synx_obj_find_obj_in_table(fence_cfg->synx_obj, + &synx_obj_row_idx); + if (rc) { + CAM_ERR(CAM_SYNX, + "Invalid synx obj for handle: %d", fence_cfg->synx_obj); + fence_cfg->reason_code = -EINVAL; + goto out_copy; + } + + + if ((fence_cfg->sync_obj > 0) && (fence_cfg->sync_obj < CAM_SYNC_MAX_OBJS)) { + /* Associate synx object with existing sync object */ + rc = cam_sync_synx_associate_obj(fence_cfg->sync_obj, + fence_cfg->synx_obj, synx_obj_row_idx, + &is_sync_obj_signaled); + } else { + /* Create new sync object and associate synx object */ + synx_sync_create.sync_created_with_synx = false; + synx_sync_create.synx_obj = fence_cfg->synx_obj; + synx_sync_create.synx_obj_row_idx = synx_obj_row_idx; + + rc = cam_sync_create_util(&fence_cfg->sync_obj, fence_cfg->name, + NULL, &synx_sync_create); + is_sync_obj_created = true; + } + + if (rc) { + fence_cfg->reason_code = rc; + goto out_copy; + } + + if (!is_sync_obj_signaled) { + /* Register a cb for synx_obj */ + rc = cam_synx_obj_register_cb(&fence_cfg->sync_obj, + synx_obj_row_idx, cam_sync_synx_obj_cb); + if (rc) { + CAM_ERR(CAM_SYNX, + "Failed to register cb for synx_obj: %d sync_obj: %d rc: %d", + fence_cfg->synx_obj, fence_cfg->sync_obj, rc); + if (is_sync_obj_created) + cam_sync_deinit_object(sync_dev->sync_table, + fence_cfg->sync_obj, NULL, NULL); + fence_cfg->reason_code = rc; + goto out_copy; + } + } + + CAM_DBG(CAM_SYNX, + "synx_obj handle = %d imported for dma fence fd: %d sync_obj = %d[%s] num fences [requested: %u processed: %u]", + fence_cfg->synx_obj, fence_cfg->dma_fence_fd, + fence_cfg->sync_obj, fence_cfg->name, + fence_input_info->num_fences_requested, + fence_input_info->num_fences_processed); + } + +out_copy: + if (copy_to_user(u64_to_user_ptr(fence_cmd_args->input_handle), + fence_input_info, fence_cmd_args->input_data_size)) { + rc = -EFAULT; + CAM_ERR(CAM_SYNX, "copy to user failed hdl: %d size: 0x%x", + fence_cmd_args->input_handle, fence_cmd_args->input_data_size); + } + + cam_generic_fence_free_input_info_util(&fence_input_info); + return rc; +} + +static int cam_generic_fence_handle_synx_signal( + struct cam_generic_fence_cmd_args *fence_cmd_args) +{ + int32_t rc = 0, i; + struct cam_generic_fence_signal_info *fence_signal_info; + struct cam_synx_obj_signal *synx_signal_info; + + rc = cam_generic_fence_validate_signal_input_info_util( + CAM_GENERIC_FENCE_TYPE_SYNX_OBJ, fence_cmd_args, + &fence_signal_info, (void **)&synx_signal_info); + if (rc || !fence_signal_info || !synx_signal_info) { + CAM_ERR(CAM_SYNX, + "Fence input signal info validation failed rc: %d fence_input_info: %pK synx_signal_info: %pK", + rc, fence_signal_info, synx_signal_info); + return -EINVAL; + } + + for (i = 0; i < fence_signal_info->num_fences_requested; i++) { + fence_signal_info->num_fences_processed++; + + rc = cam_synx_obj_signal_obj(&synx_signal_info[i]); + if (rc) { + CAM_ERR(CAM_SYNX, + "Failed to signal for synx_obj: %d, rc: %d, status : %d", + synx_signal_info[i].synx_obj, rc, + synx_signal_info[i].status); + } + + synx_signal_info[i].reason_code = rc; + } + + if (copy_to_user(u64_to_user_ptr(fence_signal_info->fence_info_hdl), synx_signal_info, + fence_signal_info->fence_data_size)) { + rc = -EFAULT; + CAM_ERR(CAM_SYNX, "copy to user for signal data failed hdl: %d size: 0x%x", + fence_cmd_args->input_handle, + (sizeof(struct cam_synx_obj_signal) * + fence_signal_info->num_fences_requested)); + goto end; + } + + if (copy_to_user(u64_to_user_ptr(fence_cmd_args->input_handle), + fence_signal_info, sizeof(struct cam_generic_fence_signal_info))) { + rc = -EFAULT; + CAM_ERR(CAM_SYNX, "copy to user failed hdl: %d size: 0x%x", + fence_cmd_args->input_handle, + sizeof(struct cam_generic_fence_signal_info)); +} + +end: + cam_generic_fence_free_signal_input_info_util(&fence_signal_info, + (void **)&synx_signal_info); + return rc; +} + +static int cam_generic_fence_process_synx_obj_cmd( + uint32_t id, + struct cam_generic_fence_cmd_args *fence_cmd_args) +{ + int rc = -EINVAL; + + switch (id) { + case CAM_GENERIC_FENCE_CREATE: + rc = cam_generic_fence_handle_synx_create(fence_cmd_args); + break; + case CAM_GENERIC_FENCE_RELEASE: + rc = cam_generic_fence_handle_synx_release(fence_cmd_args); + break; + case CAM_GENERIC_FENCE_IMPORT: + rc = cam_generic_fence_handle_synx_import(fence_cmd_args); + break; + case CAM_GENERIC_FENCE_SIGNAL: + rc = cam_generic_fence_handle_synx_signal(fence_cmd_args); + break; + default: + CAM_ERR(CAM_SYNX, "IOCTL cmd: %u not supported for synx object", id); + break; + } + + return rc; +} +#endif + static int cam_generic_fence_handle_sync_create( struct cam_generic_fence_cmd_args *fence_cmd_args) { @@ -1244,6 +1827,14 @@ static int cam_generic_fence_handle_sync_create( struct cam_dma_fence_create_sync_obj_payload dma_sync_create; struct cam_generic_fence_input_info *fence_input_info = NULL; struct cam_generic_fence_config *fence_cfg = NULL; + bool synx_obj_created; + struct sync_synx_obj_info synx_obj_create; +#if IS_REACHABLE(CONFIG_MSM_GLOBAL_SYNX_V2) + int32_t fence_flag; + int32_t synx_obj_row_idx; + struct cam_synx_obj_release_params synx_release_params; + struct dma_fence *dma_fence_ptr; +#endif rc = cam_generic_fence_alloc_validate_input_info_util(fence_cmd_args, &fence_input_info); if (rc || !fence_input_info) { @@ -1260,6 +1851,7 @@ static int cam_generic_fence_handle_sync_create( /* Reset flag */ dma_fence_created = false; + synx_obj_created = false; fence_sel_mask = fence_cfg->fence_sel_mask; if (test_bit(CAM_GENERIC_FENCE_TYPE_DMA_FENCE, &fence_sel_mask)) { @@ -1279,20 +1871,76 @@ static int cam_generic_fence_handle_sync_create( dma_fence_created = true; } +#if IS_REACHABLE(CONFIG_MSM_GLOBAL_SYNX_V2) + /* Create a synx object */ + if (test_bit(CAM_GENERIC_FENCE_TYPE_SYNX_OBJ, &fence_sel_mask)) { + if (dma_fence_created) { + dma_fence_ptr = cam_dma_fence_get_fence_from_fd( + dma_sync_create.fd, &dma_fence_row_idx); + rc = cam_synx_obj_import_dma_fence(fence_cfg->name, + fence_cfg->params[0], dma_fence_ptr, + &fence_cfg->synx_obj, &synx_obj_row_idx); + } else { + cam_generic_fence_config_parse_params(fence_cfg, + CAM_GENERIC_FENCE_CONFIG_FLAG_PARAM_INDEX, &fence_flag); + rc = cam_synx_obj_create(fence_cfg->name, + fence_flag, &fence_cfg->synx_obj, + &synx_obj_row_idx); + } + + if (rc) { + CAM_ERR(CAM_SYNC, + "Failed to create/import synx obj at index: %d rc: %d num_fences: %u", + i, rc, fence_input_info->num_fences_requested); + + /* Release dma fence */ + if (dma_fence_created) { + release_params.use_row_idx = true; + release_params.u.dma_row_idx = dma_fence_row_idx; + + cam_dma_fence_release(&release_params); + } + /* Release synx obj */ + if (synx_obj_created) { + synx_release_params.use_row_idx = true; + synx_release_params.u.synx_row_idx = synx_obj_row_idx; + + cam_synx_obj_release(&synx_release_params); + } + goto out_copy; + } + + synx_obj_create.sync_created_with_synx = true; + synx_obj_create.synx_obj = fence_cfg->synx_obj; + synx_obj_create.synx_obj_row_idx = synx_obj_row_idx; + synx_obj_created = true; + } +#endif rc = cam_sync_create_util(&fence_cfg->sync_obj, fence_cfg->name, - (dma_fence_created ? &dma_sync_create : NULL)); + (dma_fence_created ? &dma_sync_create : NULL), + (synx_obj_created ? &synx_obj_create : NULL)); if (rc) { fence_cfg->reason_code = rc; + + CAM_ERR(CAM_SYNC, + "Failed to create sync obj at index: %d rc: %d num_fences: %u", + i, rc, fence_input_info->num_fences_requested); + /* Release dma fence */ if (dma_fence_created) { release_params.use_row_idx = true; release_params.u.dma_row_idx = dma_fence_row_idx; cam_dma_fence_release(&release_params); } +#if IS_REACHABLE(CONFIG_MSM_GLOBAL_SYNX_V2) + /* Release synx obj */ + if (synx_obj_created) { + synx_release_params.use_row_idx = true; + synx_release_params.u.synx_row_idx = synx_obj_row_idx; - CAM_ERR(CAM_SYNC, - "Failed to create sync obj at index: %d rc: %d num_fences: %u", - i, rc, fence_input_info->num_fences_requested); + cam_synx_obj_release(&synx_release_params); + } +#endif goto out_copy; } @@ -1305,19 +1953,61 @@ static int cam_generic_fence_handle_sync_create( "Failed to register cb for dma fence fd: %d sync_obj: %d rc: %d", fence_cfg->dma_fence_fd, fence_cfg->sync_obj, rc); - /* Destroy sync obj */ - cam_sync_deinit_object( - sync_dev->sync_table, fence_cfg->sync_obj, NULL); - - /* Release dma fence */ - release_params.use_row_idx = true; - release_params.u.dma_row_idx = dma_fence_row_idx; - cam_dma_fence_release(&release_params); - fence_cfg->reason_code = rc; + /* Destroy sync obj */ + cam_sync_deinit_object(sync_dev->sync_table, fence_cfg->sync_obj, + NULL, NULL); + /* Release dma fence */ + if (dma_fence_created) { + release_params.use_row_idx = true; + release_params.u.dma_row_idx = dma_fence_row_idx; + + cam_dma_fence_release(&release_params); + } +#if IS_REACHABLE(CONFIG_MSM_GLOBAL_SYNX_V2) + /* Release synx obj */ + if (synx_obj_created) { + synx_release_params.use_row_idx = true; + synx_release_params.u.synx_row_idx = synx_obj_row_idx; + + cam_synx_obj_release(&synx_release_params); + } +#endif goto out_copy; } } +#if IS_REACHABLE(CONFIG_MSM_GLOBAL_SYNX_V2) + /* Register synx object callback */ + if (test_bit(CAM_GENERIC_FENCE_TYPE_SYNX_OBJ, &fence_sel_mask)) { + rc = cam_synx_obj_register_cb(&fence_cfg->sync_obj, + synx_obj_row_idx, cam_sync_synx_obj_cb); + if (rc) { + CAM_ERR(CAM_SYNC, + "Failed to register cb for synx_obj: %d sync_obj: %d rc: %d", + fence_cfg->synx_obj, fence_cfg->sync_obj, rc); + + fence_cfg->reason_code = rc; + /* Destroy sync obj */ + cam_sync_deinit_object(sync_dev->sync_table, fence_cfg->sync_obj, + NULL, NULL); + /* Release dma fence */ + if (dma_fence_created) { + release_params.use_row_idx = true; + release_params.u.dma_row_idx = dma_fence_row_idx; + + cam_dma_fence_release(&release_params); + } + /* Release synx obj */ + if (synx_obj_created) { + synx_release_params.use_row_idx = true; + synx_release_params.u.synx_row_idx = synx_obj_row_idx; + + cam_synx_obj_release(&synx_release_params); + } + goto out_copy; + } + } +#endif CAM_DBG(CAM_SYNC, "Created sync_obj = %d[%s] with fence_sel_mask: 0x%x dma_fence_fd: %d num fences [requested: %u processed: %u]", @@ -1349,6 +2039,10 @@ static int cam_generic_fence_handle_sync_release( struct cam_dma_fence_release_params release_params; struct cam_generic_fence_input_info *fence_input_info = NULL; struct cam_generic_fence_config *fence_cfg = NULL; + struct cam_sync_check_for_synx_release check_for_synx_release; +#if IS_REACHABLE(CONFIG_MSM_GLOBAL_SYNX_V2) + struct cam_synx_obj_release_params synx_release_params; +#endif rc = cam_generic_fence_alloc_validate_input_info_util(fence_cmd_args, &fence_input_info); if (rc || !fence_input_info) { @@ -1365,9 +2059,11 @@ static int cam_generic_fence_handle_sync_release( fence_cfg->reason_code = 0; check_for_dma_release.sync_created_with_dma = false; check_for_dma_release.dma_fence_fd = fence_cfg->dma_fence_fd; + check_for_synx_release.sync_created_with_synx = false; + check_for_synx_release.synx_obj = fence_cfg->synx_obj; rc = cam_sync_deinit_object(sync_dev->sync_table, fence_cfg->sync_obj, - &check_for_dma_release); + &check_for_dma_release, &check_for_synx_release); if (rc) { fence_cfg->reason_code = rc; failed = true; @@ -1402,10 +2098,38 @@ static int cam_generic_fence_handle_sync_release( } } +#if IS_REACHABLE(CONFIG_MSM_GLOBAL_SYNX_V2) + /* Release associated synx obj */ + if (test_bit(CAM_GENERIC_FENCE_TYPE_SYNX_OBJ, &fence_sel_mask)) { + if (!check_for_synx_release.sync_created_with_synx) { + CAM_ERR(CAM_SYNC, + "Failed to release synx_obj: %d with sync_obj: %d, not created together", + fence_cfg->synx_obj, fence_cfg->sync_obj); + failed = true; + fence_cfg->reason_code = -EPERM; + continue; + } + + synx_release_params.use_row_idx = true; + synx_release_params.u.synx_row_idx = + check_for_synx_release.synx_obj_row_idx; + rc = cam_synx_obj_release(&synx_release_params); + if (rc) { + CAM_ERR(CAM_SYNC, + "Failed to destroy synx_obj at index: %d rc: %d num fences [requested: %u processed: %u]", + i, rc, fence_input_info->num_fences_requested, + fence_input_info->num_fences_processed); + fence_cfg->reason_code = rc; + failed = true; + continue; + } + } +#endif + CAM_DBG(CAM_SYNC, - "Released sync_obj = %d[%s] with fence_sel_mask: 0x%x dma_fence_fd: %d num fences [requested: %u processed: %u]", + "Released sync_obj = %d[%s] with fence_sel_mask: 0x%x dma_fence_fd: %d synx_obj: %d num fences [requested: %u processed: %u]", fence_cfg->sync_obj, fence_cfg->name, - fence_cfg->fence_sel_mask, fence_cfg->dma_fence_fd, + fence_cfg->fence_sel_mask, fence_cfg->dma_fence_fd, fence_cfg->synx_obj, fence_input_info->num_fences_requested, fence_input_info->num_fences_processed); } @@ -1483,6 +2207,11 @@ static int cam_generic_fence_parser( case CAM_GENERIC_FENCE_TYPE_DMA_FENCE: rc = cam_generic_fence_process_dma_fence_cmd(k_ioctl->id, &fence_cmd_args); break; +#if IS_REACHABLE(CONFIG_MSM_GLOBAL_SYNX_V2) + case CAM_GENERIC_FENCE_TYPE_SYNX_OBJ: + rc = cam_generic_fence_process_synx_obj_cmd(k_ioctl->id, &fence_cmd_args); + break; +#endif default: rc = -EINVAL; CAM_ERR(CAM_SYNC, "fence type: 0x%x handling not supported", @@ -1658,6 +2387,10 @@ static int cam_sync_close(struct file *filep) /* Clean dma fence table */ cam_dma_fence_close(); +#if IS_REACHABLE(CONFIG_MSM_GLOBAL_SYNX_V2) + /* Clean synx obj table */ + cam_synx_obj_close(); +#endif mutex_unlock(&sync_dev->table_lock); spin_lock_bh(&sync_dev->cam_sync_eventq_lock); @@ -1976,7 +2709,15 @@ static int cam_sync_component_bind(struct device *dev, trigger_cb_without_switch = false; cam_sync_create_debugfs(); -#if IS_REACHABLE(CONFIG_MSM_GLOBAL_SYNX) +#if IS_REACHABLE(CONFIG_MSM_GLOBAL_SYNX_V2) + /* Initialize synx obj driver */ + rc = cam_synx_obj_driver_init(); + if (rc) { + CAM_ERR(CAM_SYNC, + "Synx obj driver initialization failed rc: %d", rc); + goto dma_driver_deinit; + } +#elif IS_REACHABLE(CONFIG_MSM_GLOBAL_SYNX) CAM_DBG(CAM_SYNC, "Registering with synx driver"); cam_sync_configure_synx_obj(&sync_dev->params); rc = cam_sync_register_synx_bind_ops(&sync_dev->params); @@ -1986,7 +2727,7 @@ static int cam_sync_component_bind(struct device *dev, CAM_DBG(CAM_SYNC, "Component bound successfully"); return rc; -#if IS_REACHABLE(CONFIG_MSM_GLOBAL_SYNX) +#if IS_REACHABLE(CONFIG_MSM_GLOBAL_SYNX) || IS_REACHABLE(CONFIG_MSM_GLOBAL_SYNX_V2) dma_driver_deinit: cam_dma_fence_driver_deinit(); #endif @@ -2012,7 +2753,9 @@ static void cam_sync_component_unbind(struct device *dev, v4l2_device_unregister(sync_dev->vdev->v4l2_dev); cam_sync_media_controller_cleanup(sync_dev); -#if IS_REACHABLE(CONFIG_MSM_GLOBAL_SYNX) +#if IS_REACHABLE(CONFIG_MSM_GLOBAL_SYNX_V2) + cam_synx_obj_driver_deinit(); +#elif IS_REACHABLE(CONFIG_MSM_GLOBAL_SYNX) cam_sync_unregister_synx_bind_ops(&sync_dev->params); #endif video_unregister_device(sync_dev->vdev); diff --git a/drivers/cam_sync/cam_sync_private.h b/drivers/cam_sync/cam_sync_private.h index e91777057b..ae21a9ad4b 100644 --- a/drivers/cam_sync/cam_sync_private.h +++ b/drivers/cam_sync/cam_sync_private.h @@ -20,7 +20,11 @@ #include "cam_sync_api.h" #include "cam_sync_dma_fence.h" -#if IS_REACHABLE(CONFIG_MSM_GLOBAL_SYNX) +#if IS_REACHABLE(CONFIG_MSM_GLOBAL_SYNX_V2) +#include "cam_sync_synx.h" +#endif + +#if IS_REACHABLE(CONFIG_MSM_GLOBAL_SYNX) || IS_REACHABLE(CONFIG_MSM_GLOBAL_SYNX_V2) #include #endif @@ -141,6 +145,20 @@ struct sync_dma_fence_info { bool sync_created_with_dma; }; +/** + * struct sync_synx_obj_info - Synx object info associated with this sync obj + * + * @synx_obj : Synx object handle + * @synx_obj_row_idx : Index of the row corresponding to this synx obj + * in the synx obj table + * @sync_created_with_synx : If sync obj and synx obj are created together + */ +struct sync_synx_obj_info { + uint32_t synx_obj; + int32_t synx_obj_row_idx; + bool sync_created_with_synx; +}; + /** * struct sync_table_row - Single row of information about a sync object, used * for internal book keeping in the sync driver @@ -159,6 +177,7 @@ struct sync_dma_fence_info { * @ref_cnt : ref count of the number of usage of the fence. * @ext_fence_mask : Mask to indicate associated external fence types * @dma_fence_info : dma fence info if associated + * @synx_obj_info : synx obj info if associated */ struct sync_table_row { char name[CAM_SYNC_OBJ_NAME_LEN]; @@ -176,6 +195,7 @@ struct sync_table_row { atomic_t ref_cnt; unsigned long ext_fence_mask; struct sync_dma_fence_info dma_fence_info; + struct sync_synx_obj_info synx_obj_info; }; /** diff --git a/drivers/cam_sync/cam_sync_synx.c b/drivers/cam_sync/cam_sync_synx.c new file mode 100644 index 0000000000..24b5d013c2 --- /dev/null +++ b/drivers/cam_sync/cam_sync_synx.c @@ -0,0 +1,638 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#include "cam_sync_synx.h" + +/** + * struct cam_synx_obj_row - Synx obj row + */ +struct cam_synx_obj_row { + char name[CAM_SYNX_OBJ_NAME_LEN]; + uint32_t synx_obj; + enum cam_synx_obj_state state; + cam_sync_callback_for_synx_obj sync_cb; + bool cb_registered_for_sync; + bool sync_signal_synx; + int32_t sync_obj; +}; + +/** + * struct cam_synx_obj_device - Synx obj device + */ +struct cam_synx_obj_device { + struct cam_synx_obj_row rows[CAM_SYNX_MAX_OBJS]; + spinlock_t row_spinlocks[CAM_SYNX_MAX_OBJS]; + struct synx_session *session_handle; + struct mutex dev_lock; + DECLARE_BITMAP(bitmap, CAM_SYNX_MAX_OBJS); +}; + +static struct cam_synx_obj_device *g_cam_synx_obj_dev; +static char cam_synx_session_name[64] = "Camera_Generic_Synx_Session"; + +static int __cam_synx_obj_map_sync_status_util(uint32_t sync_status, + uint32_t *out_synx_status) +{ + if (!out_synx_status) + return -EINVAL; + + switch (sync_status) { + case CAM_SYNC_STATE_SIGNALED_SUCCESS: + *out_synx_status = SYNX_STATE_SIGNALED_SUCCESS; + break; + case CAM_SYNC_STATE_SIGNALED_CANCEL: + default: + *out_synx_status = SYNX_STATE_SIGNALED_CANCEL; + break; + } + + return 0; +} + +static int __cam_synx_obj_release(int32_t row_idx) +{ + struct cam_synx_obj_row *row = NULL; + + spin_lock_bh(&g_cam_synx_obj_dev->row_spinlocks[row_idx]); + row = &g_cam_synx_obj_dev->rows[row_idx]; + + if (row->state == CAM_SYNX_OBJ_STATE_ACTIVE) { + CAM_WARN(CAM_SYNX, + "Unsignaled synx obj being released name: %s synx_obj:%d", + row->name, row->synx_obj); + synx_signal(g_cam_synx_obj_dev->session_handle, row->synx_obj, + SYNX_STATE_SIGNALED_CANCEL); + } + + CAM_DBG(CAM_SYNX, + "Releasing synx_obj: %d[%s] row_idx: %u", + row->synx_obj, row->name, row_idx); + + synx_release(g_cam_synx_obj_dev->session_handle, row->synx_obj); + + /* deinit row */ + memset(row, 0, sizeof(struct cam_synx_obj_row)); + clear_bit(row_idx, g_cam_synx_obj_dev->bitmap); + spin_unlock_bh(&g_cam_synx_obj_dev->row_spinlocks[row_idx]); + return 0; +} + +static int __cam_synx_obj_find_free_idx(uint32_t *idx) +{ + int rc = 0; + + *idx = find_first_zero_bit(g_cam_synx_obj_dev->bitmap, CAM_SYNX_MAX_OBJS); + if (*idx < CAM_SYNX_MAX_OBJS) + set_bit(*idx, g_cam_synx_obj_dev->bitmap); + else + rc = -ENOMEM; + + if (rc) + CAM_ERR(CAM_SYNX, "No free synx idx"); + + return rc; +} + +static void __cam_synx_obj_init_row(uint32_t idx, const char *name, + uint32_t synx_obj) +{ + struct cam_synx_obj_row *row; + + spin_lock_bh(&g_cam_synx_obj_dev->row_spinlocks[idx]); + row = &g_cam_synx_obj_dev->rows[idx]; + memset(row, 0, sizeof(*row)); + row->synx_obj = synx_obj; + row->state = CAM_SYNX_OBJ_STATE_ACTIVE; + strscpy(row->name, name, CAM_SYNX_OBJ_NAME_LEN); + spin_unlock_bh(&g_cam_synx_obj_dev->row_spinlocks[idx]); +} + +static int __cam_synx_obj_release_row(int32_t row_idx) +{ + if ((row_idx < 0) || (row_idx >= CAM_SYNX_MAX_OBJS)) { + CAM_ERR(CAM_SYNX, "synx row idx: %d is invalid", + row_idx); + return -EINVAL; + } + + return __cam_synx_obj_release(row_idx); +} + +static void __cam_synx_obj_signal_cb(u32 h_synx, int status, void *data) +{ + struct cam_synx_obj_signal_sync_obj signal_sync_obj; + struct cam_synx_obj_row *synx_obj_row = NULL; + + if (!data) { + CAM_ERR(CAM_SYNX, + "Invalid data passed to synx obj : %d callback function.", + synx_obj_row->synx_obj); + return; + } + + synx_obj_row = (struct cam_synx_obj_row *)data; + + /* If this synx obj is signaled by sync obj, skip cb */ + if (synx_obj_row->sync_signal_synx) + return; + + if (synx_obj_row->synx_obj != h_synx) { + CAM_ERR(CAM_SYNX, + "Synx obj: %d callback does not match synx obj: %d in sync table.", + h_synx, synx_obj_row->synx_obj); + return; + } + + if (synx_obj_row->state == CAM_SYNX_OBJ_STATE_INVALID) { + CAM_ERR(CAM_SYNX, + "Synx obj :%d is in invalid state: %d", + synx_obj_row->synx_obj, synx_obj_row->state); + return; + } + + CAM_DBG(CAM_SYNX, "Synx obj: %d signaled, signal sync obj: %d", + synx_obj_row->synx_obj, synx_obj_row->sync_obj); + + if ((synx_obj_row->cb_registered_for_sync) && (synx_obj_row->sync_cb)) { + signal_sync_obj.synx_obj = synx_obj_row->synx_obj; + switch (status) { + case SYNX_STATE_SIGNALED_SUCCESS: + signal_sync_obj.status = CAM_SYNC_STATE_SIGNALED_SUCCESS; + break; + case SYNX_STATE_SIGNALED_CANCEL: + signal_sync_obj.status = CAM_SYNC_STATE_SIGNALED_CANCEL; + break; + default: + CAM_WARN(CAM_SYNX, + "Synx signal status %d is neither SUCCESS nor CANCEL, custom code?", + status); + signal_sync_obj.status = CAM_SYNC_STATE_SIGNALED_ERROR; + break; + } + synx_obj_row->state = CAM_SYNX_OBJ_STATE_SIGNALED; + synx_obj_row->sync_cb(synx_obj_row->sync_obj, &signal_sync_obj); + } + +} + +int cam_synx_obj_find_obj_in_table(uint32_t synx_obj, int32_t *idx) +{ + int i, rc = -EINVAL; + struct cam_synx_obj_row *row = NULL; + + for (i = 0; i < CAM_SYNX_MAX_OBJS; i++) { + spin_lock_bh(&g_cam_synx_obj_dev->row_spinlocks[i]); + row = &g_cam_synx_obj_dev->rows[i]; + if ((row->state != CAM_SYNX_OBJ_STATE_INVALID) && + (row->synx_obj == synx_obj)) { + *idx = i; + spin_unlock_bh(&g_cam_synx_obj_dev->row_spinlocks[i]); + rc = 0; + break; + } + spin_unlock_bh(&g_cam_synx_obj_dev->row_spinlocks[i]); + } + + return rc; +} + +static int __cam_synx_obj_release_obj(uint32_t synx_obj) +{ + int32_t idx; + + if (cam_synx_obj_find_obj_in_table(synx_obj, &idx)) { + CAM_ERR(CAM_SYNX, "Failed to find synx obj: %d", synx_obj); + return -EINVAL; + } + + return __cam_synx_obj_release(idx); +} + +static int __cam_synx_obj_import(const char *name, + struct synx_import_params *params, int32_t *row_idx) +{ + int rc = -1; + uint32_t idx; + + if (__cam_synx_obj_find_free_idx(&idx)) + goto end; + + rc = synx_import(g_cam_synx_obj_dev->session_handle, params); + if (rc) { + CAM_ERR(CAM_SYNX, "Synx import failed for fence : %p", + params->indv.fence); + goto free_idx; + } + + *row_idx = idx; + __cam_synx_obj_init_row(idx, name, *params->indv.new_h_synx); + + CAM_DBG(CAM_SYNX, "Imported synx obj handle: %d[%s] row_idx: %u", + *params->indv.new_h_synx, name, idx); + + return rc; + +free_idx: + clear_bit(idx, g_cam_synx_obj_dev->bitmap); +end: + return rc; +} + +static int __cam_synx_map_generic_flags_to_create(uint32_t generic_flags, + struct synx_create_params *params) +{ + if (!params) { + CAM_ERR(CAM_SYNX, "Create parameters missing"); + return -EINVAL; + } + + if (CAM_GENERIC_FENCE_FLAG_IS_GLOBAL_SYNX_OBJ & generic_flags) + params->flags |= SYNX_CREATE_GLOBAL_FENCE; + else + params->flags |= SYNX_CREATE_LOCAL_FENCE; + + return 0; +} + +static int __cam_synx_map_generic_flags_to_import(uint32_t generic_flags, + struct synx_import_indv_params *params) +{ + if (!params) { + CAM_ERR(CAM_SYNX, "Import parameters missing"); + return -EINVAL; + } + + if (CAM_GENERIC_FENCE_FLAG_IS_GLOBAL_SYNX_OBJ & generic_flags) + params->flags |= SYNX_IMPORT_GLOBAL_FENCE; + else + params->flags |= SYNX_IMPORT_LOCAL_FENCE; + + return 0; +} + +int cam_synx_obj_create(const char *name, uint32_t flags, uint32_t *synx_obj, + int32_t *row_idx) +{ + int rc = -1; + uint32_t idx; + struct synx_create_params params; + + if (__cam_synx_obj_find_free_idx(&idx)) + goto end; + + params.fence = NULL; + params.name = name; + params.flags = 0; + params.h_synx = synx_obj; + + rc = __cam_synx_map_generic_flags_to_create(flags, ¶ms); + if (rc) { + CAM_ERR(CAM_SYNX, "Failed to generate create flags"); + goto free_idx; + } + + /* + * Create Global Always - remove after userspace optimizes and + * determines when global Vs local is needed + */ + params.flags |= SYNX_CREATE_GLOBAL_FENCE; + + rc = synx_create(g_cam_synx_obj_dev->session_handle, ¶ms); + if (rc) { + CAM_ERR(CAM_SYNX, "Failed to create synx obj"); + goto free_idx; + } + + *row_idx = idx; + __cam_synx_obj_init_row(idx, name, *synx_obj); + + CAM_DBG(CAM_SYNX, "Created synx obj handle: %d[%s] row_idx: %u", + *synx_obj, name, idx); + + return rc; + +free_idx: + clear_bit(idx, g_cam_synx_obj_dev->bitmap); +end: + return rc; +} + +int cam_synx_obj_import_dma_fence(const char *name, uint32_t flags, void *fence, + uint32_t *synx_obj, int32_t *row_idx) +{ + struct synx_import_params params; + + if (!fence) { + CAM_ERR(CAM_SYNX, + "Importing DMA fence failed - fence pointer is NULL"); + return -EINVAL; + } + + params.indv.flags = 0; + params.indv.fence = fence; + params.indv.new_h_synx = synx_obj; + params.type = SYNX_IMPORT_INDV_PARAMS; + params.indv.flags |= SYNX_IMPORT_DMA_FENCE; + + if (__cam_synx_map_generic_flags_to_import(flags, ¶ms.indv)) { + CAM_ERR(CAM_SYNX, + "Importing DMA fence failed - invalid synx import flags"); + return -EINVAL; + } + + return __cam_synx_obj_import(name, ¶ms, row_idx); +} + +int cam_synx_obj_internal_signal(int32_t row_idx, + struct cam_synx_obj_signal *signal_synx_obj) +{ + int rc = 0; + uint32_t signal_status; + struct cam_synx_obj_row *row = NULL; + + if ((row_idx < 0) || (row_idx >= CAM_SYNX_MAX_OBJS)) { + CAM_ERR(CAM_SYNX, "synx obj row idx: %d is invalid", + row_idx); + return -EINVAL; + } + + spin_lock_bh(&g_cam_synx_obj_dev->row_spinlocks[row_idx]); + row = &g_cam_synx_obj_dev->rows[row_idx]; + + /* Ensures sync obj cb is not invoked */ + row->sync_signal_synx = true; + + if (row->state == CAM_SYNX_OBJ_STATE_SIGNALED) { + spin_unlock_bh(&g_cam_synx_obj_dev->row_spinlocks[row_idx]); + CAM_WARN(CAM_SYNX, "synx obj fd: %d already in signaled state", + signal_synx_obj->synx_obj); + return 0; + } + + rc = __cam_synx_obj_map_sync_status_util(signal_synx_obj->status, + &signal_status); + if (rc) { + CAM_WARN(CAM_SYNX, + "Signaling undefined status: %d for synx obj: %d", + signal_synx_obj->status, + signal_synx_obj->synx_obj); + } + + rc = synx_signal(g_cam_synx_obj_dev->session_handle, + signal_synx_obj->synx_obj, signal_status); + if (rc) + CAM_WARN(CAM_SYNX, "synx obj: %d already signaled rc: %d", + row->synx_obj, rc); + + row->state = CAM_SYNX_OBJ_STATE_SIGNALED; + spin_unlock_bh(&g_cam_synx_obj_dev->row_spinlocks[row_idx]); + + CAM_DBG(CAM_SYNX, "synx obj: %d signaled with status: %d rc: %d", + signal_synx_obj->synx_obj, signal_status, rc); + + return rc; +} + +int cam_synx_obj_release(struct cam_synx_obj_release_params *release_params) +{ + if (release_params->use_row_idx) + return __cam_synx_obj_release_row(release_params->u.synx_row_idx); + else + return __cam_synx_obj_release_obj(release_params->u.synx_obj); +} + +int cam_synx_obj_signal_obj(struct cam_synx_obj_signal *signal_synx_obj) +{ + int rc = 0; + uint32_t idx, signal_status = 0; + struct cam_synx_obj_row *row = NULL; + + rc = cam_synx_obj_find_obj_in_table( + signal_synx_obj->synx_obj, &idx); + + if (rc) { + CAM_ERR(CAM_SYNX, "Failed to find synx obj: %d", + signal_synx_obj->synx_obj); + return -EINVAL; + } + + spin_lock_bh(&g_cam_synx_obj_dev->row_spinlocks[idx]); + row = &g_cam_synx_obj_dev->rows[idx]; + if (row->state == CAM_SYNX_OBJ_STATE_SIGNALED) { + spin_unlock_bh(&g_cam_synx_obj_dev->row_spinlocks[idx]); + CAM_WARN(CAM_SYNX, "synx obj: %d already in signaled state", + signal_synx_obj->synx_obj); + return 0; + } + + rc = __cam_synx_obj_map_sync_status_util(signal_synx_obj->status, + &signal_status); + if (rc) { + CAM_WARN(CAM_SYNX, + "Signaling undefined sync status: %d for synx obj: %d", + signal_synx_obj->status, + signal_synx_obj->synx_obj); + } + + rc = synx_signal(g_cam_synx_obj_dev->session_handle, + signal_synx_obj->synx_obj, signal_status); + if (rc) + CAM_WARN(CAM_SYNX, "synx obj: %d already signaled rc: %d", + row->synx_obj, rc); + + row->state = CAM_SYNX_OBJ_STATE_SIGNALED; + spin_unlock_bh(&g_cam_synx_obj_dev->row_spinlocks[idx]); + + CAM_DBG(CAM_SYNX, "synx obj: %d signaled with status: %d rc: %d", + signal_synx_obj->synx_obj, signal_status, rc); + + return rc; +} + +int cam_synx_obj_register_cb(int32_t *sync_obj, int32_t row_idx, + cam_sync_callback_for_synx_obj sync_cb) +{ + int rc = 0; + struct cam_synx_obj_row *row = NULL; + struct synx_callback_params cb_params; + + if (!sync_obj || !sync_cb) { + CAM_ERR(CAM_SYNX, "Invalid args sync_obj: %p sync_cb: %p", + sync_obj, sync_cb); + return -EINVAL; + } + + if ((row_idx < 0) || (row_idx >= CAM_SYNX_MAX_OBJS)) { + CAM_ERR(CAM_SYNX, "synx obj idx: %d is invalid", + row_idx); + return -EINVAL; + } + + spin_lock_bh(&g_cam_synx_obj_dev->row_spinlocks[row_idx]); + row = &g_cam_synx_obj_dev->rows[row_idx]; + + if (row->state != CAM_SYNX_OBJ_STATE_ACTIVE) { + CAM_ERR(CAM_SYNX, + "synx obj at idx: %d handle: %d is not active, current state: %d", + row_idx, row->synx_obj, row->state); + rc = -EINVAL; + goto end; + } + + /** + * If the cb is already registered, return + */ + if (row->cb_registered_for_sync) { + CAM_WARN(CAM_SYNX, + "synx obj at idx: %d handle: %d has already registered a cb for sync: %d", + row_idx, row->synx_obj, row->sync_obj); + goto end; + } + + cb_params.userdata = row; + cb_params.cancel_cb_func = NULL; + cb_params.h_synx = row->synx_obj; + cb_params.cb_func = __cam_synx_obj_signal_cb; + + rc = synx_async_wait(g_cam_synx_obj_dev->session_handle, &cb_params); + if (rc) { + CAM_ERR(CAM_SYNX, + "Failed to register cb for synx obj: %d rc: %d", + row->synx_obj, rc); + goto end; + } + + row->sync_cb = sync_cb; + row->sync_obj = *sync_obj; + row->cb_registered_for_sync = true; + + CAM_DBG(CAM_SYNX, + "CB successfully registered for synx obj: %d for sync_obj: %d", + row->synx_obj, *sync_obj); + +end: + spin_unlock_bh(&g_cam_synx_obj_dev->row_spinlocks[row_idx]); + return rc; +} + +int __cam_synx_init_session(void) +{ + struct synx_queue_desc queue_desc; + struct synx_initialization_params params; + + params.name = cam_synx_session_name; + params.ptr = &queue_desc; + params.flags = SYNX_INIT_MAX; + params.id = SYNX_CLIENT_NATIVE; + g_cam_synx_obj_dev->session_handle = synx_initialize(¶ms); + + if (!g_cam_synx_obj_dev->session_handle) { + CAM_ERR(CAM_SYNX, "Synx session initialization failed"); + return -EINVAL; + } + + CAM_DBG(CAM_SYNX, "Synx session initialized: %p", + g_cam_synx_obj_dev->session_handle); + + return 0; +} + +void cam_synx_obj_close(void) +{ + int i, rc = 0; + struct cam_synx_obj_row *row = NULL; + struct synx_callback_params cb_params; + + mutex_lock(&g_cam_synx_obj_dev->dev_lock); + for (i = 0; i < CAM_SYNX_MAX_OBJS; i++) { + spin_lock_bh(&g_cam_synx_obj_dev->row_spinlocks[i]); + + row = &g_cam_synx_obj_dev->rows[i]; + if (row->state == CAM_SYNX_OBJ_STATE_INVALID) { + spin_unlock_bh(&g_cam_synx_obj_dev->row_spinlocks[i]); + continue; + } + CAM_DBG(CAM_SYNX, "Releasing synx_obj: %d[%s]", + row->synx_obj, row->name); + + /* If registered for cb, remove cb */ + if (row->cb_registered_for_sync) { + cb_params.userdata = row; + cb_params.cancel_cb_func = NULL; + cb_params.h_synx = row->synx_obj; + cb_params.cb_func = __cam_synx_obj_signal_cb; + + rc = synx_cancel_async_wait( + g_cam_synx_obj_dev->session_handle, + &cb_params); + if (rc) { + CAM_WARN(CAM_SYNX, + "Registered callback could not be canceled for synx obj : %d", + cb_params.h_synx); + } + } + + /* Signal and release the synx obj */ + if (row->state != CAM_SYNX_OBJ_STATE_SIGNALED) + synx_signal(g_cam_synx_obj_dev->session_handle, + row->synx_obj, SYNX_STATE_SIGNALED_CANCEL); + synx_release(g_cam_synx_obj_dev->session_handle, + row->synx_obj); + + memset(row, 0, sizeof(struct cam_synx_obj_row)); + clear_bit(i, g_cam_synx_obj_dev->bitmap); + spin_unlock_bh(&g_cam_synx_obj_dev->row_spinlocks[i]); + } + + mutex_unlock(&g_cam_synx_obj_dev->dev_lock); + CAM_DBG(CAM_SYNX, "Close on Camera SYNX driver"); +} + +int cam_synx_obj_driver_init(void) +{ + int i; + + g_cam_synx_obj_dev = kzalloc(sizeof(struct cam_synx_obj_device), GFP_KERNEL); + if (!g_cam_synx_obj_dev) + return -ENOMEM; + + if (__cam_synx_init_session()) + goto deinit_driver; + + mutex_init(&g_cam_synx_obj_dev->dev_lock); + for (i = 0; i < CAM_SYNX_MAX_OBJS; i++) + spin_lock_init(&g_cam_synx_obj_dev->row_spinlocks[i]); + + memset(&g_cam_synx_obj_dev->rows, 0, sizeof(g_cam_synx_obj_dev->rows)); + memset(&g_cam_synx_obj_dev->bitmap, 0, sizeof(g_cam_synx_obj_dev->bitmap)); + bitmap_zero(g_cam_synx_obj_dev->bitmap, CAM_SYNX_MAX_OBJS); + + CAM_DBG(CAM_SYNX, "Camera synx obj driver initialized"); + return 0; + +deinit_driver: + CAM_ERR(CAM_SYNX, "Camera synx obj driver initialization failed"); + kfree(g_cam_synx_obj_dev); + g_cam_synx_obj_dev = NULL; + return -EINVAL; +} + +void cam_synx_obj_driver_deinit(void) +{ + int rc; + + if (g_cam_synx_obj_dev->session_handle) { + rc = synx_uninitialize(g_cam_synx_obj_dev->session_handle); + if (rc) { + CAM_ERR(CAM_SYNX, + "Synx failed to uninitialize session: %p, rc: %d", + g_cam_synx_obj_dev->session_handle, rc); + } + } + + kfree(g_cam_synx_obj_dev); + g_cam_synx_obj_dev = NULL; + CAM_DBG(CAM_SYNX, "Camera synx obj driver deinitialized"); +} diff --git a/drivers/cam_sync/cam_sync_synx.h b/drivers/cam_sync/cam_sync_synx.h new file mode 100644 index 0000000000..e54f2e4310 --- /dev/null +++ b/drivers/cam_sync/cam_sync_synx.h @@ -0,0 +1,157 @@ +/* SPDX-License-Identifier: GPL-2.0-only + * + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + */ +#ifndef __CAM_SYNC_SYNX_H__ +#define __CAM_SYNC_SYNX_H__ + +#include +#include +#include +#include + +#include "cam_sync.h" +#include "cam_debug_util.h" + +#define CAM_SYNX_MAX_OBJS 64 +#define CAM_SYNX_OBJ_NAME_LEN 64 + +/* Synx obj state */ +enum cam_synx_obj_state { + CAM_SYNX_OBJ_STATE_INVALID, + CAM_SYNX_OBJ_STATE_ACTIVE, + CAM_SYNX_OBJ_STATE_SIGNALED, +}; + +/** + * struct cam_synx_obj_release_params - Synx release payload + * Based on the flag row_idx or synx_obj is consumed + * + * @synx_row_idx : Synx obj row idx + * @synx_obj : Synx object handle + * @use_row_idx : Use row idx + */ +struct cam_synx_obj_release_params { + union { + int32_t synx_row_idx; + uint32_t synx_obj; + } u; + bool use_row_idx; +}; + +/** + * struct cam_synx_obj_fence_signal_sync_obj - SYNX -> sync signal info + * Payload to signal sync on a synx fence being signaled + * + * @synx_obj : Synx object handle + * @status : Sync signal status + */ +struct cam_synx_obj_signal_sync_obj { + int32_t synx_obj; + int32_t status; +}; + +/* Synx obj callback function type */ +typedef int (*cam_sync_callback_for_synx_obj)(int32_t sync_obj, + struct cam_synx_obj_signal_sync_obj *signal_sync_obj); + +/** + * @brief Find the synx obj in the device's table + * + * @param synx_obj : Synx obj + * @param idx : Synx object table index + * + * @return Status of operation. Zero in case of success. + */ +int cam_synx_obj_find_obj_in_table(uint32_t synx_obj, int32_t *idx); + +/** + * @brief Create a synx object + * + * @param name : Synx obj name + * @param flags : Creation flags + * @param synx_obj : Created synx obj handle + * @param row_idx : Created synx obj table row idx + * + * @return Status of operation. Zero in case of success. + * -EINVAL will be returned if params were invalid. + * -ENOMEM will be returned if the kernel can't allocate space for + * synx object. + */ +int cam_synx_obj_create(const char *name, uint32_t flags, uint32_t *synx_obj, + int32_t *row_idx); + +/** + * @brief Signal a synx obj when sync obj is signaled + * + * @param row_idx : Synx obj table row index + * @param signal_synx_obj : Info on synx obj to be signaled + * + * @return Status of operation. Negative in case of error. Zero otherwise. + */ +int cam_synx_obj_internal_signal(int32_t row_idx, + struct cam_synx_obj_signal *signal_synx_obj); + +/** + * @brief Import a synx obj for synchronization + * + * @param name : Synx obj name + * @param flags : Import flags + * @param fence : DMA fence ptr + * @param synx_obj : New synx obj handle + * @param row_idx : Imported obj table row idx + * + * @return 0 upon success, -EINVAL if synx object is bad state + */ +int cam_synx_obj_import_dma_fence(const char *name, uint32_t flags, void *fence, + uint32_t *synx_obj, int32_t *row_idx); + +/** + * @brief Release a synx object + * + * @param release_params : Synx obj release info + * + * @return 0 upon success, negative value otherwise + */ +int cam_synx_obj_release(struct cam_synx_obj_release_params *release_params); + +/** + * @brief Signal a synx obj [userspace API] + * + * @param signal_synx_obj : Signal info + * + * @return 0 upon success, negative value otherwise + */ +int cam_synx_obj_signal_obj(struct cam_synx_obj_signal *signal_synx_obj); + +/** + * @brief Synx obj register callback + * + * @param sync_obj : Sync object + * @param row_idx : Synx obj table row idx + * @param sync_cb : Sync object callback + * + * @return Status of operation. Negative in case of error. Zero otherwise. + */ +int cam_synx_obj_register_cb(int32_t *sync_obj, int32_t row_idx, + cam_sync_callback_for_synx_obj sync_cb); + +/** + * @brief: cam synx driver close + * + */ +void cam_synx_obj_close(void); + +/** + * @brief: cam synx driver initialize + * + */ +int cam_synx_obj_driver_init(void); + +/** + * @brief: cam synx driver deinit + * + */ +void cam_synx_obj_driver_deinit(void); + +#endif /* __CAM_SYNC_SYNX_H__ */ diff --git a/drivers/cam_sync/cam_sync_util.c b/drivers/cam_sync/cam_sync_util.c index 551deac181..df35b35d70 100644 --- a/drivers/cam_sync/cam_sync_util.c +++ b/drivers/cam_sync/cam_sync_util.c @@ -149,7 +149,8 @@ clean_children_info: } int cam_sync_deinit_object(struct sync_table_row *table, uint32_t idx, - struct cam_sync_check_for_dma_release *check_for_dma_release) + struct cam_sync_check_for_dma_release *check_for_dma_release, + struct cam_sync_check_for_synx_release *check_for_synx_release) { struct sync_table_row *row = table + idx; struct sync_child_info *child_info, *temp_child; @@ -296,6 +297,19 @@ int cam_sync_deinit_object(struct sync_table_row *table, uint32_t idx, } } + /* Check if same synx obj is being released with the sync obj */ + if (test_bit(CAM_GENERIC_FENCE_TYPE_SYNX_OBJ, &row->ext_fence_mask)) { + if (check_for_synx_release) { + if (row->synx_obj_info.synx_obj == + check_for_synx_release->synx_obj) { + check_for_synx_release->synx_obj_row_idx = + row->synx_obj_info.synx_obj_row_idx; + check_for_synx_release->sync_created_with_synx = + row->synx_obj_info.sync_created_with_synx; + } + } + } + memset(row, 0, sizeof(*row)); clear_bit(idx, sync_dev->bitmap); INIT_LIST_HEAD(&row->callback_list); diff --git a/drivers/cam_sync/cam_sync_util.h b/drivers/cam_sync/cam_sync_util.h index f5c3ff5b28..32b0ce55e9 100644 --- a/drivers/cam_sync/cam_sync_util.h +++ b/drivers/cam_sync/cam_sync_util.h @@ -31,6 +31,24 @@ struct cam_sync_check_for_dma_release { bool sync_created_with_dma; }; +/** + * struct cam_sync_check_for_synx_release - + * Checks if the synx obj being released + * was created with the sync obj + * + * @synx_obj : Check if synx obj is associated with + * sync obj + * @synx_obj_row_idx : Get synx obj row idx that is associated with + * the sync obj + * @sync_created_with_synx : Set if the dma fence fd was created + * with sync obj + */ +struct cam_sync_check_for_synx_release { + int32_t synx_obj; + int32_t synx_obj_row_idx; + bool sync_created_with_synx; +}; + /** * @brief: Finds an empty row in the sync table and sets its corresponding bit * in the bit array @@ -61,14 +79,16 @@ int cam_sync_init_row(struct sync_table_row *table, /** * @brief: Function to uninitialize a row in the sync table * - * @param table : Pointer to the sync objects table - * @param idx : Index of row to initialize - * @optional param check_for_dma_release : checks for dma fence release + * @param table : Pointer to the sync objects table + * @param idx : Index of row to initialize + * @optional param check_for_dma_release : checks for dma fence release + * @optional param check_for_synx_release : checks for synx obj release * * @return Status of operation. Negative in case of error. Zero otherwise. */ int cam_sync_deinit_object(struct sync_table_row *table, uint32_t idx, - struct cam_sync_check_for_dma_release *check_for_dma_release); + struct cam_sync_check_for_dma_release *check_for_dma_release, + struct cam_sync_check_for_synx_release *check_for_synx_release); /** * @brief: Function to initialize a row in the sync table when the object is a diff --git a/drivers/cam_utils/cam_debug_util.h b/drivers/cam_utils/cam_debug_util.h index 9fe306c345..5dee7c8104 100644 --- a/drivers/cam_utils/cam_debug_util.h +++ b/drivers/cam_utils/cam_debug_util.h @@ -56,6 +56,7 @@ enum cam_debug_module_id { CAM_TPG, /* bit 33 */ CAM_DMA_FENCE, /* bit 34 */ CAM_SENSOR_UTIL, /* bit 35 */ + CAM_SYNX, /* bit 36 */ CAM_DBG_MOD_MAX }; @@ -115,6 +116,7 @@ static const char *cam_debug_mod_name[CAM_DBG_MOD_MAX] = { [CAM_TPG] = "CAM-TPG", [CAM_DMA_FENCE] = "CAM-DMA-FENCE", [CAM_SENSOR_UTIL] = "CAM-SENSOR-UTIL", + [CAM_SYNX] = "CAM_SYNX", }; #define ___CAM_DBG_MOD_NAME(module_id) \ @@ -154,7 +156,8 @@ __builtin_choose_expr(((module_id) == CAM_PRESIL_CORE), "CAM-CORE-PRESIL", \ __builtin_choose_expr(((module_id) == CAM_TPG), "CAM-TPG", \ __builtin_choose_expr(((module_id) == CAM_DMA_FENCE), "CAM-DMA-FENCE", \ __builtin_choose_expr(((module_id) == CAM_SENSOR_UTIL), "CAM-SENSOR-UTIL", \ -"CAMERA")))))))))))))))))))))))))))))))))))) +__builtin_choose_expr(((module_id) == CAM_SYNX), "CAM-SYNX", \ +"CAMERA"))))))))))))))))))))))))))))))))))))) #define CAM_DBG_MOD_NAME(module_id) \ ((module_id < CAM_DBG_MOD_MAX) ? cam_debug_mod_name[module_id] : "CAMERA")