Loading drivers/cam_core/cam_hw_mgr_intf.h +12 −9 Original line number Diff line number Diff line /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #ifndef _CAM_HW_MGR_INTF_H_ Loading Loading @@ -242,7 +242,9 @@ struct cam_hw_stream_setttings { * @num_out_map_entries: Number of out map entries * @priv: Private pointer * @request_id: Request ID * @reapply True if reapplying after bubble * @reapply: True if reapplying after bubble * @cdm_reset_before_apply: True is need to reset CDM before re-apply bubble * request * */ struct cam_hw_config_args { Loading @@ -255,6 +257,7 @@ struct cam_hw_config_args { uint64_t request_id; bool init_packet; bool reapply; bool cdm_reset_before_apply; }; /** Loading drivers/cam_isp/cam_isp_context.c +143 −14 Original line number Diff line number Diff line Loading @@ -893,6 +893,8 @@ static int __cam_isp_ctx_handle_buf_done_for_request( req_isp->bubble_detected = false; list_del_init(&req->list); atomic_set(&ctx_isp->process_bubble, 0); req_isp->cdm_reset_before_apply = false; ctx_isp->bubble_frame_cnt = 0; if (buf_done_req_id <= ctx->last_flush_req) { for (i = 0; i < req_isp->num_fence_map_out; i++) Loading Loading @@ -926,6 +928,7 @@ static int __cam_isp_ctx_handle_buf_done_for_request( list_del_init(&req->list); list_add_tail(&req->list, &ctx->free_req_list); req_isp->reapply = false; req_isp->cdm_reset_before_apply = false; CAM_DBG(CAM_REQ, "Move active request %lld to free list(cnt = %d) [all fences done], ctx %u", Loading Loading @@ -1208,6 +1211,10 @@ static int __cam_isp_ctx_notify_sof_in_activated_state( struct cam_context *ctx = ctx_isp->base; struct cam_ctx_request *req; struct cam_isp_ctx_req *req_isp; struct cam_hw_cmd_args hw_cmd_args; struct cam_isp_hw_cmd_args isp_hw_cmd_args; uint64_t last_cdm_done_req = 0; struct cam_isp_hw_epoch_event_data *epoch_done_event_data = (struct cam_isp_hw_epoch_event_data *)evt_data; Loading Loading @@ -1250,9 +1257,37 @@ static int __cam_isp_ctx_notify_sof_in_activated_state( if (ctx_isp->bubble_frame_cnt >= 1 && req_isp->bubble_detected) { hw_cmd_args.ctxt_to_hw_map = ctx_isp->hw_ctx; hw_cmd_args.cmd_type = CAM_HW_MGR_CMD_INTERNAL; isp_hw_cmd_args.cmd_type = CAM_ISP_HW_MGR_GET_LAST_CDM_DONE; hw_cmd_args.u.internal_args = (void *)&isp_hw_cmd_args; rc = ctx->hw_mgr_intf->hw_cmd( ctx->hw_mgr_intf->hw_mgr_priv, &hw_cmd_args); if (rc) { CAM_ERR(CAM_ISP, "HW command failed to get last CDM done"); return rc; } last_cdm_done_req = isp_hw_cmd_args.u.last_cdm_done; CAM_DBG(CAM_ISP, "last_cdm_done req: %d", last_cdm_done_req); if (last_cdm_done_req >= req->request_id) { CAM_INFO_RATE_LIMIT(CAM_ISP, "CDM callback detected for req: %lld, possible buf_done delay, waiting for buf_done", req->request_id); ctx_isp->bubble_frame_cnt = 0; } else { CAM_DBG(CAM_ISP, "CDM callback not happened for req: %lld, possible CDM stuck or workqueue delay", req->request_id); req_isp->num_acked = 0; ctx_isp->bubble_frame_cnt = 0; req_isp->bubble_detected = false; req_isp->cdm_reset_before_apply = true; list_del_init(&req->list); list_add(&req->list, &ctx->pending_req_list); atomic_set(&ctx_isp->process_bubble, 0); Loading @@ -1261,6 +1296,7 @@ static int __cam_isp_ctx_notify_sof_in_activated_state( "Move active req: %lld to pending list(cnt = %d) [bubble re-apply],ctx %u", req->request_id, ctx_isp->active_req_cnt, ctx->ctx_id); } } else if (req_isp->bubble_detected) { if (ctx_isp->last_sof_timestamp != ctx_isp->sof_timestamp_val) { Loading Loading @@ -1492,6 +1528,7 @@ static int __cam_isp_ctx_epoch_in_applied(struct cam_isp_context *ctx_isp, req_isp = (struct cam_isp_ctx_req *)req->req_priv; req_isp->bubble_detected = true; req_isp->reapply = true; req_isp->cdm_reset_before_apply = false; CAM_INFO(CAM_ISP, "ctx:%d Report Bubble flag %d req id:%lld", ctx->ctx_id, req_isp->bubble_report, req->request_id); Loading Loading @@ -1678,6 +1715,7 @@ static int __cam_isp_ctx_epoch_in_bubble_applied( CAM_INFO(CAM_ISP, "Ctx:%d Report Bubble flag %d req id:%lld", ctx->ctx_id, req_isp->bubble_report, req->request_id); req_isp->reapply = true; req_isp->cdm_reset_before_apply = false; if (req_isp->bubble_report && ctx->ctx_crm_intf && ctx->ctx_crm_intf->notify_err) { Loading Loading @@ -2545,11 +2583,10 @@ static int __cam_isp_ctx_apply_req_in_activated_state( cfg.priv = &req_isp->hw_update_data; cfg.init_packet = 0; cfg.reapply = req_isp->reapply; cfg.cdm_reset_before_apply = req_isp->cdm_reset_before_apply; rc = ctx->hw_mgr_intf->hw_config(ctx->hw_mgr_intf->hw_mgr_priv, &cfg); if (rc) { CAM_ERR_RATE_LIMIT(CAM_ISP, "Can not apply the configuration"); } else { if (!rc) { spin_lock_bh(&ctx->lock); ctx_isp->substate_activated = next_state; ctx_isp->last_applied_req_id = apply->request_id; Loading @@ -2565,6 +2602,22 @@ static int __cam_isp_ctx_apply_req_in_activated_state( req->request_id); __cam_isp_ctx_update_event_record(ctx_isp, CAM_ISP_CTX_EVENT_APPLY, req); } else if (rc == -EALREADY) { spin_lock_bh(&ctx->lock); req_isp->bubble_detected = true; req_isp->cdm_reset_before_apply = false; atomic_set(&ctx_isp->process_bubble, 1); list_del_init(&req->list); list_add(&req->list, &ctx->active_req_list); ctx_isp->active_req_cnt++; spin_unlock_bh(&ctx->lock); 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); } else { CAM_ERR_RATE_LIMIT(CAM_ISP, "ctx_id:%d ,Can not apply (req %lld) the configuration, rc %d", ctx->ctx_id, apply->request_id, rc); } end: return rc; Loading Loading @@ -2900,6 +2953,7 @@ static int __cam_isp_ctx_flush_req(struct cam_context *ctx, } } req_isp->reapply = false; req_isp->cdm_reset_before_apply = false; list_del_init(&req->list); list_add_tail(&req->list, &ctx->free_req_list); } Loading Loading @@ -3265,6 +3319,7 @@ static int __cam_isp_ctx_rdi_only_sof_in_bubble_applied( CAM_INFO(CAM_ISP, "Ctx:%d Report Bubble flag %d req id:%lld", ctx->ctx_id, req_isp->bubble_report, req->request_id); req_isp->reapply = true; req_isp->cdm_reset_before_apply = false; if (req_isp->bubble_report && ctx->ctx_crm_intf && ctx->ctx_crm_intf->notify_err) { Loading @@ -3285,6 +3340,7 @@ static int __cam_isp_ctx_rdi_only_sof_in_bubble_applied( ctx_isp->frame_id, ctx->ctx_id); ctx->ctx_crm_intf->notify_err(¬ify); atomic_set(&ctx_isp->process_bubble, 1); } else { req_isp->bubble_report = 0; } Loading Loading @@ -3330,7 +3386,11 @@ static int __cam_isp_ctx_rdi_only_sof_in_bubble_state( struct cam_req_mgr_trigger_notify notify; struct cam_isp_hw_sof_event_data *sof_event_data = evt_data; struct cam_isp_ctx_req *req_isp; struct cam_hw_cmd_args hw_cmd_args; struct cam_isp_hw_cmd_args isp_hw_cmd_args; uint64_t request_id = 0; uint64_t last_cdm_done_req = 0; int rc = 0; if (!evt_data) { CAM_ERR(CAM_ISP, "in valid sof event data"); Loading @@ -3342,6 +3402,71 @@ static int __cam_isp_ctx_rdi_only_sof_in_bubble_state( ctx_isp->boot_timestamp = sof_event_data->boot_time; CAM_DBG(CAM_ISP, "frame id: %lld time stamp:0x%llx", ctx_isp->frame_id, ctx_isp->sof_timestamp_val); if (atomic_read(&ctx_isp->process_bubble)) { if (list_empty(&ctx->active_req_list)) { CAM_ERR(CAM_ISP, "No available active req in bubble"); atomic_set(&ctx_isp->process_bubble, 0); return -EINVAL; } if (ctx_isp->last_sof_timestamp == ctx_isp->sof_timestamp_val) { CAM_DBG(CAM_ISP, "Tasklet delay detected! Bubble frame check skipped, sof_timestamp: %lld, ctx_id: %d", ctx_isp->sof_timestamp_val, ctx->ctx_id); goto end; } req = list_first_entry(&ctx->active_req_list, struct cam_ctx_request, list); req_isp = (struct cam_isp_ctx_req *) req->req_priv; if (req_isp->bubble_detected) { hw_cmd_args.ctxt_to_hw_map = ctx_isp->hw_ctx; hw_cmd_args.cmd_type = CAM_HW_MGR_CMD_INTERNAL; isp_hw_cmd_args.cmd_type = CAM_ISP_HW_MGR_GET_LAST_CDM_DONE; hw_cmd_args.u.internal_args = (void *)&isp_hw_cmd_args; rc = ctx->hw_mgr_intf->hw_cmd( ctx->hw_mgr_intf->hw_mgr_priv, &hw_cmd_args); if (rc) { CAM_ERR(CAM_ISP, "HW command failed to get last CDM done"); return rc; } last_cdm_done_req = isp_hw_cmd_args.u.last_cdm_done; CAM_DBG(CAM_ISP, "last_cdm_done req: %d ctx_id: %d", last_cdm_done_req, ctx->ctx_id); if (last_cdm_done_req >= req->request_id) { CAM_DBG(CAM_ISP, "CDM callback detected for req: %lld, possible buf_done delay, waiting for buf_done", req->request_id); goto end; } else { CAM_DBG(CAM_ISP, "CDM callback not happened for req: %lld, possible CDM stuck or workqueue delay", req->request_id); req_isp->num_acked = 0; req_isp->bubble_detected = false; req_isp->cdm_reset_before_apply = true; list_del_init(&req->list); list_add(&req->list, &ctx->pending_req_list); atomic_set(&ctx_isp->process_bubble, 0); ctx_isp->active_req_cnt--; CAM_DBG(CAM_REQ, "Move active req: %lld to pending list(cnt = %d) [bubble re-apply],ctx %u", req->request_id, ctx_isp->active_req_cnt, ctx->ctx_id); } goto end; } } /* * Signal all active requests with error and move the all the active * requests to free list Loading @@ -3363,6 +3488,7 @@ static int __cam_isp_ctx_rdi_only_sof_in_bubble_state( ctx_isp->active_req_cnt--; } end: /* notify reqmgr with sof signal */ if (ctx->ctx_crm_intf && ctx->ctx_crm_intf->notify_trigger) { notify.link_hdl = ctx->link_hdl; Loading Loading @@ -3393,6 +3519,7 @@ static int __cam_isp_ctx_rdi_only_sof_in_bubble_state( __cam_isp_ctx_substate_val_to_type( ctx_isp->substate_activated)); ctx_isp->last_sof_timestamp = ctx_isp->sof_timestamp_val; return 0; } Loading Loading @@ -3857,6 +3984,7 @@ static int __cam_isp_ctx_config_dev_in_top_state( req_isp->num_fence_map_in = cfg.num_in_map_entries; req_isp->num_acked = 0; req_isp->bubble_detected = false; req_isp->cdm_reset_before_apply = 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); Loading Loading @@ -4604,6 +4732,7 @@ static int __cam_isp_ctx_start_dev_in_ready(struct cam_context *ctx, start_isp.hw_config.priv = &req_isp->hw_update_data; start_isp.hw_config.init_packet = 1; start_isp.hw_config.reapply = 0; start_isp.hw_config.cdm_reset_before_apply = false; ctx_isp->last_applied_req_id = req->request_id; Loading drivers/cam_isp/cam_isp_context.h +21 −18 Original line number Diff line number Diff line /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #ifndef _CAM_ISP_CONTEXT_H_ Loading Loading @@ -148,6 +148,8 @@ struct cam_isp_ctx_irq_ops { * @hw_update_data: HW update data for this request * @event_timestamp: Timestamp for different stage of request * @reapply: True if reapplying after bubble * @cdm_reset_before_apply: For bubble re-apply when buf done not coming set * to True * */ struct cam_isp_ctx_req { Loading @@ -167,6 +169,7 @@ struct cam_isp_ctx_req { [CAM_ISP_CTX_EVENT_MAX]; bool bubble_detected; bool reapply; bool cdm_reset_before_apply; }; /** Loading Loading @@ -238,6 +241,7 @@ struct cam_isp_context_event_record { * @subscribe_event: The irq event mask that CRM subscribes to, IFE * will invoke CRM cb at those event. * @last_applied_req_id: Last applied request id * @last_sof_timestamp: SOF timestamp of the last frame * @state_monitor_head: Write index to the state monitoring array * @req_info Request id information about last buf done * @cam_isp_ctx_state_monitor: State monitoring array Loading @@ -256,7 +260,6 @@ struct cam_isp_context_event_record { * decide whether to apply request in offline ctx * @workq: Worker thread for offline ife * @trigger_id: ID provided by CRM for each ctx on the link * @last_sof_timestamp: SOF timestamp of the last frame * */ struct cam_isp_context { Loading @@ -280,6 +283,7 @@ struct cam_isp_context { int64_t reported_req_id; uint32_t subscribe_event; int64_t last_applied_req_id; uint64_t last_sof_timestamp; atomic64_t state_monitor_head; struct cam_isp_context_state_monitor cam_isp_ctx_state_monitor[ CAM_ISP_CTX_STATE_MONITOR_MAX_ENTRIES]; Loading @@ -299,7 +303,6 @@ struct cam_isp_context { atomic_t rxd_epoch; struct cam_req_mgr_core_workq *workq; int32_t trigger_id; uint64_t last_sof_timestamp; }; /** Loading drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +34 −0 Original line number Diff line number Diff line Loading @@ -2710,6 +2710,7 @@ void cam_ife_cam_cdm_callback(uint32_t handle, void *userdata, if (status == CAM_CDM_CB_STATUS_BL_SUCCESS) { complete_all(&ctx->config_done_complete); atomic_set(&ctx->cdm_done, 1); ctx->last_cdm_done_req = cookie; if (g_ife_hw_mgr.debug_cfg.per_req_reg_dump) cam_ife_mgr_handle_reg_dump(ctx, hw_update_data->reg_dump_buf_desc, Loading Loading @@ -3016,6 +3017,7 @@ static int cam_ife_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args) ife_ctx->cdm_handle = cdm_acquire.handle; ife_ctx->cdm_ops = cdm_acquire.ops; atomic_set(&ife_ctx->cdm_done, 1); ife_ctx->last_cdm_done_req = 0; acquire_hw_info = (struct cam_isp_acquire_hw_info *)acquire_args->acquire_info; Loading Loading @@ -3225,6 +3227,7 @@ static int cam_ife_mgr_acquire_dev(void *hw_mgr_priv, void *acquire_hw_args) ife_ctx->cdm_handle = cdm_acquire.handle; ife_ctx->cdm_ops = cdm_acquire.ops; atomic_set(&ife_ctx->cdm_done, 1); ife_ctx->last_cdm_done_req = 0; isp_resource = (struct cam_isp_resource *)acquire_args->acquire_info; Loading Loading @@ -3662,6 +3665,7 @@ static int cam_ife_mgr_config_hw(void *hw_mgr_priv, struct cam_ife_hw_mgr_ctx *ctx; struct cam_isp_prepare_hw_update_data *hw_update_data; unsigned long rem_jiffies = 0; bool cdm_hang_detect = false; if (!hw_mgr_priv || !config_hw_args) { CAM_ERR(CAM_ISP, Loading Loading @@ -3697,6 +3701,31 @@ static int cam_ife_mgr_config_hw(void *hw_mgr_priv, CAM_DBG(CAM_ISP, "Ctx[%pK][%d] : Applying Req %lld, init_packet=%d", ctx, ctx->ctx_index, cfg->request_id, cfg->init_packet); if (cfg->reapply && cfg->cdm_reset_before_apply) { if (ctx->last_cdm_done_req < cfg->request_id) { cdm_hang_detect = cam_cdm_detect_hang_error(ctx->cdm_handle); CAM_ERR_RATE_LIMIT(CAM_ISP, "CDM callback not received for req: %lld, last_cdm_done_req: %lld, cdm_hang_detect: %d", cfg->request_id, ctx->last_cdm_done_req, cdm_hang_detect); rc = cam_cdm_reset_hw(ctx->cdm_handle); if (rc) { CAM_ERR_RATE_LIMIT(CAM_ISP, "CDM reset unsuccessful for req: %lld. ctx: %d, rc: %d", cfg->request_id, ctx->ctx_index, rc); ctx->last_cdm_done_req = 0; return rc; } } else { CAM_ERR_RATE_LIMIT(CAM_ISP, "CDM callback received, should wait for buf done for req: %lld", cfg->request_id); return -EALREADY; } ctx->last_cdm_done_req = 0; } for (i = 0; i < CAM_IFE_HW_NUM_MAX; i++) { if (hw_update_data->bw_config_valid[i] == true) { Loading Loading @@ -4540,6 +4569,7 @@ static int cam_ife_mgr_release_hw(void *hw_mgr_priv, ctx->is_fe_enabled = false; ctx->is_offline = false; ctx->dual_ife_irq_mismatch_cnt = 0; ctx->last_cdm_done_req = 0; atomic_set(&ctx->overflow_pending, 0); for (i = 0; i < CAM_IFE_HW_NUM_MAX; i++) { ctx->sof_cnt[i] = 0; Loading Loading @@ -6523,6 +6553,10 @@ static int cam_ife_mgr_cmd(void *hw_mgr_priv, void *cmd_args) case CAM_HW_MGR_CMD_DUMP_ACQ_INFO: cam_ife_hw_mgr_dump_acq_data(ctx); break; case CAM_ISP_HW_MGR_GET_LAST_CDM_DONE: isp_hw_cmd_args->u.last_cdm_done = ctx->last_cdm_done_req; break; default: CAM_ERR(CAM_ISP, "Invalid cmd"); } Loading drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h +2 −0 Original line number Diff line number Diff line Loading @@ -133,6 +133,7 @@ struct cam_ife_hw_mgr_debug { * context * @cdm_done flag to indicate cdm has finished writing shadow * registers * @last_cdm_done_req: Last cdm done request * @is_rdi_only_context flag to specify the context has only rdi resource * @config_done_complete indicator for configuration complete * @reg_dump_buf_desc: cmd buffer descriptors for reg dump Loading Loading @@ -185,6 +186,7 @@ struct cam_ife_hw_mgr_ctx { uint32_t eof_cnt[CAM_IFE_HW_NUM_MAX]; atomic_t overflow_pending; atomic_t cdm_done; uint64_t last_cdm_done_req; uint32_t is_rdi_only_context; struct completion config_done_complete; struct cam_cmd_buf_desc reg_dump_buf_desc[ Loading Loading
drivers/cam_core/cam_hw_mgr_intf.h +12 −9 Original line number Diff line number Diff line /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #ifndef _CAM_HW_MGR_INTF_H_ Loading Loading @@ -242,7 +242,9 @@ struct cam_hw_stream_setttings { * @num_out_map_entries: Number of out map entries * @priv: Private pointer * @request_id: Request ID * @reapply True if reapplying after bubble * @reapply: True if reapplying after bubble * @cdm_reset_before_apply: True is need to reset CDM before re-apply bubble * request * */ struct cam_hw_config_args { Loading @@ -255,6 +257,7 @@ struct cam_hw_config_args { uint64_t request_id; bool init_packet; bool reapply; bool cdm_reset_before_apply; }; /** Loading
drivers/cam_isp/cam_isp_context.c +143 −14 Original line number Diff line number Diff line Loading @@ -893,6 +893,8 @@ static int __cam_isp_ctx_handle_buf_done_for_request( req_isp->bubble_detected = false; list_del_init(&req->list); atomic_set(&ctx_isp->process_bubble, 0); req_isp->cdm_reset_before_apply = false; ctx_isp->bubble_frame_cnt = 0; if (buf_done_req_id <= ctx->last_flush_req) { for (i = 0; i < req_isp->num_fence_map_out; i++) Loading Loading @@ -926,6 +928,7 @@ static int __cam_isp_ctx_handle_buf_done_for_request( list_del_init(&req->list); list_add_tail(&req->list, &ctx->free_req_list); req_isp->reapply = false; req_isp->cdm_reset_before_apply = false; CAM_DBG(CAM_REQ, "Move active request %lld to free list(cnt = %d) [all fences done], ctx %u", Loading Loading @@ -1208,6 +1211,10 @@ static int __cam_isp_ctx_notify_sof_in_activated_state( struct cam_context *ctx = ctx_isp->base; struct cam_ctx_request *req; struct cam_isp_ctx_req *req_isp; struct cam_hw_cmd_args hw_cmd_args; struct cam_isp_hw_cmd_args isp_hw_cmd_args; uint64_t last_cdm_done_req = 0; struct cam_isp_hw_epoch_event_data *epoch_done_event_data = (struct cam_isp_hw_epoch_event_data *)evt_data; Loading Loading @@ -1250,9 +1257,37 @@ static int __cam_isp_ctx_notify_sof_in_activated_state( if (ctx_isp->bubble_frame_cnt >= 1 && req_isp->bubble_detected) { hw_cmd_args.ctxt_to_hw_map = ctx_isp->hw_ctx; hw_cmd_args.cmd_type = CAM_HW_MGR_CMD_INTERNAL; isp_hw_cmd_args.cmd_type = CAM_ISP_HW_MGR_GET_LAST_CDM_DONE; hw_cmd_args.u.internal_args = (void *)&isp_hw_cmd_args; rc = ctx->hw_mgr_intf->hw_cmd( ctx->hw_mgr_intf->hw_mgr_priv, &hw_cmd_args); if (rc) { CAM_ERR(CAM_ISP, "HW command failed to get last CDM done"); return rc; } last_cdm_done_req = isp_hw_cmd_args.u.last_cdm_done; CAM_DBG(CAM_ISP, "last_cdm_done req: %d", last_cdm_done_req); if (last_cdm_done_req >= req->request_id) { CAM_INFO_RATE_LIMIT(CAM_ISP, "CDM callback detected for req: %lld, possible buf_done delay, waiting for buf_done", req->request_id); ctx_isp->bubble_frame_cnt = 0; } else { CAM_DBG(CAM_ISP, "CDM callback not happened for req: %lld, possible CDM stuck or workqueue delay", req->request_id); req_isp->num_acked = 0; ctx_isp->bubble_frame_cnt = 0; req_isp->bubble_detected = false; req_isp->cdm_reset_before_apply = true; list_del_init(&req->list); list_add(&req->list, &ctx->pending_req_list); atomic_set(&ctx_isp->process_bubble, 0); Loading @@ -1261,6 +1296,7 @@ static int __cam_isp_ctx_notify_sof_in_activated_state( "Move active req: %lld to pending list(cnt = %d) [bubble re-apply],ctx %u", req->request_id, ctx_isp->active_req_cnt, ctx->ctx_id); } } else if (req_isp->bubble_detected) { if (ctx_isp->last_sof_timestamp != ctx_isp->sof_timestamp_val) { Loading Loading @@ -1492,6 +1528,7 @@ static int __cam_isp_ctx_epoch_in_applied(struct cam_isp_context *ctx_isp, req_isp = (struct cam_isp_ctx_req *)req->req_priv; req_isp->bubble_detected = true; req_isp->reapply = true; req_isp->cdm_reset_before_apply = false; CAM_INFO(CAM_ISP, "ctx:%d Report Bubble flag %d req id:%lld", ctx->ctx_id, req_isp->bubble_report, req->request_id); Loading Loading @@ -1678,6 +1715,7 @@ static int __cam_isp_ctx_epoch_in_bubble_applied( CAM_INFO(CAM_ISP, "Ctx:%d Report Bubble flag %d req id:%lld", ctx->ctx_id, req_isp->bubble_report, req->request_id); req_isp->reapply = true; req_isp->cdm_reset_before_apply = false; if (req_isp->bubble_report && ctx->ctx_crm_intf && ctx->ctx_crm_intf->notify_err) { Loading Loading @@ -2545,11 +2583,10 @@ static int __cam_isp_ctx_apply_req_in_activated_state( cfg.priv = &req_isp->hw_update_data; cfg.init_packet = 0; cfg.reapply = req_isp->reapply; cfg.cdm_reset_before_apply = req_isp->cdm_reset_before_apply; rc = ctx->hw_mgr_intf->hw_config(ctx->hw_mgr_intf->hw_mgr_priv, &cfg); if (rc) { CAM_ERR_RATE_LIMIT(CAM_ISP, "Can not apply the configuration"); } else { if (!rc) { spin_lock_bh(&ctx->lock); ctx_isp->substate_activated = next_state; ctx_isp->last_applied_req_id = apply->request_id; Loading @@ -2565,6 +2602,22 @@ static int __cam_isp_ctx_apply_req_in_activated_state( req->request_id); __cam_isp_ctx_update_event_record(ctx_isp, CAM_ISP_CTX_EVENT_APPLY, req); } else if (rc == -EALREADY) { spin_lock_bh(&ctx->lock); req_isp->bubble_detected = true; req_isp->cdm_reset_before_apply = false; atomic_set(&ctx_isp->process_bubble, 1); list_del_init(&req->list); list_add(&req->list, &ctx->active_req_list); ctx_isp->active_req_cnt++; spin_unlock_bh(&ctx->lock); 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); } else { CAM_ERR_RATE_LIMIT(CAM_ISP, "ctx_id:%d ,Can not apply (req %lld) the configuration, rc %d", ctx->ctx_id, apply->request_id, rc); } end: return rc; Loading Loading @@ -2900,6 +2953,7 @@ static int __cam_isp_ctx_flush_req(struct cam_context *ctx, } } req_isp->reapply = false; req_isp->cdm_reset_before_apply = false; list_del_init(&req->list); list_add_tail(&req->list, &ctx->free_req_list); } Loading Loading @@ -3265,6 +3319,7 @@ static int __cam_isp_ctx_rdi_only_sof_in_bubble_applied( CAM_INFO(CAM_ISP, "Ctx:%d Report Bubble flag %d req id:%lld", ctx->ctx_id, req_isp->bubble_report, req->request_id); req_isp->reapply = true; req_isp->cdm_reset_before_apply = false; if (req_isp->bubble_report && ctx->ctx_crm_intf && ctx->ctx_crm_intf->notify_err) { Loading @@ -3285,6 +3340,7 @@ static int __cam_isp_ctx_rdi_only_sof_in_bubble_applied( ctx_isp->frame_id, ctx->ctx_id); ctx->ctx_crm_intf->notify_err(¬ify); atomic_set(&ctx_isp->process_bubble, 1); } else { req_isp->bubble_report = 0; } Loading Loading @@ -3330,7 +3386,11 @@ static int __cam_isp_ctx_rdi_only_sof_in_bubble_state( struct cam_req_mgr_trigger_notify notify; struct cam_isp_hw_sof_event_data *sof_event_data = evt_data; struct cam_isp_ctx_req *req_isp; struct cam_hw_cmd_args hw_cmd_args; struct cam_isp_hw_cmd_args isp_hw_cmd_args; uint64_t request_id = 0; uint64_t last_cdm_done_req = 0; int rc = 0; if (!evt_data) { CAM_ERR(CAM_ISP, "in valid sof event data"); Loading @@ -3342,6 +3402,71 @@ static int __cam_isp_ctx_rdi_only_sof_in_bubble_state( ctx_isp->boot_timestamp = sof_event_data->boot_time; CAM_DBG(CAM_ISP, "frame id: %lld time stamp:0x%llx", ctx_isp->frame_id, ctx_isp->sof_timestamp_val); if (atomic_read(&ctx_isp->process_bubble)) { if (list_empty(&ctx->active_req_list)) { CAM_ERR(CAM_ISP, "No available active req in bubble"); atomic_set(&ctx_isp->process_bubble, 0); return -EINVAL; } if (ctx_isp->last_sof_timestamp == ctx_isp->sof_timestamp_val) { CAM_DBG(CAM_ISP, "Tasklet delay detected! Bubble frame check skipped, sof_timestamp: %lld, ctx_id: %d", ctx_isp->sof_timestamp_val, ctx->ctx_id); goto end; } req = list_first_entry(&ctx->active_req_list, struct cam_ctx_request, list); req_isp = (struct cam_isp_ctx_req *) req->req_priv; if (req_isp->bubble_detected) { hw_cmd_args.ctxt_to_hw_map = ctx_isp->hw_ctx; hw_cmd_args.cmd_type = CAM_HW_MGR_CMD_INTERNAL; isp_hw_cmd_args.cmd_type = CAM_ISP_HW_MGR_GET_LAST_CDM_DONE; hw_cmd_args.u.internal_args = (void *)&isp_hw_cmd_args; rc = ctx->hw_mgr_intf->hw_cmd( ctx->hw_mgr_intf->hw_mgr_priv, &hw_cmd_args); if (rc) { CAM_ERR(CAM_ISP, "HW command failed to get last CDM done"); return rc; } last_cdm_done_req = isp_hw_cmd_args.u.last_cdm_done; CAM_DBG(CAM_ISP, "last_cdm_done req: %d ctx_id: %d", last_cdm_done_req, ctx->ctx_id); if (last_cdm_done_req >= req->request_id) { CAM_DBG(CAM_ISP, "CDM callback detected for req: %lld, possible buf_done delay, waiting for buf_done", req->request_id); goto end; } else { CAM_DBG(CAM_ISP, "CDM callback not happened for req: %lld, possible CDM stuck or workqueue delay", req->request_id); req_isp->num_acked = 0; req_isp->bubble_detected = false; req_isp->cdm_reset_before_apply = true; list_del_init(&req->list); list_add(&req->list, &ctx->pending_req_list); atomic_set(&ctx_isp->process_bubble, 0); ctx_isp->active_req_cnt--; CAM_DBG(CAM_REQ, "Move active req: %lld to pending list(cnt = %d) [bubble re-apply],ctx %u", req->request_id, ctx_isp->active_req_cnt, ctx->ctx_id); } goto end; } } /* * Signal all active requests with error and move the all the active * requests to free list Loading @@ -3363,6 +3488,7 @@ static int __cam_isp_ctx_rdi_only_sof_in_bubble_state( ctx_isp->active_req_cnt--; } end: /* notify reqmgr with sof signal */ if (ctx->ctx_crm_intf && ctx->ctx_crm_intf->notify_trigger) { notify.link_hdl = ctx->link_hdl; Loading Loading @@ -3393,6 +3519,7 @@ static int __cam_isp_ctx_rdi_only_sof_in_bubble_state( __cam_isp_ctx_substate_val_to_type( ctx_isp->substate_activated)); ctx_isp->last_sof_timestamp = ctx_isp->sof_timestamp_val; return 0; } Loading Loading @@ -3857,6 +3984,7 @@ static int __cam_isp_ctx_config_dev_in_top_state( req_isp->num_fence_map_in = cfg.num_in_map_entries; req_isp->num_acked = 0; req_isp->bubble_detected = false; req_isp->cdm_reset_before_apply = 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); Loading Loading @@ -4604,6 +4732,7 @@ static int __cam_isp_ctx_start_dev_in_ready(struct cam_context *ctx, start_isp.hw_config.priv = &req_isp->hw_update_data; start_isp.hw_config.init_packet = 1; start_isp.hw_config.reapply = 0; start_isp.hw_config.cdm_reset_before_apply = false; ctx_isp->last_applied_req_id = req->request_id; Loading
drivers/cam_isp/cam_isp_context.h +21 −18 Original line number Diff line number Diff line /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #ifndef _CAM_ISP_CONTEXT_H_ Loading Loading @@ -148,6 +148,8 @@ struct cam_isp_ctx_irq_ops { * @hw_update_data: HW update data for this request * @event_timestamp: Timestamp for different stage of request * @reapply: True if reapplying after bubble * @cdm_reset_before_apply: For bubble re-apply when buf done not coming set * to True * */ struct cam_isp_ctx_req { Loading @@ -167,6 +169,7 @@ struct cam_isp_ctx_req { [CAM_ISP_CTX_EVENT_MAX]; bool bubble_detected; bool reapply; bool cdm_reset_before_apply; }; /** Loading Loading @@ -238,6 +241,7 @@ struct cam_isp_context_event_record { * @subscribe_event: The irq event mask that CRM subscribes to, IFE * will invoke CRM cb at those event. * @last_applied_req_id: Last applied request id * @last_sof_timestamp: SOF timestamp of the last frame * @state_monitor_head: Write index to the state monitoring array * @req_info Request id information about last buf done * @cam_isp_ctx_state_monitor: State monitoring array Loading @@ -256,7 +260,6 @@ struct cam_isp_context_event_record { * decide whether to apply request in offline ctx * @workq: Worker thread for offline ife * @trigger_id: ID provided by CRM for each ctx on the link * @last_sof_timestamp: SOF timestamp of the last frame * */ struct cam_isp_context { Loading @@ -280,6 +283,7 @@ struct cam_isp_context { int64_t reported_req_id; uint32_t subscribe_event; int64_t last_applied_req_id; uint64_t last_sof_timestamp; atomic64_t state_monitor_head; struct cam_isp_context_state_monitor cam_isp_ctx_state_monitor[ CAM_ISP_CTX_STATE_MONITOR_MAX_ENTRIES]; Loading @@ -299,7 +303,6 @@ struct cam_isp_context { atomic_t rxd_epoch; struct cam_req_mgr_core_workq *workq; int32_t trigger_id; uint64_t last_sof_timestamp; }; /** Loading
drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +34 −0 Original line number Diff line number Diff line Loading @@ -2710,6 +2710,7 @@ void cam_ife_cam_cdm_callback(uint32_t handle, void *userdata, if (status == CAM_CDM_CB_STATUS_BL_SUCCESS) { complete_all(&ctx->config_done_complete); atomic_set(&ctx->cdm_done, 1); ctx->last_cdm_done_req = cookie; if (g_ife_hw_mgr.debug_cfg.per_req_reg_dump) cam_ife_mgr_handle_reg_dump(ctx, hw_update_data->reg_dump_buf_desc, Loading Loading @@ -3016,6 +3017,7 @@ static int cam_ife_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args) ife_ctx->cdm_handle = cdm_acquire.handle; ife_ctx->cdm_ops = cdm_acquire.ops; atomic_set(&ife_ctx->cdm_done, 1); ife_ctx->last_cdm_done_req = 0; acquire_hw_info = (struct cam_isp_acquire_hw_info *)acquire_args->acquire_info; Loading Loading @@ -3225,6 +3227,7 @@ static int cam_ife_mgr_acquire_dev(void *hw_mgr_priv, void *acquire_hw_args) ife_ctx->cdm_handle = cdm_acquire.handle; ife_ctx->cdm_ops = cdm_acquire.ops; atomic_set(&ife_ctx->cdm_done, 1); ife_ctx->last_cdm_done_req = 0; isp_resource = (struct cam_isp_resource *)acquire_args->acquire_info; Loading Loading @@ -3662,6 +3665,7 @@ static int cam_ife_mgr_config_hw(void *hw_mgr_priv, struct cam_ife_hw_mgr_ctx *ctx; struct cam_isp_prepare_hw_update_data *hw_update_data; unsigned long rem_jiffies = 0; bool cdm_hang_detect = false; if (!hw_mgr_priv || !config_hw_args) { CAM_ERR(CAM_ISP, Loading Loading @@ -3697,6 +3701,31 @@ static int cam_ife_mgr_config_hw(void *hw_mgr_priv, CAM_DBG(CAM_ISP, "Ctx[%pK][%d] : Applying Req %lld, init_packet=%d", ctx, ctx->ctx_index, cfg->request_id, cfg->init_packet); if (cfg->reapply && cfg->cdm_reset_before_apply) { if (ctx->last_cdm_done_req < cfg->request_id) { cdm_hang_detect = cam_cdm_detect_hang_error(ctx->cdm_handle); CAM_ERR_RATE_LIMIT(CAM_ISP, "CDM callback not received for req: %lld, last_cdm_done_req: %lld, cdm_hang_detect: %d", cfg->request_id, ctx->last_cdm_done_req, cdm_hang_detect); rc = cam_cdm_reset_hw(ctx->cdm_handle); if (rc) { CAM_ERR_RATE_LIMIT(CAM_ISP, "CDM reset unsuccessful for req: %lld. ctx: %d, rc: %d", cfg->request_id, ctx->ctx_index, rc); ctx->last_cdm_done_req = 0; return rc; } } else { CAM_ERR_RATE_LIMIT(CAM_ISP, "CDM callback received, should wait for buf done for req: %lld", cfg->request_id); return -EALREADY; } ctx->last_cdm_done_req = 0; } for (i = 0; i < CAM_IFE_HW_NUM_MAX; i++) { if (hw_update_data->bw_config_valid[i] == true) { Loading Loading @@ -4540,6 +4569,7 @@ static int cam_ife_mgr_release_hw(void *hw_mgr_priv, ctx->is_fe_enabled = false; ctx->is_offline = false; ctx->dual_ife_irq_mismatch_cnt = 0; ctx->last_cdm_done_req = 0; atomic_set(&ctx->overflow_pending, 0); for (i = 0; i < CAM_IFE_HW_NUM_MAX; i++) { ctx->sof_cnt[i] = 0; Loading Loading @@ -6523,6 +6553,10 @@ static int cam_ife_mgr_cmd(void *hw_mgr_priv, void *cmd_args) case CAM_HW_MGR_CMD_DUMP_ACQ_INFO: cam_ife_hw_mgr_dump_acq_data(ctx); break; case CAM_ISP_HW_MGR_GET_LAST_CDM_DONE: isp_hw_cmd_args->u.last_cdm_done = ctx->last_cdm_done_req; break; default: CAM_ERR(CAM_ISP, "Invalid cmd"); } Loading
drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h +2 −0 Original line number Diff line number Diff line Loading @@ -133,6 +133,7 @@ struct cam_ife_hw_mgr_debug { * context * @cdm_done flag to indicate cdm has finished writing shadow * registers * @last_cdm_done_req: Last cdm done request * @is_rdi_only_context flag to specify the context has only rdi resource * @config_done_complete indicator for configuration complete * @reg_dump_buf_desc: cmd buffer descriptors for reg dump Loading Loading @@ -185,6 +186,7 @@ struct cam_ife_hw_mgr_ctx { uint32_t eof_cnt[CAM_IFE_HW_NUM_MAX]; atomic_t overflow_pending; atomic_t cdm_done; uint64_t last_cdm_done_req; uint32_t is_rdi_only_context; struct completion config_done_complete; struct cam_cmd_buf_desc reg_dump_buf_desc[ Loading