From b8429f0813934c3c4351cf4ffb1b87a4b7c107fc Mon Sep 17 00:00:00 2001 From: Tejas Prajapati Date: Wed, 25 Aug 2021 15:14:42 +0530 Subject: [PATCH 01/25] msm: camera: memmgr: ref count for init and deinit Shared memory is initialized by CRM and used by ICP; with CRM not active the ICP would fail to access the shared memory if memory manager is deinit. Tracking open and close calls will help ICP driver to access the shared memory if CRM is not active. CRs-Fixed: 3019488 Change-Id: Ifdf198c2e3593050573c66aeba69d50d131435b9 Signed-off-by: Tejas Prajapati --- drivers/cam_icp/cam_icp_subdev.c | 10 +++++ drivers/cam_req_mgr/cam_mem_mgr.c | 65 +++++++++++++++++++------------ drivers/cam_req_mgr/cam_mem_mgr.h | 6 --- 3 files changed, 50 insertions(+), 31 deletions(-) diff --git a/drivers/cam_icp/cam_icp_subdev.c b/drivers/cam_icp/cam_icp_subdev.c index 1a3be9b64ad5..8a69ff7c1e8f 100644 --- a/drivers/cam_icp/cam_icp_subdev.c +++ b/drivers/cam_icp/cam_icp_subdev.c @@ -20,6 +20,7 @@ #include #include #include +#include "cam_mem_mgr.h" #include "cam_req_mgr_dev.h" #include "cam_subdev.h" #include "cam_node.h" @@ -86,10 +87,18 @@ static int cam_icp_subdev_open(struct v4l2_subdev *sd, goto end; } + + rc = cam_mem_mgr_init(); + if (rc) { + CAM_ERR(CAM_CRM, "mem mgr init failed"); + goto end; + } + hw_mgr_intf = &node->hw_mgr_intf; rc = hw_mgr_intf->hw_open(hw_mgr_intf->hw_mgr_priv, NULL); if (rc < 0) { CAM_ERR(CAM_ICP, "FW download failed"); + cam_mem_mgr_deinit(); goto end; } g_icp_dev.open_cnt++; @@ -130,6 +139,7 @@ int cam_icp_subdev_close_internal(struct v4l2_subdev *sd, goto end; } + cam_mem_mgr_deinit(); end: mutex_unlock(&g_icp_dev.icp_lock); return rc; diff --git a/drivers/cam_req_mgr/cam_mem_mgr.c b/drivers/cam_req_mgr/cam_mem_mgr.c index b928c7da46c7..9c8a404dbfe5 100644 --- a/drivers/cam_req_mgr/cam_mem_mgr.c +++ b/drivers/cam_req_mgr/cam_mem_mgr.c @@ -19,8 +19,11 @@ #include "cam_trace.h" #include "cam_common_util.h" -static struct cam_mem_table tbl; -static atomic_t cam_mem_mgr_state = ATOMIC_INIT(CAM_MEM_MGR_UNINITIALIZED); +static struct cam_mem_table tbl = { + .m_lock = __MUTEX_INITIALIZER(tbl.m_lock), +}; + +static atomic_t cam_mem_mgr_refcnt = ATOMIC_INIT(0); static void cam_mem_mgr_print_tbl(void) { @@ -164,6 +167,16 @@ int cam_mem_mgr_init(void) int i; int bitmap_size; + mutex_lock(&tbl.m_lock); + + if (atomic_inc_return(&cam_mem_mgr_refcnt) > 1) { + CAM_DBG(CAM_MEM, + "Mem mgr refcnt: %d", + atomic_read(&cam_mem_mgr_refcnt)); + mutex_unlock(&tbl.m_lock); + return 0; + } + memset(tbl.bufq, 0, sizeof(tbl.bufq)); if (cam_smmu_need_force_alloc_cached(&tbl.force_cache_allocs)) { @@ -173,8 +186,13 @@ int cam_mem_mgr_init(void) bitmap_size = BITS_TO_LONGS(CAM_MEM_BUFQ_MAX) * sizeof(long); tbl.bitmap = kzalloc(bitmap_size, GFP_KERNEL); - if (!tbl.bitmap) + if (!tbl.bitmap) { + atomic_dec(&cam_mem_mgr_refcnt); + CAM_DBG(CAM_MEM, "Mem mgr refcnt: %d", + atomic_read(&cam_mem_mgr_refcnt)); + mutex_unlock(&tbl.m_lock); return -ENOMEM; + } tbl.bits = bitmap_size * BITS_PER_BYTE; bitmap_zero(tbl.bitmap, tbl.bits); @@ -185,9 +203,8 @@ int cam_mem_mgr_init(void) tbl.bufq[i].fd = -1; tbl.bufq[i].buf_handle = -1; } - mutex_init(&tbl.m_lock); - atomic_set(&cam_mem_mgr_state, CAM_MEM_MGR_INITIALIZED); + mutex_unlock(&tbl.m_lock); cam_mem_mgr_create_debug_fs(); @@ -234,7 +251,7 @@ int cam_mem_get_io_buf(int32_t buf_handle, int32_t mmu_handle, *len_ptr = 0; - if (!atomic_read(&cam_mem_mgr_state)) { + if (!atomic_read(&cam_mem_mgr_refcnt)) { CAM_ERR(CAM_MEM, "failed. mem_mgr not initialized"); return -EINVAL; } @@ -285,12 +302,7 @@ int cam_mem_get_cpu_buf(int32_t buf_handle, uintptr_t *vaddr_ptr, size_t *len) { int idx; - if (!atomic_read(&cam_mem_mgr_state)) { - CAM_ERR(CAM_MEM, "failed. mem_mgr not initialized"); - return -EINVAL; - } - - if (!atomic_read(&cam_mem_mgr_state)) { + if (!atomic_read(&cam_mem_mgr_refcnt)) { CAM_ERR(CAM_MEM, "failed. mem_mgr not initialized"); return -EINVAL; } @@ -333,7 +345,7 @@ int cam_mem_mgr_cache_ops(struct cam_mem_cache_ops_cmd *cmd) uint32_t cache_dir; unsigned long dmabuf_flag = 0; - if (!atomic_read(&cam_mem_mgr_state)) { + if (!atomic_read(&cam_mem_mgr_refcnt)) { CAM_ERR(CAM_MEM, "failed. mem_mgr not initialized"); return -EINVAL; } @@ -659,7 +671,7 @@ int cam_mem_mgr_alloc_and_map(struct cam_mem_mgr_alloc_cmd *cmd) uintptr_t kvaddr = 0; size_t klen; - if (!atomic_read(&cam_mem_mgr_state)) { + if (!atomic_read(&cam_mem_mgr_refcnt)) { CAM_ERR(CAM_MEM, "failed. mem_mgr not initialized"); return -EINVAL; } @@ -811,7 +823,7 @@ int cam_mem_mgr_map(struct cam_mem_mgr_map_cmd *cmd) size_t len = 0; bool is_internal = false; - if (!atomic_read(&cam_mem_mgr_state)) { + if (!atomic_read(&cam_mem_mgr_refcnt)) { CAM_ERR(CAM_MEM, "failed. mem_mgr not initialized"); return -EINVAL; } @@ -998,7 +1010,6 @@ static int cam_mem_mgr_cleanup_table(void) { int i; - mutex_lock(&tbl.m_lock); for (i = 1; i < CAM_MEM_BUFQ_MAX; i++) { if (!tbl.bufq[i].active) { CAM_DBG(CAM_MEM, @@ -1034,23 +1045,27 @@ static int cam_mem_mgr_cleanup_table(void) bitmap_zero(tbl.bitmap, tbl.bits); /* We need to reserve slot 0 because 0 is invalid */ set_bit(0, tbl.bitmap); - mutex_unlock(&tbl.m_lock); return 0; } void cam_mem_mgr_deinit(void) { - atomic_set(&cam_mem_mgr_state, CAM_MEM_MGR_UNINITIALIZED); + mutex_lock(&tbl.m_lock); + if (!atomic_dec_and_test(&cam_mem_mgr_refcnt)) { + CAM_DBG(CAM_MEM, "Mem mgr refcnt: %d", + atomic_read(&cam_mem_mgr_refcnt)); + mutex_unlock(&tbl.m_lock); + return; + } + cam_mem_mgr_cleanup_table(); debugfs_remove_recursive(tbl.dentry); - mutex_lock(&tbl.m_lock); bitmap_zero(tbl.bitmap, tbl.bits); kfree(tbl.bitmap); tbl.bitmap = NULL; tbl.dbg_buf_idx = -1; mutex_unlock(&tbl.m_lock); - mutex_destroy(&tbl.m_lock); } static int cam_mem_util_unmap(int32_t idx, @@ -1148,7 +1163,7 @@ int cam_mem_mgr_release(struct cam_mem_mgr_release_cmd *cmd) int idx; int rc; - if (!atomic_read(&cam_mem_mgr_state)) { + if (!atomic_read(&cam_mem_mgr_refcnt)) { CAM_ERR(CAM_MEM, "failed. mem_mgr not initialized"); return -EINVAL; } @@ -1201,7 +1216,7 @@ int cam_mem_mgr_request_mem(struct cam_mem_mgr_request_desc *inp, enum cam_smmu_region_id region = CAM_SMMU_REGION_SHARED; - if (!atomic_read(&cam_mem_mgr_state)) { + if (!atomic_read(&cam_mem_mgr_refcnt)) { CAM_ERR(CAM_MEM, "failed. mem_mgr not initialized"); return -EINVAL; } @@ -1327,7 +1342,7 @@ int cam_mem_mgr_release_mem(struct cam_mem_mgr_memory_desc *inp) int32_t idx; int rc; - if (!atomic_read(&cam_mem_mgr_state)) { + if (!atomic_read(&cam_mem_mgr_refcnt)) { CAM_ERR(CAM_MEM, "failed. mem_mgr not initialized"); return -EINVAL; } @@ -1380,7 +1395,7 @@ int cam_mem_mgr_reserve_memory_region(struct cam_mem_mgr_request_desc *inp, int32_t smmu_hdl = 0; int32_t num_hdl = 0; - if (!atomic_read(&cam_mem_mgr_state)) { + if (!atomic_read(&cam_mem_mgr_refcnt)) { CAM_ERR(CAM_MEM, "failed. mem_mgr not initialized"); return -EINVAL; } @@ -1475,7 +1490,7 @@ int cam_mem_mgr_free_memory_region(struct cam_mem_mgr_memory_desc *inp) int rc; int32_t smmu_hdl; - if (!atomic_read(&cam_mem_mgr_state)) { + if (!atomic_read(&cam_mem_mgr_refcnt)) { CAM_ERR(CAM_MEM, "failed. mem_mgr not initialized"); return -EINVAL; } diff --git a/drivers/cam_req_mgr/cam_mem_mgr.h b/drivers/cam_req_mgr/cam_mem_mgr.h index 26ab9cb75319..9cf7a74b07cf 100644 --- a/drivers/cam_req_mgr/cam_mem_mgr.h +++ b/drivers/cam_req_mgr/cam_mem_mgr.h @@ -11,12 +11,6 @@ #include #include "cam_mem_mgr_api.h" -/* Enum for possible mem mgr states */ -enum cam_mem_mgr_state { - CAM_MEM_MGR_UNINITIALIZED, - CAM_MEM_MGR_INITIALIZED, -}; - /*Enum for possible SMMU operations */ enum cam_smmu_mapping_client { CAM_SMMU_MAPPING_USER, From ed7d45ddc51e148bda5e67879a9df75d1fc94f83 Mon Sep 17 00:00:00 2001 From: Shravya Samala Date: Mon, 6 Sep 2021 21:12:00 +0530 Subject: [PATCH 02/25] msm: camera: jpeg: Ensure in/out map entries are within allowed range Added checks to make sure in_map /out_map entries of packet io configs are within expected maximum value. CRs-Fixed: 3007258 Change-Id: I7e5a652cd8f9ae104a10a2af551fe49930849b2d Signed-off-by: Shravya Samala --- drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c b/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c index 8078ee59dc20..fa86ad313541 100644 --- a/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c +++ b/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c @@ -743,10 +743,11 @@ static int cam_jpeg_mgr_prepare_hw_update(void *hw_mgr_priv, } if ((packet->num_cmd_buf > 5) || !packet->num_patches || - !packet->num_io_configs) { - CAM_ERR(CAM_JPEG, "wrong number of cmd/patch info: %u %u", - packet->num_cmd_buf, - packet->num_patches); + !packet->num_io_configs || + (packet->num_io_configs > CAM_JPEG_IMAGE_MAX)) { + CAM_ERR(CAM_JPEG, + "wrong number of cmd/patch/io_configs info: %u %u %u", + packet->num_cmd_buf, packet->num_patches, packet->num_io_configs); return -EINVAL; } From 77cf2e394fbf54752dac08b4de2735853c4b8d47 Mon Sep 17 00:00:00 2001 From: Vishal Verma Date: Sun, 15 Aug 2021 00:14:11 +0530 Subject: [PATCH 03/25] msm: camera: flash: Add support for qup i2c flash Add Support for qup i2c based flash. Update i2c driver probe function and added regulator init at power up and init for gpio pin control table. Since positive return values are not errors for qup i2c rx and tx data transfer, fix the return type for the APIs. Added check for null pointer in get flash dt data for device node. Correct the logging group in sensor util for regulator power up function. CRs-Fixed: 3047031 Change-Id: I70558fbb489b622da25278283015139b6d4fe2a6 Signed-off-by: Vishal Verma --- .../cam_flash/cam_flash_dev.c | 54 ++++++++++++++++--- .../cam_flash/cam_flash_soc.c | 9 +++- .../cam_sensor_io/cam_sensor_qup_i2c.c | 20 +++++-- .../cam_sensor_utils/cam_sensor_util.c | 4 +- 4 files changed, 73 insertions(+), 14 deletions(-) diff --git a/drivers/cam_sensor_module/cam_flash/cam_flash_dev.c b/drivers/cam_sensor_module/cam_flash/cam_flash_dev.c index b2dd3265da69..197502ff5896 100644 --- a/drivers/cam_sensor_module/cam_flash/cam_flash_dev.c +++ b/drivers/cam_sensor_module/cam_flash/cam_flash_dev.c @@ -429,6 +429,7 @@ static int cam_flash_component_bind(struct device *dev, return -ENOMEM; fctrl->pdev = pdev; + fctrl->of_node = pdev->dev.of_node; fctrl->soc_info.pdev = pdev; fctrl->soc_info.dev = &pdev->dev; fctrl->soc_info.dev_name = pdev->name; @@ -600,13 +601,18 @@ static int32_t cam_flash_i2c_driver_probe(struct i2c_client *client, { int32_t rc = 0, i = 0; struct cam_flash_ctrl *fctrl; + struct cam_hw_soc_info *soc_info = NULL; - if (client == NULL || id == NULL) { - CAM_ERR(CAM_FLASH, "Invalid Args client: %pK id: %pK", - client, id); + if (client == NULL) { + CAM_ERR(CAM_FLASH, "Invalid Args client: %pK", + client); return -EINVAL; } + if (id == NULL) { + CAM_DBG(CAM_FLASH, "device id is Null"); + } + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { CAM_ERR(CAM_FLASH, "%s :: i2c_check_functionality failed", client->name); @@ -618,9 +624,9 @@ static int32_t cam_flash_i2c_driver_probe(struct i2c_client *client, if (!fctrl) return -ENOMEM; - i2c_set_clientdata(client, fctrl); - + client->dev.driver_data = fctrl; fctrl->io_master_info.client = client; + fctrl->of_node = client->dev.of_node; fctrl->soc_info.dev = &client->dev; fctrl->soc_info.dev_name = client->name; fctrl->io_master_info.master_type = I2C_MASTER; @@ -631,6 +637,40 @@ static int32_t cam_flash_i2c_driver_probe(struct i2c_client *client, goto free_ctrl; } + rc = cam_flash_init_default_params(fctrl); + if (rc) { + CAM_ERR(CAM_FLASH, + "failed: cam_flash_init_default_params rc %d", + rc); + goto free_ctrl; + } + + soc_info = &fctrl->soc_info; + rc = cam_sensor_util_regulator_powerup(soc_info); + if (rc < 0) { + CAM_ERR(CAM_FLASH, "regulator power up for flash failed %d", + rc); + goto free_ctrl; + } + + if (!soc_info->gpio_data) { + CAM_DBG(CAM_FLASH, "No GPIO found"); + rc = 0; + return rc; + } + + if (!soc_info->gpio_data->cam_gpio_common_tbl_size) { + CAM_DBG(CAM_FLASH, "No GPIO found"); + return -EINVAL; + } + + rc = cam_sensor_util_init_gpio_pin_tbl(soc_info, + &fctrl->power_info.gpio_num_info); + if ((rc < 0) || (!fctrl->power_info.gpio_num_info)) { + CAM_ERR(CAM_FLASH, "No/Error Flash GPIOs"); + goto free_ctrl; + } + rc = cam_flash_init_subdev(fctrl); if (rc) goto free_ctrl; @@ -699,6 +739,7 @@ static struct i2c_driver cam_flash_i2c_driver = { .remove = cam_flash_i2c_driver_remove, .driver = { .name = FLASH_DRIVER_I2C, + .of_match_table = cam_flash_dt_match, }, }; @@ -713,8 +754,9 @@ int32_t cam_flash_init_module(void) } rc = i2c_add_driver(&cam_flash_i2c_driver); - if (rc) + if (rc < 0) CAM_ERR(CAM_FLASH, "i2c_add_driver failed rc: %d", rc); + return rc; } diff --git a/drivers/cam_sensor_module/cam_flash/cam_flash_soc.c b/drivers/cam_sensor_module/cam_flash/cam_flash_soc.c index 9ec28e953f8b..9eac7a8b8aaf 100644 --- a/drivers/cam_sensor_module/cam_flash/cam_flash_soc.c +++ b/drivers/cam_sensor_module/cam_flash/cam_flash_soc.c @@ -293,7 +293,14 @@ int cam_flash_get_dt_data(struct cam_flash_ctrl *fctrl, rc = -ENOMEM; goto release_soc_res; } - of_node = fctrl->pdev->dev.of_node; + + if (fctrl->of_node == NULL) { + CAM_ERR(CAM_FLASH, "device node is NULL"); + rc = -EINVAL; + goto free_soc_private; + } + + of_node = fctrl->of_node; rc = cam_soc_util_get_dt_properties(soc_info); if (rc) { diff --git a/drivers/cam_sensor_module/cam_sensor_io/cam_sensor_qup_i2c.c b/drivers/cam_sensor_module/cam_sensor_io/cam_sensor_qup_i2c.c index 38af4f74bedb..17bcb0867abb 100644 --- a/drivers/cam_sensor_module/cam_sensor_io/cam_sensor_qup_i2c.c +++ b/drivers/cam_sensor_module/cam_sensor_io/cam_sensor_qup_i2c.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #include "cam_sensor_cmn_header.h" @@ -31,9 +31,14 @@ static int32_t cam_qup_i2c_rxdata( }, }; rc = i2c_transfer(dev_client->adapter, msgs, 2); - if (rc < 0) + if (rc < 0) { CAM_ERR(CAM_SENSOR, "failed 0x%x", saddr); - return rc; + return rc; + } + /* Returns negative errno */ + /* else the number of messages executed. */ + /* So positive values are not errors. */ + return 0; } @@ -52,9 +57,14 @@ static int32_t cam_qup_i2c_txdata( }, }; rc = i2c_transfer(dev_client->client->adapter, msg, 1); - if (rc < 0) + if (rc < 0) { CAM_ERR(CAM_SENSOR, "failed 0x%x", saddr); - return rc; + return rc; + } + /* Returns negative errno, */ + /* else the number of messages executed. */ + /* So positive values are not errors. */ + return 0; } int32_t cam_qup_i2c_read(struct i2c_client *client, diff --git a/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c b/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c index 771ca38fa6d8..a8bad02a0247 100644 --- a/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c +++ b/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c @@ -74,11 +74,11 @@ int32_t cam_sensor_util_regulator_powerup(struct cam_hw_soc_info *soc_info) if (IS_ERR_OR_NULL(soc_info->rgltr[i])) { rc = PTR_ERR(soc_info->rgltr[i]); rc = rc ? rc : -EINVAL; - CAM_ERR(CAM_ACTUATOR, "get failed for regulator %s %d", + CAM_ERR(CAM_SENSOR, "get failed for regulator %s %d", soc_info->rgltr_name[i], rc); return rc; } - CAM_DBG(CAM_ACTUATOR, "get for regulator %s", + CAM_DBG(CAM_SENSOR, "get for regulator %s", soc_info->rgltr_name[i]); } From 1f20f5bc62e02d8c5ad0f10491b533fbe75afdbb Mon Sep 17 00:00:00 2001 From: sokchetra eung Date: Tue, 17 Aug 2021 14:55:38 -0700 Subject: [PATCH 04/25] msm: camera: req_mgr: Table info dump removed Remove dump_tbl_info function and all of its invocations in CRM to prevent dumping all the handle info when holding the spin lock. CRs-Fixed: 3014074, 3014073 Change-Id: Ie98bafb489fc0d1f2d75cf0f3f08efb48d9b4062 Signed-off-by: sokchetra eung --- drivers/cam_req_mgr/cam_req_mgr_util.c | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/drivers/cam_req_mgr/cam_req_mgr_util.c b/drivers/cam_req_mgr/cam_req_mgr_util.c index 00b919fcec30..4faba1d006b6 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_util.c +++ b/drivers/cam_req_mgr/cam_req_mgr_util.c @@ -115,7 +115,7 @@ static int32_t cam_get_free_handle_index(void) idx = find_first_zero_bit(hdl_tbl->bitmap, hdl_tbl->bits); if (idx >= CAM_REQ_MGR_MAX_HANDLES_V2 || idx < 0) { - CAM_DBG(CAM_CRM, "idx: %d", idx); + CAM_ERR(CAM_CRM, "No free index found idx: %d", idx); return -ENOSR; } @@ -124,20 +124,6 @@ static int32_t cam_get_free_handle_index(void) return idx; } -void cam_dump_tbl_info(void) -{ - int i; - - for (i = 0; i < CAM_REQ_MGR_MAX_HANDLES_V2; i++) - CAM_INFO(CAM_CRM, - "i: %d session_hdl=0x%x hdl_value=0x%x type=%d state=%d dev_id=0x%llx", - i, hdl_tbl->hdl[i].session_hdl, - hdl_tbl->hdl[i].hdl_value, - hdl_tbl->hdl[i].type, - hdl_tbl->hdl[i].state, - hdl_tbl->hdl[i].dev_id); -} - int32_t cam_create_session_hdl(void *priv) { int idx; @@ -154,7 +140,6 @@ int32_t cam_create_session_hdl(void *priv) idx = cam_get_free_handle_index(); if (idx < 0) { CAM_ERR(CAM_CRM, "Unable to create session handle"); - cam_dump_tbl_info(); spin_unlock_bh(&hdl_tbl_lock); return idx; } @@ -190,7 +175,6 @@ int32_t cam_create_device_hdl(struct cam_create_dev_hdl *hdl_data) if (idx < 0) { CAM_ERR(CAM_CRM, "Unable to create device handle(idx= %d)", idx); - cam_dump_tbl_info(); spin_unlock_bh(&hdl_tbl_lock); return idx; } From 6e882932bd82a9ae993dc9941cafc03f26602127 Mon Sep 17 00:00:00 2001 From: Gaurav Jindal Date: Thu, 9 Apr 2020 14:42:44 +0530 Subject: [PATCH 05/25] msm: camera: core: Delete request from pending list in case of error While preparing hw for request, there is a possiblity of receiving invalid sync object. In this case, we need to return error. By this time, the request is already in pending list. While returning error, request is moved back to free list. But deleting from the pending list was missed. This commit deleted the request from the pending list if the sync object received is invalid. CRs-Fixed: 2660625 Change-Id: Id619452889476b0c2811c8560361205b0d89bcb9 Signed-off-by: Gaurav Jindal --- drivers/cam_core/cam_context_utils.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/cam_core/cam_context_utils.c b/drivers/cam_core/cam_context_utils.c index cfef68791326..eb1cfc581bb7 100644 --- a/drivers/cam_core/cam_context_utils.c +++ b/drivers/cam_core/cam_context_utils.c @@ -457,6 +457,9 @@ int32_t cam_context_prepare_dev_to_hw(struct cam_context *ctx, rc = cam_sync_check_valid( req->in_map_entries[j].sync_id); if (rc) { + spin_lock(&ctx->lock); + list_del_init(&req->list); + spin_unlock(&ctx->lock); CAM_ERR(CAM_CTXT, "invalid in map sync object %d", req->in_map_entries[j].sync_id); From abee20f08a78c5b9441f2d8c4b6d50641d3d2dda Mon Sep 17 00:00:00 2001 From: Vikram Sharma Date: Tue, 28 Sep 2021 22:05:01 +0530 Subject: [PATCH 06/25] msm: camera: isp: Add handling for flush in flushed state This change handles race condition in which flush is handled in flushed state. CRs-Fixed: 3038297 Change-Id: I8be1f8c70431c77366f8846d8ccab3414f3ede3e Signed-off-by: Vikram Sharma --- drivers/cam_isp/cam_isp_context.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index acd4c1acad93..87779aea1a16 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -3541,6 +3541,19 @@ hw_dump: return rc; } +static int __cam_isp_ctx_flush_req_in_flushed_state( + struct cam_context *ctx, + struct cam_req_mgr_flush_request *flush_req) +{ + if (flush_req->type == CAM_REQ_MGR_FLUSH_TYPE_ALL) { + CAM_INFO(CAM_ISP, "Flush in flushed state req id %lld ctx_id:%d", + flush_req->req_id, ctx->ctx_id); + ctx->last_flush_req = flush_req->req_id; + } + + return 0; +} + static int __cam_isp_ctx_flush_req(struct cam_context *ctx, struct list_head *req_list, struct cam_req_mgr_flush_request *flush_req) { @@ -4637,6 +4650,14 @@ static int __cam_isp_ctx_config_dev_in_top_state( packet->header.request_id); rc = -EBADR; goto free_req; + } else if ((packet_opcode == CAM_ISP_PACKET_INIT_DEV) + && (packet->header.request_id <= ctx->last_flush_req) + && ctx->last_flush_req && packet->header.request_id) { + CAM_WARN(CAM_ISP, + "last flushed req is %lld, config dev(init) for req %lld", + ctx->last_flush_req, packet->header.request_id); + rc = -EBADR; + goto free_req; } cfg.packet = packet; @@ -5927,6 +5948,7 @@ static struct cam_ctx_ops .crm_ops = { .unlink = __cam_isp_ctx_unlink_in_ready, .process_evt = __cam_isp_ctx_process_evt, + .flush_req = __cam_isp_ctx_flush_req_in_flushed_state, }, .irq_ops = NULL, .pagefault_ops = cam_isp_context_dump_requests, From 7f25abfda5dc2f637aa9d52566a58a87f3528bf9 Mon Sep 17 00:00:00 2001 From: Vikram Sharma Date: Mon, 11 Oct 2021 19:43:00 +0530 Subject: [PATCH 07/25] msm: camera: cdm: handle dead lock scenario This change handles a race condition in which cdm workqueue is scheduled on one of the cores and cdm flush is executing on another core. We come across a dead lock between fifo_lock and hw_mutex lock. CRs-Fixed: 3049531 Change-Id: Ie0b8982a7e55218fc5655f8e3d08a952fd852ed7 Signed-off-by: Vikram Sharma --- drivers/cam_cdm/cam_cdm_core_common.c | 5 ----- drivers/cam_cdm/cam_cdm_hw_core.c | 7 ++++++- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/cam_cdm/cam_cdm_core_common.c b/drivers/cam_cdm/cam_cdm_core_common.c index fd84b8d6866b..6ca94e740013 100644 --- a/drivers/cam_cdm/cam_cdm_core_common.c +++ b/drivers/cam_cdm/cam_cdm_core_common.c @@ -180,12 +180,10 @@ void cam_cdm_notify_clients(struct cam_hw_info *cdm_hw, (struct cam_cdm_bl_cb_request_entry *)data; client_idx = CAM_CDM_GET_CLIENT_IDX(node->client_hdl); - mutex_lock(&cdm_hw->hw_mutex); client = core->clients[client_idx]; if ((!client) || (client->handle != node->client_hdl)) { CAM_ERR(CAM_CDM, "Invalid client %pK hdl=%x", client, node->client_hdl); - mutex_unlock(&cdm_hw->hw_mutex); return; } cam_cdm_get_client_refcount(client); @@ -204,7 +202,6 @@ void cam_cdm_notify_clients(struct cam_hw_info *cdm_hw, } mutex_unlock(&client->lock); cam_cdm_put_client_refcount(client); - mutex_unlock(&cdm_hw->hw_mutex); return; } else if (status == CAM_CDM_CB_STATUS_HW_RESET_DONE || status == CAM_CDM_CB_STATUS_HW_FLUSH || @@ -242,7 +239,6 @@ void cam_cdm_notify_clients(struct cam_hw_info *cdm_hw, for (i = 0; i < CAM_PER_CDM_MAX_REGISTERED_CLIENTS; i++) { if (core->clients[i] != NULL) { - mutex_lock(&cdm_hw->hw_mutex); client = core->clients[i]; cam_cdm_get_client_refcount(client); mutex_lock(&client->lock); @@ -265,7 +261,6 @@ void cam_cdm_notify_clients(struct cam_hw_info *cdm_hw, } mutex_unlock(&client->lock); cam_cdm_put_client_refcount(client); - mutex_unlock(&cdm_hw->hw_mutex); } } } diff --git a/drivers/cam_cdm/cam_cdm_hw_core.c b/drivers/cam_cdm/cam_cdm_hw_core.c index 37f2a0a10967..583963a0d6e2 100644 --- a/drivers/cam_cdm/cam_cdm_hw_core.c +++ b/drivers/cam_cdm/cam_cdm_hw_core.c @@ -1238,6 +1238,7 @@ static void cam_hw_cdm_work(struct work_struct *work) return; } + mutex_lock(&cdm_hw->hw_mutex); mutex_lock(&core->bl_fifo[fifo_idx].fifo_lock); if (atomic_read(&core->bl_fifo[fifo_idx].work_record)) @@ -1251,6 +1252,7 @@ static void cam_hw_cdm_work(struct work_struct *work) core->arbitration); mutex_unlock(&core->bl_fifo[fifo_idx] .fifo_lock); + mutex_unlock(&cdm_hw->hw_mutex); return; } @@ -1289,6 +1291,7 @@ static void cam_hw_cdm_work(struct work_struct *work) } mutex_unlock(&core->bl_fifo[payload->fifo_idx] .fifo_lock); + mutex_unlock(&cdm_hw->hw_mutex); } if (payload->irq_status & @@ -1405,9 +1408,9 @@ handle_cdm_pf: cdm_hw->soc_info.index); for (i = 0; i < core->offsets->reg_data->num_bl_fifo; i++) mutex_unlock(&core->bl_fifo[i].fifo_lock); - mutex_unlock(&cdm_hw->hw_mutex); cam_cdm_notify_clients(cdm_hw, CAM_CDM_CB_STATUS_PAGEFAULT, (void *)pf_info->iova); + mutex_unlock(&cdm_hw->hw_mutex); clear_bit(CAM_CDM_ERROR_HW_STATUS, &core->cdm_status); } else { CAM_ERR(CAM_CDM, "Invalid token"); @@ -1806,9 +1809,11 @@ int cam_hw_cdm_handle_error_info( if (node != NULL) { if (node->request_type == CAM_HW_CDM_BL_CB_CLIENT) { + mutex_lock(&cdm_hw->hw_mutex); cam_cdm_notify_clients(cdm_hw, CAM_CDM_CB_STATUS_HW_ERROR, (void *)node); + mutex_unlock(&cdm_hw->hw_mutex); } else if (node->request_type == CAM_HW_CDM_BL_CB_INTERNAL) { CAM_ERR(CAM_CDM, "Invalid node=%pK %d", node, node->request_type); From 45dbb6c0cde224cb333d62a9111c264367d27df2 Mon Sep 17 00:00:00 2001 From: Trishansh Bhardwaj Date: Fri, 30 Jul 2021 05:22:31 +0000 Subject: [PATCH 08/25] msm: camera: ife: Add ife num outport bound checks Variable num_ports is provided by userspace, it it used to index res_list_isp_out. Big num_ports value can cause out of bound read. Bound check num_ports, to prevent OOB read. CRs-Fixed: 3056360 Change-Id: I86b6cf0419c68af1f510ce166e4964e177367eaf Signed-off-by: Trishansh Bhardwaj --- .../isp_hw_mgr/hw_utils/cam_isp_packet_parser.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c b/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c index 09b0cdb0e881..7357cfd9f77b 100644 --- a/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c +++ b/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c @@ -124,6 +124,12 @@ static int cam_isp_update_dual_config( cpu_addr += (cmd_desc->offset / 4); dual_config = (struct cam_isp_dual_config *)cpu_addr; + if (dual_config->num_ports > size_isp_out) { + CAM_ERR(CAM_ISP, "num_ports %d more than max_vfe_out_res %d", + dual_config->num_ports, size_isp_out); + return -EINVAL; + } + if ((dual_config->num_ports * sizeof(struct cam_isp_dual_stripe_config)) > (remain_len - offsetof(struct cam_isp_dual_config, stripes))) { @@ -132,14 +138,6 @@ static int cam_isp_update_dual_config( } for (i = 0; i < dual_config->num_ports; i++) { - if (i >= CAM_ISP_IFE_OUT_RES_BASE + size_isp_out) { - CAM_ERR(CAM_ISP, - "failed update for i:%d > size_isp_out:%d", - i, size_isp_out); - rc = -EINVAL; - goto end; - } - hw_mgr_res = &res_list_isp_out[i]; if (!hw_mgr_res) { CAM_ERR(CAM_ISP, From 8a251d8af120b79e98a7498e16ff4b77b7d38800 Mon Sep 17 00:00:00 2001 From: Vikram Sharma Date: Thu, 14 Oct 2021 16:56:51 +0530 Subject: [PATCH 09/25] msm: camera: isp: Fix PPI index based on the phy selection 1) There is one to one mapping for ppi index with phy index but phy select is not always equal to phy number,for some targets "phy_sel = phy_idx + 1", and for some targets it is "phy_sel = phy_idx", ppi_index should be updated accordingly. 2) Updated to configure ppi cfg register as. for cphy, disable dphy in config register. for dphy, do nothing (both cphy and dphy will be selected). then enable all lanes. CRs-Fixed: 3057665 Change-Id: I1d5d66034a5563b5adcb8163acf9a668d10d4a19 Signed-off-by: Vikram Sharma --- .../isp_hw/ppi_hw/cam_csid_ppi_core.c | 32 ++++--------------- .../isp_hw/ppi_hw/cam_csid_ppi_core.h | 2 +- .../isp_hw/tfe_csid_hw/cam_tfe_csid530.h | 3 +- .../isp_hw/tfe_csid_hw/cam_tfe_csid_core.c | 10 ++++-- .../isp_hw/tfe_csid_hw/cam_tfe_csid_core.h | 1 + 5 files changed, 19 insertions(+), 29 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ppi_hw/cam_csid_ppi_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ppi_hw/cam_csid_ppi_core.c index 42a84af64e24..0fa94fc5fde5 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ppi_hw/cam_csid_ppi_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ppi_hw/cam_csid_ppi_core.c @@ -163,9 +163,7 @@ static int cam_csid_ppi_init_hw(void *hw_priv, void *init_args, { int i, rc = 0; uint32_t num_lanes; - uint32_t lanes[CAM_CSID_PPI_HW_MAX] = {0, 0, 0, 0}; uint32_t cphy; - bool dl0, dl1; uint32_t ppi_cfg_val = 0; struct cam_csid_ppi_hw *ppi_hw; struct cam_hw_info *ppi_hw_info; @@ -180,7 +178,6 @@ static int cam_csid_ppi_init_hw(void *hw_priv, void *init_args, goto end; } - dl0 = dl1 = false; ppi_hw_info = (struct cam_hw_info *)hw_priv; ppi_hw = (struct cam_csid_ppi_hw *)ppi_hw_info->core_info; ppi_reg = ppi_hw->ppi_info->ppi_reg; @@ -195,30 +192,15 @@ static int cam_csid_ppi_init_hw(void *hw_priv, void *init_args, CAM_DBG(CAM_ISP, "lane_cfg 0x%x | num_lanes 0x%x | lane_type 0x%x", ppi_cfg.lane_cfg, num_lanes, cphy); - for (i = 0; i < num_lanes; i++) { - lanes[i] = ppi_cfg.lane_cfg & (0x3 << (4 * i)); - (lanes[i] < 2) ? (dl0 = true) : (dl1 = true); - CAM_DBG(CAM_ISP, "lanes[%d] %d", i, lanes[i]); + if (cphy) { + ppi_cfg_val |= PPI_CFG_CPHY_DLX_SEL(0); + ppi_cfg_val |= PPI_CFG_CPHY_DLX_SEL(1); + } else { + ppi_cfg_val = 0; } - if (num_lanes) { - if (cphy) { - for (i = 0; i < num_lanes; i++) { - ppi_cfg_val |= PPI_CFG_CPHY_DLX_SEL(lanes[i]); - ppi_cfg_val |= PPI_CFG_CPHY_DLX_EN(lanes[i]); - } - } else { - if (dl0) - ppi_cfg_val |= PPI_CFG_CPHY_DLX_EN(0); - if (dl1) - ppi_cfg_val |= PPI_CFG_CPHY_DLX_EN(1); - } - } else { - CAM_ERR(CAM_ISP, - "Number of lanes to enable is cannot be zero"); - rc = -1; - goto end; - } + for (i = 0; i < CAM_CSID_PPI_LANES_MAX; i++) + ppi_cfg_val |= PPI_CFG_CPHY_DLX_EN(i); CAM_DBG(CAM_ISP, "ppi_cfg_val 0x%x", ppi_cfg_val); soc_info = &ppi_hw->hw_info->soc_info; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ppi_hw/cam_csid_ppi_core.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/ppi_hw/cam_csid_ppi_core.h index dc0edf7e50ce..5f8873f529a7 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ppi_hw/cam_csid_ppi_core.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ppi_hw/cam_csid_ppi_core.h @@ -25,7 +25,7 @@ /* * Select the PHY (CPHY set '1' or DPHY set '0') */ -#define PPI_CFG_CPHY_DLX_SEL(X) ((X < 2) ? BIT(X) : 0) +#define PPI_CFG_CPHY_DLX_SEL(X) BIT(X) #define PPI_CFG_CPHY_DLX_EN(X) BIT(4+X) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid530.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid530.h index b0e9dc862c4d..fa54bb4f1c06 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid530.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid530.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2021, The Linux Foundation. All rights reserved. */ #ifndef _CAM_TFE_CSID_530_H_ @@ -134,6 +134,7 @@ static struct cam_tfe_csid_csi2_rx_reg_offset .csid_csi2_rx_irq_set_addr = 0x2c, /*CSI2 rx control */ + .phy_sel_base = 1, .csid_csi2_rx_cfg0_addr = 0x100, .csid_csi2_rx_cfg1_addr = 0x104, .csid_csi2_rx_capture_ctrl_addr = 0x108, diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.c index 7c86db7b8912..c0ef268f4198 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.c @@ -960,8 +960,14 @@ static int cam_tfe_csid_enable_csi2( cam_io_w_mb(val, soc_info->reg_map[0].mem_base + csid_reg->csi2_reg->csid_csi2_rx_irq_mask_addr); + /* + * There is one to one mapping for ppi index with phy index + * we do not always update phy sel equal to phy number,for some + * targets "phy_sel = phy_num + 1", and for some targets it is + * "phy_sel = phy_num", ppi_index should be updated accordingly + */ + ppi_index = csid_hw->csi2_rx_cfg.phy_sel - csid_reg->csi2_reg->phy_sel_base; - ppi_index = csid_hw->csi2_rx_cfg.phy_sel; if (csid_hw->ppi_hw_intf[ppi_index] && csid_hw->ppi_enable) { ppi_lane_cfg.lane_type = csid_hw->csi2_rx_cfg.lane_type; ppi_lane_cfg.lane_num = csid_hw->csi2_rx_cfg.lane_num; @@ -1005,7 +1011,7 @@ static int cam_tfe_csid_disable_csi2( cam_io_w_mb(0, soc_info->reg_map[0].mem_base + csid_reg->csi2_reg->csid_csi2_rx_cfg1_addr); - ppi_index = csid_hw->csi2_rx_cfg.phy_sel; + ppi_index = csid_hw->csi2_rx_cfg.phy_sel - csid_reg->csi2_reg->phy_sel_base; if (csid_hw->ppi_hw_intf[ppi_index] && csid_hw->ppi_enable) { /* De-Initialize the PPI bridge */ CAM_DBG(CAM_ISP, "ppi_index to de-init %d\n", ppi_index); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.h index b13d4b0473f8..c2e8d343196b 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.h @@ -185,6 +185,7 @@ struct cam_tfe_csid_csi2_rx_reg_offset { uint32_t csid_csi2_rx_total_crc_err_addr; /*configurations */ + uint32_t phy_sel_base; uint32_t csi2_rst_srb_all; uint32_t csi2_rst_done_shift_val; uint32_t csi2_irq_mask_all; From f49b4dd0b9179677aa177b248fc383593cc625f4 Mon Sep 17 00:00:00 2001 From: Wyes Karny Date: Mon, 15 Nov 2021 13:08:06 +0530 Subject: [PATCH 10/25] msm: camera: cdm: Fix deadlock issue in CDM handle error Fix deadlock issue in CDM handle error. CRs-Fixed: 3073203 Change-Id: Ia63e1841fc00e74e4c03a1d6b28e94814748aa8f Signed-off-by: Wyes Karny --- drivers/cam_cdm/cam_cdm_hw_core.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/cam_cdm/cam_cdm_hw_core.c b/drivers/cam_cdm/cam_cdm_hw_core.c index 583963a0d6e2..bd1e938a0d0f 100644 --- a/drivers/cam_cdm/cam_cdm_hw_core.c +++ b/drivers/cam_cdm/cam_cdm_hw_core.c @@ -1809,11 +1809,9 @@ int cam_hw_cdm_handle_error_info( if (node != NULL) { if (node->request_type == CAM_HW_CDM_BL_CB_CLIENT) { - mutex_lock(&cdm_hw->hw_mutex); cam_cdm_notify_clients(cdm_hw, CAM_CDM_CB_STATUS_HW_ERROR, (void *)node); - mutex_unlock(&cdm_hw->hw_mutex); } else if (node->request_type == CAM_HW_CDM_BL_CB_INTERNAL) { CAM_ERR(CAM_CDM, "Invalid node=%pK %d", node, node->request_type); From 572462dbf6f2ca50fad3c9207b906fcdf56700f9 Mon Sep 17 00:00:00 2001 From: Tejas Prajapati Date: Thu, 11 Nov 2021 12:43:59 +0530 Subject: [PATCH 11/25] msm: camera: isp: handle buf_done at apply failure from deferred list For RDI only context where the buf_done is handled from wait list, if the buf_done is moved to deferred list then the bubble recovery might fail. To make sure the bubble is processed the request needs to be moved pending list. This change helps moving the request from active list to pending list. CRs-Fixed: 3079621 Change-Id: Ibb271e68ca2312cbd3d71bd64e2ed7963bf60b55 Signed-off-by: Tejas Prajapati --- drivers/cam_isp/cam_isp_context.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index 87779aea1a16..9992e6261956 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -4119,6 +4119,16 @@ static int __cam_isp_ctx_rdi_only_sof_in_bubble_state( CAM_DBG(CAM_ISP, "CDM callback detected for req: %lld, possible buf_done delay, waiting for buf_done", req->request_id); + if (req_isp->num_fence_map_out == + req_isp->num_deferred_acks) { + __cam_isp_handle_deferred_buf_done(ctx_isp, req, + true, + CAM_SYNC_STATE_SIGNALED_ERROR, + CAM_SYNC_ISP_EVENT_BUBBLE); + + __cam_isp_ctx_handle_buf_done_for_req_list( + ctx_isp, req); + } goto end; } else { CAM_WARN(CAM_ISP, From 1f76cca6da19481a659a84a33f19917111017c25 Mon Sep 17 00:00:00 2001 From: sokchetra eung Date: Fri, 27 Aug 2021 15:54:21 -0700 Subject: [PATCH 12/25] msm: camera: reqmgr: Prevent session deadlock Releasing session lock before unlink and acquiring it immediately after to allow workq to be done. Check link state after acquiring session lock in process_ req to return if link is IDLE. CRs-Fixed: 3003287 Change-Id: Ie7a8ffc4edcb123db290d6da047d748b3e99d68b Signed-off-by: sokchetra eung --- drivers/cam_req_mgr/cam_req_mgr_core.c | 34 ++++++++++++++++---------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.c b/drivers/cam_req_mgr/cam_req_mgr_core.c index 18dcb1bc2b96..05e6fdb90381 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.c +++ b/drivers/cam_req_mgr/cam_req_mgr_core.c @@ -1714,20 +1714,20 @@ static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link, return -EINVAL; } + mutex_lock(&session->lock); /* - * In case if the wq is scheduled while destroying session - * the session mutex is already taken and will cause a - * dead lock. To avoid further processing check link state - * and exit. + * During session destroy/unlink the link state is updated and session + * mutex is released when flushing the workq. In case the wq is scheduled + * thereafter this API will then check the updated link state and exit */ spin_lock_bh(&link->link_state_spin_lock); if (link->state == CAM_CRM_LINK_STATE_IDLE) { spin_unlock_bh(&link->link_state_spin_lock); + mutex_unlock(&session->lock); return -EPERM; } spin_unlock_bh(&link->link_state_spin_lock); - mutex_lock(&session->lock); in_q = link->req.in_q; /* * Check if new read index, @@ -3786,13 +3786,17 @@ end: /** * __cam_req_mgr_unlink() * - * @brief : Unlink devices on a link structure from the session - * @link : Pointer to the link structure + * @brief : Unlink devices on a link structure from the session + * This API is to be invoked with session mutex held + * @session: session of the link + * @link : Pointer to the link structure * * @return: 0 for success, negative for failure * */ -static int __cam_req_mgr_unlink(struct cam_req_mgr_core_link *link) +static int __cam_req_mgr_unlink( + struct cam_req_mgr_core_session *session, + struct cam_req_mgr_core_link *link) { int rc; @@ -3808,14 +3812,16 @@ static int __cam_req_mgr_unlink(struct cam_req_mgr_core_link *link) } mutex_lock(&link->lock); - spin_lock_bh(&link->link_state_spin_lock); /* Destroy timer of link */ crm_timer_exit(&link->watchdog); spin_unlock_bh(&link->link_state_spin_lock); + /* Release session mutex for workq processing */ + mutex_unlock(&session->lock); /* Destroy workq of link */ cam_req_mgr_workq_destroy(&link->workq); - + /* Acquire session mutex after workq flush */ + mutex_lock(&session->lock); /* Cleanup request tables and unlink devices */ __cam_req_mgr_destroy_link_info(link); /* Free memory holding data of linked devs */ @@ -3857,6 +3863,7 @@ int cam_req_mgr_destroy_session( goto end; } + mutex_lock(&cam_session->lock); if (cam_session->num_links) { CAM_DBG(CAM_CRM, "destroy session %x num_active_links %d", @@ -3872,7 +3879,7 @@ int cam_req_mgr_destroy_session( link->link_hdl); /* Ignore return value since session is going away */ link->is_shutdown = is_shutdown; - __cam_req_mgr_unlink(link); + __cam_req_mgr_unlink(cam_session, link); __cam_req_mgr_free_link(link); } } @@ -4153,8 +4160,9 @@ int cam_req_mgr_unlink(struct cam_req_mgr_unlink_info *unlink_info) rc = -EINVAL; goto done; } - - rc = __cam_req_mgr_unlink(link); + mutex_lock(&cam_session->lock); + rc = __cam_req_mgr_unlink(cam_session, link); + mutex_unlock(&cam_session->lock); /* Free curent link and put back into session's free pool of links */ __cam_req_mgr_unreserve_link(cam_session, link); From 4fbb1700efdee1ce0e6ed27e7ca777d65148dfda Mon Sep 17 00:00:00 2001 From: Vikram Sharma Date: Mon, 18 Oct 2021 13:15:15 +0530 Subject: [PATCH 13/25] msm: camera: ope: Increase max bl limit and max stripe to process MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Increase “OPE_MAX_CDM_BLS” to 32 from 24 and MAX_STRIPES to 64 from 48 to process 108M frame. CRs-Fixed: 3082993 Change-Id: I9e3631cc86c5e10e4e2020d4a9b2264ea282e437 Signed-off-by: Vikram Sharma --- drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.h | 2 +- include/uapi/camera/media/cam_ope.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.h b/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.h index f6206f0c8bf0..a90cd56abc42 100644 --- a/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.h +++ b/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.h @@ -50,7 +50,7 @@ #define OPE_CMDS OPE_MAX_CMD_BUFS #define CAM_MAX_IN_RES 8 -#define OPE_MAX_CDM_BLS 24 +#define OPE_MAX_CDM_BLS 32 #define CAM_OPE_MAX_PER_PATH_VOTES 6 #define CAM_OPE_BW_CONFIG_UNKNOWN 0 diff --git a/include/uapi/camera/media/cam_ope.h b/include/uapi/camera/media/cam_ope.h index d9badbcdff3d..b6a9a41d8dfe 100644 --- a/include/uapi/camera/media/cam_ope.h +++ b/include/uapi/camera/media/cam_ope.h @@ -73,7 +73,7 @@ #define OPE_MAX_IO_BUFS (OPE_OUT_RES_MAX + OPE_IN_RES_MAX) #define OPE_MAX_PASS 1 #define OPE_MAX_PLANES 2 -#define OPE_MAX_STRIPES 48 +#define OPE_MAX_STRIPES 64 #define OPE_MAX_BATCH_SIZE 16 /** From 8eeacc770c200536caebed42081da9705cbff566 Mon Sep 17 00:00:00 2001 From: Alok Chauhan Date: Fri, 19 Nov 2021 12:25:48 +0530 Subject: [PATCH 14/25] msm: camera: ope: Update request timeout for NRT/RT context Currently the ope request timeout value for RT and NRT context are same. In some usecases, NRT request processing takes more time. Hence, initialize the RT and NRT request timeout value separately. CRs-Fixed: 3082993 Change-Id: I17e86d26403fb21cdff518a81dee7a19c865144e Signed-off-by: Alok Chauhan --- drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c | 18 +++++++++++------- drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.h | 5 ++++- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c b/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c index 978160a6a6ac..6057ec7b5cc1 100644 --- a/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c +++ b/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c @@ -624,8 +624,8 @@ static bool cam_ope_check_req_delay(struct cam_ope_ctx *ctx_data, ts.tv_nsec); if (ts_ns - req_time < - ((OPE_REQUEST_TIMEOUT - - OPE_REQUEST_TIMEOUT / 10) * 1000000)) { + ((ctx_data->req_timer_timeout - + ctx_data->req_timer_timeout / 10) * 1000000)) { CAM_INFO(CAM_OPE, "ctx: %d, ts_ns : %llu", ctx_data->ctx_id, ts_ns); cam_ope_req_timer_reset(ctx_data); @@ -848,7 +848,7 @@ static int cam_ope_start_req_timer(struct cam_ope_ctx *ctx_data) int rc = 0; rc = crm_timer_init(&ctx_data->req_watch_dog, - OPE_REQUEST_TIMEOUT, ctx_data, &cam_ope_req_timer_cb); + ctx_data->req_timer_timeout, ctx_data, &cam_ope_req_timer_cb); if (rc) CAM_ERR(CAM_OPE, "Failed to start timer"); @@ -2626,11 +2626,15 @@ static int cam_ope_mgr_acquire_hw(void *hw_priv, void *hw_acquire_args) goto end; } strlcpy(cdm_acquire->identifier, "ope", sizeof("ope")); - if (ctx->ope_acquire.dev_type == OPE_DEV_TYPE_OPE_RT) + if (ctx->ope_acquire.dev_type == OPE_DEV_TYPE_OPE_RT) { cdm_acquire->priority = CAM_CDM_BL_FIFO_3; + ctx->req_timer_timeout = OPE_REQUEST_RT_TIMEOUT; + } else if (ctx->ope_acquire.dev_type == - OPE_DEV_TYPE_OPE_NRT) + OPE_DEV_TYPE_OPE_NRT) { cdm_acquire->priority = CAM_CDM_BL_FIFO_0; + ctx->req_timer_timeout = OPE_REQUEST_NRT_TIMEOUT; + } else goto free_cdm_acquire; @@ -3300,7 +3304,7 @@ static int cam_ope_mgr_prepare_hw_update(void *hw_priv, CAM_DBG(CAM_REQ, "req_id= %llu ctx_id= %d lrt=%llu", packet->header.request_id, ctx_data->ctx_id, ctx_data->last_req_time); - cam_ope_req_timer_modify(ctx_data, OPE_REQUEST_TIMEOUT); + cam_ope_req_timer_modify(ctx_data, ctx_data->req_timer_timeout); set_bit(request_idx, ctx_data->bitmap); mutex_unlock(&ctx_data->ctx_mutex); @@ -3620,7 +3624,7 @@ static int cam_ope_mgr_hw_dump(void *hw_priv, void *hw_dump_args) cur_ts = ktime_to_timespec64(cur_time); req_ts = ktime_to_timespec64(ctx_data->req_list[idx]->submit_timestamp); - if (diff < (OPE_REQUEST_TIMEOUT * 1000)) { + if (diff < (ctx_data->req_timer_timeout * 1000)) { CAM_INFO(CAM_OPE, "No Error req %llu %ld:%06ld %ld:%06ld", dump_args->request_id, req_ts.tv_sec, diff --git a/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.h b/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.h index f6206f0c8bf0..247b6b0f0abe 100644 --- a/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.h +++ b/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.h @@ -60,7 +60,8 @@ #define CLK_HW_MAX 0x1 #define OPE_DEVICE_IDLE_TIMEOUT 400 -#define OPE_REQUEST_TIMEOUT 200 +#define OPE_REQUEST_RT_TIMEOUT 200 +#define OPE_REQUEST_NRT_TIMEOUT 400 /** * struct cam_ope_clk_bw_request_v2 @@ -447,6 +448,7 @@ struct cam_ope_cdm { * @clk_watch_dog: Clock watchdog * @clk_watch_dog_reset_counter: Reset counter * @last_flush_req: last flush req for this ctx + * @req_timer_timeout: req timer timeout value */ struct cam_ope_ctx { void *context_priv; @@ -470,6 +472,7 @@ struct cam_ope_ctx { uint32_t clk_watch_dog_reset_counter; uint64_t last_flush_req; bool pf_mid_found; + uint64_t req_timer_timeout; }; /** From ce9b4b3f1227d3667fa11f6c49af8e0907f8d26d Mon Sep 17 00:00:00 2001 From: Zhenlin Lian Date: Tue, 16 Nov 2021 13:53:58 +0800 Subject: [PATCH 15/25] msm: camera: config: Enable camera drivers for qcs610 Add camera config files for target qcs610. Change-Id: I4fefaa0254aa8267b4375bb4270f286f46ec7997 Signed-off-by: Zhenlin Lian --- Makefile | 9 +++++++++ config/sm6150camera.conf | 18 ++++++++++++++++++ config/sm6150cameraconf.h | 12 ++++++++++++ 3 files changed, 39 insertions(+) create mode 100644 config/sm6150camera.conf create mode 100644 config/sm6150cameraconf.h diff --git a/Makefile b/Makefile index cb00746debf3..2568ff61c873 100644 --- a/Makefile +++ b/Makefile @@ -38,6 +38,10 @@ ifeq ($(CONFIG_ARCH_YUPIK), y) include $(srctree)/techpack/camera/config/yupikcamera.conf endif +ifeq ($(CONFIG_ARCH_SM6150), y) +include $(srctree)/techpack/camera/config/sm6150camera.conf +endif + ifeq ($(CONFIG_ARCH_KONA), y) LINUXINCLUDE += \ -include $(srctree)/techpack/camera/config/konacameraconf.h @@ -83,6 +87,11 @@ LINUXINCLUDE += \ -include $(srctree)/techpack/camera/config/yupikcameraconf.h endif +ifeq ($(CONFIG_ARCH_SM6150), y) +LINUXINCLUDE += \ + -include $(srctree)/techpack/camera/config/sm6150cameraconf.h +endif + endif ifneq (,$(filter $(CONFIG_SPECTRA_CAMERA), y m)) diff --git a/config/sm6150camera.conf b/config/sm6150camera.conf new file mode 100644 index 000000000000..66b3a4cd548f --- /dev/null +++ b/config/sm6150camera.conf @@ -0,0 +1,18 @@ +# SPDX-License-Identifier: GPL-2.0-only +# Copyright (c) 2021, The Linux Foundation. All rights reserved. + +ifeq ($(CONFIG_QGKI),y) +export CONFIG_SPECTRA_CAMERA=m +$(info "QGKI Spectra Camera Building as DLKM") +else +export CONFIG_SPECTRA_CAMERA=m +$(info "GKI Spectra Camera Building as DLKM") +endif + +ifneq (,$(filter $(CONFIG_SPECTRA_CAMERA), y m)) +export CONFIG_SPECTRA_ISP=y +export CONFIG_SPECTRA_SENSOR=y +export CONFIG_SPECTRA_ICP=y +export CONFIG_SPECTRA_JPEG=y +export CONFIG_SPECTRA_CUSTOM=y +endif diff --git a/config/sm6150cameraconf.h b/config/sm6150cameraconf.h new file mode 100644 index 000000000000..d736f140093e --- /dev/null +++ b/config/sm6150cameraconf.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2021, The Linux Foundation. All rights reserved. + */ + + +#define CONFIG_SPECTRA_CAMERA 1 +#define CONFIG_SPECTRA_ISP 1 +#define CONFIG_SPECTRA_SENSOR 1 +#define CONFIG_SPECTRA_ICP 1 +#define CONFIG_SPECTRA_JPEG 1 +#define CONFIG_SPECTRA_CUSTOM 1 From c6de9ec432f31ae0713fb068e3cd1ef2b40d9722 Mon Sep 17 00:00:00 2001 From: Tejas Prajapati Date: Wed, 24 Nov 2021 10:50:39 +0530 Subject: [PATCH 16/25] msm: camera: isp: Add eof notification for rdi only context For RDI only context EOF is not notified; it should be notified, for the corner case if the flash is configured to apply at EOF then it will block apply for ISP on SOF as well until the EOF is notified, this change adds EOF notification. CRs-Fixed: 3091241 Change-Id: If6d974d092d640d9def89bbcf7a88fba0d85579b Signed-off-by: Tejas Prajapati --- drivers/cam_isp/cam_isp_context.c | 10 +++++----- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 8 ++++++++ drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c | 6 ++++++ 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index 9992e6261956..f3d454914204 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -4315,7 +4315,7 @@ static struct cam_isp_ctx_irq_ops __cam_isp_ctx_rdi_only_sof_in_top_state, __cam_isp_ctx_reg_upd_in_sof, NULL, - NULL, + __cam_isp_ctx_notify_eof_in_activated_state, NULL, }, }, @@ -4326,7 +4326,7 @@ static struct cam_isp_ctx_irq_ops __cam_isp_ctx_rdi_only_sof_in_applied_state, NULL, NULL, - NULL, + __cam_isp_ctx_notify_eof_in_activated_state, __cam_isp_ctx_buf_done_in_applied, }, }, @@ -4337,7 +4337,7 @@ static struct cam_isp_ctx_irq_ops __cam_isp_ctx_rdi_only_sof_in_top_state, NULL, NULL, - NULL, + __cam_isp_ctx_notify_eof_in_activated_state, __cam_isp_ctx_buf_done_in_epoch, }, }, @@ -4348,7 +4348,7 @@ static struct cam_isp_ctx_irq_ops __cam_isp_ctx_rdi_only_sof_in_bubble_state, __cam_isp_ctx_rdi_only_reg_upd_in_bubble_state, NULL, - NULL, + __cam_isp_ctx_notify_eof_in_activated_state, __cam_isp_ctx_buf_done_in_bubble, }, }, @@ -4359,7 +4359,7 @@ static struct cam_isp_ctx_irq_ops __cam_isp_ctx_rdi_only_sof_in_bubble_applied, __cam_isp_ctx_rdi_only_reg_upd_in_bubble_applied_state, NULL, - NULL, + __cam_isp_ctx_notify_eof_in_activated_state, __cam_isp_ctx_buf_done_in_bubble_applied, }, }, diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index 487f1eda3457..8af790e2d3b2 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -7990,6 +7990,14 @@ static int cam_ife_hw_mgr_handle_hw_eof( case CAM_ISP_HW_VFE_IN_RDI1: case CAM_ISP_HW_VFE_IN_RDI2: case CAM_ISP_HW_VFE_IN_RDI3: + if (!ife_hw_mgr_ctx->is_rdi_only_context) + break; + if (atomic_read(&ife_hw_mgr_ctx->overflow_pending)) + break; + ife_hw_irq_eof_cb(ife_hw_mgr_ctx->common.cb_priv, + CAM_ISP_HW_EVENT_EOF, (void *)&eof_done_event_data); + break; + case CAM_ISP_HW_VFE_IN_PDLIB: case CAM_ISP_HW_VFE_IN_LCR: break; diff --git a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c index 4b33439c44f3..aa6e8c15aa8e 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c @@ -5649,6 +5649,12 @@ static int cam_tfe_hw_mgr_handle_hw_eof( case CAM_ISP_HW_TFE_IN_RDI0: case CAM_ISP_HW_TFE_IN_RDI1: case CAM_ISP_HW_TFE_IN_RDI2: + if (!tfe_hw_mgr_ctx->is_rdi_only_context) + break; + if (atomic_read(&tfe_hw_mgr_ctx->overflow_pending)) + break; + tfe_hw_irq_eof_cb(tfe_hw_mgr_ctx->common.cb_priv, + CAM_ISP_HW_EVENT_EOF, (void *)&eof_done_event_data); break; default: From 4856f7a40a673e60987482c62492946e48445e36 Mon Sep 17 00:00:00 2001 From: Tejas Prajapati Date: Mon, 20 Dec 2021 14:44:36 +0530 Subject: [PATCH 17/25] msm: camera: reqmgr: check if link handle is correctly passed Instead of the link handle if the dev handle is passed for dumping the request information, this can lead to accessing invalid data structure. To avodi accessing invalid data structure based on the dev handle, first check if the link handle passed in IOCTL is matchting with looked up link handle. CRs-Fixed: 3097336 Change-Id: I815457ff96e3b26fe9fa886bd984d53d209e4edb Signed-off-by: Tejas Prajapati --- drivers/cam_req_mgr/cam_req_mgr_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.c b/drivers/cam_req_mgr/cam_req_mgr_core.c index 05e6fdb90381..ac04553899a2 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.c +++ b/drivers/cam_req_mgr/cam_req_mgr_core.c @@ -4542,7 +4542,7 @@ int cam_req_mgr_dump_request(struct cam_dump_req_cmd *dump_req) link = (struct cam_req_mgr_core_link *) cam_get_device_priv(dump_req->link_hdl); - if (!link) { + if (!link || link->link_hdl != dump_req->link_hdl) { CAM_DBG(CAM_CRM, "link ptr NULL %x", dump_req->link_hdl); rc = -EINVAL; goto end; From deb0914ed40c4149d42454f2fbe4bf14b2dc4eb8 Mon Sep 17 00:00:00 2001 From: Alok Chauhan Date: Tue, 28 Dec 2021 11:46:46 +0530 Subject: [PATCH 18/25] msm: camera: ope: Fix for 32-bit kernel Use div_u64 to do 64-bit division. CRs-Fixed: 3099898 Change-Id: I405461ea02d0ec668cb7be764543a9a16bd1c3e6 Signed-off-by: Alok Chauhan Signed-off-by: Nirmal Abraham --- drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c b/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c index 6057ec7b5cc1..b76f97a7461c 100644 --- a/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c +++ b/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2022, The Linux Foundation. All rights reserved. */ #include @@ -19,6 +19,7 @@ #include #include #include +#include #include "cam_sync_api.h" #include "cam_packet_util.h" @@ -625,7 +626,7 @@ static bool cam_ope_check_req_delay(struct cam_ope_ctx *ctx_data, if (ts_ns - req_time < ((ctx_data->req_timer_timeout - - ctx_data->req_timer_timeout / 10) * 1000000)) { + div_u64(ctx_data->req_timer_timeout, 10)) * 1000000)) { CAM_INFO(CAM_OPE, "ctx: %d, ts_ns : %llu", ctx_data->ctx_id, ts_ns); cam_ope_req_timer_reset(ctx_data); From 691ddd437ff6f2ce33a43e6c2133bd7db08609de Mon Sep 17 00:00:00 2001 From: Tejas Prajapati Date: Wed, 29 Dec 2021 11:05:49 +0530 Subject: [PATCH 19/25] msm: camera: reqmgr: reader writer locks to avoid memory faults Shared memory is initialized by CRM and used by other drivers; with CRM not active other drivers would fail to access the shared memory if memory manager is deinit. Reader Writer locks can prevent the open/close/ioctl calls from other drivers if CRM open/close is already being processed. Issue observed with the below sequence if drivers are opened from UMD directly without this change. CRM Open successful,ICP open successful, CRM close in progress, ICP open successful, mem mgr deinit and CRM close successful, ICP tries to access HFI memory and result in crash. This change helps to serialze the calls and prevents issue. CRs-Fixed: 3019488 Change-Id: I464411576a5a04f5d0b402c403ce8a1d4df7dad0 Signed-off-by: Tejas Prajapati --- drivers/cam_core/cam_subdev.c | 2 + drivers/cam_fd/cam_fd_dev.c | 5 ++ drivers/cam_icp/cam_icp_subdev.c | 13 +--- drivers/cam_isp/cam_isp_dev.c | 4 ++ drivers/cam_jpeg/cam_jpeg_dev.c | 3 + drivers/cam_lrme/cam_lrme_dev.c | 5 ++ drivers/cam_ope/cam_ope_subdev.c | 3 + drivers/cam_req_mgr/cam_mem_mgr.c | 65 +++++++------------ drivers/cam_req_mgr/cam_mem_mgr.h | 6 ++ drivers/cam_req_mgr/cam_req_mgr_dev.c | 30 +++++++++ drivers/cam_req_mgr/cam_req_mgr_util.c | 9 +++ drivers/cam_req_mgr/cam_subdev.h | 14 ++++ .../cam_actuator/cam_actuator_core.c | 5 ++ .../cam_csiphy/cam_csiphy_core.c | 6 ++ .../cam_eeprom/cam_eeprom_core.c | 4 ++ .../cam_flash/cam_flash_dev.c | 5 ++ .../cam_sensor_module/cam_ois/cam_ois_core.c | 4 ++ .../cam_sensor/cam_sensor_core.c | 5 ++ 18 files changed, 138 insertions(+), 50 deletions(-) diff --git a/drivers/cam_core/cam_subdev.c b/drivers/cam_core/cam_subdev.c index cbe1b4ca3336..c1f345fabf1a 100644 --- a/drivers/cam_core/cam_subdev.c +++ b/drivers/cam_core/cam_subdev.c @@ -55,8 +55,10 @@ static long cam_subdev_ioctl(struct v4l2_subdev *sd, unsigned int cmd, switch (cmd) { case VIDIOC_CAM_CONTROL: + cam_req_mgr_rwsem_read_op(CAM_SUBDEV_LOCK); rc = cam_node_handle_ioctl(node, (struct cam_control *) arg); + cam_req_mgr_rwsem_read_op(CAM_SUBDEV_UNLOCK); break; case CAM_SD_SHUTDOWN: if (!cam_req_mgr_is_shutdown()) { diff --git a/drivers/cam_fd/cam_fd_dev.c b/drivers/cam_fd/cam_fd_dev.c index a58db056f6fb..e34c9bcc1e0b 100644 --- a/drivers/cam_fd/cam_fd_dev.c +++ b/drivers/cam_fd/cam_fd_dev.c @@ -44,8 +44,11 @@ static int cam_fd_dev_open(struct v4l2_subdev *sd, { struct cam_fd_dev *fd_dev = &g_fd_dev; + cam_req_mgr_rwsem_read_op(CAM_SUBDEV_LOCK); + if (!fd_dev->probe_done) { CAM_ERR(CAM_FD, "FD Dev not initialized, fd_dev=%pK", fd_dev); + cam_req_mgr_rwsem_read_op(CAM_SUBDEV_UNLOCK); return -ENODEV; } @@ -54,6 +57,8 @@ static int cam_fd_dev_open(struct v4l2_subdev *sd, CAM_DBG(CAM_FD, "FD Subdev open count %d", fd_dev->open_cnt); mutex_unlock(&fd_dev->lock); + cam_req_mgr_rwsem_read_op(CAM_SUBDEV_UNLOCK); + return 0; } diff --git a/drivers/cam_icp/cam_icp_subdev.c b/drivers/cam_icp/cam_icp_subdev.c index 8a69ff7c1e8f..a15c726a963d 100644 --- a/drivers/cam_icp/cam_icp_subdev.c +++ b/drivers/cam_icp/cam_icp_subdev.c @@ -20,7 +20,6 @@ #include #include #include -#include "cam_mem_mgr.h" #include "cam_req_mgr_dev.h" #include "cam_subdev.h" #include "cam_node.h" @@ -74,6 +73,8 @@ static int cam_icp_subdev_open(struct v4l2_subdev *sd, struct cam_node *node = v4l2_get_subdevdata(sd); int rc = 0; + cam_req_mgr_rwsem_read_op(CAM_SUBDEV_LOCK); + mutex_lock(&g_icp_dev.icp_lock); if (g_icp_dev.open_cnt >= 1) { CAM_ERR(CAM_ICP, "ICP subdev is already opened"); @@ -87,23 +88,16 @@ static int cam_icp_subdev_open(struct v4l2_subdev *sd, goto end; } - - rc = cam_mem_mgr_init(); - if (rc) { - CAM_ERR(CAM_CRM, "mem mgr init failed"); - goto end; - } - hw_mgr_intf = &node->hw_mgr_intf; rc = hw_mgr_intf->hw_open(hw_mgr_intf->hw_mgr_priv, NULL); if (rc < 0) { CAM_ERR(CAM_ICP, "FW download failed"); - cam_mem_mgr_deinit(); goto end; } g_icp_dev.open_cnt++; end: mutex_unlock(&g_icp_dev.icp_lock); + cam_req_mgr_rwsem_read_op(CAM_SUBDEV_UNLOCK); return rc; } @@ -139,7 +133,6 @@ int cam_icp_subdev_close_internal(struct v4l2_subdev *sd, goto end; } - cam_mem_mgr_deinit(); end: mutex_unlock(&g_icp_dev.icp_lock); return rc; diff --git a/drivers/cam_isp/cam_isp_dev.c b/drivers/cam_isp/cam_isp_dev.c index 9409c1015c6c..d2f8720541e6 100644 --- a/drivers/cam_isp/cam_isp_dev.c +++ b/drivers/cam_isp/cam_isp_dev.c @@ -64,10 +64,14 @@ static const struct of_device_id cam_isp_dt_match[] = { static int cam_isp_subdev_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) { + cam_req_mgr_rwsem_read_op(CAM_SUBDEV_LOCK); + mutex_lock(&g_isp_dev.isp_mutex); g_isp_dev.open_cnt++; mutex_unlock(&g_isp_dev.isp_mutex); + cam_req_mgr_rwsem_read_op(CAM_SUBDEV_UNLOCK); + return 0; } diff --git a/drivers/cam_jpeg/cam_jpeg_dev.c b/drivers/cam_jpeg/cam_jpeg_dev.c index a47476a06144..166db14e75ce 100644 --- a/drivers/cam_jpeg/cam_jpeg_dev.c +++ b/drivers/cam_jpeg/cam_jpeg_dev.c @@ -48,11 +48,14 @@ static const struct of_device_id cam_jpeg_dt_match[] = { static int cam_jpeg_subdev_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) { + cam_req_mgr_rwsem_read_op(CAM_SUBDEV_LOCK); mutex_lock(&g_jpeg_dev.jpeg_mutex); g_jpeg_dev.open_cnt++; mutex_unlock(&g_jpeg_dev.jpeg_mutex); + cam_req_mgr_rwsem_read_op(CAM_SUBDEV_UNLOCK); + return 0; } diff --git a/drivers/cam_lrme/cam_lrme_dev.c b/drivers/cam_lrme/cam_lrme_dev.c index 5055444c3d8a..f46bb25362fe 100644 --- a/drivers/cam_lrme/cam_lrme_dev.c +++ b/drivers/cam_lrme/cam_lrme_dev.c @@ -59,9 +59,12 @@ static int cam_lrme_dev_open(struct v4l2_subdev *sd, { struct cam_lrme_dev *lrme_dev = g_lrme_dev; + cam_req_mgr_rwsem_read_op(CAM_SUBDEV_LOCK); + if (!lrme_dev) { CAM_ERR(CAM_LRME, "LRME Dev not initialized, dev=%pK", lrme_dev); + cam_req_mgr_rwsem_read_op(CAM_SUBDEV_UNLOCK); return -ENODEV; } @@ -69,6 +72,8 @@ static int cam_lrme_dev_open(struct v4l2_subdev *sd, lrme_dev->open_cnt++; mutex_unlock(&lrme_dev->lock); + cam_req_mgr_rwsem_read_op(CAM_SUBDEV_UNLOCK); + return 0; } diff --git a/drivers/cam_ope/cam_ope_subdev.c b/drivers/cam_ope/cam_ope_subdev.c index a04abe3bcf8c..e4007cbabac0 100644 --- a/drivers/cam_ope/cam_ope_subdev.c +++ b/drivers/cam_ope/cam_ope_subdev.c @@ -69,6 +69,8 @@ static int cam_ope_subdev_open(struct v4l2_subdev *sd, struct cam_node *node = v4l2_get_subdevdata(sd); int rc = 0; + cam_req_mgr_rwsem_read_op(CAM_SUBDEV_LOCK); + mutex_lock(&g_ope_dev.ope_lock); if (g_ope_dev.open_cnt >= 1) { CAM_ERR(CAM_OPE, "OPE subdev is already opened"); @@ -92,6 +94,7 @@ static int cam_ope_subdev_open(struct v4l2_subdev *sd, CAM_DBG(CAM_OPE, "OPE HW open success: %d", rc); end: mutex_unlock(&g_ope_dev.ope_lock); + cam_req_mgr_rwsem_read_op(CAM_SUBDEV_UNLOCK); return rc; } diff --git a/drivers/cam_req_mgr/cam_mem_mgr.c b/drivers/cam_req_mgr/cam_mem_mgr.c index 9c8a404dbfe5..b928c7da46c7 100644 --- a/drivers/cam_req_mgr/cam_mem_mgr.c +++ b/drivers/cam_req_mgr/cam_mem_mgr.c @@ -19,11 +19,8 @@ #include "cam_trace.h" #include "cam_common_util.h" -static struct cam_mem_table tbl = { - .m_lock = __MUTEX_INITIALIZER(tbl.m_lock), -}; - -static atomic_t cam_mem_mgr_refcnt = ATOMIC_INIT(0); +static struct cam_mem_table tbl; +static atomic_t cam_mem_mgr_state = ATOMIC_INIT(CAM_MEM_MGR_UNINITIALIZED); static void cam_mem_mgr_print_tbl(void) { @@ -167,16 +164,6 @@ int cam_mem_mgr_init(void) int i; int bitmap_size; - mutex_lock(&tbl.m_lock); - - if (atomic_inc_return(&cam_mem_mgr_refcnt) > 1) { - CAM_DBG(CAM_MEM, - "Mem mgr refcnt: %d", - atomic_read(&cam_mem_mgr_refcnt)); - mutex_unlock(&tbl.m_lock); - return 0; - } - memset(tbl.bufq, 0, sizeof(tbl.bufq)); if (cam_smmu_need_force_alloc_cached(&tbl.force_cache_allocs)) { @@ -186,13 +173,8 @@ int cam_mem_mgr_init(void) bitmap_size = BITS_TO_LONGS(CAM_MEM_BUFQ_MAX) * sizeof(long); tbl.bitmap = kzalloc(bitmap_size, GFP_KERNEL); - if (!tbl.bitmap) { - atomic_dec(&cam_mem_mgr_refcnt); - CAM_DBG(CAM_MEM, "Mem mgr refcnt: %d", - atomic_read(&cam_mem_mgr_refcnt)); - mutex_unlock(&tbl.m_lock); + if (!tbl.bitmap) return -ENOMEM; - } tbl.bits = bitmap_size * BITS_PER_BYTE; bitmap_zero(tbl.bitmap, tbl.bits); @@ -203,8 +185,9 @@ int cam_mem_mgr_init(void) tbl.bufq[i].fd = -1; tbl.bufq[i].buf_handle = -1; } + mutex_init(&tbl.m_lock); - mutex_unlock(&tbl.m_lock); + atomic_set(&cam_mem_mgr_state, CAM_MEM_MGR_INITIALIZED); cam_mem_mgr_create_debug_fs(); @@ -251,7 +234,7 @@ int cam_mem_get_io_buf(int32_t buf_handle, int32_t mmu_handle, *len_ptr = 0; - if (!atomic_read(&cam_mem_mgr_refcnt)) { + if (!atomic_read(&cam_mem_mgr_state)) { CAM_ERR(CAM_MEM, "failed. mem_mgr not initialized"); return -EINVAL; } @@ -302,7 +285,12 @@ int cam_mem_get_cpu_buf(int32_t buf_handle, uintptr_t *vaddr_ptr, size_t *len) { int idx; - if (!atomic_read(&cam_mem_mgr_refcnt)) { + if (!atomic_read(&cam_mem_mgr_state)) { + CAM_ERR(CAM_MEM, "failed. mem_mgr not initialized"); + return -EINVAL; + } + + if (!atomic_read(&cam_mem_mgr_state)) { CAM_ERR(CAM_MEM, "failed. mem_mgr not initialized"); return -EINVAL; } @@ -345,7 +333,7 @@ int cam_mem_mgr_cache_ops(struct cam_mem_cache_ops_cmd *cmd) uint32_t cache_dir; unsigned long dmabuf_flag = 0; - if (!atomic_read(&cam_mem_mgr_refcnt)) { + if (!atomic_read(&cam_mem_mgr_state)) { CAM_ERR(CAM_MEM, "failed. mem_mgr not initialized"); return -EINVAL; } @@ -671,7 +659,7 @@ int cam_mem_mgr_alloc_and_map(struct cam_mem_mgr_alloc_cmd *cmd) uintptr_t kvaddr = 0; size_t klen; - if (!atomic_read(&cam_mem_mgr_refcnt)) { + if (!atomic_read(&cam_mem_mgr_state)) { CAM_ERR(CAM_MEM, "failed. mem_mgr not initialized"); return -EINVAL; } @@ -823,7 +811,7 @@ int cam_mem_mgr_map(struct cam_mem_mgr_map_cmd *cmd) size_t len = 0; bool is_internal = false; - if (!atomic_read(&cam_mem_mgr_refcnt)) { + if (!atomic_read(&cam_mem_mgr_state)) { CAM_ERR(CAM_MEM, "failed. mem_mgr not initialized"); return -EINVAL; } @@ -1010,6 +998,7 @@ static int cam_mem_mgr_cleanup_table(void) { int i; + mutex_lock(&tbl.m_lock); for (i = 1; i < CAM_MEM_BUFQ_MAX; i++) { if (!tbl.bufq[i].active) { CAM_DBG(CAM_MEM, @@ -1045,27 +1034,23 @@ static int cam_mem_mgr_cleanup_table(void) bitmap_zero(tbl.bitmap, tbl.bits); /* We need to reserve slot 0 because 0 is invalid */ set_bit(0, tbl.bitmap); + mutex_unlock(&tbl.m_lock); return 0; } void cam_mem_mgr_deinit(void) { - mutex_lock(&tbl.m_lock); - if (!atomic_dec_and_test(&cam_mem_mgr_refcnt)) { - CAM_DBG(CAM_MEM, "Mem mgr refcnt: %d", - atomic_read(&cam_mem_mgr_refcnt)); - mutex_unlock(&tbl.m_lock); - return; - } - + atomic_set(&cam_mem_mgr_state, CAM_MEM_MGR_UNINITIALIZED); cam_mem_mgr_cleanup_table(); debugfs_remove_recursive(tbl.dentry); + mutex_lock(&tbl.m_lock); bitmap_zero(tbl.bitmap, tbl.bits); kfree(tbl.bitmap); tbl.bitmap = NULL; tbl.dbg_buf_idx = -1; mutex_unlock(&tbl.m_lock); + mutex_destroy(&tbl.m_lock); } static int cam_mem_util_unmap(int32_t idx, @@ -1163,7 +1148,7 @@ int cam_mem_mgr_release(struct cam_mem_mgr_release_cmd *cmd) int idx; int rc; - if (!atomic_read(&cam_mem_mgr_refcnt)) { + if (!atomic_read(&cam_mem_mgr_state)) { CAM_ERR(CAM_MEM, "failed. mem_mgr not initialized"); return -EINVAL; } @@ -1216,7 +1201,7 @@ int cam_mem_mgr_request_mem(struct cam_mem_mgr_request_desc *inp, enum cam_smmu_region_id region = CAM_SMMU_REGION_SHARED; - if (!atomic_read(&cam_mem_mgr_refcnt)) { + if (!atomic_read(&cam_mem_mgr_state)) { CAM_ERR(CAM_MEM, "failed. mem_mgr not initialized"); return -EINVAL; } @@ -1342,7 +1327,7 @@ int cam_mem_mgr_release_mem(struct cam_mem_mgr_memory_desc *inp) int32_t idx; int rc; - if (!atomic_read(&cam_mem_mgr_refcnt)) { + if (!atomic_read(&cam_mem_mgr_state)) { CAM_ERR(CAM_MEM, "failed. mem_mgr not initialized"); return -EINVAL; } @@ -1395,7 +1380,7 @@ int cam_mem_mgr_reserve_memory_region(struct cam_mem_mgr_request_desc *inp, int32_t smmu_hdl = 0; int32_t num_hdl = 0; - if (!atomic_read(&cam_mem_mgr_refcnt)) { + if (!atomic_read(&cam_mem_mgr_state)) { CAM_ERR(CAM_MEM, "failed. mem_mgr not initialized"); return -EINVAL; } @@ -1490,7 +1475,7 @@ int cam_mem_mgr_free_memory_region(struct cam_mem_mgr_memory_desc *inp) int rc; int32_t smmu_hdl; - if (!atomic_read(&cam_mem_mgr_refcnt)) { + if (!atomic_read(&cam_mem_mgr_state)) { CAM_ERR(CAM_MEM, "failed. mem_mgr not initialized"); return -EINVAL; } diff --git a/drivers/cam_req_mgr/cam_mem_mgr.h b/drivers/cam_req_mgr/cam_mem_mgr.h index 9cf7a74b07cf..26ab9cb75319 100644 --- a/drivers/cam_req_mgr/cam_mem_mgr.h +++ b/drivers/cam_req_mgr/cam_mem_mgr.h @@ -11,6 +11,12 @@ #include #include "cam_mem_mgr_api.h" +/* Enum for possible mem mgr states */ +enum cam_mem_mgr_state { + CAM_MEM_MGR_UNINITIALIZED, + CAM_MEM_MGR_INITIALIZED, +}; + /*Enum for possible SMMU operations */ enum cam_smmu_mapping_client { CAM_SMMU_MAPPING_USER, diff --git a/drivers/cam_req_mgr/cam_req_mgr_dev.c b/drivers/cam_req_mgr/cam_req_mgr_dev.c index 350c9ea171bf..63e61d160391 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_dev.c +++ b/drivers/cam_req_mgr/cam_req_mgr_dev.c @@ -8,6 +8,7 @@ #include #include #include +#include #include @@ -35,6 +36,8 @@ static struct cam_req_mgr_device g_dev; struct kmem_cache *g_cam_req_mgr_timer_cachep; static struct list_head cam_req_mgr_ordered_sd_list; +DECLARE_RWSEM(rwsem_lock); + static struct device_attribute camera_debug_sysfs_attr = __ATTR(debug_node, 0600, NULL, cam_debug_sysfs_node_store); @@ -103,10 +106,29 @@ static void cam_v4l2_device_cleanup(void) g_dev.v4l2_dev = NULL; } + +void cam_req_mgr_rwsem_read_op(enum cam_subdev_rwsem lock) +{ + if (lock == CAM_SUBDEV_LOCK) + down_read(&rwsem_lock); + else if (lock == CAM_SUBDEV_UNLOCK) + up_read(&rwsem_lock); +} + +static void cam_req_mgr_rwsem_write_op(enum cam_subdev_rwsem lock) +{ + if (lock == CAM_SUBDEV_LOCK) + down_write(&rwsem_lock); + else if (lock == CAM_SUBDEV_UNLOCK) + up_write(&rwsem_lock); +} + static int cam_req_mgr_open(struct file *filep) { int rc; + cam_req_mgr_rwsem_write_op(CAM_SUBDEV_LOCK); + mutex_lock(&g_dev.cam_lock); if (g_dev.open_cnt >= 1) { rc = -EALREADY; @@ -133,12 +155,14 @@ static int cam_req_mgr_open(struct file *filep) } mutex_unlock(&g_dev.cam_lock); + cam_req_mgr_rwsem_write_op(CAM_SUBDEV_UNLOCK); return rc; mem_mgr_init_fail: v4l2_fh_release(filep); end: mutex_unlock(&g_dev.cam_lock); + cam_req_mgr_rwsem_write_op(CAM_SUBDEV_UNLOCK); return rc; } @@ -168,10 +192,14 @@ static int cam_req_mgr_close(struct file *filep) CAM_WARN(CAM_CRM, "release invoked associated userspace process has died, open_cnt: %d", g_dev.open_cnt); + + cam_req_mgr_rwsem_write_op(CAM_SUBDEV_LOCK); + mutex_lock(&g_dev.cam_lock); if (g_dev.open_cnt <= 0) { mutex_unlock(&g_dev.cam_lock); + cam_req_mgr_rwsem_write_op(CAM_SUBDEV_UNLOCK); return -EINVAL; } @@ -203,6 +231,8 @@ static int cam_req_mgr_close(struct file *filep) cam_mem_mgr_deinit(); mutex_unlock(&g_dev.cam_lock); + cam_req_mgr_rwsem_write_op(CAM_SUBDEV_UNLOCK); + return 0; } diff --git a/drivers/cam_req_mgr/cam_req_mgr_util.c b/drivers/cam_req_mgr/cam_req_mgr_util.c index 4faba1d006b6..3c44058d2813 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_util.c +++ b/drivers/cam_req_mgr/cam_req_mgr_util.c @@ -15,6 +15,7 @@ #include "cam_req_mgr_util.h" #include "cam_debug_util.h" #include "cam_context.h" +#include "cam_subdev.h" static struct cam_req_mgr_util_hdl_tbl *hdl_tbl; static DEFINE_SPINLOCK(hdl_tbl_lock); @@ -163,6 +164,14 @@ int32_t cam_create_device_hdl(struct cam_create_dev_hdl *hdl_data) int idx; int rand = 0; int32_t handle; + bool crm_active; + + crm_active = cam_req_mgr_is_open(CAM_CRM); + if (!crm_active) { + CAM_ERR(CAM_CRM, "CRM is not ACTIVE"); + spin_unlock_bh(&hdl_tbl_lock); + return -EINVAL; + } spin_lock_bh(&hdl_tbl_lock); if (!hdl_tbl) { diff --git a/drivers/cam_req_mgr/cam_subdev.h b/drivers/cam_req_mgr/cam_subdev.h index e37d7177c8a3..1e994bc69e33 100644 --- a/drivers/cam_req_mgr/cam_subdev.h +++ b/drivers/cam_req_mgr/cam_subdev.h @@ -28,6 +28,11 @@ enum cam_subdev_close_seq_priority { CAM_SD_CLOSE_LOW_PRIORITY }; +enum cam_subdev_rwsem { + CAM_SUBDEV_LOCK = 1, + CAM_SUBDEV_UNLOCK, +}; + /** * struct cam_subdev - describes a camera sub-device * @@ -130,6 +135,15 @@ int cam_register_subdev(struct cam_subdev *sd); */ int cam_unregister_subdev(struct cam_subdev *sd); +/** + * cam_req_mgr_rwsem_read_op() + * + * @brief : API to acquire read semaphore lock to platform framework. + * + * @lock : value indicates to lock or unlock the read lock + */ +void cam_req_mgr_rwsem_read_op(enum cam_subdev_rwsem lock); + /** * cam_req_mgr_is_open() * diff --git a/drivers/cam_sensor_module/cam_actuator/cam_actuator_core.c b/drivers/cam_sensor_module/cam_actuator/cam_actuator_core.c index 9c0d7abd043d..722f91e334b3 100644 --- a/drivers/cam_sensor_module/cam_actuator/cam_actuator_core.c +++ b/drivers/cam_sensor_module/cam_actuator/cam_actuator_core.c @@ -859,6 +859,11 @@ int32_t cam_actuator_driver_cmd(struct cam_actuator_ctrl_t *a_ctrl, actuator_acq_dev.device_handle = cam_create_device_hdl(&bridge_params); + if (actuator_acq_dev.device_handle <= 0) { + rc = -EFAULT; + CAM_ERR(CAM_ACTUATOR, "Can not create device handle"); + goto release_mutex; + } a_ctrl->bridge_intf.device_hdl = actuator_acq_dev.device_handle; a_ctrl->bridge_intf.session_hdl = actuator_acq_dev.session_handle; diff --git a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c index 210179307a9e..06c02c1932f1 100644 --- a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c +++ b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c @@ -1182,6 +1182,12 @@ int32_t cam_csiphy_core_cfg(void *phy_dev, index = csiphy_dev->acquire_count; csiphy_acq_dev.device_handle = cam_create_device_hdl(&bridge_params); + if (csiphy_acq_dev.device_handle <= 0) { + rc = -EFAULT; + CAM_ERR(CAM_CSIPHY, "Can not create device handle"); + goto release_mutex; + } + csiphy_dev->csiphy_info[index].hdl_data.device_hdl = csiphy_acq_dev.device_handle; csiphy_dev->csiphy_info[index].hdl_data.session_hdl = diff --git a/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_core.c b/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_core.c index 8e4270373331..78130f6a66de 100644 --- a/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_core.c +++ b/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_core.c @@ -360,6 +360,10 @@ static int32_t cam_eeprom_get_dev_handle(struct cam_eeprom_ctrl_t *e_ctrl, eeprom_acq_dev.device_handle = cam_create_device_hdl(&bridge_params); + if (eeprom_acq_dev.device_handle <= 0) { + CAM_ERR(CAM_EEPROM, "Can not create device handle"); + return -EFAULT; + } e_ctrl->bridge_intf.device_hdl = eeprom_acq_dev.device_handle; e_ctrl->bridge_intf.session_hdl = eeprom_acq_dev.session_handle; diff --git a/drivers/cam_sensor_module/cam_flash/cam_flash_dev.c b/drivers/cam_sensor_module/cam_flash/cam_flash_dev.c index 197502ff5896..cc57a7124ae9 100644 --- a/drivers/cam_sensor_module/cam_flash/cam_flash_dev.c +++ b/drivers/cam_sensor_module/cam_flash/cam_flash_dev.c @@ -68,6 +68,11 @@ static int32_t cam_flash_driver_cmd(struct cam_flash_ctrl *fctrl, flash_acq_dev.device_handle = cam_create_device_hdl(&bridge_params); + if (flash_acq_dev.device_handle <= 0) { + rc = -EFAULT; + CAM_ERR(CAM_FLASH, "Can not create device handle"); + goto release_mutex; + } fctrl->bridge_intf.device_hdl = flash_acq_dev.device_handle; fctrl->bridge_intf.session_hdl = diff --git a/drivers/cam_sensor_module/cam_ois/cam_ois_core.c b/drivers/cam_sensor_module/cam_ois/cam_ois_core.c index 543f7a9f3eb2..b8cc002edb91 100644 --- a/drivers/cam_sensor_module/cam_ois/cam_ois_core.c +++ b/drivers/cam_sensor_module/cam_ois/cam_ois_core.c @@ -86,6 +86,10 @@ static int cam_ois_get_dev_handle(struct cam_ois_ctrl_t *o_ctrl, ois_acq_dev.device_handle = cam_create_device_hdl(&bridge_params); + if (ois_acq_dev.device_handle <= 0) { + CAM_ERR(CAM_OIS, "Can not create device handle"); + return -EFAULT; + } o_ctrl->bridge_intf.device_hdl = ois_acq_dev.device_handle; o_ctrl->bridge_intf.session_hdl = ois_acq_dev.session_handle; diff --git a/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c b/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c index 38846433fd0a..8298f9f81bc6 100644 --- a/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c +++ b/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c @@ -839,6 +839,11 @@ int32_t cam_sensor_driver_cmd(struct cam_sensor_ctrl_t *s_ctrl, sensor_acq_dev.device_handle = cam_create_device_hdl(&bridge_params); + if (sensor_acq_dev.device_handle <= 0) { + rc = -EFAULT; + CAM_ERR(CAM_SENSOR, "Can not create device handle"); + goto release_mutex; + } s_ctrl->bridge_intf.device_hdl = sensor_acq_dev.device_handle; s_ctrl->bridge_intf.session_hdl = sensor_acq_dev.session_handle; From a35c7c2f108c7102ab1c6bd5b570d81751fd0275 Mon Sep 17 00:00:00 2001 From: Tejas Prajapati Date: Wed, 17 Nov 2021 16:53:17 +0530 Subject: [PATCH 20/25] msm: camera: tfe: dump csid clock and path data at overflow On overflow dump the AB and IB votes, tfe clock, CSID clock and respective bus path data for acquire time and addr_status registers. CRs-Fixed: 3118430 Change-Id: Ia38eb4350e8e38562b6d22769b38637480da0b9d Signed-off-by: Tejas Prajapati --- drivers/cam_cpas/cam_cpas_hw.c | 3 + drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c | 75 ++++++++++++++++++- .../isp_hw/tfe_csid_hw/cam_tfe_csid_core.c | 32 +++++++- .../isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.c | 2 +- 4 files changed, 109 insertions(+), 3 deletions(-) diff --git a/drivers/cam_cpas/cam_cpas_hw.c b/drivers/cam_cpas/cam_cpas_hw.c index 15623b525e55..5aeda25f8415 100644 --- a/drivers/cam_cpas/cam_cpas_hw.c +++ b/drivers/cam_cpas/cam_cpas_hw.c @@ -1030,6 +1030,7 @@ static int cam_cpas_util_apply_default_axi_vote( struct cam_cpas *cpas_core = (struct cam_cpas *) cpas_hw->core_info; struct cam_cpas_axi_port *axi_port = NULL; uint64_t mnoc_ab_bw = 0, mnoc_ib_bw = 0; + uint64_t applied_ab_bw = 0, applied_ib_bw = 0; int rc = 0, i = 0; mutex_lock(&cpas_core->tree_lock); @@ -1057,6 +1058,8 @@ static int cam_cpas_util_apply_default_axi_vote( mnoc_ab_bw, mnoc_ib_bw, rc); goto unlock_tree; } + cpas_core->axi_port[i].applied_ab_bw = applied_ab_bw; + cpas_core->axi_port[i].applied_ib_bw = applied_ib_bw; } unlock_tree: diff --git a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c index aa6e8c15aa8e..e5342bd95163 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c @@ -5405,6 +5405,65 @@ end: return 0; } +static int cam_tfe_hw_mgr_handle_hw_dump_info( + void *ctx, + void *evt_info) +{ + struct cam_tfe_hw_mgr_ctx *tfe_hw_mgr_ctx = + (struct cam_tfe_hw_mgr_ctx *)ctx; + struct cam_isp_hw_event_info *event_info = + (struct cam_isp_hw_event_info *)evt_info; + struct cam_isp_hw_mgr_res *hw_mgr_res = NULL; + struct cam_hw_intf *hw_intf; + uint32_t i, out_port_id; + uint64_t dummy_args; + int rc = 0; + + list_for_each_entry(hw_mgr_res, + &tfe_hw_mgr_ctx->res_list_tfe_csid, list) { + for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) { + if (!hw_mgr_res->hw_res[i]) + continue; + hw_intf = hw_mgr_res->hw_res[i]->hw_intf; + if (hw_intf->hw_ops.process_cmd) { + rc = hw_intf->hw_ops.process_cmd( + hw_intf->hw_priv, + CAM_ISP_HW_CMD_CSID_CLOCK_DUMP, + &dummy_args, + sizeof(uint64_t)); + if (rc) + CAM_ERR(CAM_ISP, + "CSID Clock Dump failed"); + } + } + } + + if (event_info->res_type == CAM_ISP_RESOURCE_VFE_OUT) { + out_port_id = event_info->res_id & 0xFF; + if (out_port_id >= CAM_TFE_HW_OUT_RES_MAX) { + CAM_ERR(CAM_ISP, + "Resource out of range"); + goto end; + } + hw_mgr_res = + &tfe_hw_mgr_ctx->res_list_tfe_out[out_port_id]; + for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) { + if (!hw_mgr_res->hw_res[i]) + continue; + hw_intf = hw_mgr_res->hw_res[i]->hw_intf; + if (hw_intf->hw_ops.process_cmd) { + rc = hw_intf->hw_ops.process_cmd( + hw_intf->hw_priv, + CAM_ISP_HW_CMD_DUMP_BUS_INFO, + (void *)event_info, + sizeof(struct cam_isp_hw_event_info)); + } + } + } +end: + return rc; +} + static int cam_tfe_hw_mgr_handle_csid_event( struct cam_isp_hw_event_info *event_info) { @@ -5433,8 +5492,10 @@ static int cam_tfe_hw_mgr_handle_csid_event( } static int cam_tfe_hw_mgr_handle_hw_err( + void *ctx, void *evt_info) { + struct cam_tfe_hw_mgr_ctx *tfe_hw_mgr_ctx; struct cam_isp_hw_event_info *event_info = evt_info; struct cam_isp_hw_error_event_data error_event_data = {0}; struct cam_tfe_hw_event_recovery_data recovery_data = {0}; @@ -5456,6 +5517,18 @@ static int cam_tfe_hw_mgr_handle_hw_err( return rc; } + if (ctx) { + tfe_hw_mgr_ctx = + (struct cam_tfe_hw_mgr_ctx *)ctx; + if (event_info->res_type == + CAM_ISP_RESOURCE_TFE_IN && + !tfe_hw_mgr_ctx->is_rdi_only_context && + event_info->res_id != + CAM_ISP_HW_TFE_IN_CAMIF) + cam_tfe_hw_mgr_handle_hw_dump_info( + tfe_hw_mgr_ctx, event_info); + } + core_idx = event_info->hw_idx; if (g_tfe_hw_mgr.debug_cfg.enable_recovery) @@ -5738,7 +5811,7 @@ static int cam_tfe_hw_mgr_event_handler( break; case CAM_ISP_HW_EVENT_ERROR: - rc = cam_tfe_hw_mgr_handle_hw_err(evt_info); + rc = cam_tfe_hw_mgr_handle_hw_err(priv, evt_info); break; default: diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.c index c0ef268f4198..41137cd57efd 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.c @@ -2610,6 +2610,19 @@ static int cam_tfe_csid_set_csid_clock( return 0; } +static int cam_tfe_csid_dump_csid_clock( + struct cam_tfe_csid_hw *csid_hw, void *cmd_args) +{ + if (!csid_hw) + return -EINVAL; + + CAM_INFO(CAM_ISP, "CSID:%d clock rate %llu", + csid_hw->hw_intf->hw_idx, + csid_hw->clk_rate); + + return 0; +} + static int cam_tfe_csid_get_csid_clock( struct cam_tfe_csid_hw *csid_hw, void *cmd_args) { @@ -2916,6 +2929,9 @@ static int cam_tfe_csid_process_cmd(void *hw_priv, case CAM_ISP_HW_CMD_CSID_CLOCK_UPDATE: rc = cam_tfe_csid_set_csid_clock(csid_hw, cmd_args); break; + case CAM_ISP_HW_CMD_CSID_CLOCK_DUMP: + rc = cam_tfe_csid_dump_csid_clock(csid_hw, cmd_args); + break; case CAM_TFE_CSID_CMD_GET_REG_DUMP: rc = cam_tfe_csid_get_regdump(csid_hw, cmd_args); break; @@ -3519,9 +3535,23 @@ handle_fatal_error: is_error_irq = true; } - if (is_error_irq || log_en) + if (is_error_irq || log_en) { + CAM_ERR(CAM_ISP, + "CSID %d irq status TOP: 0x%x RX: 0x%x IPP: 0x%x", + csid_hw->hw_intf->hw_idx, + irq_status[TFE_CSID_IRQ_REG_TOP], + irq_status[TFE_CSID_IRQ_REG_RX], + irq_status[TFE_CSID_IRQ_REG_IPP]); + CAM_ERR(CAM_ISP, + "RDI0: 0x%x RDI1: 0x%x RDI2: 0x%x CSID clk:%d", + irq_status[TFE_CSID_IRQ_REG_RDI0], + irq_status[TFE_CSID_IRQ_REG_RDI1], + irq_status[TFE_CSID_IRQ_REG_RDI2], + csid_hw->clk_rate); + cam_tfe_csid_handle_hw_err_irq(csid_hw, CAM_ISP_HW_ERROR_NONE, irq_status); + } if (csid_hw->irq_debug_cnt >= CAM_TFE_CSID_IRQ_SOF_DEBUG_CNT_MAX) { cam_tfe_csid_sof_irq_debug(csid_hw, &sof_irq_debug_en); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.c index 74eae1a23ff3..042fe6b892fc 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.c @@ -444,7 +444,7 @@ static void cam_tfe_log_error_irq_status( "TFE clock rate:%d TFE total bw applied:%lld", top_priv->hw_clk_rate, top_priv->total_bw_applied); - + cam_cpas_log_votes(); } static int cam_tfe_error_irq_bottom_half( From 583fb300c8fe93f842ef01c35eed72175b3f9d8d Mon Sep 17 00:00:00 2001 From: Nirmal Abraham Date: Thu, 3 Feb 2022 12:09:19 +0530 Subject: [PATCH 21/25] msm: camera: reqmgr: Avoid freeing subdev twice The 'l_device' pointer in __cam_req_mgr_destroy_subdev is set to NULL after freeing but this is done on a local copy of the variable in stack. This results in double-free when this function is called again. To avoid this, pass 'l_device' pointer by reference and assign it to NULL after freeing. CRs-Fixed: 3120468 Change-Id: If2dde6f1c702bee26a3c8a68c2f45bafbf0f7cd6 Signed-off-by: Nirmal Abraham --- drivers/cam_req_mgr/cam_req_mgr_core.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.c b/drivers/cam_req_mgr/cam_req_mgr_core.c index 18dcb1bc2b96..80eed1cfd526 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.c +++ b/drivers/cam_req_mgr/cam_req_mgr_core.c @@ -1,6 +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. */ #include @@ -2281,10 +2282,13 @@ static int __cam_req_mgr_create_subdevs( * */ static void __cam_req_mgr_destroy_subdev( - struct cam_req_mgr_connected_device *l_device) + struct cam_req_mgr_connected_device **l_device) { - kfree(l_device); - l_device = NULL; + CAM_DBG(CAM_CRM, "*l_device %pK", *l_device); + if (*(l_device) != NULL) { + kfree(*(l_device)); + *l_device = NULL; + } } /** @@ -3820,7 +3824,7 @@ static int __cam_req_mgr_unlink(struct cam_req_mgr_core_link *link) __cam_req_mgr_destroy_link_info(link); /* Free memory holding data of linked devs */ - __cam_req_mgr_destroy_subdev(link->l_dev); + __cam_req_mgr_destroy_subdev(&link->l_dev); /* Destroy the link handle */ rc = cam_destroy_device_hdl(link->link_hdl); @@ -3995,7 +3999,7 @@ int cam_req_mgr_link(struct cam_req_mgr_ver_info *link_info) mutex_unlock(&g_crm_core_dev->crm_lock); return rc; setup_failed: - __cam_req_mgr_destroy_subdev(link->l_dev); + __cam_req_mgr_destroy_subdev(&link->l_dev); create_subdev_failed: cam_destroy_device_hdl(link->link_hdl); link_info->u.link_info_v1.link_hdl = -1; @@ -4111,7 +4115,7 @@ int cam_req_mgr_link_v2(struct cam_req_mgr_ver_info *link_info) mutex_unlock(&g_crm_core_dev->crm_lock); return rc; setup_failed: - __cam_req_mgr_destroy_subdev(link->l_dev); + __cam_req_mgr_destroy_subdev(&link->l_dev); create_subdev_failed: cam_destroy_device_hdl(link->link_hdl); link_info->u.link_info_v2.link_hdl = -1; From f33380f1828c21262133e60112422c7493498f26 Mon Sep 17 00:00:00 2001 From: zhuo Date: Tue, 4 Jan 2022 10:54:30 +0800 Subject: [PATCH 22/25] msm: camera: cdm: Fix workqueue timing issue Due to workqueue does not process the work in order, so sometimes the later work will be processed earlier. Such as, when submit request order: 1/2/3, cdm interrupt come order: 1/2/3, workqueue process order: 2/1/3, when process 2 request, which currently will notify 1/2 CDM clients and remove 1/2 from submit list. After that, when process 1 request, will notify 3, actually 3 is not done at the moment, which maybe cause smmu page fault issue. And sometimes, when there is a delay in handling interrupts, then HLOS handles two interrupts as one only. This change only notify the request less than and equal to the interrupt request. CRs-Fixed: 3130447 Change-Id: I0fd0e8adee48767e5ab7db1921a8284d107c2f40 Signed-off-by: zhuo --- drivers/cam_cdm/cam_cdm.h | 3 +++ drivers/cam_cdm/cam_cdm_hw_core.c | 39 +++++++++++++++++-------------- 2 files changed, 25 insertions(+), 17 deletions(-) diff --git a/drivers/cam_cdm/cam_cdm.h b/drivers/cam_cdm/cam_cdm.h index dc2c164e0b2c..df19116abab6 100644 --- a/drivers/cam_cdm/cam_cdm.h +++ b/drivers/cam_cdm/cam_cdm.h @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. */ #ifndef _CAM_CDM_H_ @@ -68,6 +69,8 @@ #define CAM_CDM_BL_FIFO_LENGTH_MAX_DEFAULT 0x40 #define CAM_CDM_BL_FIFO_LENGTH_CFG_SHIFT 0x10 #define CAM_CDM_BL_FIFO_FLUSH_SHIFT 0x3 +#define CAM_CDM_BL_FIFO_BOUNDARY_CHECK \ + (CAM_CDM_BL_FIFO_LENGTH_MAX_DEFAULT / 2) #define CAM_CDM_BL_FIFO_REQ_SIZE_MAX 0x00 #define CAM_CDM_BL_FIFO_REQ_SIZE_MAX_DIV2 0x01 diff --git a/drivers/cam_cdm/cam_cdm_hw_core.c b/drivers/cam_cdm/cam_cdm_hw_core.c index bd1e938a0d0f..901f84c3e034 100644 --- a/drivers/cam_cdm/cam_cdm_hw_core.c +++ b/drivers/cam_cdm/cam_cdm_hw_core.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. */ #include @@ -1263,26 +1264,30 @@ static void cam_hw_cdm_work(struct work_struct *work) list_for_each_entry_safe(node, tnode, &core->bl_fifo[fifo_idx].bl_request_list, entry) { - if (node->request_type == - CAM_HW_CDM_BL_CB_CLIENT) { - cam_cdm_notify_clients(cdm_hw, - CAM_CDM_CB_STATUS_BL_SUCCESS, - (void *)node); - } else if (node->request_type == - CAM_HW_CDM_BL_CB_INTERNAL) { - CAM_ERR(CAM_CDM, - "Invalid node=%pK %d", - node, - node->request_type); - } - list_del_init(&node->entry); - if (node->bl_tag == payload->irq_data) { + if ((node->bl_tag <= payload->irq_data) || + ((node->bl_tag - payload->irq_data) > + CAM_CDM_BL_FIFO_BOUNDARY_CHECK)) { + if (node->request_type == + CAM_HW_CDM_BL_CB_CLIENT) { + cam_cdm_notify_clients(cdm_hw, + CAM_CDM_CB_STATUS_BL_SUCCESS, + (void *)node); + } else if (node->request_type == + CAM_HW_CDM_BL_CB_INTERNAL) { + CAM_ERR(CAM_CDM, + "Invalid node=%pK %d", + node, + node->request_type); + } + list_del_init(&node->entry); + if (node->bl_tag == payload->irq_data) { + kfree(node); + node = NULL; + break; + } kfree(node); node = NULL; - break; } - kfree(node); - node = NULL; } } else { CAM_INFO(CAM_CDM, From e5cbfaf0af5149271e57deca9f47b5a98ef407ac Mon Sep 17 00:00:00 2001 From: Yash Upadhyay Date: Mon, 21 Feb 2022 10:07:23 +0530 Subject: [PATCH 23/25] msm: camera: reqmgr: Validate the link handle Instead of correct link handle, if some other handle like dev handle is passed then it may access some other data space. To avoid such scenario, need to check whether link handle passed by ioctl is same as retrieved link handle. CRs-Fixed: 3120454 Change-Id: Idff2e3c25b60563788ffb426c7cabc367c3c97f8 Signed-off-by: Yash Upadhyay --- drivers/cam_req_mgr/cam_req_mgr_core.c | 80 +++++++++++++++++--------- drivers/cam_req_mgr/cam_req_mgr_core.h | 2 + drivers/cam_utils/cam_debug_util.h | 3 + 3 files changed, 57 insertions(+), 28 deletions(-) diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.c b/drivers/cam_req_mgr/cam_req_mgr_core.c index ac04553899a2..5d37b3edc99a 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.c +++ b/drivers/cam_req_mgr/cam_req_mgr_core.c @@ -3857,8 +3857,10 @@ int cam_req_mgr_destroy_session( mutex_lock(&g_crm_core_dev->crm_lock); cam_session = (struct cam_req_mgr_core_session *) cam_get_device_priv(ses_info->session_hdl); - if (!cam_session) { - CAM_ERR(CAM_CRM, "failed to get session priv"); + if (!cam_session || (cam_session->session_hdl != ses_info->session_hdl)) { + CAM_ERR(CAM_CRM, "session: %s, ses_info->ses_hdl:%x, session->ses_hdl:%x", + CAM_IS_NULL_TO_STR(cam_session), ses_info->session_hdl, + (!cam_session) ? CAM_REQ_MGR_DEFAULT_HDL_VAL : cam_session->session_hdl); rc = -ENOENT; goto end; @@ -3928,8 +3930,10 @@ int cam_req_mgr_link(struct cam_req_mgr_ver_info *link_info) /* session hdl's priv data is cam session struct */ cam_session = (struct cam_req_mgr_core_session *) cam_get_device_priv(link_info->u.link_info_v1.session_hdl); - if (!cam_session) { - CAM_DBG(CAM_CRM, "NULL pointer"); + if (!cam_session || (cam_session->session_hdl != link_info->u.link_info_v1.session_hdl)) { + CAM_ERR(CAM_CRM, "session: %s, link_info->ses_hdl:%x, session->ses_hdl:%x", + CAM_IS_NULL_TO_STR(cam_session), link_info->u.link_info_v1.session_hdl, + (!cam_session) ? CAM_REQ_MGR_DEFAULT_HDL_VAL : cam_session->session_hdl); mutex_unlock(&g_crm_core_dev->crm_lock); return -EINVAL; } @@ -4038,8 +4042,10 @@ int cam_req_mgr_link_v2(struct cam_req_mgr_ver_info *link_info) /* session hdl's priv data is cam session struct */ cam_session = (struct cam_req_mgr_core_session *) cam_get_device_priv(link_info->u.link_info_v2.session_hdl); - if (!cam_session) { - CAM_DBG(CAM_CRM, "NULL pointer"); + if (!cam_session || (cam_session->session_hdl != link_info->u.link_info_v2.session_hdl)) { + CAM_ERR(CAM_CRM, "session: %s, link_info->ses_hdl:%x, session->ses_hdl:%x", + CAM_IS_NULL_TO_STR(cam_session), link_info->u.link_info_v2.session_hdl, + (!cam_session) ? CAM_REQ_MGR_DEFAULT_HDL_VAL : cam_session->session_hdl); mutex_unlock(&g_crm_core_dev->crm_lock); return -EINVAL; } @@ -4147,16 +4153,20 @@ int cam_req_mgr_unlink(struct cam_req_mgr_unlink_info *unlink_info) /* session hdl's priv data is cam session struct */ cam_session = (struct cam_req_mgr_core_session *) cam_get_device_priv(unlink_info->session_hdl); - if (!cam_session) { - CAM_ERR(CAM_CRM, "NULL pointer"); + if (!cam_session || (cam_session->session_hdl != unlink_info->session_hdl)) { + CAM_ERR(CAM_CRM, "session: %s, unlink_info->ses_hdl:%x, cam_session->ses_hdl:%x", + CAM_IS_NULL_TO_STR(cam_session), unlink_info->session_hdl, + (!cam_session) ? CAM_REQ_MGR_DEFAULT_HDL_VAL : cam_session->session_hdl); mutex_unlock(&g_crm_core_dev->crm_lock); return -EINVAL; } /* link hdl's priv data is core_link struct */ link = cam_get_device_priv(unlink_info->link_hdl); - if (!link) { - CAM_ERR(CAM_CRM, "NULL pointer"); + if (!link || (link->link_hdl != unlink_info->link_hdl)) { + CAM_ERR(CAM_CRM, "link: %s, unlink_info->link_hdl:%x, link->link_hdl:%x", + CAM_IS_NULL_TO_STR(link), unlink_info->link_hdl, + (!link) ? CAM_REQ_MGR_DEFAULT_HDL_VAL : link->link_hdl); rc = -EINVAL; goto done; } @@ -4189,8 +4199,10 @@ int cam_req_mgr_schedule_request( mutex_lock(&g_crm_core_dev->crm_lock); link = (struct cam_req_mgr_core_link *) cam_get_device_priv(sched_req->link_hdl); - if (!link) { - CAM_DBG(CAM_CRM, "link ptr NULL %x", sched_req->link_hdl); + if (!link || (link->link_hdl != sched_req->link_hdl)) { + CAM_ERR(CAM_CRM, "link: %s, sched_req->link_hdl:%x, link->link_hdl:%x", + CAM_IS_NULL_TO_STR(link), sched_req->link_hdl, + (!link) ? CAM_REQ_MGR_DEFAULT_HDL_VAL : link->link_hdl); rc = -EINVAL; goto end; } @@ -4274,8 +4286,10 @@ int cam_req_mgr_sync_config( /* session hdl's priv data is cam session struct */ cam_session = (struct cam_req_mgr_core_session *) cam_get_device_priv(sync_info->session_hdl); - if (!cam_session) { - CAM_ERR(CAM_CRM, "NULL pointer"); + if (!cam_session || (cam_session->session_hdl != sync_info->session_hdl)) { + CAM_ERR(CAM_CRM, "session: %s, sync_info->session_hdl:%x, session->ses_hdl:%x", + CAM_IS_NULL_TO_STR(cam_session), sync_info->session_hdl, + (!cam_session) ? CAM_REQ_MGR_DEFAULT_HDL_VAL : cam_session->session_hdl); mutex_unlock(&g_crm_core_dev->crm_lock); return -EINVAL; } @@ -4291,8 +4305,10 @@ int cam_req_mgr_sync_config( } link[i] = cam_get_device_priv(sync_info->link_hdls[i]); - if (!link[i]) { - CAM_ERR(CAM_CRM, "link%d NULL pointer", i); + if (!link[i] || (link[i]->link_hdl != sync_info->link_hdls[i])) { + CAM_ERR(CAM_CRM, "link: %s, sync_info->link_hdl:%x, link->link_hdl:%x", + CAM_IS_NULL_TO_STR(link), sync_info->link_hdls[i], + (!link[i]) ? CAM_REQ_MGR_DEFAULT_HDL_VAL : link[i]->link_hdl); rc = -EINVAL; goto done; } @@ -4368,8 +4384,10 @@ int cam_req_mgr_flush_requests( /* session hdl's priv data is cam session struct */ session = (struct cam_req_mgr_core_session *) cam_get_device_priv(flush_info->session_hdl); - if (!session) { - CAM_ERR(CAM_CRM, "Invalid session %x", flush_info->session_hdl); + if (!session || (session->session_hdl != flush_info->session_hdl)) { + CAM_ERR(CAM_CRM, "session: %s, flush_info->ses_hdl:%x, session->ses_hdl:%x", + CAM_IS_NULL_TO_STR(session), flush_info->session_hdl, + (!session) ? CAM_REQ_MGR_DEFAULT_HDL_VAL : session->session_hdl); rc = -EINVAL; goto end; } @@ -4381,8 +4399,10 @@ int cam_req_mgr_flush_requests( link = (struct cam_req_mgr_core_link *) cam_get_device_priv(flush_info->link_hdl); - if (!link) { - CAM_DBG(CAM_CRM, "link ptr NULL %x", flush_info->link_hdl); + if (!link || (link->link_hdl != flush_info->link_hdl)) { + CAM_ERR(CAM_CRM, "link: %s, flush_info->link_hdl:%x, link->link_hdl:%x", + CAM_IS_NULL_TO_STR(link), flush_info->link_hdl, + (!link) ? CAM_REQ_MGR_DEFAULT_HDL_VAL : link->link_hdl); rc = -EINVAL; goto end; } @@ -4440,9 +4460,10 @@ int cam_req_mgr_link_control(struct cam_req_mgr_link_control *control) for (i = 0; i < control->num_links; i++) { link = (struct cam_req_mgr_core_link *) cam_get_device_priv(control->link_hdls[i]); - if (!link) { - CAM_ERR(CAM_CRM, "Link(%d) is NULL on session 0x%x", - i, control->session_hdl); + if (!link || (link->link_hdl != control->link_hdls[i])) { + CAM_ERR(CAM_CRM, "link: %s, control->link_hdl:%x, link->link_hdl:%x", + CAM_IS_NULL_TO_STR(link), control->link_hdls[i], + (!link) ? CAM_REQ_MGR_DEFAULT_HDL_VAL : link->link_hdl); rc = -EINVAL; break; } @@ -4528,9 +4549,10 @@ int cam_req_mgr_dump_request(struct cam_dump_req_cmd *dump_req) /* session hdl's priv data is cam session struct */ session = (struct cam_req_mgr_core_session *) cam_get_device_priv(dump_req->session_handle); - if (!session) { - CAM_ERR(CAM_CRM, "Invalid session %x", - dump_req->session_handle); + if (!session || (session->session_hdl != dump_req->session_handle)) { + CAM_ERR(CAM_CRM, "session: %s, dump_req->ses_hdl:%x, session->ses_hdl:%x", + CAM_IS_NULL_TO_STR(session), dump_req->session_handle, + (!session) ? CAM_REQ_MGR_DEFAULT_HDL_VAL : session->session_hdl); rc = -EINVAL; goto end; } @@ -4542,8 +4564,10 @@ int cam_req_mgr_dump_request(struct cam_dump_req_cmd *dump_req) link = (struct cam_req_mgr_core_link *) cam_get_device_priv(dump_req->link_hdl); - if (!link || link->link_hdl != dump_req->link_hdl) { - CAM_DBG(CAM_CRM, "link ptr NULL %x", dump_req->link_hdl); + if (!link || (link->link_hdl != dump_req->link_hdl)) { + CAM_ERR(CAM_CRM, "link: %s, dump_req->link_hdl:%x, link->link_hdl:%x", + CAM_IS_NULL_TO_STR(link), dump_req->link_hdl, + (!link) ? CAM_REQ_MGR_DEFAULT_HDL_VAL : link->link_hdl); rc = -EINVAL; goto end; } diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.h b/drivers/cam_req_mgr/cam_req_mgr_core.h index 8b6edaa3f9ff..6f75677c29c2 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.h +++ b/drivers/cam_req_mgr/cam_req_mgr_core.h @@ -1,6 +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. */ #ifndef _CAM_REQ_MGR_CORE_H_ #define _CAM_REQ_MGR_CORE_H_ @@ -18,6 +19,7 @@ #define CAM_REQ_MGR_WATCHDOG_TIMEOUT_MAX 50000 #define CAM_REQ_MGR_SCHED_REQ_TIMEOUT 1000 #define CAM_REQ_MGR_SIMULATE_SCHED_REQ 30 +#define CAM_REQ_MGR_DEFAULT_HDL_VAL 0 #define FORCE_DISABLE_RECOVERY 2 #define FORCE_ENABLE_RECOVERY 1 diff --git a/drivers/cam_utils/cam_debug_util.h b/drivers/cam_utils/cam_debug_util.h index 5232501525d1..28fc4c2399a2 100644 --- a/drivers/cam_utils/cam_debug_util.h +++ b/drivers/cam_utils/cam_debug_util.h @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. */ #ifndef _CAM_DEBUG_UTIL_H_ @@ -8,6 +9,8 @@ #include +#define CAM_IS_NULL_TO_STR(ptr) ((ptr) ? "Non-NULL" : "NULL") + /* Module IDs used for debug logging */ #define CAM_CDM (1 << 0) #define CAM_CORE (1 << 1) From a4b0246d27818b388e7e6bbe28db3f4aab7c6aa9 Mon Sep 17 00:00:00 2001 From: Tejas Prajapati Date: Mon, 7 Mar 2022 17:18:33 +0530 Subject: [PATCH 24/25] msm: camera: memmgr: update correct length in bufq In a corner case, race condition to free the original ion buf allocated and new ion buffer with same fd but different size after freeing the origianl ion buf might result into mismatches in the real ion buf size assigned in bufq. To avoid this update length in bufq with local variable. CRs-Fixed: 3142221 Change-Id: I23d91445bd088bbde19ffa191e158256166f2053 Signed-off-by: Tejas Prajapati --- drivers/cam_req_mgr/cam_mem_mgr.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/cam_req_mgr/cam_mem_mgr.c b/drivers/cam_req_mgr/cam_mem_mgr.c index b928c7da46c7..ee227f943272 100644 --- a/drivers/cam_req_mgr/cam_mem_mgr.c +++ b/drivers/cam_req_mgr/cam_mem_mgr.c @@ -1,6 +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. */ #include @@ -758,7 +759,7 @@ int cam_mem_mgr_alloc_and_map(struct cam_mem_mgr_alloc_cmd *cmd) tbl.bufq[idx].kmdvaddr = kvaddr; tbl.bufq[idx].vaddr = hw_vaddr; tbl.bufq[idx].dma_buf = dmabuf; - tbl.bufq[idx].len = cmd->len; + tbl.bufq[idx].len = len; tbl.bufq[idx].num_hdl = cmd->num_hdl; memcpy(tbl.bufq[idx].hdls, cmd->mmu_hdls, sizeof(int32_t) * cmd->num_hdl); From dd87df520d403d8afb2eb37953227180da06a7e9 Mon Sep 17 00:00:00 2001 From: Tejas Prajapati Date: Fri, 3 Dec 2021 16:36:26 +0530 Subject: [PATCH 25/25] msm: camera: ife: dump data at overlflow for rdi only use case Below information is dumped at the overflow 1. Dump SOF, EPOCH, EOF and Error time. 2. Dump IRQ status. 3. Cpas AB, IB votes. 4. Dump width and height of all the acquired ports. 5. CSID clock. CRs-Fixed: 3159425 Change-Id: I580d8f4d50c49568a6bc9ae8d06fc4b93f11891c Signed-off-by: Tejas Prajapati --- .../isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c | 345 +++++++++++++++--- 1 file changed, 303 insertions(+), 42 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c index 5b33a6ecb0e1..72bc959b6126 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c @@ -16,6 +16,7 @@ #include "cam_tasklet_util.h" #include "cam_vfe_bus.h" #include "cam_vfe_bus_ver2.h" +#include "cam_vfe_soc.h" #include "cam_vfe_core.h" #include "cam_debug_util.h" #include "cam_cpas_api.h" @@ -80,6 +81,12 @@ enum cam_vfe_bus_comp_grp_id { CAM_VFE_BUS_COMP_GROUP_ID_5 = 0x5, }; +struct cam_vfe_bus_error_info { + uint32_t bitmask; + uint32_t vfe_output; + char *error_description; +}; + struct cam_vfe_bus_ver2_common_data { uint32_t core_index; void __iomem *mem_base; @@ -99,6 +106,7 @@ struct cam_vfe_bus_ver2_common_data { uint32_t num_sec_out; uint32_t addr_no_sync; cam_hw_mgr_event_cb_func event_cb; + bool is_lite; bool hw_init; bool support_consumed_addr; bool disable_ubwc_comp; @@ -193,6 +201,7 @@ struct cam_vfe_bus_ver2_priv { struct cam_isp_resource_node bus_client[CAM_VFE_BUS_VER2_MAX_CLIENTS]; struct cam_isp_resource_node comp_grp[CAM_VFE_BUS_VER2_COMP_GRP_MAX]; struct cam_isp_resource_node vfe_out[CAM_VFE_BUS_VER2_VFE_OUT_MAX]; + uint32_t vfe_out_map_outtype[CAM_VFE_BUS_VER2_VFE_OUT_MAX]; struct list_head free_comp_grp; struct list_head free_dual_comp_grp; @@ -204,6 +213,138 @@ struct cam_vfe_bus_ver2_priv { uint32_t max_out_res; }; +static const struct cam_vfe_bus_error_info vfe_error_list[] = { + { + .bitmask = 0x80000000, + .vfe_output = CAM_VFE_BUS_VER2_VFE_OUT_FULL_DISP, + .error_description = "DISP C 1:1" + }, + { + .bitmask = 0x40000000, + .vfe_output = CAM_VFE_BUS_VER2_VFE_OUT_FULL_DISP, + .error_description = "DISP Y 1:1" + }, + { + .bitmask = 0x01000000, + .vfe_output = CAM_VFE_BUS_VER2_VFE_OUT_STATS_TL_BG, + .error_description = "STATS TINTLESS BG" + }, + { + .bitmask = 0x00800000, + .vfe_output = CAM_VFE_BUS_VER2_VFE_OUT_STATS_BHIST, + .error_description = "STATS BHIST" + }, + { + .bitmask = 0x00400000, + .vfe_output = CAM_VFE_BUS_VER2_VFE_OUT_STATS_IHIST, + .error_description = "STATS IHIST" + }, + { + .bitmask = 0x00200000, + .vfe_output = CAM_VFE_BUS_VER2_VFE_OUT_STATS_CS, + .error_description = "STATS CS" + }, + { + .bitmask = 0x00100000, + .vfe_output = CAM_VFE_BUS_VER2_VFE_OUT_STATS_RS, + .error_description = "STATS RS" + }, + { + .bitmask = 0x00080000, + .vfe_output = CAM_VFE_BUS_VER2_VFE_OUT_STATS_HDR_BHIST, + .error_description = "STATS HDR BHIST" + }, + { + .bitmask = 0x00040000, + .vfe_output = CAM_VFE_BUS_VER2_VFE_OUT_STATS_BF, + .error_description = "STATS BAF" + }, + { + .bitmask = 0x00020000, + .vfe_output = CAM_VFE_BUS_VER2_VFE_OUT_STATS_AWB_BG, + .error_description = "STATS AWB BG" + }, + { + .bitmask = 0x00010000, + .vfe_output = CAM_VFE_BUS_VER2_VFE_OUT_STATS_HDR_BE, + .error_description = "STATS HDR BE" + }, + { + .bitmask = 0x00004000, + .vfe_output = CAM_VFE_BUS_VER2_VFE_OUT_2PD, + .error_description = "PD" + }, + { + .bitmask = 0x00002000, + .vfe_output = CAM_VFE_BUS_VER2_VFE_OUT_RAW_DUMP, + .error_description = "PIXEL RAW DUMP" + }, + { + .bitmask = 0x00001000, + .vfe_output = CAM_VFE_BUS_VER2_VFE_OUT_FULL, + .error_description = "VID C 1:1" + }, + { + .bitmask = 0x00000800, + .vfe_output = CAM_VFE_BUS_VER2_VFE_OUT_FULL, + .error_description = "VID Y 1:1" + }, + { + .bitmask = 0x00000400, + .vfe_output = CAM_VFE_BUS_VER2_VFE_OUT_FD, + .error_description = "FD C" + }, + { + .bitmask = 0x00000200, + .vfe_output = CAM_VFE_BUS_VER2_VFE_OUT_FD, + .error_description = "FD Y" + }, + { + .bitmask = 0x00000020, + .vfe_output = CAM_VFE_BUS_VER2_VFE_OUT_RDI3, + .error_description = "Full RDI 3" + }, + { + .bitmask = 0x00000010, + .vfe_output = CAM_VFE_BUS_VER2_VFE_OUT_RDI2, + .error_description = "Full RDI 2" + }, + { + .bitmask = 0x00000008, + .vfe_output = CAM_VFE_BUS_VER2_VFE_OUT_RDI1, + .error_description = "Full RDI 1" + }, + { + .bitmask = 0x00000004, + .vfe_output = CAM_VFE_BUS_VER2_VFE_OUT_RDI0, + .error_description = "Full RDI 0" + }, +}; + +static const struct cam_vfe_bus_error_info vfe_lite_error_list[] = { + { + .bitmask = 0x04, + .vfe_output = CAM_VFE_BUS_VER2_VFE_OUT_RDI0, + .error_description = "Lite RDI 0" + }, + { + .bitmask = 0x08, + .vfe_output = CAM_VFE_BUS_VER2_VFE_OUT_RDI1, + .error_description = "Lite RDI 1" + }, + { + .bitmask = 0x10, + .vfe_output = CAM_VFE_BUS_VER2_VFE_OUT_RDI2, + .error_description = "Lite RDI 2" + }, + { + .bitmask = 0x20, + .vfe_output = CAM_VFE_BUS_VER2_VFE_OUT_RDI3, + .error_description = "Lite RDI 3" + } +}; + + static int cam_vfe_bus_process_cmd( struct cam_isp_resource_node *priv, uint32_t cmd_type, void *cmd_args, uint32_t arg_size); @@ -481,6 +622,22 @@ static enum cam_vfe_bus_ver2_vfe_out_type } } +static enum cam_vfe_bus_ver2_vfe_out_type + cam_vfe_bus_ver2_get_out_res_id_and_index( + struct cam_vfe_bus_ver2_priv *bus_priv, + uint32_t res_type, uint32_t *index) +{ + uint32_t vfe_out_type; + + vfe_out_type = cam_vfe_bus_get_out_res_id(res_type); + if (vfe_out_type == CAM_VFE_BUS_VER2_VFE_OUT_MAX) + *index = CAM_VFE_BUS_VER2_VFE_OUT_MAX; + else + *index = bus_priv->vfe_out_map_outtype[vfe_out_type]; + + return vfe_out_type; +} + static int cam_vfe_bus_get_num_wm( enum cam_vfe_bus_ver2_vfe_out_type res_type, uint32_t format) @@ -1440,6 +1597,94 @@ static int cam_vfe_bus_handle_wm_done_bottom_half(void *handler_priv, return rc; } +static int cam_vfe_bus_ver2_print_dimensions( + uint32_t res_id, + struct cam_vfe_bus_ver2_priv *bus_priv) +{ + struct cam_isp_resource_node *rsrc_node = NULL; + struct cam_vfe_bus_ver2_vfe_out_data *rsrc_data = NULL; + struct cam_vfe_bus_ver2_wm_resource_data *wm_data = NULL; + struct cam_vfe_bus_ver2_common_data *common_data = NULL; + int i; + uint32_t addr_status0, addr_status1; + enum cam_vfe_bus_ver2_vfe_out_type vfe_out_res_id = + CAM_VFE_BUS_VER2_VFE_OUT_MAX; + uint32_t outmap_index = CAM_VFE_BUS_VER2_VFE_OUT_MAX; + + if (!bus_priv) { + CAM_ERR(CAM_ISP, "Invalid bus private data, res_id: %d", + res_id); + return -EINVAL; + } + + vfe_out_res_id = cam_vfe_bus_ver2_get_out_res_id_and_index(bus_priv, + res_id, &outmap_index); + + if ((vfe_out_res_id == CAM_VFE_BUS_VER2_VFE_OUT_MAX) || + (outmap_index >= bus_priv->num_out)) { + CAM_WARN_RATE_LIMIT(CAM_ISP, + "target does not support req res id :0x%x outtype:%d index:%d", + res_id, + vfe_out_res_id, outmap_index); + return -EINVAL; + } + + rsrc_node = &bus_priv->vfe_out[outmap_index]; + rsrc_data = rsrc_node->res_priv; + if (!rsrc_data) { + CAM_ERR(CAM_ISP, "VFE out data is null, res_id: %d", + vfe_out_res_id); + return -EINVAL; + } + + for (i = 0; i < rsrc_data->num_wm; i++) { + wm_data = rsrc_data->wm_res[i]->res_priv; + common_data = rsrc_data->common_data; + addr_status0 = cam_io_r_mb(common_data->mem_base + + wm_data->hw_regs->status0); + addr_status1 = cam_io_r_mb(common_data->mem_base + + wm_data->hw_regs->status1); + + CAM_INFO(CAM_ISP, + "VFE:%d WM:%d width:%u height:%u stride:%u x_init:%u en_cfg:%u acquired width:%u height:%u", + wm_data->common_data->core_index, wm_data->index, + wm_data->width, + wm_data->height, + wm_data->stride, wm_data->h_init, + wm_data->en_cfg, + wm_data->acquired_width, + wm_data->acquired_height); + CAM_INFO(CAM_ISP, + "hw:%d WM:%d last consumed address:0x%x last frame addr:0x%x", + common_data->hw_intf->hw_idx, + wm_data->index, + addr_status0, + addr_status1); + } + return 0; +} + +static void cam_vfe_print_violations( + char *error_type, + const struct cam_vfe_bus_error_info *error_list, + uint32_t num_errors, + uint32_t status, + struct cam_vfe_bus_ver2_priv *bus_priv) +{ + int i; + + for (i = 0; i < num_errors; i++) { + if (status & error_list[i].bitmask) { + CAM_INFO(CAM_ISP, "%s: %s violation", + error_list[i].error_description, + error_type); + if (bus_priv != NULL) + cam_vfe_bus_ver2_print_dimensions( + error_list[i].vfe_output, + bus_priv); + } + } +} static int cam_vfe_bus_err_bottom_half(void *handler_priv, void *evt_payload_priv) @@ -1448,7 +1693,10 @@ static int cam_vfe_bus_err_bottom_half(void *handler_priv, struct cam_vfe_bus_ver2_priv *bus_priv = handler_priv; struct cam_vfe_bus_ver2_common_data *common_data; struct cam_isp_hw_event_info evt_info; + const struct cam_vfe_bus_error_info *error_list = NULL; uint32_t val = 0; + uint32_t error_list_size = 0; + uint32_t status = 0; if (!handler_priv || !evt_payload_priv) return -EINVAL; @@ -1459,77 +1707,76 @@ static int cam_vfe_bus_err_bottom_half(void *handler_priv, val = evt_payload->debug_status_0; CAM_ERR(CAM_ISP, "Bus Violation: debug_status_0 = 0x%x", val); - if (val & 0x01) + error_list = common_data->is_lite ? + vfe_lite_error_list : vfe_error_list; + error_list_size = common_data->is_lite ? + ARRAY_SIZE(vfe_lite_error_list) : ARRAY_SIZE(vfe_error_list); + + if (val & 0x00000004) CAM_INFO(CAM_ISP, "RDI 0 violation"); - if (val & 0x02) + if (val & 0x00000008) CAM_INFO(CAM_ISP, "RDI 1 violation"); - if (val & 0x04) + if (val & 0x00000010) CAM_INFO(CAM_ISP, "RDI 2 violation"); - if (val & 0x08) - CAM_INFO(CAM_ISP, "VID Y 1:1 UBWC violation"); + if (val & 0x00000020) + CAM_INFO(CAM_ISP, "RDI 3 violation"); - if (val & 0x010) - CAM_INFO(CAM_ISP, "VID C 1:1 UBWC violation"); - - if (val & 0x020) - CAM_INFO(CAM_ISP, "VID YC 4:1 violation"); - - if (val & 0x040) - CAM_INFO(CAM_ISP, "VID YC 16:1 violation"); - - if (val & 0x080) + if (val & 0x00000200) CAM_INFO(CAM_ISP, "FD Y violation"); - if (val & 0x0100) + if (val & 0x00000400) CAM_INFO(CAM_ISP, "FD C violation"); - if (val & 0x0200) + if (val & 0x00001000) + CAM_INFO(CAM_ISP, "VID C 1:1 UBWC violation"); + + if (val & 0x00000800) + CAM_INFO(CAM_ISP, "VID Y 1:1 UBWC violation"); + + if (val & 0x00002000) CAM_INFO(CAM_ISP, "RAW DUMP violation"); - if (val & 0x0400) + if (val & 0x00004000) CAM_INFO(CAM_ISP, "PDAF violation"); - if (val & 0x0800) + if (val & 0x00010000) CAM_INFO(CAM_ISP, "STATs HDR BE violation"); - if (val & 0x01000) - CAM_INFO(CAM_ISP, "STATs HDR BHIST violation"); - - if (val & 0x02000) - CAM_INFO(CAM_ISP, "STATs TINTLESS BG violation"); - - if (val & 0x04000) - CAM_INFO(CAM_ISP, "STATs BF violation"); - - if (val & 0x08000) + if (val & 0x00020000) CAM_INFO(CAM_ISP, "STATs AWB BG UBWC violation"); - if (val & 0x010000) - CAM_INFO(CAM_ISP, "STATs BHIST violation"); + if (val & 0x00040000) + CAM_INFO(CAM_ISP, "STATs BF violation"); - if (val & 0x020000) + if (val & 0x00080000) + CAM_INFO(CAM_ISP, "STATs HDR BHIST violation"); + + if (val & 0x00100000) CAM_INFO(CAM_ISP, "STATs RS violation"); - if (val & 0x040000) + if (val & 0x00200000) CAM_INFO(CAM_ISP, "STATs CS violation"); - if (val & 0x080000) + if (val & 0x00400000) CAM_INFO(CAM_ISP, "STATs IHIST violation"); - if (val & 0x0100000) + if (val & 0x00800000) + CAM_INFO(CAM_ISP, "STATs BHIST violation"); + + if (val & 0x01000000) + CAM_INFO(CAM_ISP, "STATs TINTLESS BG violation"); + + if (val & 0x40000000) CAM_INFO(CAM_ISP, "DISP Y 1:1 UBWC violation"); - if (val & 0x0200000) + if (val & 0x80000000) CAM_INFO(CAM_ISP, "DISP C 1:1 UBWC violation"); - if (val & 0x0400000) - CAM_INFO(CAM_ISP, "DISP YC 4:1 violation"); - - if (val & 0x0800000) - CAM_INFO(CAM_ISP, "DISP YC 16:1 violation"); + cam_vfe_print_violations("Error", error_list, + error_list_size, status, bus_priv); cam_vfe_bus_put_evt_payload(common_data, &evt_payload); @@ -2550,7 +2797,8 @@ static int cam_vfe_bus_init_vfe_out_resource(uint32_t index, return -EINVAL; } - vfe_out = &ver2_bus_priv->vfe_out[vfe_out_type]; + ver2_bus_priv->vfe_out_map_outtype[vfe_out_type] = index; + vfe_out = &ver2_bus_priv->vfe_out[index]; if (vfe_out->res_state != CAM_ISP_RESOURCE_STATE_UNAVAILABLE || vfe_out->res_priv) { CAM_ERR(CAM_ISP, @@ -3830,6 +4078,7 @@ int cam_vfe_bus_ver2_init( struct cam_vfe_bus_ver2_priv *bus_priv = NULL; struct cam_vfe_bus *vfe_bus_local; struct cam_vfe_bus_ver2_hw_info *ver2_hw_info = bus_hw_info; + struct cam_vfe_soc_private *soc_private = NULL; CAM_DBG(CAM_ISP, "Enter"); @@ -3842,6 +4091,13 @@ int cam_vfe_bus_ver2_init( goto end; } + soc_private = soc_info->soc_private; + if (!soc_private) { + CAM_ERR(CAM_ISP, "Invalid soc_private"); + rc = -ENODEV; + goto end; + } + vfe_bus_local = kzalloc(sizeof(struct cam_vfe_bus), GFP_KERNEL); if (!vfe_bus_local) { CAM_DBG(CAM_ISP, "Failed to alloc for vfe_bus"); @@ -3876,6 +4132,7 @@ int cam_vfe_bus_ver2_init( bus_priv->common_data.support_consumed_addr = ver2_hw_info->support_consumed_addr; bus_priv->common_data.disable_ubwc_comp = false; + bus_priv->common_data.is_lite = soc_private->is_ife_lite; mutex_init(&bus_priv->common_data.bus_mutex); @@ -3909,6 +4166,10 @@ int cam_vfe_bus_ver2_init( } } + for (i = 0; i < CAM_VFE_BUS_VER2_VFE_OUT_MAX; i++) + bus_priv->vfe_out_map_outtype[i] = + CAM_VFE_BUS_VER2_VFE_OUT_MAX; + for (i = 0; i < bus_priv->num_out; i++) { rc = cam_vfe_bus_init_vfe_out_resource(i, bus_priv, bus_hw_info);