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

Commit fe424e73 authored by Gaurav Jindal's avatar Gaurav Jindal
Browse files

msm: camera: isp: Opimitize handling of CSID error dumping



Due to scheduling issues, delay in scheduling of workq for
dumping non-fatal CSID errors and triggering recovery for
csid fatal errors is observed. This can cause the tasks to
get exahust in csid irq handler.
This commit optimizes the number of tasks scheduled for workq
and also limits the number of logs in case of tasks getting exhaust.
It also makes the CSID recovery debugfs based.

Change-Id: I582a5ab396dd127ad1fa0acda167ab1a3e317c11
Signed-off-by: default avatarGaurav Jindal <gjindal@codeaurora.org>
parent b6929c7d
Loading
Loading
Loading
Loading
+22 −2
Original line number Diff line number Diff line
@@ -5024,8 +5024,12 @@ 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_DBG(CAM_ISP, "No notify error cb for ctx %d",
				ife_hwr_mgr_ctx->ctx_index);
	}

	/* fill the affected_core in recovery data */
@@ -6101,11 +6105,27 @@ static int cam_ife_hw_mgr_handle_csid_event(
	struct cam_isp_hw_error_event_data  error_event_data = {0};
	struct cam_hw_event_recovery_data        recovery_data = {0};

	if (!priv || !evt_data) {
		CAM_ERR(CAM_ISP, "Invalid Parameters %pK %pK",
			ife_hwr_mgr_ctx, evt_data);
		return -EINVAL;
	}

	ife_hwr_mgr_ctx = (struct cam_ife_hw_mgr_ctx *)priv;
	payload = (struct cam_csid_hw_evt_payload  *)evt_data;
	CAM_DBG(CAM_ISP, "CSID[%d] type %d event %d",
		payload->hw_idx, payload->evt_type,
		evt_id);

	/* We can be in this condition if due to scheduling delays
	 * workq is late and by the time context is released
	 */
	if (!ife_hwr_mgr_ctx->ctx_in_use) {
		CAM_INFO(CAM_ISP, "ctx %d not in use",
			ife_hwr_mgr_ctx->ctx_index);
		return 0;

	}
	switch (evt_id) {
	case CAM_ISP_HW_EVENT_ERROR:
		goto handle_error;
+35 −9
Original line number Diff line number Diff line
@@ -2748,6 +2748,8 @@ static int cam_ife_csid_release(void *hw_priv,
	res = (struct cam_isp_resource_node *)release_args;

	mutex_lock(&csid_hw->hw_info->hw_mutex);
	csid_hw->event_cb = NULL;
	csid_hw->ctx = NULL;
	if ((res->res_type == CAM_ISP_RESOURCE_CID &&
		res->res_id >= CAM_IFE_CSID_CID_MAX) ||
		(res->res_type == CAM_ISP_RESOURCE_PIX_PATH &&
@@ -3422,16 +3424,29 @@ static int cam_csid_event_dispatch_process(void *priv, void *data)
		CAM_ERR(CAM_ISP, "Invalid parameters");
		return -EINVAL;
	}
	if (!csid_hw->event_cb) {
		CAM_ERR(CAM_ISP, "hw_idx %d Error Cb not registered",
			csid_hw->hw_intf->hw_idx);
	if (!csid_hw->event_cb || !csid_hw->ctx) {
		CAM_ERR_RATE_LIMIT(CAM_ISP,
			"hw_idx %d Invalid args %pK %pK",
			csid_hw->hw_intf->hw_idx,
			csid_hw->event_cb,
			csid_hw->ctx);
		return -EINVAL;
	}
	work_data = (struct cam_csid_hw_work_data *)data;
	CAM_ERR_RATE_LIMIT(CAM_ISP, "idx %d err %d phy %d",
	if (csid_hw->ctx != work_data->ctx) {
		CAM_ERR_RATE_LIMIT(CAM_ISP,
			"hw_idx %d ctx mismatch %pK, %pK",
			csid_hw->hw_intf->hw_idx,
			csid_hw->ctx,
			work_data->ctx);
		return -EINVAL;
	}

	CAM_ERR_RATE_LIMIT(CAM_ISP, "idx %d err %d phy %d cnt %d",
		csid_hw->hw_intf->hw_idx,
		work_data->evt_type,
		csid_hw->csi2_rx_cfg.phy_sel);
		csid_hw->csi2_rx_cfg.phy_sel,
		csid_hw->csi2_cfg_cnt);

	for (i = 0; i < CSID_IRQ_STATUS_MAX; i++)
		CAM_ERR_RATE_LIMIT(CAM_ISP, "status %s: %x",
@@ -3446,7 +3461,9 @@ static int cam_csid_event_dispatch_process(void *priv, void *data)
		if (csid_hw->fatal_err_detected)
			break;
		csid_hw->fatal_err_detected = true;
		rc = csid_hw->event_cb(csid_hw->ctx,

		if (csid_hw->csid_debug & CSID_DEBUG_RECOVERY_ENABLED)
			rc = csid_hw->event_cb(work_data->ctx,
				CAM_ISP_HW_EVENT_ERROR, &evt_payload);
		break;

@@ -3474,11 +3491,15 @@ static int cam_csid_dispatch_irq(struct cam_ife_csid_hw *csid_hw,

	task = cam_req_mgr_workq_get_task(csid_hw->work);
	if (!task) {
		CAM_ERR(CAM_ISP, "Can not get task for worker");
		CAM_ERR_RATE_LIMIT(CAM_ISP,
			"CSID[%d] Can not get task for worker, evt_type %d",
			csid_hw->hw_intf->hw_idx,
			evt_type);
		return -ENOMEM;
	}
	work_data = (struct cam_csid_hw_work_data *)task->payload;
	work_data->evt_type = evt_type;
	work_data->ctx = csid_hw->ctx;
	for (i = 0; i < CSID_IRQ_STATUS_MAX; i++)
		work_data->irq_status[i] = irq_status[i];

@@ -3501,6 +3522,7 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data)
	uint32_t i;
	uint32_t val, val2;
	bool fatal_err_detected = false;
	bool need_dump_csid_err = false;
	uint32_t sof_irq_debug_en = 0;
	unsigned long flags;
	uint32_t irq_status[CSID_IRQ_STATUS_MAX] = {0};
@@ -3599,18 +3621,22 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data)
		if (irq_status[CSID_IRQ_STATUS_RX] &
			CSID_CSI2_RX_ERROR_CPHY_EOT_RECEPTION) {
			csid_hw->error_irq_count++;
			need_dump_csid_err = true;
		}
		if (irq_status[CSID_IRQ_STATUS_RX] &
			CSID_CSI2_RX_ERROR_CPHY_SOT_RECEPTION) {
			csid_hw->error_irq_count++;
			need_dump_csid_err = true;
		}
		if (irq_status[CSID_IRQ_STATUS_RX] &
			CSID_CSI2_RX_ERROR_STREAM_UNDERFLOW) {
			csid_hw->error_irq_count++;
			need_dump_csid_err = true;
		}
		if (irq_status[CSID_IRQ_STATUS_RX] &
			CSID_CSI2_RX_ERROR_UNBOUNDED_FRAME) {
			csid_hw->error_irq_count++;
			need_dump_csid_err = true;
		}
	}

@@ -3618,7 +3644,7 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data)
		CAM_IFE_CSID_MAX_IRQ_ERROR_COUNT) {
		fatal_err_detected = true;
		csid_hw->error_irq_count = 0;
	} else if (csid_hw->error_irq_count) {
	} else if (need_dump_csid_err) {
		cam_csid_dispatch_irq(csid_hw,
			CAM_ISP_HW_ERROR_CSID_NON_FATAL,
			irq_status);
+3 −1
Original line number Diff line number Diff line
@@ -81,6 +81,7 @@
#define CSID_DEBUG_ENABLE_CPHY_PKT_CAPTURE        BIT(6)
#define CSID_DEBUG_ENABLE_HBI_VBI_INFO            BIT(7)
#define CSID_DEBUG_DISABLE_EARLY_EOF              BIT(8)
#define CSID_DEBUG_RECOVERY_ENABLED               BIT(24)

/* enum cam_csid_path_halt_mode select the path halt mode control */
enum cam_csid_path_halt_mode {
@@ -422,11 +423,12 @@ struct cam_ife_csid_cid_data {
 * Later other fields can be added to this data
 * @evt_type   : Event type from CSID
 * @irq_status : IRQ Status register
 *
 * @ctx        : pointer to ctx
 */
struct cam_csid_hw_work_data {
	uint32_t           evt_type;
	uint32_t           irq_status[CSID_IRQ_STATUS_MAX];
	void              *ctx;
};

/**