Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1b8eb232 authored by Harsh Shah's avatar Harsh Shah Committed by Gerrit - the friendly Code Review server
Browse files

msm: camera: isp: Fix few stability issues and add logs



Added protection for array out of bounds in buf_done_fail_log.
Fixed active_cnt by decrementing it correctly. Without the active_cnt
fix, rdi only context can see random freeze. Added some debug
logs that can be enabled when needed to get useful information. Fix
the irq mask being subscribed for in camif. Change sync_mode in csid
acquire from Master to None. With Master, crop is enabled and it
causes errors due to unavailability of correct cropping information.

Change-Id: Ibeadc6fbb2509307d7b8f543bef5f5cd05dae434
Signed-off-by: default avatarHarsh Shah <harshs@codeaurora.org>
parent 8d16e27a
Loading
Loading
Loading
Loading
+63 −21
Original line number Original line Diff line number Diff line
@@ -151,6 +151,13 @@ static void __cam_isp_ctx_handle_buf_done_fail_log(
{
{
	int i;
	int i;


	if (req_isp->num_fence_map_out >= CAM_ISP_CTX_RES_MAX) {
		CAM_ERR_RATE_LIMIT(CAM_ISP,
			"Num Resources exceed mMAX %d >= %d ",
			req_isp->num_fence_map_out, CAM_ISP_CTX_RES_MAX);
		return;
	}

	CAM_ERR_RATE_LIMIT(CAM_ISP,
	CAM_ERR_RATE_LIMIT(CAM_ISP,
		"Resource Handles that fail to generate buf_done in prev frame");
		"Resource Handles that fail to generate buf_done in prev frame");
	for (i = 0; i < req_isp->num_fence_map_out; i++) {
	for (i = 0; i < req_isp->num_fence_map_out; i++) {
@@ -202,22 +209,30 @@ static int __cam_isp_ctx_handle_buf_done_in_activated_state(
			continue;
			continue;
		}
		}


		if (req_isp->fence_map_out[j].sync_id == -1) {
			__cam_isp_ctx_handle_buf_done_fail_log(req_isp);
			continue;
		}

		if (!bubble_state) {
		if (!bubble_state) {
			CAM_DBG(CAM_ISP, "Sync with success: fd 0x%x",
			CAM_DBG(CAM_ISP,
				"Sync with success: req %lld res 0x%x fd 0x%x",
				req->request_id,
				req_isp->fence_map_out[j].resource_handle,
				req_isp->fence_map_out[j].sync_id);
				req_isp->fence_map_out[j].sync_id);
			if (req_isp->fence_map_out[j].sync_id == -1)

				__cam_isp_ctx_handle_buf_done_fail_log(req_isp);
			rc = cam_sync_signal(req_isp->fence_map_out[j].sync_id,
			else
				rc = cam_sync_signal(req_isp->
					fence_map_out[j].sync_id,
				CAM_SYNC_STATE_SIGNALED_SUCCESS);
				CAM_SYNC_STATE_SIGNALED_SUCCESS);
			if (rc)
			if (rc)
				CAM_ERR(CAM_ISP, "Sync failed with rc = %d",
				CAM_DBG(CAM_ISP, "Sync failed with rc = %d",
					 rc);
					 rc);

		} else if (!req_isp->bubble_report) {
		} else if (!req_isp->bubble_report) {
			CAM_DBG(CAM_ISP, "Sync with failure: fd 0x%x",
			CAM_DBG(CAM_ISP,
				"Sync with failure: req %lld res 0x%x fd 0x%x",
				req->request_id,
				req_isp->fence_map_out[j].resource_handle,
				req_isp->fence_map_out[j].sync_id);
				req_isp->fence_map_out[j].sync_id);

			rc = cam_sync_signal(req_isp->fence_map_out[j].sync_id,
			rc = cam_sync_signal(req_isp->fence_map_out[j].sync_id,
				CAM_SYNC_STATE_SIGNALED_ERROR);
				CAM_SYNC_STATE_SIGNALED_ERROR);
			if (rc)
			if (rc)
@@ -230,6 +245,9 @@ static int __cam_isp_ctx_handle_buf_done_in_activated_state(
			 * bubble detects. But for safety, we just move the
			 * bubble detects. But for safety, we just move the
			 * current active request to the pending list here.
			 * current active request to the pending list here.
			 */
			 */
			CAM_DBG(CAM_ISP,
				"buf done with bubble state %d recovery %d",
				bubble_state, req_isp->bubble_report);
			list_del_init(&req->list);
			list_del_init(&req->list);
			list_add(&req->list, &ctx->pending_req_list);
			list_add(&req->list, &ctx->pending_req_list);
			continue;
			continue;
@@ -238,10 +256,20 @@ static int __cam_isp_ctx_handle_buf_done_in_activated_state(
		CAM_DBG(CAM_ISP, "req %lld, reset sync id 0x%x",
		CAM_DBG(CAM_ISP, "req %lld, reset sync id 0x%x",
			req->request_id,
			req->request_id,
			req_isp->fence_map_out[j].sync_id);
			req_isp->fence_map_out[j].sync_id);
		if (!rc) {
			req_isp->num_acked++;
			req_isp->num_acked++;
			req_isp->fence_map_out[j].sync_id = -1;
			req_isp->fence_map_out[j].sync_id = -1;
		}
		}
	}


	if (req_isp->num_acked > req_isp->num_fence_map_out) {
		/* Should not happen */
		CAM_ERR(CAM_ISP,
			"WARNING: req_id %lld num_acked %d > map_out %d",
			req->request_id, req_isp->num_acked,
			req_isp->num_fence_map_out);
		WARN_ON(req_isp->num_acked > req_isp->num_fence_map_out);
	}
	if (req_isp->num_acked == req_isp->num_fence_map_out) {
	if (req_isp->num_acked == req_isp->num_fence_map_out) {
		list_del_init(&req->list);
		list_del_init(&req->list);
		list_add_tail(&req->list, &ctx->free_req_list);
		list_add_tail(&req->list, &ctx->free_req_list);
@@ -779,7 +807,9 @@ static int __cam_isp_ctx_apply_req_in_activated_state(
{
{
	int rc = 0;
	int rc = 0;
	struct cam_ctx_request          *req;
	struct cam_ctx_request          *req;
	struct cam_ctx_request          *active_req;
	struct cam_isp_ctx_req          *req_isp;
	struct cam_isp_ctx_req          *req_isp;
	struct cam_isp_ctx_req          *active_req_isp;
	struct cam_isp_context          *ctx_isp;
	struct cam_isp_context          *ctx_isp;
	struct cam_hw_config_args        cfg;
	struct cam_hw_config_args        cfg;


@@ -817,9 +847,20 @@ static int __cam_isp_ctx_apply_req_in_activated_state(


	if (ctx_isp->active_req_cnt >=  2) {
	if (ctx_isp->active_req_cnt >=  2) {
		CAM_ERR_RATE_LIMIT(CAM_ISP,
		CAM_ERR_RATE_LIMIT(CAM_ISP,
			"Reject apply request due to congestion(cnt = %d)",
			"Reject apply request (id %lld) due to congestion(cnt = %d)",
			req->request_id,
			ctx_isp->active_req_cnt);
			ctx_isp->active_req_cnt);
		__cam_isp_ctx_handle_buf_done_fail_log(req_isp);
		if (!list_empty(&ctx->active_req_list)) {
			active_req = list_first_entry(&ctx->active_req_list,
				struct cam_ctx_request, list);
			active_req_isp =
				(struct cam_isp_ctx_req *) active_req->req_priv;
			__cam_isp_ctx_handle_buf_done_fail_log(active_req_isp);
		} else {
			CAM_ERR_RATE_LIMIT(CAM_ISP,
				"WARNING: should not happen (cnt = %d) but active_list empty",
				ctx_isp->active_req_cnt);
		}
			rc = -EFAULT;
			rc = -EFAULT;
			goto end;
			goto end;
	}
	}
@@ -1212,6 +1253,7 @@ static int __cam_isp_ctx_rdi_only_sof_in_bubble_state(
					CAM_SYNC_STATE_SIGNALED_ERROR);
					CAM_SYNC_STATE_SIGNALED_ERROR);
			}
			}
		list_add_tail(&req->list, &ctx->free_req_list);
		list_add_tail(&req->list, &ctx->free_req_list);
		ctx_isp->active_req_cnt--;
	}
	}


	/* notify reqmgr with sof signal */
	/* notify reqmgr with sof signal */
+1 −1
Original line number Original line Diff line number Diff line
@@ -809,7 +809,7 @@ static int cam_ife_hw_mgr_acquire_res_ife_csid_ipp(
		csid_res->is_dual_vfe = 1;
		csid_res->is_dual_vfe = 1;
	else {
	else {
		csid_res->is_dual_vfe = 0;
		csid_res->is_dual_vfe = 0;
		csid_acquire.sync_mode = CAM_ISP_HW_SYNC_MASTER;
		csid_acquire.sync_mode = CAM_ISP_HW_SYNC_NONE;
	}
	}


	list_for_each_entry(cid_res, &ife_ctx->res_list_ife_cid,
	list_for_each_entry(cid_res, &ife_ctx->res_list_ife_cid,
+2 −2
Original line number Original line Diff line number Diff line
@@ -513,8 +513,8 @@ int cam_isp_add_io_buffers(


	for (i = 0; i < prepare->packet->num_io_configs; i++) {
	for (i = 0; i < prepare->packet->num_io_configs; i++) {
		CAM_DBG(CAM_ISP, "======= io config idx %d ============", i);
		CAM_DBG(CAM_ISP, "======= io config idx %d ============", i);
		CAM_DBG(CAM_ISP, "resource_type:%d fence:%d",
		CAM_DBG(CAM_ISP, "i %d resource_type:%d fence:%d",
			io_cfg[i].resource_type, io_cfg[i].fence);
			i, io_cfg[i].resource_type, io_cfg[i].fence);
		CAM_DBG(CAM_ISP, "format: %d", io_cfg[i].format);
		CAM_DBG(CAM_ISP, "format: %d", io_cfg[i].format);
		CAM_DBG(CAM_ISP, "direction %d",
		CAM_DBG(CAM_ISP, "direction %d",
			io_cfg[i].direction);
			io_cfg[i].direction);
+39 −10
Original line number Original line Diff line number Diff line
@@ -1253,6 +1253,11 @@ static int cam_ife_csid_enable_csi2(
		CSID_CSI2_RX_ERROR_LANE3_FIFO_OVERFLOW |
		CSID_CSI2_RX_ERROR_LANE3_FIFO_OVERFLOW |
		CSID_CSI2_RX_ERROR_CPHY_EOT_RECEPTION |
		CSID_CSI2_RX_ERROR_CPHY_EOT_RECEPTION |
		CSID_CSI2_RX_ERROR_CPHY_SOT_RECEPTION |
		CSID_CSI2_RX_ERROR_CPHY_SOT_RECEPTION |
		CSID_CSI2_RX_ERROR_CRC |
		CSID_CSI2_RX_ERROR_ECC |
		CSID_CSI2_RX_ERROR_MMAPPED_VC_DT |
		CSID_CSI2_RX_ERROR_STREAM_UNDERFLOW |
		CSID_CSI2_RX_ERROR_UNBOUNDED_FRAME |
		CSID_CSI2_RX_ERROR_CPHY_PH_CRC;
		CSID_CSI2_RX_ERROR_CPHY_PH_CRC;


	/* Enable the interrupt based on csid debug info set */
	/* Enable the interrupt based on csid debug info set */
@@ -2545,8 +2550,8 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data)
	struct cam_ife_csid_hw          *csid_hw;
	struct cam_ife_csid_hw          *csid_hw;
	struct cam_hw_soc_info          *soc_info;
	struct cam_hw_soc_info          *soc_info;
	struct cam_ife_csid_reg_offset  *csid_reg;
	struct cam_ife_csid_reg_offset  *csid_reg;
	uint32_t i, irq_status_top, irq_status_rx, irq_status_ipp = 0,
	uint32_t i, irq_status_top, irq_status_rx, irq_status_ipp = 0;
		irq_status_rdi[4];
	uint32_t irq_status_rdi[4] = {0, 0, 0, 0};
	uint32_t val;
	uint32_t val;


	csid_hw = (struct cam_ife_csid_hw *)data;
	csid_hw = (struct cam_ife_csid_hw *)data;
@@ -2593,8 +2598,12 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data)
	cam_io_w_mb(1, soc_info->reg_map[0].mem_base +
	cam_io_w_mb(1, soc_info->reg_map[0].mem_base +
		csid_reg->cmn_reg->csid_irq_cmd_addr);
		csid_reg->cmn_reg->csid_irq_cmd_addr);


	CAM_DBG(CAM_ISP, "irq_status_top = 0x%x", irq_status_top);
	CAM_DBG(CAM_ISP, "irq_status_rx = 0x%x", irq_status_rx);
	CAM_DBG(CAM_ISP, "irq_status_rx = 0x%x", irq_status_rx);
	CAM_DBG(CAM_ISP, "irq_status_ipp = 0x%x", irq_status_ipp);
	CAM_DBG(CAM_ISP, "irq_status_ipp = 0x%x", irq_status_ipp);
	CAM_DBG(CAM_ISP, "irq_status_rdi0= 0x%x", irq_status_rdi[0]);
	CAM_DBG(CAM_ISP, "irq_status_rdi1= 0x%x", irq_status_rdi[1]);
	CAM_DBG(CAM_ISP, "irq_status_rdi2= 0x%x", irq_status_rdi[2]);


	if (irq_status_top) {
	if (irq_status_top) {
		CAM_DBG(CAM_ISP, "CSID global reset complete......Exit");
		CAM_DBG(CAM_ISP, "CSID global reset complete......Exit");
@@ -2609,35 +2618,55 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data)
	}
	}


	if (irq_status_rx & CSID_CSI2_RX_ERROR_LANE0_FIFO_OVERFLOW) {
	if (irq_status_rx & CSID_CSI2_RX_ERROR_LANE0_FIFO_OVERFLOW) {
		pr_err_ratelimited("CSID:%d lane 0 over flow",
		CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d lane 0 over flow",
			 csid_hw->hw_intf->hw_idx);
			 csid_hw->hw_intf->hw_idx);
	}
	}
	if (irq_status_rx & CSID_CSI2_RX_ERROR_LANE1_FIFO_OVERFLOW) {
	if (irq_status_rx & CSID_CSI2_RX_ERROR_LANE1_FIFO_OVERFLOW) {
		pr_err_ratelimited("CSID:%d lane 1 over flow",
		CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d lane 1 over flow",
			 csid_hw->hw_intf->hw_idx);
			 csid_hw->hw_intf->hw_idx);
	}
	}
	if (irq_status_rx & CSID_CSI2_RX_ERROR_LANE2_FIFO_OVERFLOW) {
	if (irq_status_rx & CSID_CSI2_RX_ERROR_LANE2_FIFO_OVERFLOW) {
		pr_err_ratelimited("CSID:%d lane 2 over flow",
		CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d lane 2 over flow",
			 csid_hw->hw_intf->hw_idx);
			 csid_hw->hw_intf->hw_idx);
	}
	}
	if (irq_status_rx & CSID_CSI2_RX_ERROR_LANE3_FIFO_OVERFLOW) {
	if (irq_status_rx & CSID_CSI2_RX_ERROR_LANE3_FIFO_OVERFLOW) {
		pr_err_ratelimited("CSID:%d lane 3 over flow",
		CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d lane 3 over flow",
			 csid_hw->hw_intf->hw_idx);
			 csid_hw->hw_intf->hw_idx);
	}
	}
	if (irq_status_rx & CSID_CSI2_RX_ERROR_TG_FIFO_OVERFLOW) {
	if (irq_status_rx & CSID_CSI2_RX_ERROR_TG_FIFO_OVERFLOW) {
		pr_err_ratelimited("CSID:%d TG OVER  FLOW",
		CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d TG OVER  FLOW",
			 csid_hw->hw_intf->hw_idx);
			 csid_hw->hw_intf->hw_idx);
	}
	}
	if (irq_status_rx & CSID_CSI2_RX_ERROR_CPHY_EOT_RECEPTION) {
	if (irq_status_rx & CSID_CSI2_RX_ERROR_CPHY_EOT_RECEPTION) {
		pr_err_ratelimited("CSID:%d CPHY_EOT_RECEPTION",
		CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d CPHY_EOT_RECEPTION",
			 csid_hw->hw_intf->hw_idx);
			 csid_hw->hw_intf->hw_idx);
	}
	}
	if (irq_status_rx & CSID_CSI2_RX_ERROR_CPHY_SOT_RECEPTION) {
	if (irq_status_rx & CSID_CSI2_RX_ERROR_CPHY_SOT_RECEPTION) {
		pr_err_ratelimited("CSID:%d CPHY_SOT_RECEPTION",
		CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d CPHY_SOT_RECEPTION",
			 csid_hw->hw_intf->hw_idx);
			 csid_hw->hw_intf->hw_idx);
	}
	}
	if (irq_status_rx & CSID_CSI2_RX_ERROR_CPHY_PH_CRC) {
	if (irq_status_rx & CSID_CSI2_RX_ERROR_CPHY_PH_CRC) {
		pr_err_ratelimited("CSID:%d CPHY_PH_CRC",
		CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d CPHY_PH_CRC",
			 csid_hw->hw_intf->hw_idx);
	}
	if (irq_status_rx & CSID_CSI2_RX_ERROR_CRC) {
		CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d ERROR_CRC",
			 csid_hw->hw_intf->hw_idx);
	}
	if (irq_status_rx & CSID_CSI2_RX_ERROR_ECC) {
		CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d ERROR_ECC",
			 csid_hw->hw_intf->hw_idx);
	}
	if (irq_status_rx & CSID_CSI2_RX_ERROR_MMAPPED_VC_DT) {
		CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d MMAPPED_VC_DT",
			 csid_hw->hw_intf->hw_idx);
	}
		if (irq_status_rx & CSID_CSI2_RX_ERROR_STREAM_UNDERFLOW) {
		CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d ERROR_STREAM_UNDERFLOW",
			 csid_hw->hw_intf->hw_idx);
	}
	if (irq_status_rx & CSID_CSI2_RX_ERROR_UNBOUNDED_FRAME) {
		CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d UNBOUNDED_FRAME",
			 csid_hw->hw_intf->hw_idx);
			 csid_hw->hw_intf->hw_idx);
	}
	}


+1 −1
Original line number Original line Diff line number Diff line
@@ -34,7 +34,7 @@ static uint32_t irq_reg_offset[CAM_IFE_IRQ_REGISTERS_MAX] = {


static uint32_t camif_irq_reg_mask[CAM_IFE_IRQ_REGISTERS_MAX] = {
static uint32_t camif_irq_reg_mask[CAM_IFE_IRQ_REGISTERS_MAX] = {
	0x0003FD1F,
	0x0003FD1F,
	0x0FFF7EB3,
	0x0FFF7EBC,
};
};


static uint32_t rdi_irq_reg_mask[CAM_IFE_IRQ_REGISTERS_MAX] = {
static uint32_t rdi_irq_reg_mask[CAM_IFE_IRQ_REGISTERS_MAX] = {
Loading