diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index 2b3117a7f0..dd5eb580d8 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -102,18 +102,18 @@ static void __cam_isp_ctx_update_event_record( break; } - INC_HEAD(&ctx_isp->event_record_head[event], + INC_HEAD(&ctx_isp->dbg_monitors.event_record_head[event], CAM_ISP_CTX_EVENT_RECORD_MAX_ENTRIES, &iterator); cur_time = ktime_get(); if (req) { req_isp = (struct cam_isp_ctx_req *) req->req_priv; - ctx_isp->event_record[event][iterator].req_id = + ctx_isp->dbg_monitors.event_record[event][iterator].req_id = req->request_id; req_isp->event_timestamp[event] = cur_time; } else { - ctx_isp->event_record[event][iterator].req_id = 0; + ctx_isp->dbg_monitors.event_record[event][iterator].req_id = 0; } - ctx_isp->event_record[event][iterator].timestamp = cur_time; + ctx_isp->dbg_monitors.event_record[event][iterator].timestamp = cur_time; } static int __cam_isp_ctx_handle_sof_freeze_evt( @@ -169,7 +169,7 @@ static int __cam_isp_ctx_print_event_record(struct cam_isp_context *ctx_isp) struct cam_context *ctx = ctx_isp->base; for (i = 0; i < CAM_ISP_CTX_EVENT_MAX; i++) { - state_head = atomic64_read(&ctx_isp->event_record_head[i]); + state_head = atomic64_read(&ctx_isp->dbg_monitors.event_record_head[i]); if (state_head == -1) { return 0; @@ -188,7 +188,7 @@ static int __cam_isp_ctx_print_event_record(struct cam_isp_context *ctx_isp) memset(buf, 0, CAM_ISP_CONTEXT_DBG_BUF_LEN); for (j = 0; j < num_entries; j++) { - record = &ctx_isp->event_record[i][index]; + record = &ctx_isp->dbg_monitors.event_record[i][index]; ts = ktime_to_timespec64(record->timestamp); len += scnprintf(buf + len, CAM_ISP_CONTEXT_DBG_BUF_LEN - len, "%llu[%lld:%06lld] ", record->req_id, ts.tv_sec, @@ -222,19 +222,19 @@ static int __cam_isp_ctx_dump_event_record( } for (i = 0; i < CAM_ISP_CTX_EVENT_MAX; i++) { - state_head = atomic64_read(&ctx_isp->event_record_head[i]); + state_head = atomic64_read(&ctx_isp->dbg_monitors.event_record_head[i]); - if (state_head == -1) { + if (state_head == -1) return 0; - } else if (state_head < CAM_ISP_CTX_EVENT_RECORD_MAX_ENTRIES) { + else if (state_head < CAM_ISP_CTX_EVENT_RECORD_MAX_ENTRIES) { num_entries = state_head + 1; oldest_entry = 0; } else { num_entries = CAM_ISP_CTX_EVENT_RECORD_MAX_ENTRIES; - div_u64_rem(state_head + 1, - CAM_ISP_CTX_EVENT_RECORD_MAX_ENTRIES, + div_u64_rem(state_head + 1, CAM_ISP_CTX_EVENT_RECORD_MAX_ENTRIES, &oldest_entry); } + index = oldest_entry; if (dump_args->buf_len <= dump_args->offset) { @@ -254,9 +254,8 @@ static int __cam_isp_ctx_dump_event_record( remain_len, min_len); return -ENOSPC; } - for (j = 0; j < num_entries; j++) { - record = &ctx_isp->event_record[i][index]; + record = &ctx_isp->dbg_monitors.event_record[i][index]; rc = cam_common_user_dump_helper(dump_args, cam_isp_ctx_user_dump_events, record, sizeof(uint64_t), "ISP_EVT_%s:", @@ -267,8 +266,8 @@ static int __cam_isp_ctx_dump_event_record( rc); return rc; } - index = (index + 1) % - CAM_ISP_CTX_EVENT_RECORD_MAX_ENTRIES; + + index = (index + 1) % CAM_ISP_CTX_EVENT_RECORD_MAX_ENTRIES; } } return rc; @@ -402,7 +401,7 @@ static int __cam_isp_ctx_minidump_cb(void *priv, void *args) md->rxd_epoch = atomic_read(&ctx_isp->rxd_epoch); for (i = 0; i < CAM_ISP_CTX_EVENT_MAX; i++) { - memcpy(md->event_record[i], ctx_isp->event_record[i], + memcpy(md->event_record[i], ctx_isp->dbg_monitors.event_record[i], sizeof(struct cam_isp_context_event_record) * CAM_ISP_CTX_EVENT_RECORD_MAX_ENTRIES); } @@ -465,17 +464,18 @@ static void __cam_isp_ctx_update_state_monitor_array( int iterator; struct cam_context *ctx = ctx_isp->base; - INC_HEAD(&ctx_isp->state_monitor_head, + INC_HEAD(&ctx_isp->dbg_monitors.state_monitor_head, CAM_ISP_CTX_STATE_MONITOR_MAX_ENTRIES, &iterator); - ctx_isp->cam_isp_ctx_state_monitor[iterator].curr_state = + ctx_isp->dbg_monitors.state_monitor[iterator].curr_state = ctx_isp->substate_activated; - ctx_isp->cam_isp_ctx_state_monitor[iterator].frame_id = + ctx_isp->dbg_monitors.state_monitor[iterator].frame_id = ctx_isp->frame_id; - ctx_isp->cam_isp_ctx_state_monitor[iterator].trigger = + ctx_isp->dbg_monitors.state_monitor[iterator].trigger = trigger_type; - ctx_isp->cam_isp_ctx_state_monitor[iterator].req_id = + ctx_isp->dbg_monitors.state_monitor[iterator].req_id = req_id; + if (trigger_type == CAM_ISP_STATE_CHANGE_TRIGGER_CDM_DONE) ctx_isp->cam_isp_ctx_state_monitor[iterator].evt_time_stamp = ctx->cdm_done_ts; @@ -484,6 +484,79 @@ static void __cam_isp_ctx_update_state_monitor_array( &ctx_isp->cam_isp_ctx_state_monitor[iterator].evt_time_stamp); } +static int __cam_isp_ctx_update_frame_timing_record( + enum cam_isp_hw_event_type hw_evt, struct cam_isp_context *ctx_isp) +{ + uint32_t index = 0; + + /* Update event index on IFE SOF - primary event */ + if (hw_evt == CAM_ISP_HW_EVENT_SOF) + INC_HEAD(&ctx_isp->dbg_monitors.frame_monitor_head, + CAM_ISP_CTX_MAX_FRAME_RECORDS, &index); + else + div_u64_rem(atomic64_read(&ctx_isp->dbg_monitors.frame_monitor_head), + CAM_ISP_CTX_MAX_FRAME_RECORDS, &index); + + switch (hw_evt) { + case CAM_ISP_HW_EVENT_SOF: + CAM_GET_BOOT_TIMESTAMP(ctx_isp->dbg_monitors.frame_monitor[index].sof_ts); + break; + case CAM_ISP_HW_EVENT_EOF: + CAM_GET_BOOT_TIMESTAMP(ctx_isp->dbg_monitors.frame_monitor[index].eof_ts); + break; + case CAM_ISP_HW_EVENT_EPOCH: + CAM_GET_BOOT_TIMESTAMP(ctx_isp->dbg_monitors.frame_monitor[index].epoch_ts); + break; + case CAM_ISP_HW_SECONDARY_EVENT: + CAM_GET_BOOT_TIMESTAMP(ctx_isp->dbg_monitors.frame_monitor[index].secondary_sof_ts); + break; + default: + break; + } + + return 0; +} + +static void __cam_isp_ctx_dump_frame_timing_record( + struct cam_isp_context *ctx_isp) +{ + int i = 0; + int64_t state_head = 0; + uint32_t index, num_entries, oldest_entry; + + state_head = atomic64_read(&ctx_isp->dbg_monitors.frame_monitor_head); + + if (state_head == -1) + return; + + if (state_head < CAM_ISP_CTX_MAX_FRAME_RECORDS) { + num_entries = state_head + 1; + oldest_entry = 0; + } else { + num_entries = CAM_ISP_CTX_MAX_FRAME_RECORDS; + div_u64_rem(state_head + 1, CAM_ISP_CTX_MAX_FRAME_RECORDS, + &oldest_entry); + } + + index = oldest_entry; + for (i = 0; i < num_entries; i++) { + CAM_INFO(CAM_ISP, + "Index: %u SOF_TS: %llu.%llu EPOCH_TS: %llu.%llu EOF_TS: %llu.%llu SEC_SOF: %llu.%llu", + index, + ctx_isp->dbg_monitors.frame_monitor[index].sof_ts.tv_sec, + ctx_isp->dbg_monitors.frame_monitor[index].sof_ts.tv_nsec / NSEC_PER_USEC, + ctx_isp->dbg_monitors.frame_monitor[index].epoch_ts.tv_sec, + ctx_isp->dbg_monitors.frame_monitor[index].epoch_ts.tv_nsec / NSEC_PER_USEC, + ctx_isp->dbg_monitors.frame_monitor[index].eof_ts.tv_sec, + ctx_isp->dbg_monitors.frame_monitor[index].eof_ts.tv_nsec / NSEC_PER_USEC, + ctx_isp->dbg_monitors.frame_monitor[index].secondary_sof_ts.tv_sec, + ctx_isp->dbg_monitors.frame_monitor[index].secondary_sof_ts.tv_nsec / + NSEC_PER_USEC); + + index = (index + 1) % CAM_ISP_CTX_MAX_FRAME_RECORDS; + } +} + static const char *__cam_isp_ctx_substate_val_to_type( enum cam_isp_ctx_activated_substate type) { @@ -548,17 +621,18 @@ static void __cam_isp_ctx_dump_state_monitor_array( uint32_t index, num_entries, oldest_entry; struct tm ts; - state_head = atomic64_read(&ctx_isp->state_monitor_head); + state_head = atomic64_read(&ctx_isp->dbg_monitors.state_monitor_head); - if (state_head == -1) { + if (state_head == -1) return; - } else if (state_head < CAM_ISP_CTX_STATE_MONITOR_MAX_ENTRIES) { - num_entries = state_head; + + if (state_head < CAM_ISP_CTX_STATE_MONITOR_MAX_ENTRIES) { + num_entries = state_head + 1; oldest_entry = 0; } else { num_entries = CAM_ISP_CTX_STATE_MONITOR_MAX_ENTRIES; - div_u64_rem(state_head + 1, - CAM_ISP_CTX_STATE_MONITOR_MAX_ENTRIES, &oldest_entry); + div_u64_rem(state_head + 1, CAM_ISP_CTX_STATE_MONITOR_MAX_ENTRIES, + &oldest_entry); } CAM_ERR(CAM_ISP, @@ -570,16 +644,15 @@ static void __cam_isp_ctx_dump_state_monitor_array( time64_to_tm(ctx_isp->cam_isp_ctx_state_monitor[index].evt_time_stamp.tv_sec, 0, &ts); CAM_ERR(CAM_ISP, - "Idx[%d] time[%d-%d %d:%d:%d.%lld]:Substate[%s] Frame[%lld] Req[%llu] evt[%s]", - index, - ts.tm_mon + 1, ts.tm_mday, ts.tm_hour, ts.tm_min, ts.tm_sec, - ctx_isp->cam_isp_ctx_state_monitor[index].evt_time_stamp.tv_nsec / 1000000, - __cam_isp_ctx_substate_val_to_type( - ctx_isp->cam_isp_ctx_state_monitor[index].curr_state), - ctx_isp->cam_isp_ctx_state_monitor[index].frame_id, - ctx_isp->cam_isp_ctx_state_monitor[index].req_id, - __cam_isp_hw_evt_val_to_type( - ctx_isp->cam_isp_ctx_state_monitor[index].trigger)); + "Idx[%d] time[%d-%d %d:%d:%d.%lld]:Substate[%s] Frame[%lld] Req[%llu] evt[%s]", + index, ts.tm_mon + 1, ts.tm_mday, ts.tm_hour, ts.tm_min, ts.tm_sec, + ctx_isp->cam_isp_ctx_state_monitor[index].evt_time_stamp.tv_nsec / 1000000, + __cam_isp_ctx_substate_val_to_type( + ctx_isp->cam_isp_ctx_state_monitor[index].curr_state), + ctx_isp->cam_isp_ctx_state_monitor[index].frame_id, + ctx_isp->cam_isp_ctx_state_monitor[index].req_id, + __cam_isp_hw_evt_val_to_type( + ctx_isp->cam_isp_ctx_state_monitor[index].trigger)); index = (index + 1) % CAM_ISP_CTX_STATE_MONITOR_MAX_ENTRIES; } @@ -610,7 +683,7 @@ static int __cam_isp_ctx_user_dump_state_monitor_array( int index; uint32_t oldest_entry; uint32_t num_entries; - uint64_t state_head; + uint64_t state_head = 0; if (!dump_args || !ctx_isp) { CAM_ERR(CAM_ISP, "Invalid args %pK %pK", @@ -618,7 +691,7 @@ static int __cam_isp_ctx_user_dump_state_monitor_array( return -EINVAL; } - state_head = atomic64_read(&ctx_isp->state_monitor_head); + state_head = atomic64_read(&ctx_isp->dbg_monitors.state_monitor_head); if (state_head == -1) { return 0; @@ -638,12 +711,12 @@ static int __cam_isp_ctx_user_dump_state_monitor_array( rc = cam_common_user_dump_helper(dump_args, cam_isp_ctx_user_dump_state_monitor_array_info, - &ctx_isp->cam_isp_ctx_state_monitor[index], + &ctx_isp->dbg_monitors.state_monitor[index], sizeof(uint64_t), "ISP_STATE_MONITOR.%s.%s:", __cam_isp_ctx_substate_val_to_type( - ctx_isp->cam_isp_ctx_state_monitor[index].curr_state), + ctx_isp->dbg_monitors.state_monitor[index].curr_state), __cam_isp_hw_evt_val_to_type( - ctx_isp->cam_isp_ctx_state_monitor[index].trigger)); + ctx_isp->dbg_monitors.state_monitor[index].trigger)); if (rc) { CAM_ERR(CAM_ISP, "CAM ISP CONTEXT: Event record dump failed, rc: %d", rc); @@ -1520,7 +1593,11 @@ static void __cam_isp_ctx_handle_buf_done_fail_log( } } - if (!ctx_isp->sof_dbg_irq_en) + ctx_isp->congestion_cnt++; + + /* Trigger SOF freeze debug dump on 3 or greater instances of congestion */ + if ((ctx_isp->congestion_cnt >= CAM_ISP_CONTEXT_CONGESTION_CNT_MAX) && + (!ctx_isp->sof_dbg_irq_en)) __cam_isp_ctx_handle_sof_freeze_evt(ctx); } @@ -1531,6 +1608,7 @@ static void __cam_isp_context_reset_internal_recovery_params( atomic_set(&ctx_isp->process_bubble, 0); ctx_isp->aeb_error_cnt = 0; ctx_isp->bubble_frame_cnt = 0; + ctx_isp->congestion_cnt = 0; ctx_isp->sof_dbg_irq_en = false; } @@ -3744,6 +3822,8 @@ static int __cam_isp_ctx_handle_error(struct cam_isp_context *ctx_isp, if (!ctx_isp->offline_context) __cam_isp_ctx_pause_crm_timer(ctx); + __cam_isp_ctx_dump_frame_timing_record(ctx_isp); + __cam_isp_ctx_trigger_reg_dump(CAM_HW_MGR_CMD_REG_DUMP_ON_ERROR, ctx); __cam_isp_get_notification_evt_params(error_event_data->error_type, @@ -4162,6 +4242,9 @@ static void __cam_isp_ctx_notify_aeb_error_for_sec_event( /* Change state to HALT, stop further processing of HW events */ ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_HALT; + + /* Dump AEB debug info */ + __cam_isp_ctx_dump_frame_timing_record(ctx_isp); } static int __cam_isp_ctx_trigger_internal_recovery( @@ -4280,6 +4363,8 @@ static int __cam_isp_ctx_handle_secondary_events( CAM_ISP_STATE_CHANGE_TRIGGER_SEC_EVT_SOF, ctx_isp->last_applied_req_id); + __cam_isp_ctx_update_frame_timing_record(CAM_ISP_HW_SECONDARY_EVENT, ctx_isp); + /* Slave RDI's frame starting post IFE EPOCH - Fatal */ if ((ctx_isp->substate_activated == CAM_ISP_CTX_ACTIVATED_APPLIED) || @@ -4696,6 +4781,10 @@ static int __cam_isp_ctx_apply_req_in_activated_state( rc = -EFAULT; goto end; } + + /* Reset congestion counter */ + ctx_isp->congestion_cnt = 0; + req_isp->bubble_report = apply->report_if_bubble; /* @@ -5481,6 +5570,7 @@ static int __cam_isp_ctx_flush_req_in_top_state( end: ctx_isp->bubble_frame_cnt = 0; + ctx_isp->congestion_cnt = 0; ctx_isp->sof_dbg_irq_en = false; atomic_set(&ctx_isp->process_bubble, 0); atomic_set(&ctx_isp->rxd_epoch, 0); @@ -6288,10 +6378,11 @@ static int __cam_isp_ctx_release_hw_in_top_state(struct cam_context *ctx, ctx_isp->vfe_bus_comp_grp = NULL; ctx_isp->sfe_bus_comp_grp = NULL; - atomic64_set(&ctx_isp->state_monitor_head, -1); + atomic64_set(&ctx_isp->dbg_monitors.state_monitor_head, -1); + atomic64_set(&ctx_isp->dbg_monitors.frame_monitor_head, -1); for (i = 0; i < CAM_ISP_CTX_EVENT_MAX; i++) - atomic64_set(&ctx_isp->event_record_head[i], -1); + atomic64_set(&ctx_isp->dbg_monitors.event_record_head[i], -1); /* * Ideally, we should never have any active request here. * But we still add some sanity check code here to help the debug @@ -6366,9 +6457,10 @@ static int __cam_isp_ctx_release_dev_in_top_state(struct cam_context *ctx, ctx_isp->v4l2_event_sub_ids = 0; ctx_isp->resume_hw_in_flushed = false; - atomic64_set(&ctx_isp->state_monitor_head, -1); + atomic64_set(&ctx_isp->dbg_monitors.state_monitor_head, -1); + atomic64_set(&ctx_isp->dbg_monitors.frame_monitor_head, -1); for (i = 0; i < CAM_ISP_CTX_EVENT_MAX; i++) - atomic64_set(&ctx_isp->event_record_head[i], -1); + atomic64_set(&ctx_isp->dbg_monitors.event_record_head[i], -1); /* * Ideally, we should never have any active request here. * But we still add some sanity check code here to help the debug @@ -6862,9 +6954,10 @@ static int __cam_isp_ctx_acquire_dev_in_available(struct cam_context *ctx, ctx_isp->hw_acquired = true; ctx_isp->split_acquire = false; ctx->ctxt_to_hw_map = param.ctxt_to_hw_map; - atomic64_set(&ctx_isp->state_monitor_head, -1); + atomic64_set(&ctx_isp->dbg_monitors.state_monitor_head, -1); + atomic64_set(&ctx_isp->dbg_monitors.frame_monitor_head, -1); for (i = 0; i < CAM_ISP_CTX_EVENT_MAX; i++) - atomic64_set(&ctx_isp->event_record_head[i], -1); + atomic64_set(&ctx_isp->dbg_monitors.event_record_head[i], -1); CAM_INFO(CAM_ISP, "Ctx_type: %u, ctx_id: %u, hw_mgr_ctx: %u", isp_hw_cmd_args.u.ctx_type, ctx->ctx_id, param.hw_mgr_ctx_id); @@ -7052,10 +7145,11 @@ static int __cam_isp_ctx_acquire_hw_v1(struct cam_context *ctx, ctx_isp->hw_acquired = true; ctx->ctxt_to_hw_map = param.ctxt_to_hw_map; - atomic64_set(&ctx_isp->state_monitor_head, -1); + atomic64_set(&ctx_isp->dbg_monitors.state_monitor_head, -1); + atomic64_set(&ctx_isp->dbg_monitors.frame_monitor_head, -1); for (i = 0; i < CAM_ISP_CTX_EVENT_MAX; i++) - atomic64_set(&ctx_isp->event_record_head[i], -1); + atomic64_set(&ctx_isp->dbg_monitors.event_record_head[i], -1); trace_cam_context_state("ISP", ctx); CAM_INFO(CAM_ISP, @@ -7530,6 +7624,7 @@ static inline void __cam_isp_context_reset_ctx_params( ctx_isp->reported_req_id = 0; ctx_isp->reported_frame_id = 0; ctx_isp->bubble_frame_cnt = 0; + ctx_isp->congestion_cnt = 0; ctx_isp->recovery_req_id = 0; ctx_isp->aeb_error_cnt = 0; ctx_isp->out_of_sync_cnt = 0; @@ -7598,10 +7693,11 @@ static int __cam_isp_ctx_start_dev_in_ready(struct cam_context *ctx, (req_isp->num_fence_map_out) ? CAM_ISP_CTX_ACTIVATED_EPOCH : CAM_ISP_CTX_ACTIVATED_SOF; - atomic64_set(&ctx_isp->state_monitor_head, -1); + atomic64_set(&ctx_isp->dbg_monitors.state_monitor_head, -1); + atomic64_set(&ctx_isp->dbg_monitors.frame_monitor_head, -1); for (i = 0; i < CAM_ISP_CTX_EVENT_MAX; i++) - atomic64_set(&ctx_isp->event_record_head[i], -1); + atomic64_set(&ctx_isp->dbg_monitors.event_record_head[i], -1); /* * In case of CSID TPG we might receive SOF and RUP IRQs @@ -7777,14 +7873,16 @@ static int __cam_isp_ctx_stop_dev_in_activated_unlock( ctx_isp->last_applied_req_id = 0; ctx_isp->req_info.last_bufdone_req_id = 0; ctx_isp->bubble_frame_cnt = 0; + ctx_isp->congestion_cnt = 0; ctx_isp->sof_dbg_irq_en = false; atomic_set(&ctx_isp->process_bubble, 0); atomic_set(&ctx_isp->internal_recovery_set, 0); atomic_set(&ctx_isp->rxd_epoch, 0); - atomic64_set(&ctx_isp->state_monitor_head, -1); + atomic64_set(&ctx_isp->dbg_monitors.state_monitor_head, -1); + atomic64_set(&ctx_isp->dbg_monitors.frame_monitor_head, -1); for (i = 0; i < CAM_ISP_CTX_EVENT_MAX; i++) - atomic64_set(&ctx_isp->event_record_head[i], -1); + atomic64_set(&ctx_isp->dbg_monitors.event_record_head[i], -1); CAM_DBG(CAM_ISP, "Stop device success next state %d on ctx %u link: 0x%x", ctx->state, ctx->ctx_id, ctx->link_hdl); @@ -8279,7 +8377,12 @@ static int __cam_isp_ctx_handle_irq_in_activated(void *context, __cam_isp_ctx_dump_state_monitor_array(ctx_isp); } - CAM_DBG(CAM_ISP, "Exit: State %d Substate[%s], ctx:%u link: 0x%x", + if ((evt_id == CAM_ISP_HW_EVENT_SOF) || + (evt_id == CAM_ISP_HW_EVENT_EOF) || + (evt_id == CAM_ISP_HW_EVENT_EPOCH)) + __cam_isp_ctx_update_frame_timing_record(evt_id, ctx_isp); + + CAM_DBG(CAM_ISP, "Exit: State %d Substate[%s] on ctx: %d", ctx->state, __cam_isp_ctx_substate_val_to_type( ctx_isp->substate_activated), ctx->ctx_id, ctx->link_hdl); @@ -8675,6 +8778,7 @@ int cam_isp_context_init(struct cam_isp_context *ctx, ctx->active_req_cnt = 0; ctx->reported_req_id = 0; ctx->bubble_frame_cnt = 0; + ctx->congestion_cnt = 0; ctx->req_info.last_bufdone_req_id = 0; ctx->v4l2_event_sub_ids = 0; @@ -8705,13 +8809,15 @@ int cam_isp_context_init(struct cam_isp_context *ctx, /* initializing current state for error logging */ for (i = 0; i < CAM_ISP_CTX_STATE_MONITOR_MAX_ENTRIES; i++) { - ctx->cam_isp_ctx_state_monitor[i].curr_state = + ctx->dbg_monitors.state_monitor[i].curr_state = CAM_ISP_CTX_ACTIVATED_MAX; } - atomic64_set(&ctx->state_monitor_head, -1); + atomic64_set(&ctx->dbg_monitors.state_monitor_head, -1); for (i = 0; i < CAM_ISP_CTX_EVENT_MAX; i++) - atomic64_set(&ctx->event_record_head[i], -1); + atomic64_set(&ctx->dbg_monitors.event_record_head[i], -1); + + atomic64_set(&ctx->dbg_monitors.frame_monitor_head, -1); if (!isp_ctx_debug.dentry) cam_isp_context_debug_register(); diff --git a/drivers/cam_isp/cam_isp_context.h b/drivers/cam_isp/cam_isp_context.h index d3eb185ba9..653538efda 100644 --- a/drivers/cam_isp/cam_isp_context.h +++ b/drivers/cam_isp/cam_isp_context.h @@ -62,6 +62,15 @@ /* Debug Buffer length*/ #define CAM_ISP_CONTEXT_DBG_BUF_LEN 300 +/* Maximum entries in frame record */ +#define CAM_ISP_CTX_MAX_FRAME_RECORDS 5 + + +/* + * Congestion count threshold + */ +#define CAM_ISP_CONTEXT_CONGESTION_CNT_MAX 3 + /* forward declaration */ struct cam_isp_context; @@ -243,6 +252,56 @@ struct cam_isp_context_event_record { ktime_t timestamp; }; +/** + * + * + * struct cam_isp_context_frame_timing_record - Frame timing events + * + * @sof_ts: SOF timestamp + * @eof_ts: EOF ts + * @epoch_ts: EPOCH ts + * @secondary_sof_ts: Secondary SOF ts + * + */ +struct cam_isp_context_frame_timing_record { + struct timespec64 sof_ts; + struct timespec64 eof_ts; + struct timespec64 epoch_ts; + struct timespec64 secondary_sof_ts; +}; + + +/** + * + * + * struct cam_isp_context_debug_monitors - ISP context debug monitors + * + * @state_monitor_head: State machine monitor head + * @state_monitor: State machine monitor info + * @event_record_head: Request Event monitor head + * @event_record: Request event monitor info + * @frame_monitor_head: Frame timing monitor head + * @frame_monitor: Frame timing event monitor + * + */ +struct cam_isp_context_debug_monitors { + /* State machine monitoring */ + atomic64_t state_monitor_head; + struct cam_isp_context_state_monitor state_monitor[ + CAM_ISP_CTX_STATE_MONITOR_MAX_ENTRIES]; + + /* Req event monitor */ + atomic64_t event_record_head[ + CAM_ISP_CTX_EVENT_MAX]; + struct cam_isp_context_event_record event_record[ + CAM_ISP_CTX_EVENT_MAX][CAM_ISP_CTX_EVENT_RECORD_MAX_ENTRIES]; + + /* Frame timing monitor */ + atomic64_t frame_monitor_head; + struct cam_isp_context_frame_timing_record frame_monitor[ + CAM_ISP_CTX_MAX_FRAME_RECORDS]; +}; + /** * struct cam_isp_context - ISP context object * @@ -271,11 +330,11 @@ struct cam_isp_context_event_record { * @aeb_error_cnt: Count number of times a specific AEB error scenario is * enountered * @out_of_sync_cnt: Out of sync error count for AEB + * @congestion_cnt: Count number of times congestion was encountered + * consecutively * @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 - * @event_record_head: Write index to the state monitoring array - * @event_record: Event record array + * @dbg_monitors: Debug monitors for ISP context * @rdi_only_context: Get context type information. * true, if context is rdi only context * @offline_context: Indicate whether context is for offline IFE @@ -341,14 +400,12 @@ struct cam_isp_context { uint32_t bubble_frame_cnt; uint32_t aeb_error_cnt; uint32_t out_of_sync_cnt; + uint32_t congestion_cnt; atomic64_t state_monitor_head; struct cam_isp_context_state_monitor cam_isp_ctx_state_monitor[ CAM_ISP_CTX_STATE_MONITOR_MAX_ENTRIES]; struct cam_isp_context_req_id_info req_info; - atomic64_t event_record_head[ - CAM_ISP_CTX_EVENT_MAX]; - struct cam_isp_context_event_record event_record[ - CAM_ISP_CTX_EVENT_MAX][CAM_ISP_CTX_EVENT_RECORD_MAX_ENTRIES]; + struct cam_isp_context_debug_monitors dbg_monitors; bool rdi_only_context; bool offline_context; bool vfps_aux_context; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_hw_ver2.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_hw_ver2.c index 028f015692..626bb2785c 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_hw_ver2.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_hw_ver2.c @@ -113,6 +113,24 @@ static bool cam_ife_csid_ver2_disable_sof_retime( return false; } +static uint64_t __cam_ife_csid_ver2_get_time_stamp(void __iomem *mem_base, + uint32_t timestamp0_addr, uint32_t timestamp1_addr, + bool ts_comb_vcdt_en, uint32_t ts_comb_vcdt_mask) +{ + uint64_t timestamp_val, time_hi, time_lo; + + time_hi = cam_io_r_mb(mem_base + timestamp1_addr); + time_lo = cam_io_r_mb(mem_base + timestamp0_addr); + if (ts_comb_vcdt_en) + time_lo &= ~ts_comb_vcdt_mask; + + timestamp_val = (time_hi << 32) | time_lo; + + return mul_u64_u32_div(timestamp_val, + CAM_IFE_CSID_QTIMER_MUL_FACTOR, + CAM_IFE_CSID_QTIMER_DIV_FACTOR); +} + static void cam_ife_csid_ver2_print_camif_timestamps( struct cam_ife_csid_ver2_hw *csid_hw) { @@ -120,6 +138,10 @@ static void cam_ife_csid_ver2_print_camif_timestamps( struct cam_isp_resource_node *res; bool found = false; int i; + struct cam_hw_soc_info *soc_info = &csid_hw->hw_info->soc_info; + const struct cam_ife_csid_ver2_path_reg_info *path_reg; + struct cam_ife_csid_ver2_reg_info *csid_reg = + (struct cam_ife_csid_ver2_reg_info *)csid_hw->core_info->csid_reg; for (i = CAM_IFE_PIX_PATH_RES_RDI_0; i < CAM_IFE_PIX_PATH_RES_MAX; i++) { res = &csid_hw->path_res[i]; @@ -148,13 +170,50 @@ static void cam_ife_csid_ver2_print_camif_timestamps( break; } - if (found && path_cfg) + + if (found && path_cfg) { + path_reg = csid_reg->path_reg[res->res_id]; + CAM_INFO(CAM_ISP, - "CSID[%u] %s SOF timestamp:[%lld.%09lld] EPOCH timestamp:[%lld.%09lld] EOF timestamp:[%lld.%09lld]", + "CSID[%u] %s SOF[%lld:%lld] EPOCH[%lld:%lld] EOF[%lld:%lld]", csid_hw->hw_intf->hw_idx, res->res_name, path_cfg->sof_ts.tv_sec, path_cfg->sof_ts.tv_nsec, path_cfg->epoch_ts.tv_sec, path_cfg->epoch_ts.tv_nsec, path_cfg->eof_ts.tv_sec, path_cfg->eof_ts.tv_nsec); + + if (!path_reg) { + CAM_ERR(CAM_ISP, "CSID:%d no path registers for res :%d", + csid_hw->hw_intf->hw_idx, res->res_id); + return; + } + + CAM_INFO(CAM_ISP, + "qtimer current [SOF: 0x%llx EOF: 0x%llx] prev [SOF: 0x%llx EOF: 0x%llx]", + __cam_ife_csid_ver2_get_time_stamp( + soc_info->reg_map[0].mem_base, + path_reg->timestamp_curr0_sof_addr, + path_reg->timestamp_curr1_sof_addr, + path_cfg->ts_comb_vcdt_en, + csid_reg->cmn_reg->ts_comb_vcdt_mask), + __cam_ife_csid_ver2_get_time_stamp( + soc_info->reg_map[0].mem_base, + path_reg->timestamp_curr0_eof_addr, + path_reg->timestamp_curr1_eof_addr, + path_cfg->ts_comb_vcdt_en, + csid_reg->cmn_reg->ts_comb_vcdt_mask), + __cam_ife_csid_ver2_get_time_stamp( + soc_info->reg_map[0].mem_base, + path_reg->timestamp_perv0_sof_addr, + path_reg->timestamp_perv1_sof_addr, + path_cfg->ts_comb_vcdt_en, + csid_reg->cmn_reg->ts_comb_vcdt_mask), + __cam_ife_csid_ver2_get_time_stamp( + soc_info->reg_map[0].mem_base, + path_reg->timestamp_perv0_eof_addr, + path_reg->timestamp_perv1_eof_addr, + path_cfg->ts_comb_vcdt_en, + csid_reg->cmn_reg->ts_comb_vcdt_mask)); + } } static void cam_ife_csid_ver2_update_event_ts( @@ -5803,25 +5862,6 @@ static int cam_ife_csid_ver2_program_offline_go_cmd( return 0; } -static uint64_t __cam_ife_csid_ver2_get_time_stamp(void __iomem *mem_base, - uint32_t timestamp0_addr, uint32_t timestamp1_addr, - bool ts_comb_vcdt_en, uint32_t ts_comb_vcdt_mask) -{ - uint64_t timestamp_val, time_hi, time_lo, mask; - - time_hi = cam_io_r_mb(mem_base + timestamp1_addr); - time_lo = cam_io_r_mb(mem_base + timestamp0_addr); - mask = (uint64_t)ts_comb_vcdt_mask; - if (ts_comb_vcdt_en) - time_lo &= ~mask; - - timestamp_val = (time_hi << 32) | time_lo; - - return mul_u64_u32_div(timestamp_val, - CAM_IFE_CSID_QTIMER_MUL_FACTOR, - CAM_IFE_CSID_QTIMER_DIV_FACTOR); -} - static int cam_ife_csid_ver2_get_time_stamp( struct cam_ife_csid_ver2_hw *csid_hw, void *cmd_args) { diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c index 9ecb5eac7b..83e8aa3f39 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c @@ -2446,7 +2446,7 @@ static void cam_vfe_bus_ver3_print_wm_info( struct cam_vfe_bus_ver3_common_data *common_data, uint8_t *wm_name) { - uint32_t addr_status0, addr_status1, addr_status2, addr_status3; + uint32_t addr_status0, addr_status1, addr_status2, addr_status3, limiter; addr_status0 = cam_io_r_mb(common_data->mem_base + wm_data->hw_regs->addr_status_0); @@ -2456,6 +2456,8 @@ static void cam_vfe_bus_ver3_print_wm_info( wm_data->hw_regs->addr_status_2); addr_status3 = cam_io_r_mb(common_data->mem_base + wm_data->hw_regs->addr_status_3); + limiter = cam_io_r_mb(common_data->mem_base + + wm_data->hw_regs->bw_limiter_addr); CAM_INFO(CAM_ISP, "VFE:%u WM:%d wm_name:%s width:%u height:%u stride:%u x_init:%u en_cfg:%u acquired width:%u height:%u", @@ -2467,13 +2469,9 @@ static void cam_vfe_bus_ver3_print_wm_info( wm_data->acquired_width, wm_data->acquired_height); CAM_INFO(CAM_ISP, - "hw:%u WM:%d last consumed address:0x%x last frame addr:0x%x fifo cnt:0x%x current client address:0x%x", - common_data->hw_intf->hw_idx, - wm_data->index, - addr_status0, - addr_status1, - addr_status2, - addr_status3); + "VFE:%u WM:%u last consumed address:0x%x last frame addr:0x%x fifo cnt:0x%x current client address:0x%x limiter: 0x%x", + common_data->hw_intf->hw_idx, wm_data->index, + addr_status0, addr_status1, addr_status2, addr_status3, limiter); } static int cam_vfe_bus_ver3_print_dimensions( diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver4.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver4.c index fb04127bda..cff8603674 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver4.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver4.c @@ -503,8 +503,9 @@ int cam_vfe_top_ver4_dump_timestamps( ktime_get_boottime_ts64(&ts); CAM_INFO(CAM_ISP, - "VFE[%u] current monotonic timestamp:[%lld.%09lld]", - vfe_priv->hw_intf->hw_idx, ts.tv_sec, ts.tv_nsec); + "VFE[%u] res: %u current_ts: %lld:%lld epoch_factor: %u%%", + vfe_priv->hw_intf->hw_idx, res_id, ts.tv_sec, ts.tv_nsec, + vfe_priv->epoch_factor); CAM_INFO(CAM_ISP, "VFE[%u] CAMIF Error timestamp:[%lld.%09lld] SOF timestamp:[%lld.%09lld] EPOCH timestamp:[%lld.%09lld] EOF timestamp:[%lld.%09lld]", diff --git a/drivers/cam_utils/cam_common_util.h b/drivers/cam_utils/cam_common_util.h index b87dfa180b..1f4c0f4c53 100644 --- a/drivers/cam_utils/cam_common_util.h +++ b/drivers/cam_utils/cam_common_util.h @@ -38,6 +38,7 @@ #define CAM_TRIGGER_PANIC(format, args...) panic("CAMERA - " format "\n", ##args) +#define CAM_GET_BOOT_TIMESTAMP(timestamp) ktime_get_boottime_ts64(&(timestamp)) #define CAM_GET_TIMESTAMP(timestamp) ktime_get_real_ts64(&(timestamp)) #define CAM_GET_TIMESTAMP_DIFF_IN_MICRO(ts_start, ts_end, diff_microsec) \ ({ \