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

Commit 5f7b7386 authored by Gaurav Jindal's avatar Gaurav Jindal Committed by Gerrit - the friendly Code Review server
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 or 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>
Signed-off-by: default avatarVishalsingh Hajeri <vhajeri@codeaurora.org>
Signed-off-by: default avatarMukund Madhusudan Atre <matre@codeaurora.org>
parent 9b8cae4b
Loading
Loading
Loading
Loading
+8 −2
Original line number Diff line number Diff line
@@ -2036,8 +2036,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;
+60 −4
Original line number Diff line number Diff line
@@ -1909,6 +1909,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;

@@ -2048,6 +2050,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
@@ -7327,6 +7331,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];

@@ -7342,8 +7352,13 @@ static int cam_ife_hw_mgr_find_affected_ctx(
		 * In the call back function corresponding ISP context
		 * will update CRM about fatal Error
		 */
		if (notify_err_cb)
			notify_err_cb(ife_hwr_mgr_ctx->common.cb_priv,
				CAM_ISP_HW_EVENT_ERROR, error_event_data);
		else {
			CAM_WARN(CAM_ISP, "Error call back is not set");
			goto end;
		}
	}

	/* fill the affected_core in recovery data */
@@ -7352,7 +7367,7 @@ static int cam_ife_hw_mgr_find_affected_ctx(
		CAM_DBG(CAM_ISP, "Vfe core %d is affected (%d)",
			 i, recovery_data->affected_core[i]);
	}

end:
	return 0;
}

@@ -7414,6 +7429,33 @@ static int cam_ife_hw_mgr_handle_hw_dump_info(
	return rc;
}

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_ife_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                                *ctx,
	void                                *evt_info)
@@ -7444,6 +7486,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)
@@ -7454,6 +7503,8 @@ static int cam_ife_hw_mgr_handle_hw_err(

	rc = cam_ife_hw_mgr_find_affected_ctx(&error_event_data,
		core_idx, &recovery_data);
	if ((rc != 0) || !(recovery_data.no_of_context))
		goto end;

	if (event_info->err_type == CAM_VFE_IRQ_STATUS_VIOLATION)
		recovery_data.error_type = CAM_ISP_HW_ERROR_VIOLATION;
@@ -7461,7 +7512,8 @@ 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);

end:
	spin_unlock(&g_ife_hw_mgr.ctx_lock);
	return rc;
}

@@ -7849,6 +7901,9 @@ static int cam_ife_hw_mgr_debug_register(void)
	dbgfileptr = debugfs_create_bool("enable_req_dump", 0644,
		g_ife_hw_mgr.debug_cfg.dentry,
		&g_ife_hw_mgr.debug_cfg.enable_req_dump);
	dbgfileptr = debugfs_create_u32("enable_csid_recovery", 0644,
		g_ife_hw_mgr.debug_cfg.dentry,
		&g_ife_hw_mgr.debug_cfg.enable_csid_recovery);
	dbgfileptr = debugfs_create_file("ife_camif_debug", 0644,
		g_ife_hw_mgr.debug_cfg.dentry, NULL, &cam_ife_camif_debug);
	dbgfileptr = debugfs_create_bool("per_req_reg_dump", 0644,
@@ -7881,6 +7936,7 @@ int cam_ife_hw_mgr_init(struct cam_hw_mgr_intf *hw_mgr_intf, int *iommu_hdl)
	memset(&g_ife_hw_mgr, 0, sizeof(g_ife_hw_mgr));

	mutex_init(&g_ife_hw_mgr.ctx_mutex);
	spin_lock_init(&g_ife_hw_mgr.ctx_lock);

	if (CAM_IFE_HW_NUM_MAX != CAM_IFE_CSID_HW_NUM_MAX) {
		CAM_ERR(CAM_ISP, "CSID num is different then IFE num");
+3 −0
Original line number Diff line number Diff line
@@ -38,6 +38,7 @@ enum cam_ife_res_master_slave {
 * @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
@@ -47,6 +48,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;
@@ -199,6 +201,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
@@ -53,6 +53,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,
};

+379 −93

File changed.

Preview size limit exceeded, changes collapsed.

Loading