From a2b2dfab21deb5f8aa6ac52d9a22fc80bec9904b Mon Sep 17 00:00:00 2001 From: Shivakumar Malke Date: Thu, 22 Sep 2022 21:35:14 +0530 Subject: [PATCH] msm: camera: isp: Handle RUP in applied substate In TFE top-half handler, TOP register status is read first and then based on top register status, bus register status is read. There could be a corner case where bufdone irq top-half handling is ongoing, top status registers are read, and while reading bus register status we might have got SOF and RUP irqs. Since RUP and Bufdone both come from bus side, RUP bit is set during this bus register read. Hence, RUP is handled first along with bufdone and then SOF irq is handled. There is no handling in statemachine for such RUP's in RDI only context statemachine. Hence leading to bubble condition resulting in frame drop To overcome such scenario, handling for RUP in applied substate is introduced in RDI only statemachine. CRs-Fixed: 3298719 Change-Id: I5cc8a0c122aa09c22da6536303f849344454c480 Signed-off-by: Shivakumar Malke --- drivers/cam_isp/cam_isp_context.c | 61 ++++++++++++++++++++++++++++++- 1 file changed, 60 insertions(+), 1 deletion(-) diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index f3d454914204..b01a2a63744c 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -4305,6 +4305,65 @@ error: return 0; } +static int __cam_isp_ctx_rdi_only_reg_upd_in_applied_state( + struct cam_isp_context *ctx_isp, void *evt_data) +{ + struct cam_ctx_request *req = NULL; + struct cam_context *ctx = ctx_isp->base; + struct cam_isp_ctx_req *req_isp; + uint64_t request_id = 0; + + if (list_empty(&ctx->wait_req_list)) { + CAM_ERR(CAM_ISP, "Reg upd ack with no waiting request"); + goto end; + } + ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_EPOCH; + + req = list_first_entry(&ctx->wait_req_list, + struct cam_ctx_request, list); + list_del_init(&req->list); + + req_isp = (struct cam_isp_ctx_req *) req->req_priv; + + request_id = (req_isp->hw_update_data.packet_opcode_type == + CAM_ISP_PACKET_INIT_DEV) ? 0 : req->request_id; + + if (req_isp->num_fence_map_out != 0) { + list_add_tail(&req->list, &ctx->active_req_list); + ctx_isp->active_req_cnt++; + request_id = req->request_id; + CAM_DBG(CAM_REQ, + "move request %lld to active list(cnt = %d), ctx %u", + req->request_id, ctx_isp->active_req_cnt, ctx->ctx_id); + __cam_isp_ctx_update_event_record(ctx_isp, + CAM_ISP_CTX_EVENT_RUP, req); + } else { + /* no io config, so the request is completed. */ + list_add_tail(&req->list, &ctx->free_req_list); + CAM_DBG(CAM_ISP, + "move active request %lld to free list(cnt = %d), ctx %u", + req->request_id, ctx_isp->active_req_cnt, ctx->ctx_id); + } + + CAM_DBG(CAM_ISP, "next Substate[%s]", + __cam_isp_ctx_substate_val_to_type( + ctx_isp->substate_activated)); + + __cam_isp_ctx_update_event_record(ctx_isp, + CAM_ISP_CTX_EVENT_RUP, req); + + return 0; +end: + __cam_isp_ctx_update_event_record(ctx_isp, + CAM_ISP_CTX_EVENT_RUP, NULL); + /* + * There is no request in the pending list, move the sub state machine + * to SOF sub state + */ + ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_SOF; + return 0; +} + static struct cam_isp_ctx_irq_ops cam_isp_ctx_rdi_only_activated_state_machine_irq [CAM_ISP_CTX_ACTIVATED_MAX] = { @@ -4324,7 +4383,7 @@ static struct cam_isp_ctx_irq_ops .irq_ops = { __cam_isp_ctx_handle_error, __cam_isp_ctx_rdi_only_sof_in_applied_state, - NULL, + __cam_isp_ctx_rdi_only_reg_upd_in_applied_state, NULL, __cam_isp_ctx_notify_eof_in_activated_state, __cam_isp_ctx_buf_done_in_applied,