From 583fb300c8fe93f842ef01c35eed72175b3f9d8d Mon Sep 17 00:00:00 2001 From: Nirmal Abraham Date: Thu, 3 Feb 2022 12:09:19 +0530 Subject: [PATCH 1/4] 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 e5cbfaf0af5149271e57deca9f47b5a98ef407ac Mon Sep 17 00:00:00 2001 From: Yash Upadhyay Date: Mon, 21 Feb 2022 10:07:23 +0530 Subject: [PATCH 2/4] 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 3/4] 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 4/4] 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);