From c7c2597175b2f74d5144433f17e4b3f26f7ac225 Mon Sep 17 00:00:00 2001 From: Dharmender Sharma Date: Thu, 15 Dec 2022 15:35:30 +0530 Subject: [PATCH] msm: camera: common: Resolve potential data race conditions Add locks before shared variable access in request manager, csid driver and smmu appi files to avoid data race conditions. CRs-Fixed: 3348931 Change-Id: Ifa860bf157047f23bd2bc460a16e9405de0d5c83 Signed-off-by: Dharmender Sharma --- .../isp_hw/ife_csid_hw/cam_ife_csid_hw_ver1.c | 16 ++++++++++++++-- drivers/cam_req_mgr/cam_req_mgr_core.c | 18 +++++++++++++++++- drivers/cam_smmu/cam_smmu_api.c | 14 ++++++++++---- 3 files changed, 41 insertions(+), 7 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_hw_ver1.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_hw_ver1.c index 4900748ddc..9432be007e 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_hw_ver1.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_hw_ver1.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved. - * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved. */ #include @@ -2619,10 +2619,13 @@ static int cam_ife_csid_ver1_enable_hw(struct cam_ife_csid_ver1_hw *csid_hw) csid_hw->core_info->csid_reg; soc_info = &csid_hw->hw_info->soc_info; + mutex_lock(&csid_hw->hw_info->hw_mutex); + /* overflow check before increment */ if (csid_hw->hw_info->open_count == UINT_MAX) { CAM_ERR(CAM_ISP, "CSID:%d Open count reached max", csid_hw->hw_intf->hw_idx); + mutex_unlock(&csid_hw->hw_info->hw_mutex); return -EINVAL; } @@ -2631,8 +2634,10 @@ static int cam_ife_csid_ver1_enable_hw(struct cam_ife_csid_ver1_hw *csid_hw) if (csid_hw->hw_info->open_count > 1) { CAM_DBG(CAM_ISP, "CSID hw has already been enabled"); + mutex_unlock(&csid_hw->hw_info->hw_mutex); return rc; } + mutex_unlock(&csid_hw->hw_info->hw_mutex); rc = cam_soc_util_get_clk_level(soc_info, csid_hw->clk_rate, soc_info->src_clk_idx, &clk_lvl); @@ -2709,7 +2714,9 @@ disable_soc: cam_ife_csid_disable_soc_resources(soc_info); csid_hw->hw_info->hw_state = CAM_HW_STATE_POWER_DOWN; err: + mutex_lock(&csid_hw->hw_info->hw_mutex); csid_hw->hw_info->open_count--; + mutex_unlock(&csid_hw->hw_info->hw_mutex); return rc; } @@ -2851,17 +2858,22 @@ static int cam_ife_csid_ver1_disable_hw( int rc = 0; unsigned long flags; + mutex_lock(&csid_hw->hw_info->hw_mutex); /* Check for refcount */ if (!csid_hw->hw_info->open_count) { CAM_WARN(CAM_ISP, "Unbalanced disable_hw"); + mutex_unlock(&csid_hw->hw_info->hw_mutex); return rc; } /* Decrement ref Count */ csid_hw->hw_info->open_count--; - if (csid_hw->hw_info->open_count) + if (csid_hw->hw_info->open_count) { + mutex_unlock(&csid_hw->hw_info->hw_mutex); return rc; + } + mutex_unlock(&csid_hw->hw_info->hw_mutex); soc_info = &csid_hw->hw_info->soc_info; csid_reg = (struct cam_ife_csid_ver1_reg_info *) diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.c b/drivers/cam_req_mgr/cam_req_mgr_core.c index cbcec46ba7..387c97ac45 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.c +++ b/drivers/cam_req_mgr/cam_req_mgr_core.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved. - * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved. */ #include @@ -47,7 +47,9 @@ void cam_req_mgr_core_link_reset(struct cam_req_mgr_core_link *link) link->req.l_tbl = NULL; link->req.num_tbl = 0; link->watchdog = NULL; + spin_lock_bh(&link->link_state_spin_lock); link->state = CAM_CRM_LINK_STATE_AVAILABLE; + spin_unlock_bh(&link->link_state_spin_lock); link->parent = NULL; link->sync_link_sof_skip = false; link->open_req_cnt = 0; @@ -71,7 +73,9 @@ void cam_req_mgr_core_link_reset(struct cam_req_mgr_core_link *link) link->try_for_internal_recovery = false; link->is_sending_req = false; atomic_set(&link->eof_event_cnt, 0); + mutex_lock(&link->lock); link->properties_mask = CAM_LINK_PROPERTY_NONE; + mutex_unlock(&link->lock); link->cont_empty_slots = 0; __cam_req_mgr_reset_apply_data(link); @@ -1810,11 +1814,14 @@ static int __cam_req_mgr_check_multi_sync_link_ready( { int i, rc = 0; + spin_lock_bh(&link->link_state_spin_lock); if (link->state == CAM_CRM_LINK_STATE_IDLE) { + spin_unlock_bh(&link->link_state_spin_lock); CAM_ERR(CAM_CRM, "link hdl %x is in idle state", link->link_hdl); return -EINVAL; } + spin_unlock_bh(&link->link_state_spin_lock); for (i = 0; i < num_sync_links; i++) { if (sync_link[i]) { @@ -2689,7 +2696,11 @@ static struct cam_req_mgr_core_link *__cam_req_mgr_reserve_link( sizeof(struct cam_req_mgr_slot) * MAX_REQ_SLOTS); link->req.in_q = in_q; in_q->num_slots = 0; + + spin_lock_bh(&link->link_state_spin_lock); link->state = CAM_CRM_LINK_STATE_IDLE; + spin_unlock_bh(&link->link_state_spin_lock); + link->parent = (void *)session; link->is_sending_req = false; @@ -5170,7 +5181,9 @@ int cam_req_mgr_link_control(struct cam_req_mgr_link_control *control) /* Wait for the streaming of sync link */ link->initial_skip = true; /* Pause the timer before sensor stream on */ + spin_lock_bh(&link->link_state_spin_lock); link->watchdog->pause_timer = true; + spin_unlock_bh(&link->link_state_spin_lock); /* notify nodes */ __cam_req_mgr_send_evt(0, CAM_REQ_MGR_LINK_EVT_RESUME, CRM_KMD_ERR_MAX, link); @@ -5216,13 +5229,16 @@ int cam_req_mgr_link_properties(struct cam_req_mgr_link_properties *properties) goto end; } + spin_lock_bh(&link->link_state_spin_lock); if (link->state != CAM_CRM_LINK_STATE_READY) { + spin_unlock_bh(&link->link_state_spin_lock); CAM_ERR(CAM_CRM, "Only can config link 0x%x properties in ready state", link->link_hdl); rc = -EAGAIN; goto end; } + spin_unlock_bh(&link->link_state_spin_lock); mutex_lock(&link->lock); link->properties_mask = properties->properties_mask; diff --git a/drivers/cam_smmu/cam_smmu_api.c b/drivers/cam_smmu/cam_smmu_api.c index 270b844aed..b6628fc562 100644 --- a/drivers/cam_smmu/cam_smmu_api.c +++ b/drivers/cam_smmu/cam_smmu_api.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2014-2021, The Linux Foundation. All rights reserved. - * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved. */ #include @@ -1111,6 +1111,11 @@ void cam_smmu_reset_iommu_table(enum cam_smmu_init_dir ops) int j = 0; for (i = 0; i < iommu_cb_set.cb_num; i++) { + if (ops == CAM_SMMU_TABLE_INIT) + mutex_init(&iommu_cb_set.cb_info[i].lock); + + mutex_lock(&iommu_cb_set.cb_info[i].lock); + iommu_cb_set.cb_info[i].handle = HANDLE_INIT; INIT_LIST_HEAD(&iommu_cb_set.cb_info[i].smmu_buf_list); INIT_LIST_HEAD(&iommu_cb_set.cb_info[i].smmu_buf_kernel_list); @@ -1122,9 +1127,10 @@ void cam_smmu_reset_iommu_table(enum cam_smmu_init_dir ops) iommu_cb_set.cb_info[i].token[j] = NULL; iommu_cb_set.cb_info[i].handler[j] = NULL; } - if (ops == CAM_SMMU_TABLE_INIT) - mutex_init(&iommu_cb_set.cb_info[i].lock); - else + + mutex_unlock(&iommu_cb_set.cb_info[i].lock); + + if (ops != CAM_SMMU_TABLE_INIT) mutex_destroy(&iommu_cb_set.cb_info[i].lock); } }