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

Commit e71c354c authored by Vikram Sharma's avatar Vikram Sharma Committed by Gerrit - the friendly Code Review server
Browse files

msm: camera: cam_isp: Recovery after IRQ delayed



Dynamic FPS to Detect IRQ delay.

If the irq is delayed, the frame drop is reported. This commit
helps to recover from the frame drop.
We a added a new blob  command to report fps from UMD to KMD. This patch
Use this fps to calculate If there is a IRQ delay or not. If yes then It
sets a flag 'irq_delay_detected'.

Change-Id: I3cbcd9275d705f8c2458c7860780fbab615fabc4
Signed-off-by: default avatarVikram Sharma <vikramsa@codeaurora.org>
parent 5def64ce
Loading
Loading
Loading
Loading
+132 −11
Original line number Diff line number Diff line
@@ -452,6 +452,14 @@ static int __cam_isp_ctx_handle_buf_done_in_activated_state(
	trace_cam_buf_done("ISP", ctx, req);

	req_isp = (struct cam_isp_ctx_req *) req->req_priv;
	if (ctx_isp->frame_id == 1)
		ctx_isp->irq_timestamps = done->irq_mono_boot_time;
	else if (ctx_isp->fps && ((done->irq_mono_boot_time -
		ctx_isp->irq_timestamps) > ((1000*1000)/ctx_isp->fps)))
		ctx_isp->irq_delay_detect = true;

	ctx_isp->irq_timestamps = done->irq_mono_boot_time;

	for (i = 0; i < done->num_handles; i++) {
		for (j = 0; j < req_isp->num_fence_map_out; j++) {
			if (done->resource_handle[i] ==
@@ -565,6 +573,26 @@ static int __cam_isp_ctx_handle_buf_done_in_activated_state(
			ctx_isp->substate_activated);
	}

	if (ctx_isp->active_req_cnt && ctx_isp->irq_delay_detect) {
		CAM_ERR(CAM_ISP, "isp req[%lld] IRQ buf done got delayed",
				req->request_id);
		req = list_first_entry(&ctx->active_req_list,
			struct cam_ctx_request, list);
		req_isp = (struct cam_isp_ctx_req *) req->req_priv;

		for (j = 0; j < req_isp->num_fence_map_out; j++) {
			rc = cam_sync_signal(req_isp->fence_map_out[j].sync_id,
				CAM_SYNC_STATE_SIGNALED_ERROR);
			if (rc)
				CAM_DBG(CAM_ISP, "Sync failed with rc = %d",
					rc);
			req_isp->fence_map_out[j].sync_id = -1;
		}
		list_del_init(&req->list);
		list_add_tail(&req->list, &ctx->free_req_list);
		ctx_isp->active_req_cnt--;
	}
	ctx_isp->irq_delay_detect = false;
end:
	return rc;
}
@@ -643,12 +671,47 @@ static void __cam_isp_ctx_send_sof_timestamp(
static int __cam_isp_ctx_reg_upd_in_epoch_state(
	struct cam_isp_context *ctx_isp, void *evt_data)
{
	if (ctx_isp->frame_id == 1)
	struct cam_isp_hw_reg_update_event_data  *rup_event_data = evt_data;

	struct cam_context      *ctx     = ctx_isp->base;
	struct cam_ctx_request  *req     = NULL;
	struct cam_isp_ctx_req  *req_isp = NULL;

	if (ctx_isp->frame_id == 1) {
		CAM_DBG(CAM_ISP, "Reg update for early PCR");
	else
		if (!list_empty(&ctx->active_req_list)) {
			req = list_first_entry(&ctx->active_req_list,
					struct cam_ctx_request, list);
			req_isp = (struct cam_isp_ctx_req *) req->req_priv;
		} else if (!list_empty(&ctx->wait_req_list)) {
			req = list_first_entry(&ctx->active_req_list,
					struct cam_ctx_request, list);
			req_isp = (struct cam_isp_ctx_req *) req->req_priv;
		}
	} else {
		if (!list_empty(&ctx->wait_req_list)) {
			req = list_first_entry(&ctx->active_req_list,
					struct cam_ctx_request, list);
			req_isp = (struct cam_isp_ctx_req *) req->req_priv;
		}
		CAM_WARN(CAM_ISP,
			"Unexpected reg update in activated substate:%d for frame_id:%lld",
			ctx_isp->substate_activated, ctx_isp->frame_id);
	}

	if (req_isp && req_isp->hw_update_data.fps) {
		ctx_isp->fps = req_isp->hw_update_data.fps;
		CAM_DBG(CAM_ISP, "req_isp %pK, Upadting ctx_isp->fps %d",
				req_isp, ctx_isp->fps);
	}

	if (ctx_isp->frame_id == 1)
		ctx_isp->irq_timestamps = rup_event_data->irq_mono_boot_time;
	else if (ctx_isp->fps && ((rup_event_data->irq_mono_boot_time -
			ctx_isp->irq_timestamps) > ((1000*1000)/ctx_isp->fps)))
		ctx_isp->irq_delay_detect = true;

	ctx_isp->irq_timestamps = rup_event_data->irq_mono_boot_time;
	return 0;
}

@@ -658,7 +721,8 @@ static int __cam_isp_ctx_reg_upd_in_activated_state(
	int rc = 0;
	struct cam_ctx_request  *req;
	struct cam_context      *ctx = ctx_isp->base;
	struct cam_isp_ctx_req  *req_isp;
	struct cam_isp_ctx_req  *req_isp = NULL;
	struct cam_isp_hw_reg_update_event_data  *rup_event_data = evt_data;

	if (list_empty(&ctx->wait_req_list)) {
		CAM_ERR(CAM_ISP, "Reg upd ack with no waiting request");
@@ -683,13 +747,22 @@ static int __cam_isp_ctx_reg_upd_in_activated_state(
			req->request_id, ctx_isp->active_req_cnt, ctx->ctx_id);
	}

	if (req_isp && req_isp->hw_update_data.fps)
		ctx_isp->fps = req_isp->hw_update_data.fps;

	/*
	 * This function only called directly from applied and bubble applied
	 * state so change substate here.
	 */
	ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_EPOCH;
	CAM_DBG(CAM_ISP, "next substate %d", ctx_isp->substate_activated);
	if (ctx_isp->frame_id == 1)
		ctx_isp->irq_timestamps = rup_event_data->irq_mono_boot_time;
	else if (ctx_isp->fps && ((rup_event_data->irq_mono_boot_time -
			ctx_isp->irq_timestamps) > ((1000*1000)/ctx_isp->fps)))
		ctx_isp->irq_delay_detect = true;

	ctx_isp->irq_timestamps = rup_event_data->irq_mono_boot_time;
end:
	return rc;
}
@@ -817,6 +890,14 @@ static int __cam_isp_ctx_sof_in_activated_state(
	ctx_isp->sof_timestamp_val = sof_event_data->timestamp;
	ctx_isp->boot_timestamp = sof_event_data->boot_time;

	if (ctx_isp->frame_id == 1)
		ctx_isp->irq_timestamps = sof_event_data->irq_mono_boot_time;
	else if (ctx_isp->fps && ((sof_event_data->irq_mono_boot_time -
			ctx_isp->irq_timestamps) > ((1000*1000)/ctx_isp->fps)))
		ctx_isp->irq_delay_detect = true;

	ctx_isp->irq_timestamps = sof_event_data->irq_mono_boot_time;

	CAM_DBG(CAM_ISP, "frame id: %lld time stamp:0x%llx, ctx %u",
		ctx_isp->frame_id, ctx_isp->sof_timestamp_val, ctx->ctx_id);

@@ -828,8 +909,9 @@ static int __cam_isp_ctx_reg_upd_in_sof(struct cam_isp_context *ctx_isp,
{
	int rc = 0;
	struct cam_ctx_request *req = NULL;
	struct cam_isp_ctx_req *req_isp;
	struct cam_isp_ctx_req *req_isp = NULL;
	struct cam_context *ctx = ctx_isp->base;
	struct cam_isp_hw_reg_update_event_data  *rup_event_data = evt_data;

	if (ctx->state != CAM_CTX_ACTIVATED && ctx_isp->frame_id > 1) {
		CAM_DBG(CAM_ISP, "invalid RUP");
@@ -852,6 +934,16 @@ static int __cam_isp_ctx_reg_upd_in_sof(struct cam_isp_context *ctx_isp,
				"receive rup in unexpected state");
	}

	if (req_isp && req_isp->hw_update_data.fps)
		ctx_isp->fps = req_isp->hw_update_data.fps;

	if (ctx_isp->frame_id == 1)
		ctx_isp->irq_timestamps = rup_event_data->irq_mono_boot_time;
	else if (ctx_isp->fps && ((rup_event_data->irq_mono_boot_time -
			ctx_isp->irq_timestamps) > ((1000*1000)/ctx_isp->fps)))
		ctx_isp->irq_delay_detect = true;

	ctx_isp->irq_timestamps = rup_event_data->irq_mono_boot_time;
end:
	return rc;
}
@@ -860,9 +952,10 @@ static int __cam_isp_ctx_epoch_in_applied(struct cam_isp_context *ctx_isp,
	void *evt_data)
{
	struct cam_ctx_request    *req;
	struct cam_isp_ctx_req    *req_isp;
	struct cam_isp_ctx_req    *req_isp = NULL;
	struct cam_context        *ctx = ctx_isp->base;
	uint64_t  request_id = 0;
	struct cam_isp_hw_epoch_event_data *epoch_hw_event_data = evt_data;

	if (list_empty(&ctx->wait_req_list)) {
		/*
@@ -928,6 +1021,15 @@ static int __cam_isp_ctx_epoch_in_applied(struct cam_isp_context *ctx_isp,
		ctx_isp->substate_activated);
end:

	if (ctx_isp->frame_id == 1)
		ctx_isp->irq_timestamps =
			epoch_hw_event_data->irq_mono_boot_time;
	else if (ctx_isp->fps && ((epoch_hw_event_data->irq_mono_boot_time -
			ctx_isp->irq_timestamps) > ((1000*1000)/ctx_isp->fps)))
		ctx_isp->irq_delay_detect = true;

	ctx_isp->irq_timestamps = epoch_hw_event_data->irq_mono_boot_time;

	return 0;
}

@@ -960,6 +1062,14 @@ static int __cam_isp_ctx_sof_in_epoch(struct cam_isp_context *ctx_isp,
	ctx_isp->sof_timestamp_val = sof_event_data->timestamp;
	ctx_isp->boot_timestamp = sof_event_data->boot_time;

	if (ctx_isp->frame_id == 1)
		ctx_isp->irq_timestamps = sof_event_data->irq_mono_boot_time;
	else if (ctx_isp->fps && ((sof_event_data->irq_mono_boot_time -
			ctx_isp->irq_timestamps) > ((1000*1000)/ctx_isp->fps)))
		ctx_isp->irq_delay_detect = true;

	ctx_isp->irq_timestamps = sof_event_data->irq_mono_boot_time;

	if (list_empty(&ctx->active_req_list))
		ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_SOF;
	else
@@ -1442,7 +1552,7 @@ static int __cam_isp_ctx_fs2_reg_upd_in_sof(struct cam_isp_context *ctx_isp,
{
	int rc = 0;
	struct cam_ctx_request *req = NULL;
	struct cam_isp_ctx_req *req_isp;
	struct cam_isp_ctx_req *req_isp = NULL;
	struct cam_context *ctx = ctx_isp->base;

	if (ctx->state != CAM_CTX_ACTIVATED && ctx_isp->frame_id > 1) {
@@ -1466,6 +1576,9 @@ static int __cam_isp_ctx_fs2_reg_upd_in_sof(struct cam_isp_context *ctx_isp,
				"receive rup in unexpected state");
	}

	if (req_isp && req_isp->hw_update_data.fps)
		ctx_isp->fps = req_isp->hw_update_data.fps;

end:
	return rc;
}
@@ -1476,7 +1589,7 @@ static int __cam_isp_ctx_fs2_reg_upd_in_applied_state(
	int rc = 0;
	struct cam_ctx_request  *req = NULL;
	struct cam_context      *ctx = ctx_isp->base;
	struct cam_isp_ctx_req  *req_isp;
	struct cam_isp_ctx_req  *req_isp = NULL;
	struct cam_req_mgr_trigger_notify  notify;
	uint64_t  request_id  = 0;

@@ -1499,6 +1612,9 @@ static int __cam_isp_ctx_fs2_reg_upd_in_applied_state(
		list_add_tail(&req->list, &ctx->free_req_list);
	}

	if (req_isp && req_isp->hw_update_data.fps)
		ctx_isp->fps = req_isp->hw_update_data.fps;

	/*
	 * This function only called directly from applied and bubble applied
	 * state so change substate here.
@@ -2393,7 +2509,7 @@ static int __cam_isp_ctx_rdi_only_reg_upd_in_bubble_applied_state(
{
	struct cam_ctx_request  *req;
	struct cam_context      *ctx = ctx_isp->base;
	struct cam_isp_ctx_req  *req_isp;
	struct cam_isp_ctx_req  *req_isp = NULL;
	struct cam_req_mgr_trigger_notify  notify;
	uint64_t  request_id  = 0;

@@ -2448,6 +2564,9 @@ static int __cam_isp_ctx_rdi_only_reg_upd_in_bubble_applied_state(
			jiffies_to_msecs(jiffies);
	}

	if (req_isp && req_isp->hw_update_data.fps)
		ctx_isp->fps = req_isp->hw_update_data.fps;

	__cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id,
		CAM_REQ_MGR_SOF_EVENT_SUCCESS);
	CAM_DBG(CAM_ISP, "next substate %d", ctx_isp->substate_activated);
@@ -2723,7 +2842,7 @@ static int __cam_isp_ctx_config_dev_in_top_state(
{
	int rc = 0, i;
	struct cam_ctx_request           *req = NULL;
	struct cam_isp_ctx_req           *req_isp;
	struct cam_isp_ctx_req           *req_isp = NULL;
	uintptr_t                         packet_addr;
	struct cam_packet                *packet;
	size_t                            len = 0;
@@ -2812,6 +2931,7 @@ static int __cam_isp_ctx_config_dev_in_top_state(
		rc = -EFAULT;
		goto free_cpu_buf;
	}

	req_isp->num_cfg = cfg.num_hw_update_entries;
	req_isp->num_fence_map_out = cfg.num_out_map_entries;
	req_isp->num_fence_map_in = cfg.num_in_map_entries;
@@ -2868,6 +2988,7 @@ static int __cam_isp_ctx_config_dev_in_top_state(
			CAM_ERR(CAM_ISP, "Recevied Update in wrong state");
		}
	}

	if (rc)
		goto put_ref;

@@ -3649,8 +3770,6 @@ static int __cam_isp_ctx_apply_req(struct cam_context *ctx,
	return rc;
}



static int __cam_isp_ctx_handle_irq_in_activated(void *context,
	uint32_t evt_id, void *evt_data)
{
@@ -3856,6 +3975,8 @@ int cam_isp_context_init(struct cam_isp_context *ctx,
	for (i = 0; i < CAM_CTX_REQ_MAX; i++) {
		ctx->req_base[i].req_priv = &ctx->req_isp[i];
		ctx->req_isp[i].base = &ctx->req_base[i];
		/*Set default fps value to 30 FPS*/
		ctx->req_isp[i].hw_update_data.fps = CAM_ISP_CTX_DEFAULT_FPS;
	}

	/* camera context setup */
+11 −0
Original line number Diff line number Diff line
@@ -34,6 +34,11 @@
 */
#define CAM_ISP_CTX_CFG_MAX                     22

/*
 * Defalut fps value set to 30
 */
#define CAM_ISP_CTX_DEFAULT_FPS                 30

/*
 * Maximum entries in state monitoring array for error logging
 */
@@ -180,6 +185,9 @@ struct cam_isp_context_req_id_info {
 * @hw_acquired:               Indicate whether HW resources are acquired
 * @init_received:             Indicate whether init config packet is received
 * @split_acquire:             Indicate whether a separate acquire is expected
 * @irq_delay_detect:          Indicate whether a irq delay has detected or not
 * @irq_timestamps:            Timestamp from last handled IRQ
 * @fps:                       Current FPS for the activated state.
 *
 */
struct cam_isp_context {
@@ -209,6 +217,9 @@ struct cam_isp_context {
	bool                             hw_acquired;
	bool                             init_received;
	bool                             split_acquire;
	bool                             irq_delay_detect;
	uint64_t                         irq_timestamps;
	uint32_t                         fps;
};

/**
+23 −3
Original line number Diff line number Diff line
@@ -4046,6 +4046,7 @@ static int cam_isp_packet_generic_blob_handler(void *user_data,
		break;
	case CAM_ISP_GENERIC_BLOB_TYPE_FPS_CONFIG: {
		struct cam_fps_config *fps_config;
		struct cam_isp_prepare_hw_update_data   *prepare_hw_data;

		if (blob_size < sizeof(struct cam_fps_config)) {
			CAM_ERR(CAM_ISP, "Invalid fps blob size %u expected %u",
@@ -4054,6 +4055,10 @@ static int cam_isp_packet_generic_blob_handler(void *user_data,
		}

		fps_config = (struct cam_fps_config *)blob_data;
		prepare_hw_data = (struct cam_isp_prepare_hw_update_data  *)
			prepare->priv;

		prepare_hw_data->fps = fps_config->fps;

		rc = cam_isp_blob_fps_config(blob_type, blob_info,
			fps_config, prepare);
@@ -4956,6 +4961,8 @@ static int cam_ife_hw_mgr_handle_reg_update(
				break;

			if (!rup_status) {
				rup_event_data.irq_mono_boot_time =
					evt_payload->ts.time_usecs;
				ife_hwr_irq_rup_cb(
					ife_hwr_mgr_ctx->common.cb_priv,
					CAM_ISP_HW_EVENT_REG_UPDATE,
@@ -4985,6 +4992,8 @@ static int cam_ife_hw_mgr_handle_reg_update(
			if (atomic_read(&ife_hwr_mgr_ctx->overflow_pending))
				break;
			if (!rup_status) {
				rup_event_data.irq_mono_boot_time =
					evt_payload->ts.time_usecs;
				/* Send the Reg update hw event */
				ife_hwr_irq_rup_cb(
					ife_hwr_mgr_ctx->common.cb_priv,
@@ -5344,6 +5353,8 @@ static int cam_ife_hw_mgr_handle_sof(
						ife_hw_mgr_ctx,
						&sof_done_event_data.timestamp,
						&sof_done_event_data.boot_time);
					sof_done_event_data.irq_mono_boot_time =
						evt_payload->ts.time_usecs;

					ife_hw_irq_sof_cb(
						ife_hw_mgr_ctx->common.cb_priv,
@@ -5367,6 +5378,8 @@ static int cam_ife_hw_mgr_handle_sof(
					ife_hw_mgr_ctx,
					&sof_done_event_data.timestamp,
					&sof_done_event_data.boot_time);
				sof_done_event_data.irq_mono_boot_time =
					evt_payload->ts.time_usecs;

				ife_hw_irq_sof_cb(
					ife_hw_mgr_ctx->common.cb_priv,
@@ -5452,13 +5465,15 @@ static int cam_ife_hw_mgr_handle_eof_for_camif_hw_res(
				if (atomic_read(
					&ife_hwr_mgr_ctx->overflow_pending))
					break;
				if (!eof_status)
				if (!eof_status) {
					eof_done_event_data.irq_mono_boot_time =
						evt_payload->ts.time_usecs;
					ife_hwr_irq_eof_cb(
						ife_hwr_mgr_ctx->common.cb_priv,
						CAM_ISP_HW_EVENT_EOF,
						&eof_done_event_data);
				}

			}
			break;
		/* Handling dual VFE Scenario */
		case 1:
@@ -5499,11 +5514,14 @@ static int cam_ife_hw_mgr_handle_eof_for_camif_hw_res(
			if (atomic_read(&ife_hwr_mgr_ctx->overflow_pending))
				break;

			if (!rc)
			if (!rc) {
				eof_done_event_data.irq_mono_boot_time =
					evt_payload->ts.time_usecs;
				ife_hwr_irq_eof_cb(
					ife_hwr_mgr_ctx->common.cb_priv,
					CAM_ISP_HW_EVENT_EOF,
					&eof_done_event_data);
			}

			break;

@@ -5603,6 +5621,8 @@ static int cam_ife_hw_mgr_handle_buf_done_for_hw_res(

			if (atomic_read(&ife_hwr_mgr_ctx->overflow_pending))
				break;
			buf_done_event_data.irq_mono_boot_time =
					evt_payload->ts.time_usecs;
			/* Report for Successful buf_done event if any */
			if (buf_done_event_data.num_handles > 0 &&
				ife_hwr_irq_wm_done_cb) {
+16 −4
Original line number Diff line number Diff line
@@ -130,6 +130,7 @@ struct cam_isp_bw_config_internal {
 * @bw_config:              BW config information
 * @bw_config_valid:        Flag indicating whether the bw_config at the index
 *                          is valid or not
 * @fps:                    fps vaue which has been updated in hw
 *
 */
struct cam_isp_prepare_hw_update_data {
@@ -137,6 +138,7 @@ struct cam_isp_prepare_hw_update_data {
	struct cam_isp_bw_config_internal     bw_config[CAM_IFE_HW_NUM_MAX];
	struct cam_isp_bw_config_internal_ab  bw_config_ab[CAM_IFE_HW_NUM_MAX];
	bool                                bw_config_valid[CAM_IFE_HW_NUM_MAX];
	uint32_t                            fps;
};


@@ -145,11 +147,13 @@ struct cam_isp_prepare_hw_update_data {
 *
 * @timestamp:          Time stamp for the sof event
 * @boot_time:          Boot time stamp for the sof event
 * @irq_mono_boot_time: Time stamp till the execution of IRQ wrt event started
 *
 */
struct cam_isp_hw_sof_event_data {
	uint64_t       timestamp;
	uint64_t       boot_time;
	uint64_t       irq_mono_boot_time;
};

/**
@@ -157,20 +161,24 @@ struct cam_isp_hw_sof_event_data {
 *                         CAM_HW_EVENT_REG_UPDATE
 *
 * @timestamp:          Time stamp for the reg update event
 * @irq_mono_boot_time: Time stamp till the execution of IRQ wrt event started
 *
 */
struct cam_isp_hw_reg_update_event_data {
	uint64_t       timestamp;
	uint64_t       irq_mono_boot_time;
};

/**
 * struct cam_isp_hw_epoch_event_data - Event payload for CAM_HW_EVENT_EPOCH
 *
 * @timestamp:          Time stamp for the epoch event
 * @irq_mono_boot_time: Time stamp till the execution of this event started
 *
 */
struct cam_isp_hw_epoch_event_data {
	uint64_t       timestamp;
	uint64_t       irq_mono_boot_time;
};

/**
@@ -179,6 +187,7 @@ struct cam_isp_hw_epoch_event_data {
 * @num_handles:           Number of resource handeles
 * @resource_handle:       Resource handle array
 * @timestamp:             Timestamp for the buf done event
 * @irq_mono_boot_time:    Time stamp till the execution of this event started
 *
 */
struct cam_isp_hw_done_event_data {
@@ -186,16 +195,19 @@ struct cam_isp_hw_done_event_data {
	uint32_t             resource_handle[
				CAM_NUM_OUT_PER_COMP_IRQ_MAX];
	uint64_t       timestamp;
	uint64_t       irq_mono_boot_time;
};

/**
 * struct cam_isp_hw_eof_event_data - Event payload for CAM_HW_EVENT_EOF
 *
 * @timestamp:             Timestamp for the eof event
 * @irq_mono_boot_time:    Time stamp till the execution of this event started
 *
 */
struct cam_isp_hw_eof_event_data {
	uint64_t       timestamp;
	uint64_t       irq_mono_boot_time;
};

/**
+2 −0
Original line number Diff line number Diff line
@@ -28,11 +28,13 @@
 * @mono_time:          Monotonic boot time
 * @vt_time:            AV Timer time
 * @ticks:              Qtimer ticks
 * @time_usecs:         time in micro seconds
 */
struct cam_isp_timestamp {
	struct timeval          mono_time;
	struct timeval          vt_time;
	uint64_t                ticks;
	uint64_t                time_usecs;
};

/*
Loading