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

Commit 7ff37150 authored by Gaurav Jindal's avatar Gaurav Jindal
Browse files

msm: camera: isp: Added CSID recovery mechanism



CSID is not able to recover from the fatal errors like lane
overflows, continuous unbound frames and ESD errors. To recover
from such errors, it is necessary to restart the sensor as
just starting the ISP hw do not make any change as the sensor
can still be in bad state.
This commit implements tasklet based CSID recovery mechanism.
On detecting an error in CSID interrupt, tasklet is scheduled
which in turn will call the ISP hw manager to notify the ISP
context, from here a notification is sent to CRM to send a
message to trigger full recovery. This full recovery includes
the sensor release and start.
This feature is debugfs based. Based on need this can be turned
on.

CRs-Fixed: 2642216
Change-Id: Iecf9916d3672d71a1367886cc934b5a2b148f918
Signed-off-by: default avatarGaurav Jindal <gjindal@codeaurora.org>
parent 52bd957a
Loading
Loading
Loading
Loading
+8 −2
Original line number Diff line number Diff line
@@ -1947,8 +1947,14 @@ static int __cam_isp_ctx_handle_error(struct cam_isp_context *ctx_isp,
		if (notify.error == CRM_KMD_ERR_FATAL) {
			req_msg.session_hdl = ctx_isp->base->session_hdl;
			req_msg.u.err_msg.device_hdl = ctx_isp->base->dev_hdl;

			if (error_type == CAM_ISP_HW_ERROR_CSID_FATAL)
				req_msg.u.err_msg.error_type =
					CAM_REQ_MGR_ERROR_TYPE_FULL_RECOVERY;
			else
				req_msg.u.err_msg.error_type =
					CAM_REQ_MGR_ERROR_TYPE_RECOVERY;

			req_msg.u.err_msg.link_hdl = ctx_isp->base->link_hdl;
			req_msg.u.err_msg.request_id = error_request_id;
			req_msg.u.err_msg.resource_size = 0x0;
+53 −0
Original line number Diff line number Diff line
@@ -1787,6 +1787,8 @@ static int cam_ife_hw_mgr_acquire_res_ife_csid_pxl(
		csid_acquire.in_port = in_port;
		csid_acquire.out_port = in_port->data;
		csid_acquire.node_res = NULL;
		csid_acquire.event_cb = cam_ife_hw_mgr_event_handler;
		csid_acquire.priv = ife_ctx;
		csid_acquire.crop_enable = crop_enable;
		csid_acquire.drop_enable = false;

@@ -1916,6 +1918,8 @@ static int cam_ife_hw_mgr_acquire_res_ife_csid_rdi(
		csid_acquire.in_port = in_port;
		csid_acquire.out_port = out_port;
		csid_acquire.node_res = NULL;
		csid_acquire.event_cb = cam_ife_hw_mgr_event_handler;
		csid_acquire.priv = ife_ctx;

		/*
		 * Enable RDI pixel drop by default. CSID will enable only for
@@ -6793,6 +6797,12 @@ static int cam_ife_hw_mgr_find_affected_ctx(
			affected_core, CAM_IFE_HW_NUM_MAX))
			continue;

		if (atomic_read(&ife_hwr_mgr_ctx->overflow_pending)) {
			CAM_INFO(CAM_ISP, "CTX:%d already error reported",
				ife_hwr_mgr_ctx->ctx_index);
			continue;
		}

		atomic_set(&ife_hwr_mgr_ctx->overflow_pending, 1);
		notify_err_cb = ife_hwr_mgr_ctx->common.event_cb[event_type];

@@ -6822,6 +6832,33 @@ static int cam_ife_hw_mgr_find_affected_ctx(
	return 0;
}

static int cam_ife_hw_mgr_handle_csid_event(
	struct cam_isp_hw_event_info *event_info)
{
	struct cam_isp_hw_error_event_data  error_event_data = {0};
	struct cam_hw_event_recovery_data     recovery_data = {0};

	/* this can be extended based on the types of error
	 * received from CSID
	 */
	switch (event_info->err_type) {
	case CAM_ISP_HW_ERROR_CSID_FATAL: {

		if (!g_ife_hw_mgr.debug_cfg.enable_csid_recovery)
			break;

		error_event_data.error_type = event_info->err_type;
		cam_ife_hw_mgr_find_affected_ctx(&error_event_data,
			event_info->hw_idx,
			&recovery_data);
		break;
	}
	default:
		break;
	}
	return 0;
}

static int cam_ife_hw_mgr_handle_hw_err(
	void                                *evt_info)
{
@@ -6838,6 +6875,13 @@ static int cam_ife_hw_mgr_handle_hw_err(
	else if (event_info->res_type == CAM_ISP_RESOURCE_VFE_OUT)
		error_event_data.error_type = CAM_ISP_HW_ERROR_BUSIF_OVERFLOW;

	spin_lock(&g_ife_hw_mgr.ctx_lock);
	if (event_info->err_type == CAM_ISP_HW_ERROR_CSID_FATAL) {
		rc = cam_ife_hw_mgr_handle_csid_event(event_info);
		spin_unlock(&g_ife_hw_mgr.ctx_lock);
		return rc;
	}

	core_idx = event_info->hw_idx;

	if (g_ife_hw_mgr.debug_cfg.enable_recovery)
@@ -6855,6 +6899,7 @@ static int cam_ife_hw_mgr_handle_hw_err(
		recovery_data.error_type = CAM_ISP_HW_ERROR_OVERFLOW;

	cam_ife_hw_mgr_do_error_recovery(&recovery_data);
	spin_unlock(&g_ife_hw_mgr.ctx_lock);

	return rc;
}
@@ -7318,6 +7363,14 @@ static int cam_ife_hw_mgr_debug_register(void)
		goto err;
	}

	if (!debugfs_create_u32("enable_csid_recovery",
		0644,
		g_ife_hw_mgr.debug_cfg.dentry,
		&g_ife_hw_mgr.debug_cfg.enable_csid_recovery)) {
		CAM_ERR(CAM_ISP, "failed to create enable_csid_recovery");
		goto err;
	}

	if (!debugfs_create_bool("enable_req_dump",
		0644,
		g_ife_hw_mgr.debug_cfg.dentry,
+3 −0
Original line number Diff line number Diff line
@@ -81,6 +81,7 @@ struct ctx_base_info {
 * @dentry:                    Debugfs entry
 * @csid_debug:                csid debug information
 * @enable_recovery:           enable recovery
 * @enable_csid_recovery:      enable csid recovery
 * @enable_diag_sensor_status: enable sensor diagnosis status
 * @enable_req_dump:           Enable request dump on HW errors
 * @per_req_reg_dump:          Enable per request reg dump
@@ -90,6 +91,7 @@ struct cam_ife_hw_mgr_debug {
	struct dentry  *dentry;
	uint64_t       csid_debug;
	uint32_t       enable_recovery;
	uint32_t       enable_csid_recovery;
	uint32_t       camif_debug;
	bool           enable_req_dump;
	bool           per_req_reg_dump;
@@ -231,6 +233,7 @@ struct cam_ife_hw_mgr {
	struct cam_vfe_hw_get_hw_cap   ife_dev_caps[CAM_IFE_HW_NUM_MAX];
	struct cam_req_mgr_core_workq *workq;
	struct cam_ife_hw_mgr_debug    debug_cfg;
	spinlock_t                     ctx_lock;
};

/**
+1 −0
Original line number Diff line number Diff line
@@ -44,6 +44,7 @@ enum cam_isp_hw_err_type {
	CAM_ISP_HW_ERROR_P2I_ERROR,
	CAM_ISP_HW_ERROR_VIOLATION,
	CAM_ISP_HW_ERROR_BUSIF_OVERFLOW,
	CAM_ISP_HW_ERROR_CSID_FATAL,
	CAM_ISP_HW_ERROR_MAX,
};

+380 −94

File changed.

Preview size limit exceeded, changes collapsed.

Loading