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

Commit 8c8f2766 authored by Junzhe Zou's avatar Junzhe Zou
Browse files

msm: camera: isp: clean up logic to handle bubble



Move request to active list whenever bubble is detected and wait for
buf done. Remove the request from active list after buf done from all
the ports are returned.

Change-Id: Ic9e3b0d28ab8beef7018b781fbcfcba83add8281
Signed-off-by: default avatarJunzhe Zou <jnzhezou@codeaurora.org>
parent c99cc37c
Loading
Loading
Loading
Loading
+60 −42
Original line number Diff line number Diff line
@@ -376,7 +376,7 @@ static int __cam_isp_ctx_handle_buf_done_in_activated_state(
			continue;
		}

		if (!bubble_state) {
		if (!req_isp->bubble_detected) {
			CAM_DBG(CAM_ISP,
				"Sync with success: req %lld res 0x%x fd 0x%x",
				req->request_id,
@@ -403,15 +403,14 @@ static int __cam_isp_ctx_handle_buf_done_in_activated_state(
		} else {
			/*
			 * Ignore the buffer done if bubble detect is on
			 * In most case, active list should be empty when
			 * bubble detects. But for safety, we just move the
			 * current active request to the pending list here.
			 * Increment the ack number here, and queue the
			 * request back to pending list whenever all the
			 * buffers are done.
			 */
			req_isp->num_acked++;
			CAM_DBG(CAM_ISP,
				"buf done with bubble state %d recovery %d",
				bubble_state, req_isp->bubble_report);
			list_del_init(&req->list);
			list_add(&req->list, &ctx->pending_req_list);
			continue;
		}

@@ -432,10 +431,25 @@ static int __cam_isp_ctx_handle_buf_done_in_activated_state(
			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)
		return rc;

	ctx_isp->active_req_cnt--;

	if (req_isp->bubble_detected && req_isp->bubble_report) {
		req_isp->num_acked = 0;
		req_isp->bubble_detected = false;
		list_del_init(&req->list);
		list_add(&req->list, &ctx->pending_req_list);

		CAM_DBG(CAM_REQ,
			"Move active request %lld to pending list(cnt = %d) [bubble recovery]",
			 req->request_id, ctx_isp->active_req_cnt);
	} else {
		list_del_init(&req->list);
		list_add_tail(&req->list, &ctx->free_req_list);
		ctx_isp->active_req_cnt--;

		CAM_DBG(CAM_REQ,
			"Move active request %lld to free list(cnt = %d) [all fences done]",
			 req->request_id, ctx_isp->active_req_cnt);
@@ -733,15 +747,13 @@ static int __cam_isp_ctx_epoch_in_applied(struct cam_isp_context *ctx_isp,
	req = list_first_entry(&ctx->wait_req_list, struct cam_ctx_request,
		list);
	req_isp = (struct cam_isp_ctx_req *)req->req_priv;
	req_isp->bubble_detected = true;

	CAM_DBG(CAM_ISP, "Report Bubble flag %d", req_isp->bubble_report);
	if (req_isp->bubble_report && ctx->ctx_crm_intf &&
		ctx->ctx_crm_intf->notify_err) {
		struct cam_req_mgr_error_notify notify;

		list_del_init(&req->list);
		list_add(&req->list, &ctx->pending_req_list);

		notify.link_hdl = ctx->link_hdl;
		notify.dev_hdl = ctx->dev_hdl;
		notify.req_id = req->request_id;
@@ -750,17 +762,18 @@ static int __cam_isp_ctx_epoch_in_applied(struct cam_isp_context *ctx_isp,
		CAM_DBG(CAM_ISP, "Notify CRM about Bubble frame %lld",
			ctx_isp->frame_id);
	} else {
		req_isp->bubble_report = 0;
	}

	/*
		 * Since can not bubble report, always move the request to
		 * active list.
	 * Always move the request to active list. Let buf done
	 * function handles the rest.
	 */
		list_del_init(&req->list);
		list_add_tail(&req->list, &ctx->active_req_list);
		ctx_isp->active_req_cnt++;
	CAM_DBG(CAM_REQ, "move request %lld to active list(cnt = %d)",
		req->request_id, ctx_isp->active_req_cnt);
		req_isp->bubble_report = 0;
	}
	ctx_isp->active_req_cnt++;
	list_del_init(&req->list);
	list_add_tail(&req->list, &ctx->active_req_list);

	if (req->request_id > ctx_isp->reported_req_id) {
		request_id = req->request_id;
@@ -883,13 +896,12 @@ static int __cam_isp_ctx_epoch_in_bubble_applied(
	req = list_first_entry(&ctx->wait_req_list, struct cam_ctx_request,
		list);
	req_isp = (struct cam_isp_ctx_req *)req->req_priv;
	list_del_init(&req->list);
	req_isp->bubble_detected = true;

	if (req_isp->bubble_report && ctx->ctx_crm_intf &&
		ctx->ctx_crm_intf->notify_err) {
		struct cam_req_mgr_error_notify notify;

		list_add(&req->list, &ctx->pending_req_list);
		notify.link_hdl = ctx->link_hdl;
		notify.dev_hdl = ctx->dev_hdl;
		notify.req_id = req->request_id;
@@ -899,16 +911,18 @@ static int __cam_isp_ctx_epoch_in_bubble_applied(
			"Notify CRM about Bubble req_id %llu frame %lld",
			req->request_id, ctx_isp->frame_id);
	} else {
		req_isp->bubble_report = 0;
	}

	/*
		 * If we can not report bubble, then treat it as if no bubble
		 * report. Just move the req to active list.
	 * Always move the request to active list. Let buf done
	 * function handles the rest.
	 */
		list_add_tail(&req->list, &ctx->active_req_list);
		ctx_isp->active_req_cnt++;
	CAM_DBG(CAM_ISP, "move request %lld to active list(cnt = %d)",
		req->request_id, ctx_isp->active_req_cnt);
		req_isp->bubble_report = 0;
	}
	ctx_isp->active_req_cnt++;
	list_del_init(&req->list);
	list_add_tail(&req->list, &ctx->active_req_list);

	if (!req_isp->bubble_report) {
		if (req->request_id > ctx_isp->reported_req_id) {
@@ -1410,6 +1424,7 @@ static int __cam_isp_ctx_flush_req_in_top_state(
		CAM_DBG(CAM_ISP, "try to flush active list");
		rc = __cam_isp_ctx_flush_req(ctx, &ctx->active_req_list,
		flush_req);
		ctx_isp->active_req_cnt = 0;
		spin_unlock_bh(&ctx->lock);

		/* Start hw */
@@ -1608,12 +1623,12 @@ static int __cam_isp_ctx_rdi_only_sof_in_bubble_applied(
	CAM_DBG(CAM_ISP, "frame id: %lld time stamp:0x%llx",
		ctx_isp->frame_id, ctx_isp->sof_timestamp_val);

	if (list_empty(&ctx->pending_req_list)) {
	if (list_empty(&ctx->wait_req_list)) {
		/*
		 * If no pending req in epoch, this is an error case.
		 * The recovery is to go back to sof state
		 */
		CAM_ERR(CAM_ISP, "No pending request");
		CAM_ERR(CAM_ISP, "No wait request");
		ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_SOF;

		/* Send SOF event as empty frame*/
@@ -1623,9 +1638,10 @@ static int __cam_isp_ctx_rdi_only_sof_in_bubble_applied(
		goto end;
	}

	req = list_first_entry(&ctx->pending_req_list, struct cam_ctx_request,
	req = list_first_entry(&ctx->wait_req_list, struct cam_ctx_request,
		list);
	req_isp = (struct cam_isp_ctx_req *)req->req_priv;
	req_isp->bubble_detected = true;

	CAM_DBG(CAM_ISP, "Report Bubble flag %d", req_isp->bubble_report);
	if (req_isp->bubble_report && ctx->ctx_crm_intf &&
@@ -1640,17 +1656,18 @@ static int __cam_isp_ctx_rdi_only_sof_in_bubble_applied(
		CAM_DBG(CAM_ISP, "Notify CRM about Bubble frame %lld",
			ctx_isp->frame_id);
	} else {
		req_isp->bubble_report = 0;
	}

	/*
		 * Since can not bubble report, always move the request to
		 * active list.
	 * Always move the request to active list. Let buf done
	 * function handles the rest.
	 */
	ctx_isp->active_req_cnt++;
	list_del_init(&req->list);
	list_add_tail(&req->list, &ctx->active_req_list);
		ctx_isp->active_req_cnt++;
	CAM_DBG(CAM_ISP, "move request %lld to active list(cnt = %d)",
			req->request_id, ctx_isp->active_req_cnt);
		req_isp->bubble_report = 0;
	}

	if (!req_isp->bubble_report) {
		if (req->request_id > ctx_isp->reported_req_id) {
@@ -2079,6 +2096,7 @@ static int __cam_isp_ctx_config_dev_in_top_state(
	req_isp->num_fence_map_out = cfg.num_out_map_entries;
	req_isp->num_fence_map_in = cfg.num_in_map_entries;
	req_isp->num_acked = 0;
	req_isp->bubble_detected = false;

	for (i = 0; i < req_isp->num_fence_map_out; i++) {
		rc = cam_sync_get_obj_ref(req_isp->fence_map_out[i].sync_id);
+1 −0
Original line number Diff line number Diff line
@@ -115,6 +115,7 @@ struct cam_isp_ctx_req {
	uint32_t                              num_acked;
	int32_t                               bubble_report;
	struct cam_isp_prepare_hw_update_data hw_update_data;
	bool                                  bubble_detected;
};

/**