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 <quic_dharshar@quicinc.com>
This commit is contained in:

committed by
Camera Software Integration

parent
ee6f0d4042
commit
c7c2597175
@@ -1,7 +1,7 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0-only
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
|
* 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 <linux/iopoll.h>
|
#include <linux/iopoll.h>
|
||||||
@@ -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;
|
csid_hw->core_info->csid_reg;
|
||||||
soc_info = &csid_hw->hw_info->soc_info;
|
soc_info = &csid_hw->hw_info->soc_info;
|
||||||
|
|
||||||
|
mutex_lock(&csid_hw->hw_info->hw_mutex);
|
||||||
|
|
||||||
/* overflow check before increment */
|
/* overflow check before increment */
|
||||||
if (csid_hw->hw_info->open_count == UINT_MAX) {
|
if (csid_hw->hw_info->open_count == UINT_MAX) {
|
||||||
CAM_ERR(CAM_ISP, "CSID:%d Open count reached max",
|
CAM_ERR(CAM_ISP, "CSID:%d Open count reached max",
|
||||||
csid_hw->hw_intf->hw_idx);
|
csid_hw->hw_intf->hw_idx);
|
||||||
|
mutex_unlock(&csid_hw->hw_info->hw_mutex);
|
||||||
return -EINVAL;
|
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) {
|
if (csid_hw->hw_info->open_count > 1) {
|
||||||
CAM_DBG(CAM_ISP, "CSID hw has already been enabled");
|
CAM_DBG(CAM_ISP, "CSID hw has already been enabled");
|
||||||
|
mutex_unlock(&csid_hw->hw_info->hw_mutex);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
mutex_unlock(&csid_hw->hw_info->hw_mutex);
|
||||||
|
|
||||||
rc = cam_soc_util_get_clk_level(soc_info, csid_hw->clk_rate,
|
rc = cam_soc_util_get_clk_level(soc_info, csid_hw->clk_rate,
|
||||||
soc_info->src_clk_idx, &clk_lvl);
|
soc_info->src_clk_idx, &clk_lvl);
|
||||||
@@ -2709,7 +2714,9 @@ disable_soc:
|
|||||||
cam_ife_csid_disable_soc_resources(soc_info);
|
cam_ife_csid_disable_soc_resources(soc_info);
|
||||||
csid_hw->hw_info->hw_state = CAM_HW_STATE_POWER_DOWN;
|
csid_hw->hw_info->hw_state = CAM_HW_STATE_POWER_DOWN;
|
||||||
err:
|
err:
|
||||||
|
mutex_lock(&csid_hw->hw_info->hw_mutex);
|
||||||
csid_hw->hw_info->open_count--;
|
csid_hw->hw_info->open_count--;
|
||||||
|
mutex_unlock(&csid_hw->hw_info->hw_mutex);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2851,17 +2858,22 @@ static int cam_ife_csid_ver1_disable_hw(
|
|||||||
int rc = 0;
|
int rc = 0;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
|
mutex_lock(&csid_hw->hw_info->hw_mutex);
|
||||||
/* Check for refcount */
|
/* Check for refcount */
|
||||||
if (!csid_hw->hw_info->open_count) {
|
if (!csid_hw->hw_info->open_count) {
|
||||||
CAM_WARN(CAM_ISP, "Unbalanced disable_hw");
|
CAM_WARN(CAM_ISP, "Unbalanced disable_hw");
|
||||||
|
mutex_unlock(&csid_hw->hw_info->hw_mutex);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Decrement ref Count */
|
/* Decrement ref Count */
|
||||||
csid_hw->hw_info->open_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;
|
return rc;
|
||||||
|
}
|
||||||
|
mutex_unlock(&csid_hw->hw_info->hw_mutex);
|
||||||
|
|
||||||
soc_info = &csid_hw->hw_info->soc_info;
|
soc_info = &csid_hw->hw_info->soc_info;
|
||||||
csid_reg = (struct cam_ife_csid_ver1_reg_info *)
|
csid_reg = (struct cam_ife_csid_ver1_reg_info *)
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0-only
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2016-2021, The Linux Foundation. All rights reserved.
|
* 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 <linux/module.h>
|
#include <linux/module.h>
|
||||||
@@ -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.l_tbl = NULL;
|
||||||
link->req.num_tbl = 0;
|
link->req.num_tbl = 0;
|
||||||
link->watchdog = NULL;
|
link->watchdog = NULL;
|
||||||
|
spin_lock_bh(&link->link_state_spin_lock);
|
||||||
link->state = CAM_CRM_LINK_STATE_AVAILABLE;
|
link->state = CAM_CRM_LINK_STATE_AVAILABLE;
|
||||||
|
spin_unlock_bh(&link->link_state_spin_lock);
|
||||||
link->parent = NULL;
|
link->parent = NULL;
|
||||||
link->sync_link_sof_skip = false;
|
link->sync_link_sof_skip = false;
|
||||||
link->open_req_cnt = 0;
|
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->try_for_internal_recovery = false;
|
||||||
link->is_sending_req = false;
|
link->is_sending_req = false;
|
||||||
atomic_set(&link->eof_event_cnt, 0);
|
atomic_set(&link->eof_event_cnt, 0);
|
||||||
|
mutex_lock(&link->lock);
|
||||||
link->properties_mask = CAM_LINK_PROPERTY_NONE;
|
link->properties_mask = CAM_LINK_PROPERTY_NONE;
|
||||||
|
mutex_unlock(&link->lock);
|
||||||
link->cont_empty_slots = 0;
|
link->cont_empty_slots = 0;
|
||||||
__cam_req_mgr_reset_apply_data(link);
|
__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;
|
int i, rc = 0;
|
||||||
|
|
||||||
|
spin_lock_bh(&link->link_state_spin_lock);
|
||||||
if (link->state == CAM_CRM_LINK_STATE_IDLE) {
|
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",
|
CAM_ERR(CAM_CRM, "link hdl %x is in idle state",
|
||||||
link->link_hdl);
|
link->link_hdl);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
spin_unlock_bh(&link->link_state_spin_lock);
|
||||||
|
|
||||||
for (i = 0; i < num_sync_links; i++) {
|
for (i = 0; i < num_sync_links; i++) {
|
||||||
if (sync_link[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);
|
sizeof(struct cam_req_mgr_slot) * MAX_REQ_SLOTS);
|
||||||
link->req.in_q = in_q;
|
link->req.in_q = in_q;
|
||||||
in_q->num_slots = 0;
|
in_q->num_slots = 0;
|
||||||
|
|
||||||
|
spin_lock_bh(&link->link_state_spin_lock);
|
||||||
link->state = CAM_CRM_LINK_STATE_IDLE;
|
link->state = CAM_CRM_LINK_STATE_IDLE;
|
||||||
|
spin_unlock_bh(&link->link_state_spin_lock);
|
||||||
|
|
||||||
link->parent = (void *)session;
|
link->parent = (void *)session;
|
||||||
link->is_sending_req = false;
|
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 */
|
/* Wait for the streaming of sync link */
|
||||||
link->initial_skip = true;
|
link->initial_skip = true;
|
||||||
/* Pause the timer before sensor stream on */
|
/* Pause the timer before sensor stream on */
|
||||||
|
spin_lock_bh(&link->link_state_spin_lock);
|
||||||
link->watchdog->pause_timer = true;
|
link->watchdog->pause_timer = true;
|
||||||
|
spin_unlock_bh(&link->link_state_spin_lock);
|
||||||
/* notify nodes */
|
/* notify nodes */
|
||||||
__cam_req_mgr_send_evt(0, CAM_REQ_MGR_LINK_EVT_RESUME,
|
__cam_req_mgr_send_evt(0, CAM_REQ_MGR_LINK_EVT_RESUME,
|
||||||
CRM_KMD_ERR_MAX, link);
|
CRM_KMD_ERR_MAX, link);
|
||||||
@@ -5216,13 +5229,16 @@ int cam_req_mgr_link_properties(struct cam_req_mgr_link_properties *properties)
|
|||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
spin_lock_bh(&link->link_state_spin_lock);
|
||||||
if (link->state != CAM_CRM_LINK_STATE_READY) {
|
if (link->state != CAM_CRM_LINK_STATE_READY) {
|
||||||
|
spin_unlock_bh(&link->link_state_spin_lock);
|
||||||
CAM_ERR(CAM_CRM,
|
CAM_ERR(CAM_CRM,
|
||||||
"Only can config link 0x%x properties in ready state",
|
"Only can config link 0x%x properties in ready state",
|
||||||
link->link_hdl);
|
link->link_hdl);
|
||||||
rc = -EAGAIN;
|
rc = -EAGAIN;
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
spin_unlock_bh(&link->link_state_spin_lock);
|
||||||
|
|
||||||
mutex_lock(&link->lock);
|
mutex_lock(&link->lock);
|
||||||
link->properties_mask = properties->properties_mask;
|
link->properties_mask = properties->properties_mask;
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0-only
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2014-2021, The Linux Foundation. All rights reserved.
|
* 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 <linux/module.h>
|
#include <linux/module.h>
|
||||||
@@ -1111,6 +1111,11 @@ void cam_smmu_reset_iommu_table(enum cam_smmu_init_dir ops)
|
|||||||
int j = 0;
|
int j = 0;
|
||||||
|
|
||||||
for (i = 0; i < iommu_cb_set.cb_num; i++) {
|
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;
|
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_list);
|
||||||
INIT_LIST_HEAD(&iommu_cb_set.cb_info[i].smmu_buf_kernel_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].token[j] = NULL;
|
||||||
iommu_cb_set.cb_info[i].handler[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);
|
mutex_unlock(&iommu_cb_set.cb_info[i].lock);
|
||||||
else
|
|
||||||
|
if (ops != CAM_SMMU_TABLE_INIT)
|
||||||
mutex_destroy(&iommu_cb_set.cb_info[i].lock);
|
mutex_destroy(&iommu_cb_set.cb_info[i].lock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user