Loading drivers/media/platform/msm/camera/cam_cdm/cam_cdm_util.c +148 −1 Original line number Diff line number Diff line /* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. /* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -714,3 +714,150 @@ void cam_cdm_util_dump_cmd_buf( } } while (buf_now <= cmd_buf_end); } static long cam_cdm_util_dump_reg_cont_cmd_v2( uint32_t *cmd_buf_addr, struct cam_cdm_cmd_buf_dump_info *dump_info) { long ret = 0; struct cdm_regcontinuous_cmd *p_regcont_cmd; uint32_t *temp_ptr = cmd_buf_addr; int i = 0; struct cam_cdm_cmd_dump_header *hdr; uint32_t *addr, *start; uint8_t *dst; uint32_t min_len, remain_len; p_regcont_cmd = (struct cdm_regcontinuous_cmd *)temp_ptr; temp_ptr += CDMCmdHeaderSizes[CAM_CDM_CMD_REG_CONT]; ret += CDMCmdHeaderSizes[CAM_CDM_CMD_REG_CONT]; CAM_DBG(CAM_CDM, "REG_CONT: COUNT: %u OFFSET: 0x%X", p_regcont_cmd->count, p_regcont_cmd->offset); min_len = (sizeof(uint32_t) * p_regcont_cmd->count) + sizeof(struct cam_cdm_cmd_dump_header); remain_len = dump_info->dst_max_size - dump_info->dst_offset; if (remain_len < min_len) { CAM_ERR_RATE_LIMIT(CAM_CDM, "Dump buffer exhaust %d %d", remain_len, min_len); return ret; } dst = (char *)dump_info->dst_start + dump_info->dst_offset; hdr = (struct cam_cdm_cmd_dump_header *)dst; snprintf(hdr->tag, CAM_CDM_CMD_TAG_MAX_LEN, "CDM_REG_CONT:"); hdr->word_size = sizeof(uint32_t); addr = (uint32_t *)(dst + sizeof(struct cam_cdm_cmd_dump_header)); start = addr; *addr++ = p_regcont_cmd->offset; *addr++ = p_regcont_cmd->count; for (i = 0; i < p_regcont_cmd->count; i++) { *addr = *temp_ptr; temp_ptr++; addr++; ret++; } hdr->size = hdr->word_size * (addr - start); dump_info->dst_offset += hdr->size + sizeof(struct cam_cdm_cmd_dump_header); return ret; } static long cam_cdm_util_dump_reg_random_cmd_v2( uint32_t *cmd_buf_addr, struct cam_cdm_cmd_buf_dump_info *dump_info) { struct cdm_regrandom_cmd *p_regrand_cmd; uint32_t *temp_ptr = cmd_buf_addr; long ret = 0; int i = 0; uint32_t *addr, *start; struct cam_cdm_cmd_dump_header *hdr; uint8_t *dst; uint32_t min_len, remain_len; p_regrand_cmd = (struct cdm_regrandom_cmd *)temp_ptr; temp_ptr += CDMCmdHeaderSizes[CAM_CDM_CMD_REG_RANDOM]; ret += CDMCmdHeaderSizes[CAM_CDM_CMD_REG_RANDOM]; min_len = (2 * sizeof(uint32_t) * p_regrand_cmd->count) + sizeof(struct cam_cdm_cmd_dump_header); remain_len = dump_info->dst_max_size - dump_info->dst_offset; if (remain_len < min_len) { CAM_ERR_RATE_LIMIT(CAM_CDM, "Dump buffer exhaust %d %d", remain_len, min_len); return ret; } dst = (char *)dump_info->dst_start + dump_info->dst_offset; hdr = (struct cam_cdm_cmd_dump_header *)dst; snprintf(hdr->tag, CAM_CDM_CMD_TAG_MAX_LEN, "CDM_REG_RANDOM:"); hdr->word_size = sizeof(uint32_t); addr = (uint32_t *)(dst + sizeof(struct cam_cdm_cmd_dump_header)); start = addr; *addr++ = p_regrand_cmd->count; for (i = 0; i < p_regrand_cmd->count; i++) { addr[0] = temp_ptr[0] & CAM_CDM_REG_OFFSET_MASK; addr[1] = temp_ptr[1]; temp_ptr += 2; addr += 2; ret += 2; } hdr->size = hdr->word_size * (addr - start); dump_info->dst_offset += hdr->size + sizeof(struct cam_cdm_cmd_dump_header); return ret; } void cam_cdm_util_dump_cmd_bufs_v2( struct cam_cdm_cmd_buf_dump_info *dump_info) { uint32_t cmd = 0; uint32_t *buf_now; if (!dump_info || !dump_info->src_start || !dump_info->src_end || !dump_info->dst_start) { CAM_INFO(CAM_CDM, "Invalid args"); return; } buf_now = dump_info->src_start; do { cmd = *dump_info->src_start; cmd = cmd >> CAM_CDM_COMMAND_OFFSET; switch (cmd) { case CAM_CDM_CMD_DMI: case CAM_CDM_CMD_DMI_32: case CAM_CDM_CMD_DMI_64: buf_now += CDMCmdHeaderSizes[CAM_CDM_CMD_DMI]; break; case CAM_CDM_CMD_REG_CONT: buf_now += cam_cdm_util_dump_reg_cont_cmd_v2(buf_now, dump_info); break; case CAM_CDM_CMD_REG_RANDOM: buf_now += cam_cdm_util_dump_reg_random_cmd_v2(buf_now, dump_info); break; case CAM_CDM_CMD_BUFF_INDIRECT: buf_now += CDMCmdHeaderSizes[CAM_CDM_CMD_BUFF_INDIRECT]; break; case CAM_CDM_CMD_GEN_IRQ: buf_now += CDMCmdHeaderSizes[CAM_CDM_CMD_GEN_IRQ]; break; case CAM_CDM_CMD_WAIT_EVENT: buf_now += CDMCmdHeaderSizes[CAM_CDM_CMD_WAIT_EVENT]; break; case CAM_CDM_CMD_CHANGE_BASE: buf_now += CDMCmdHeaderSizes[CAM_CDM_CMD_CHANGE_BASE]; break; case CAM_CDM_CMD_PERF_CTRL: buf_now += CDMCmdHeaderSizes[CAM_CDM_CMD_PERF_CTRL]; break; default: CAM_INFO(CAM_CDM, "Invalid CMD: 0x%x buf 0x%x", cmd, *buf_now); buf_now++; break; } } while (buf_now <= dump_info->src_end); } drivers/media/platform/msm/camera/cam_cdm/cam_cdm_util.h +43 −1 Original line number Diff line number Diff line /* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. /* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading @@ -13,6 +13,9 @@ #ifndef _CAM_CDM_UTIL_H_ #define _CAM_CDM_UTIL_H_ /* Max len for tag name for header while dumping cmd buffer*/ #define CAM_CDM_CMD_TAG_MAX_LEN 32 enum cam_cdm_command { CAM_CDM_CMD_UNUSED = 0x0, CAM_CDM_CMD_DMI = 0x1, Loading Loading @@ -151,6 +154,34 @@ void (*cdm_write_genirq)( uint32_t userdata); }; /** * struct cam_cdm_cmd_buf_dump_info; - Camera CDM dump info * @src_start: source start address * @src_end: source end address * @dst_start: dst start address * @dst_offset: dst offset * @dst_max_size max size of destination buffer */ struct cam_cdm_cmd_buf_dump_info { uint32_t *src_start; uint32_t *src_end; uintptr_t dst_start; uint32_t dst_offset; uint32_t dst_max_size; }; /** * struct cam_cdm_cmd_dump_header- Camera CDM dump header * @tag: tag name for header * @size: size of data * @word_size: size of each word */ struct cam_cdm_cmd_dump_header { char tag[CAM_CDM_CMD_TAG_MAX_LEN]; uint64_t size; uint32_t word_size; }; /** * cam_cdm_util_log_cmd_bufs() * Loading @@ -163,6 +194,17 @@ void (*cdm_write_genirq)( void cam_cdm_util_dump_cmd_buf( uint32_t *cmd_buffer_start, uint32_t *cmd_buffer_end); /** * cam_cdm_util_dump_cmd_bufs_v2() * * @brief: Util function to log cdm command buffers * to a buffer * * @dump_info: Information about source and destination buffers * */ void cam_cdm_util_dump_cmd_bufs_v2( struct cam_cdm_cmd_buf_dump_info *dump_info); #endif /* _CAM_CDM_UTIL_H_ */ drivers/media/platform/msm/camera/cam_isp/cam_isp_context.c +331 −13 Original line number Diff line number Diff line Loading @@ -29,13 +29,123 @@ static const char isp_dev_name[] = "cam-isp"; #define INC_STATE_MONITOR_HEAD(head) \ #define INC_HEAD(head, max_entries) \ (atomic64_add_return(1, head) % \ CAM_ISP_CTX_STATE_MONITOR_MAX_ENTRIES) max_entries) static int cam_isp_context_dump_active_request(void *data, unsigned long iova, uint32_t buf_info); static const char *__cam_isp_evt_val_to_type( uint32_t evt_id) { switch (evt_id) { case CAM_ISP_CTX_EVENT_SUBMIT: return "SUBMIT"; case CAM_ISP_CTX_EVENT_APPLY: return "APPLY"; case CAM_ISP_CTX_EVENT_EPOCH: return "EPOCH"; case CAM_ISP_CTX_EVENT_RUP: return "RUP"; case CAM_ISP_CTX_EVENT_BUFDONE: return "BUFDONE"; default: return "CAM_ISP_EVENT_INVALID"; } } static void __cam_isp_ctx_update_event_record( struct cam_isp_context *ctx_isp, enum cam_isp_ctx_event event, struct cam_ctx_request *req) { int iterator = 0; struct cam_isp_ctx_req *req_isp; struct timeval cur_time; switch (event) { case CAM_ISP_CTX_EVENT_EPOCH: case CAM_ISP_CTX_EVENT_RUP: case CAM_ISP_CTX_EVENT_BUFDONE: break; case CAM_ISP_CTX_EVENT_SUBMIT: case CAM_ISP_CTX_EVENT_APPLY: if (!req) { CAM_ERR(CAM_ISP, "Invalid arg for event %d", event); return; } break; default: break; } iterator = INC_HEAD(&ctx_isp->event_record_head[event], CAM_ISP_CTX_EVENT_RECORD_MAX_ENTRIES); cam_common_util_get_curr_timestamp(&cur_time); if (req) { req_isp = (struct cam_isp_ctx_req *) req->req_priv; ctx_isp->event_record[event][iterator].req_id = req->request_id; req_isp->event_timestamp[event].tv_sec = cur_time.tv_sec; req_isp->event_timestamp[event].tv_usec = cur_time.tv_usec; } else { ctx_isp->event_record[event][iterator].req_id = 0; } ctx_isp->event_record[event][iterator].timestamp.tv_sec = cur_time.tv_sec; ctx_isp->event_record[event][iterator].timestamp.tv_usec = cur_time.tv_usec; } static void __cam_isp_ctx_dump_event_record( struct cam_isp_context *ctx_isp, uintptr_t cpu_addr, size_t buf_len, uint32_t *offset) { int i, j; struct cam_isp_context_event_record *record; int index; uint64_t state_head; struct cam_isp_context_dump_header *hdr; uint64_t *addr, *start; uint8_t *dst; if (!cpu_addr || !buf_len || !offset) { CAM_ERR(CAM_ISP, "Invalid args"); return; } for (i = 0; i < CAM_ISP_CTX_EVENT_MAX; i++) { state_head = atomic64_read(&ctx_isp->event_record_head[i]); dst = (char *)cpu_addr + *offset; hdr = (struct cam_isp_context_dump_header *)dst; snprintf(hdr->tag, CAM_ISP_CONTEXT_DUMP_TAG_MAX_LEN, "ISP_EVT_%s:", __cam_isp_evt_val_to_type(i)); hdr->word_size = sizeof(uint64_t); addr = (uint64_t *)(dst + sizeof(struct cam_isp_context_dump_header)); start = addr; for (j = CAM_ISP_CTX_EVENT_RECORD_MAX_ENTRIES - 1; j >= 0; j--) { index = (((state_head - j) + CAM_ISP_CTX_EVENT_RECORD_MAX_ENTRIES) % CAM_ISP_CTX_EVENT_RECORD_MAX_ENTRIES); record = &ctx_isp->event_record[i][index]; *addr++ = record->req_id; *addr++ = record->timestamp.tv_sec; *addr++ = record->timestamp.tv_usec; } hdr->size = hdr->word_size * (addr - start); *offset += hdr->size + sizeof(struct cam_isp_context_dump_header); } } static void __cam_isp_ctx_update_state_monitor_array( struct cam_isp_context *ctx_isp, enum cam_isp_hw_event_type hw_event, Loading @@ -44,7 +154,8 @@ static void __cam_isp_ctx_update_state_monitor_array( { int iterator = 0; iterator = INC_STATE_MONITOR_HEAD(&ctx_isp->state_monitor_head); iterator = INC_HEAD(&ctx_isp->state_monitor_head, CAM_ISP_CTX_STATE_MONITOR_MAX_ENTRIES); ctx_isp->cam_isp_ctx_state_monitor[iterator].curr_state = curr_state; ctx_isp->cam_isp_ctx_state_monitor[iterator].next_state = Loading Loading @@ -160,7 +271,11 @@ static void __cam_isp_ctx_dump_state_monitor_array( } } static void cam_isp_ctx_dump_req(struct cam_isp_ctx_req *req_isp) static void cam_isp_ctx_dump_req(struct cam_isp_ctx_req *req_isp, uintptr_t cpu_addr, size_t buf_len, uint32_t *offset, bool dump_to_buff) { int i = 0, rc = 0; size_t len = 0; Loading @@ -168,6 +283,7 @@ static void cam_isp_ctx_dump_req(struct cam_isp_ctx_req *req_isp) uint32_t *buf_start, *buf_end; size_t remain_len = 0; bool need_put = false; struct cam_cdm_cmd_buf_dump_info dump_info; for (i = 0; i < req_isp->num_cfg; i++) { rc = cam_packet_util_get_cmd_mem_addr( Loading Loading @@ -202,7 +318,21 @@ static void cam_isp_ctx_dump_req(struct cam_isp_ctx_req *req_isp) req_isp->cfg[i].offset); buf_end = (uint32_t *)((uint8_t *) buf_start + req_isp->cfg[i].len - 1); if (dump_to_buff) { if (!cpu_addr || !offset || !buf_len) { CAM_ERR(CAM_ISP, "Invalid args"); break; } dump_info.src_start = buf_start; dump_info.src_end = buf_end; dump_info.dst_start = cpu_addr; dump_info.dst_offset = *offset; dump_info.dst_max_size = buf_len; cam_cdm_util_dump_cmd_bufs_v2(&dump_info); *offset = dump_info.dst_offset; } else { cam_cdm_util_dump_cmd_buf(buf_start, buf_end); } if (cam_mem_put_cpu_buf(req_isp->cfg[i].handle)) CAM_WARN(CAM_ISP, "Failed to put cpu buf: 0x%x", req_isp->cfg[i].handle); Loading @@ -216,6 +346,7 @@ static int __cam_isp_ctx_enqueue_request_in_order( struct cam_ctx_request *req_current; struct cam_ctx_request *req_prev; struct list_head temp_list; struct cam_isp_context *ctx_isp; INIT_LIST_HEAD(&temp_list); spin_lock_bh(&ctx->lock); Loading Loading @@ -246,6 +377,9 @@ static int __cam_isp_ctx_enqueue_request_in_order( } } } ctx_isp = (struct cam_isp_context *) ctx->ctx_priv; __cam_isp_ctx_update_event_record(ctx_isp, CAM_ISP_CTX_EVENT_SUBMIT, req); spin_unlock_bh(&ctx->lock); return 0; } Loading Loading @@ -490,7 +624,6 @@ static int __cam_isp_ctx_handle_buf_done_in_activated_state( req_isp->fence_map_out[j].resource_handle, req_isp->fence_map_out[j].sync_id, ctx->ctx_id); rc = cam_sync_signal(req_isp->fence_map_out[j].sync_id, CAM_SYNC_STATE_SIGNALED_SUCCESS); if (rc) Loading Loading @@ -560,6 +693,8 @@ static int __cam_isp_ctx_handle_buf_done_in_activated_state( CAM_ISP_HW_EVENT_DONE, ctx_isp->substate_activated, ctx_isp->substate_activated); __cam_isp_ctx_update_event_record(ctx_isp, CAM_ISP_CTX_EVENT_BUFDONE, req); } else { list_del_init(&req->list); list_add_tail(&req->list, &ctx->free_req_list); Loading @@ -574,6 +709,8 @@ static int __cam_isp_ctx_handle_buf_done_in_activated_state( CAM_ISP_HW_EVENT_DONE, ctx_isp->substate_activated, ctx_isp->substate_activated); __cam_isp_ctx_update_event_record(ctx_isp, CAM_ISP_CTX_EVENT_BUFDONE, req); } if (ctx_isp->active_req_cnt && ctx_isp->irq_delay_detect) { Loading Loading @@ -742,6 +879,10 @@ static int __cam_isp_ctx_reg_upd_in_activated_state( 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); Loading Loading @@ -776,7 +917,7 @@ static int __cam_isp_ctx_notify_sof_in_activated_state( int rc = 0; struct cam_req_mgr_trigger_notify notify; struct cam_context *ctx = ctx_isp->base; struct cam_ctx_request *req; struct cam_ctx_request *req = NULL; uint64_t request_id = 0; /* Loading Loading @@ -807,6 +948,8 @@ static int __cam_isp_ctx_notify_sof_in_activated_state( ctx_isp->req_info.reported_req_id = request_id; ctx_isp->req_info.last_reported_id_time_stamp = jiffies_to_msecs(jiffies); __cam_isp_ctx_update_event_record(ctx_isp, CAM_ISP_CTX_EVENT_EPOCH, req); break; } } Loading Loading @@ -973,6 +1116,8 @@ static int __cam_isp_ctx_epoch_in_applied(struct cam_isp_context *ctx_isp, __cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id, CAM_REQ_MGR_SOF_EVENT_SUCCESS); __cam_isp_ctx_update_event_record(ctx_isp, CAM_ISP_CTX_EVENT_EPOCH, NULL); goto end; } Loading Loading @@ -1018,6 +1163,8 @@ static int __cam_isp_ctx_epoch_in_applied(struct cam_isp_context *ctx_isp, } __cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id, CAM_REQ_MGR_SOF_EVENT_ERROR); __cam_isp_ctx_update_event_record(ctx_isp, CAM_ISP_CTX_EVENT_EPOCH, req); ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_BUBBLE; CAM_DBG(CAM_ISP, "next substate %d", Loading Loading @@ -1128,7 +1275,8 @@ static int __cam_isp_ctx_epoch_in_bubble_applied( __cam_isp_ctx_dump_state_monitor_array(ctx_isp, true); __cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id, CAM_REQ_MGR_SOF_EVENT_SUCCESS); __cam_isp_ctx_update_event_record(ctx_isp, CAM_ISP_CTX_EVENT_EPOCH, NULL); ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_BUBBLE; goto end; } Loading Loading @@ -1175,13 +1323,20 @@ static int __cam_isp_ctx_epoch_in_bubble_applied( jiffies_to_msecs(jiffies); __cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id, CAM_REQ_MGR_SOF_EVENT_ERROR); } else __cam_isp_ctx_update_event_record(ctx_isp, CAM_ISP_CTX_EVENT_EPOCH, req); } else { __cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id, CAM_REQ_MGR_SOF_EVENT_SUCCESS); } else __cam_isp_ctx_update_event_record(ctx_isp, CAM_ISP_CTX_EVENT_EPOCH, NULL); } } else { __cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id, CAM_REQ_MGR_SOF_EVENT_SUCCESS); __cam_isp_ctx_update_event_record(ctx_isp, CAM_ISP_CTX_EVENT_EPOCH, NULL); } ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_BUBBLE; CAM_DBG(CAM_ISP, "next substate %d", ctx_isp->substate_activated); end: Loading Loading @@ -1253,7 +1408,7 @@ static int __cam_isp_ctx_handle_error(struct cam_isp_context *ctx_isp, req_isp = (struct cam_isp_ctx_req *) req_to_dump->req_priv; if (error_event_data->enable_reg_dump) cam_isp_ctx_dump_req(req_isp); cam_isp_ctx_dump_req(req_isp, 0, 0, NULL, false); list_for_each_entry_safe(req, req_temp, &ctx->active_req_list, list) { Loading Loading @@ -1916,6 +2071,8 @@ static int __cam_isp_ctx_apply_req_in_activated_state( CAM_DBG(CAM_ISP, "new substate state %d, applied req %lld", next_state, ctx_isp->req_info.last_applied_req_id); __cam_isp_ctx_update_event_record(ctx_isp, CAM_ISP_CTX_EVENT_APPLY, req); spin_unlock_bh(&ctx->lock); } end: Loading Loading @@ -1971,6 +2128,160 @@ static int __cam_isp_ctx_apply_req_in_bubble( return rc; } static int __cam_isp_ctx_dump_req_info(struct cam_context *ctx, struct cam_ctx_request *req, uintptr_t cpu_addr, size_t buf_len, uint32_t *offset) { int rc = 0; struct cam_isp_ctx_req *req_isp; struct cam_isp_context *ctx_isp; int i; struct cam_isp_context_dump_header *hdr; int32_t *addr, *start; uint8_t *dst; if (!req || !ctx || !offset || !cpu_addr || !buf_len) { CAM_ERR(CAM_ISP, "Invalid parameters %pK %pK %u %pK %pK %pK ", req, ctx, offset, cpu_addr, buf_len); return -EINVAL; } req_isp = (struct cam_isp_ctx_req *)req->req_priv; ctx_isp = (struct cam_isp_context *)ctx->ctx_priv; dst = (char *)cpu_addr + *offset; hdr = (struct cam_isp_context_dump_header *)dst; hdr->word_size = sizeof(int32_t); snprintf(hdr->tag, CAM_ISP_CONTEXT_DUMP_TAG_MAX_LEN, "ISP_OUT_FENCE:"); addr = (int32_t *)(dst + sizeof(struct cam_isp_context_dump_header)); start = addr; for (i = 0; i < req_isp->num_fence_map_out; i++) { if (req_isp->fence_map_out[i].sync_id != -1) { *addr++ = req_isp->fence_map_out[i].resource_handle; *addr++ = req_isp->fence_map_out[i].sync_id; } } hdr->size = hdr->word_size * (addr - start); *offset += hdr->size + sizeof(struct cam_isp_context_dump_header); cam_isp_ctx_dump_req(req_isp, cpu_addr, buf_len, offset, true); return rc; } static int __cam_isp_ctx_dump_in_top_state(struct cam_context *ctx, struct cam_req_mgr_dump_info *dump_info) { struct cam_ctx_request *req = NULL; struct cam_isp_ctx_req *req_isp; struct cam_ctx_request *req_temp; struct cam_hw_dump_args dump_args; struct cam_isp_context *ctx_isp; uint64_t diff = 0; struct timeval cur_time; int rc = 0; uintptr_t cpu_addr; size_t buf_len; struct cam_isp_context_dump_header *hdr; uint64_t *addr, *start; uint8_t *dst; bool is_dump_only_event_record = false; list_for_each_entry_safe(req, req_temp, &ctx->active_req_list, list) { if (req->request_id == dump_info->req_id) { CAM_DBG(CAM_ISP, "isp active dumping req: %lld", dump_info->req_id); goto hw_dump; } } list_for_each_entry_safe(req, req_temp, &ctx->wait_req_list, list) { if (req->request_id == dump_info->req_id) { CAM_ERR(CAM_ISP, "isp dumping wait req: %lld", dump_info->req_id); goto hw_dump; } } return rc; hw_dump: if (req) { req_isp = (struct cam_isp_ctx_req *) req->req_priv; cam_common_util_get_curr_timestamp(&cur_time); diff = cam_common_util_get_time_diff(&cur_time, &req_isp->event_timestamp[CAM_ISP_CTX_EVENT_APPLY]); if (diff < CAM_ISP_CTX_RESPONSE_TIME_THRESHOLD) { CAM_INFO(CAM_ISP, "req %lld found no error", req->request_id); is_dump_only_event_record = true; } ctx_isp = (struct cam_isp_context *) ctx->ctx_priv; rc = cam_mem_get_cpu_buf(dump_info->buf_handle, &cpu_addr, &buf_len); if (!cpu_addr || !buf_len || rc) { CAM_ERR(CAM_ISP, "lnvalid addr %u len %zu rc %d", dump_info->buf_handle, buf_len, rc); return rc; } /* we take for isp sw information to be max as 2048*/ if ((buf_len - dump_info->offset) < CAM_ISP_CTX_DUMP_MIN_LENGTH) { CAM_ERR(CAM_ISP, "Dump buffer exhaust %u %u", buf_len, dump_info->offset); goto end; } dst = (char *)cpu_addr + dump_info->offset; hdr = (struct cam_isp_context_dump_header *)dst; snprintf(hdr->tag, CAM_ISP_CONTEXT_DUMP_TAG_MAX_LEN, "ISP_CTX_DUMP:"); hdr->word_size = sizeof(uint64_t); addr = (uint64_t *)(dst + sizeof(struct cam_isp_context_dump_header)); start = addr; *addr++ = req->request_id; *addr++ = req_isp->event_timestamp [CAM_ISP_CTX_EVENT_APPLY].tv_sec; *addr++ = req_isp->event_timestamp [CAM_ISP_CTX_EVENT_APPLY].tv_usec; *addr++ = cur_time.tv_sec; *addr++ = cur_time.tv_usec; hdr->size = hdr->word_size * (addr - start); dump_info->offset += hdr->size + sizeof(struct cam_isp_context_dump_header); spin_lock_bh(&ctx->lock); __cam_isp_ctx_dump_event_record(ctx_isp, cpu_addr, buf_len, &dump_info->offset); spin_unlock_bh(&ctx->lock); if (is_dump_only_event_record) goto end; rc = __cam_isp_ctx_dump_req_info(ctx, req, cpu_addr, buf_len, &dump_info->offset); if (rc) { CAM_ERR(CAM_ISP, "Dump Req info fail %lld", req->request_id); goto end; } if (ctx->hw_mgr_intf->hw_dump) { dump_args.offset = dump_info->offset; dump_args.request_id = dump_info->req_id; dump_args.buf_handle = dump_info->buf_handle; dump_args.ctxt_to_hw_map = ctx_isp->hw_ctx; rc = ctx->hw_mgr_intf->hw_dump( ctx->hw_mgr_intf->hw_mgr_priv, &dump_args); dump_info->offset = dump_args.offset; } end: rc = cam_mem_put_cpu_buf(dump_info->buf_handle); if (rc) CAM_ERR(CAM_ISP, "Cpu put failed handle %u", dump_info->buf_handle); } return rc; } static int __cam_isp_ctx_flush_req(struct cam_context *ctx, struct list_head *req_list, struct cam_req_mgr_flush_request *flush_req) { Loading Loading @@ -2510,7 +2821,7 @@ static int __cam_isp_ctx_rdi_only_sof_in_bubble_state( static int __cam_isp_ctx_rdi_only_reg_upd_in_bubble_applied_state( struct cam_isp_context *ctx_isp, void *evt_data) { struct cam_ctx_request *req; struct cam_ctx_request *req = NULL; struct cam_context *ctx = ctx_isp->base; struct cam_isp_ctx_req *req_isp = NULL; struct cam_req_mgr_trigger_notify notify; Loading Loading @@ -2572,6 +2883,8 @@ static int __cam_isp_ctx_rdi_only_reg_upd_in_bubble_applied_state( __cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id, CAM_REQ_MGR_SOF_EVENT_SUCCESS); __cam_isp_ctx_update_event_record(ctx_isp, CAM_ISP_CTX_EVENT_RUP, req); CAM_DBG(CAM_ISP, "next substate %d", ctx_isp->substate_activated); return 0; Loading @@ -2579,6 +2892,8 @@ static int __cam_isp_ctx_rdi_only_reg_upd_in_bubble_applied_state( /* Send SOF event as idle frame*/ __cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id, CAM_REQ_MGR_SOF_EVENT_SUCCESS); __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 Loading Loading @@ -3839,6 +4154,7 @@ static struct cam_ctx_ops .unlink = __cam_isp_ctx_unlink_in_acquired, .get_dev_info = __cam_isp_ctx_get_dev_info_in_acquired, .flush_req = __cam_isp_ctx_flush_req_in_top_state, .dump_req = __cam_isp_ctx_dump_in_top_state, }, .irq_ops = NULL, .pagefault_ops = cam_isp_context_dump_active_request, Loading @@ -3854,6 +4170,7 @@ static struct cam_ctx_ops .crm_ops = { .unlink = __cam_isp_ctx_unlink_in_ready, .flush_req = __cam_isp_ctx_flush_req_in_ready, .dump_req = __cam_isp_ctx_dump_in_top_state, }, .irq_ops = NULL, .pagefault_ops = cam_isp_context_dump_active_request, Loading @@ -3871,6 +4188,7 @@ static struct cam_ctx_ops .apply_req = __cam_isp_ctx_apply_req, .flush_req = __cam_isp_ctx_flush_req_in_top_state, .process_evt = __cam_isp_ctx_process_evt, .dump_req = __cam_isp_ctx_dump_in_top_state, }, .irq_ops = __cam_isp_ctx_handle_irq_in_activated, .pagefault_ops = cam_isp_context_dump_active_request, Loading drivers/media/platform/msm/camera/cam_isp/cam_isp_context.h +66 −0 File changed.Preview size limit exceeded, changes collapsed. Show changes drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +109 −0 Original line number Diff line number Diff line Loading @@ -4576,6 +4576,114 @@ static int cam_ife_mgr_cmd(void *hw_mgr_priv, void *cmd_args) return rc; } static int cam_ife_mgr_dump(void *hw_mgr_priv, void *args) { struct cam_isp_hw_dump_args isp_hw_dump_args; struct cam_hw_dump_args *dump_args = (struct cam_hw_dump_args *)args; struct cam_ife_hw_mgr_res *hw_mgr_res; struct cam_hw_intf *hw_intf; struct cam_ife_hw_mgr_ctx *ife_ctx = (struct cam_ife_hw_mgr_ctx *) dump_args->ctxt_to_hw_map; int i; int rc = 0; rc = cam_mem_get_cpu_buf(dump_args->buf_handle, &isp_hw_dump_args.cpu_addr, &isp_hw_dump_args.buf_len); if (!isp_hw_dump_args.cpu_addr || !isp_hw_dump_args.buf_len || rc) { CAM_ERR(CAM_ISP, "lnvalid addr %u len %zu rc %d", dump_args->buf_handle, isp_hw_dump_args.buf_len, rc); return rc; } isp_hw_dump_args.offset = dump_args->offset; isp_hw_dump_args.req_id = dump_args->request_id; list_for_each_entry(hw_mgr_res, &ife_ctx->res_list_ife_csid, list) { for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) { if (!hw_mgr_res->hw_res[i]) continue; hw_intf = hw_mgr_res->hw_res[i]->hw_intf; switch (hw_mgr_res->hw_res[i]->res_id) { case CAM_IFE_PIX_PATH_RES_RDI_0: case CAM_IFE_PIX_PATH_RES_RDI_1: case CAM_IFE_PIX_PATH_RES_RDI_2: case CAM_IFE_PIX_PATH_RES_RDI_3: if (ife_ctx->is_rdi_only_context && hw_intf->hw_ops.process_cmd) { rc = hw_intf->hw_ops.process_cmd( hw_intf->hw_priv, CAM_ISP_HW_CMD_DUMP_HW, &isp_hw_dump_args, sizeof(struct cam_isp_hw_dump_args)); } break; case CAM_IFE_PIX_PATH_RES_IPP: if (hw_intf->hw_ops.process_cmd) { rc = hw_intf->hw_ops.process_cmd( hw_intf->hw_priv, CAM_ISP_HW_CMD_DUMP_HW, &isp_hw_dump_args, sizeof(struct cam_isp_hw_dump_args)); } break; default: CAM_DBG(CAM_ISP, "not a valid res %d", hw_mgr_res->res_id); break; } } } list_for_each_entry(hw_mgr_res, &ife_ctx->res_list_ife_src, list) { for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) { if (!hw_mgr_res->hw_res[i]) continue; hw_intf = hw_mgr_res->hw_res[i]->hw_intf; switch (hw_mgr_res->res_id) { case CAM_ISP_HW_VFE_IN_RDI0: case CAM_ISP_HW_VFE_IN_RDI1: case CAM_ISP_HW_VFE_IN_RDI2: case CAM_ISP_HW_VFE_IN_RDI3: if (ife_ctx->is_rdi_only_context && hw_intf->hw_ops.process_cmd) { rc = hw_intf->hw_ops.process_cmd( hw_intf->hw_priv, CAM_ISP_HW_CMD_DUMP_HW, &isp_hw_dump_args, sizeof(struct cam_isp_hw_dump_args)); } break; case CAM_ISP_HW_VFE_IN_CAMIF: if (hw_intf->hw_ops.process_cmd) { rc = hw_intf->hw_ops.process_cmd( hw_intf->hw_priv, CAM_ISP_HW_CMD_DUMP_HW, &isp_hw_dump_args, sizeof(struct cam_isp_hw_dump_args)); } break; default: CAM_DBG(CAM_ISP, "not a valid res %d", hw_mgr_res->res_id); break; } } } dump_args->offset = isp_hw_dump_args.offset; rc = cam_mem_put_cpu_buf(dump_args->buf_handle); if (rc) CAM_ERR(CAM_FD, "Cpu put failed handle %u", dump_args->buf_handle); return rc; } static int cam_ife_mgr_cmd_get_sof_timestamp( struct cam_ife_hw_mgr_ctx *ife_ctx, uint64_t *time_stamp, Loading Loading @@ -6190,6 +6298,7 @@ int cam_ife_hw_mgr_init(struct cam_hw_mgr_intf *hw_mgr_intf, int *iommu_hdl) hw_mgr_intf->hw_config = cam_ife_mgr_config_hw; hw_mgr_intf->hw_cmd = cam_ife_mgr_cmd; hw_mgr_intf->hw_reset = cam_ife_mgr_reset; hw_mgr_intf->hw_dump = cam_ife_mgr_dump; if (iommu_hdl) *iommu_hdl = g_ife_hw_mgr.mgr_common.img_iommu_hdl; Loading Loading
drivers/media/platform/msm/camera/cam_cdm/cam_cdm_util.c +148 −1 Original line number Diff line number Diff line /* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. /* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -714,3 +714,150 @@ void cam_cdm_util_dump_cmd_buf( } } while (buf_now <= cmd_buf_end); } static long cam_cdm_util_dump_reg_cont_cmd_v2( uint32_t *cmd_buf_addr, struct cam_cdm_cmd_buf_dump_info *dump_info) { long ret = 0; struct cdm_regcontinuous_cmd *p_regcont_cmd; uint32_t *temp_ptr = cmd_buf_addr; int i = 0; struct cam_cdm_cmd_dump_header *hdr; uint32_t *addr, *start; uint8_t *dst; uint32_t min_len, remain_len; p_regcont_cmd = (struct cdm_regcontinuous_cmd *)temp_ptr; temp_ptr += CDMCmdHeaderSizes[CAM_CDM_CMD_REG_CONT]; ret += CDMCmdHeaderSizes[CAM_CDM_CMD_REG_CONT]; CAM_DBG(CAM_CDM, "REG_CONT: COUNT: %u OFFSET: 0x%X", p_regcont_cmd->count, p_regcont_cmd->offset); min_len = (sizeof(uint32_t) * p_regcont_cmd->count) + sizeof(struct cam_cdm_cmd_dump_header); remain_len = dump_info->dst_max_size - dump_info->dst_offset; if (remain_len < min_len) { CAM_ERR_RATE_LIMIT(CAM_CDM, "Dump buffer exhaust %d %d", remain_len, min_len); return ret; } dst = (char *)dump_info->dst_start + dump_info->dst_offset; hdr = (struct cam_cdm_cmd_dump_header *)dst; snprintf(hdr->tag, CAM_CDM_CMD_TAG_MAX_LEN, "CDM_REG_CONT:"); hdr->word_size = sizeof(uint32_t); addr = (uint32_t *)(dst + sizeof(struct cam_cdm_cmd_dump_header)); start = addr; *addr++ = p_regcont_cmd->offset; *addr++ = p_regcont_cmd->count; for (i = 0; i < p_regcont_cmd->count; i++) { *addr = *temp_ptr; temp_ptr++; addr++; ret++; } hdr->size = hdr->word_size * (addr - start); dump_info->dst_offset += hdr->size + sizeof(struct cam_cdm_cmd_dump_header); return ret; } static long cam_cdm_util_dump_reg_random_cmd_v2( uint32_t *cmd_buf_addr, struct cam_cdm_cmd_buf_dump_info *dump_info) { struct cdm_regrandom_cmd *p_regrand_cmd; uint32_t *temp_ptr = cmd_buf_addr; long ret = 0; int i = 0; uint32_t *addr, *start; struct cam_cdm_cmd_dump_header *hdr; uint8_t *dst; uint32_t min_len, remain_len; p_regrand_cmd = (struct cdm_regrandom_cmd *)temp_ptr; temp_ptr += CDMCmdHeaderSizes[CAM_CDM_CMD_REG_RANDOM]; ret += CDMCmdHeaderSizes[CAM_CDM_CMD_REG_RANDOM]; min_len = (2 * sizeof(uint32_t) * p_regrand_cmd->count) + sizeof(struct cam_cdm_cmd_dump_header); remain_len = dump_info->dst_max_size - dump_info->dst_offset; if (remain_len < min_len) { CAM_ERR_RATE_LIMIT(CAM_CDM, "Dump buffer exhaust %d %d", remain_len, min_len); return ret; } dst = (char *)dump_info->dst_start + dump_info->dst_offset; hdr = (struct cam_cdm_cmd_dump_header *)dst; snprintf(hdr->tag, CAM_CDM_CMD_TAG_MAX_LEN, "CDM_REG_RANDOM:"); hdr->word_size = sizeof(uint32_t); addr = (uint32_t *)(dst + sizeof(struct cam_cdm_cmd_dump_header)); start = addr; *addr++ = p_regrand_cmd->count; for (i = 0; i < p_regrand_cmd->count; i++) { addr[0] = temp_ptr[0] & CAM_CDM_REG_OFFSET_MASK; addr[1] = temp_ptr[1]; temp_ptr += 2; addr += 2; ret += 2; } hdr->size = hdr->word_size * (addr - start); dump_info->dst_offset += hdr->size + sizeof(struct cam_cdm_cmd_dump_header); return ret; } void cam_cdm_util_dump_cmd_bufs_v2( struct cam_cdm_cmd_buf_dump_info *dump_info) { uint32_t cmd = 0; uint32_t *buf_now; if (!dump_info || !dump_info->src_start || !dump_info->src_end || !dump_info->dst_start) { CAM_INFO(CAM_CDM, "Invalid args"); return; } buf_now = dump_info->src_start; do { cmd = *dump_info->src_start; cmd = cmd >> CAM_CDM_COMMAND_OFFSET; switch (cmd) { case CAM_CDM_CMD_DMI: case CAM_CDM_CMD_DMI_32: case CAM_CDM_CMD_DMI_64: buf_now += CDMCmdHeaderSizes[CAM_CDM_CMD_DMI]; break; case CAM_CDM_CMD_REG_CONT: buf_now += cam_cdm_util_dump_reg_cont_cmd_v2(buf_now, dump_info); break; case CAM_CDM_CMD_REG_RANDOM: buf_now += cam_cdm_util_dump_reg_random_cmd_v2(buf_now, dump_info); break; case CAM_CDM_CMD_BUFF_INDIRECT: buf_now += CDMCmdHeaderSizes[CAM_CDM_CMD_BUFF_INDIRECT]; break; case CAM_CDM_CMD_GEN_IRQ: buf_now += CDMCmdHeaderSizes[CAM_CDM_CMD_GEN_IRQ]; break; case CAM_CDM_CMD_WAIT_EVENT: buf_now += CDMCmdHeaderSizes[CAM_CDM_CMD_WAIT_EVENT]; break; case CAM_CDM_CMD_CHANGE_BASE: buf_now += CDMCmdHeaderSizes[CAM_CDM_CMD_CHANGE_BASE]; break; case CAM_CDM_CMD_PERF_CTRL: buf_now += CDMCmdHeaderSizes[CAM_CDM_CMD_PERF_CTRL]; break; default: CAM_INFO(CAM_CDM, "Invalid CMD: 0x%x buf 0x%x", cmd, *buf_now); buf_now++; break; } } while (buf_now <= dump_info->src_end); }
drivers/media/platform/msm/camera/cam_cdm/cam_cdm_util.h +43 −1 Original line number Diff line number Diff line /* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. /* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading @@ -13,6 +13,9 @@ #ifndef _CAM_CDM_UTIL_H_ #define _CAM_CDM_UTIL_H_ /* Max len for tag name for header while dumping cmd buffer*/ #define CAM_CDM_CMD_TAG_MAX_LEN 32 enum cam_cdm_command { CAM_CDM_CMD_UNUSED = 0x0, CAM_CDM_CMD_DMI = 0x1, Loading Loading @@ -151,6 +154,34 @@ void (*cdm_write_genirq)( uint32_t userdata); }; /** * struct cam_cdm_cmd_buf_dump_info; - Camera CDM dump info * @src_start: source start address * @src_end: source end address * @dst_start: dst start address * @dst_offset: dst offset * @dst_max_size max size of destination buffer */ struct cam_cdm_cmd_buf_dump_info { uint32_t *src_start; uint32_t *src_end; uintptr_t dst_start; uint32_t dst_offset; uint32_t dst_max_size; }; /** * struct cam_cdm_cmd_dump_header- Camera CDM dump header * @tag: tag name for header * @size: size of data * @word_size: size of each word */ struct cam_cdm_cmd_dump_header { char tag[CAM_CDM_CMD_TAG_MAX_LEN]; uint64_t size; uint32_t word_size; }; /** * cam_cdm_util_log_cmd_bufs() * Loading @@ -163,6 +194,17 @@ void (*cdm_write_genirq)( void cam_cdm_util_dump_cmd_buf( uint32_t *cmd_buffer_start, uint32_t *cmd_buffer_end); /** * cam_cdm_util_dump_cmd_bufs_v2() * * @brief: Util function to log cdm command buffers * to a buffer * * @dump_info: Information about source and destination buffers * */ void cam_cdm_util_dump_cmd_bufs_v2( struct cam_cdm_cmd_buf_dump_info *dump_info); #endif /* _CAM_CDM_UTIL_H_ */
drivers/media/platform/msm/camera/cam_isp/cam_isp_context.c +331 −13 Original line number Diff line number Diff line Loading @@ -29,13 +29,123 @@ static const char isp_dev_name[] = "cam-isp"; #define INC_STATE_MONITOR_HEAD(head) \ #define INC_HEAD(head, max_entries) \ (atomic64_add_return(1, head) % \ CAM_ISP_CTX_STATE_MONITOR_MAX_ENTRIES) max_entries) static int cam_isp_context_dump_active_request(void *data, unsigned long iova, uint32_t buf_info); static const char *__cam_isp_evt_val_to_type( uint32_t evt_id) { switch (evt_id) { case CAM_ISP_CTX_EVENT_SUBMIT: return "SUBMIT"; case CAM_ISP_CTX_EVENT_APPLY: return "APPLY"; case CAM_ISP_CTX_EVENT_EPOCH: return "EPOCH"; case CAM_ISP_CTX_EVENT_RUP: return "RUP"; case CAM_ISP_CTX_EVENT_BUFDONE: return "BUFDONE"; default: return "CAM_ISP_EVENT_INVALID"; } } static void __cam_isp_ctx_update_event_record( struct cam_isp_context *ctx_isp, enum cam_isp_ctx_event event, struct cam_ctx_request *req) { int iterator = 0; struct cam_isp_ctx_req *req_isp; struct timeval cur_time; switch (event) { case CAM_ISP_CTX_EVENT_EPOCH: case CAM_ISP_CTX_EVENT_RUP: case CAM_ISP_CTX_EVENT_BUFDONE: break; case CAM_ISP_CTX_EVENT_SUBMIT: case CAM_ISP_CTX_EVENT_APPLY: if (!req) { CAM_ERR(CAM_ISP, "Invalid arg for event %d", event); return; } break; default: break; } iterator = INC_HEAD(&ctx_isp->event_record_head[event], CAM_ISP_CTX_EVENT_RECORD_MAX_ENTRIES); cam_common_util_get_curr_timestamp(&cur_time); if (req) { req_isp = (struct cam_isp_ctx_req *) req->req_priv; ctx_isp->event_record[event][iterator].req_id = req->request_id; req_isp->event_timestamp[event].tv_sec = cur_time.tv_sec; req_isp->event_timestamp[event].tv_usec = cur_time.tv_usec; } else { ctx_isp->event_record[event][iterator].req_id = 0; } ctx_isp->event_record[event][iterator].timestamp.tv_sec = cur_time.tv_sec; ctx_isp->event_record[event][iterator].timestamp.tv_usec = cur_time.tv_usec; } static void __cam_isp_ctx_dump_event_record( struct cam_isp_context *ctx_isp, uintptr_t cpu_addr, size_t buf_len, uint32_t *offset) { int i, j; struct cam_isp_context_event_record *record; int index; uint64_t state_head; struct cam_isp_context_dump_header *hdr; uint64_t *addr, *start; uint8_t *dst; if (!cpu_addr || !buf_len || !offset) { CAM_ERR(CAM_ISP, "Invalid args"); return; } for (i = 0; i < CAM_ISP_CTX_EVENT_MAX; i++) { state_head = atomic64_read(&ctx_isp->event_record_head[i]); dst = (char *)cpu_addr + *offset; hdr = (struct cam_isp_context_dump_header *)dst; snprintf(hdr->tag, CAM_ISP_CONTEXT_DUMP_TAG_MAX_LEN, "ISP_EVT_%s:", __cam_isp_evt_val_to_type(i)); hdr->word_size = sizeof(uint64_t); addr = (uint64_t *)(dst + sizeof(struct cam_isp_context_dump_header)); start = addr; for (j = CAM_ISP_CTX_EVENT_RECORD_MAX_ENTRIES - 1; j >= 0; j--) { index = (((state_head - j) + CAM_ISP_CTX_EVENT_RECORD_MAX_ENTRIES) % CAM_ISP_CTX_EVENT_RECORD_MAX_ENTRIES); record = &ctx_isp->event_record[i][index]; *addr++ = record->req_id; *addr++ = record->timestamp.tv_sec; *addr++ = record->timestamp.tv_usec; } hdr->size = hdr->word_size * (addr - start); *offset += hdr->size + sizeof(struct cam_isp_context_dump_header); } } static void __cam_isp_ctx_update_state_monitor_array( struct cam_isp_context *ctx_isp, enum cam_isp_hw_event_type hw_event, Loading @@ -44,7 +154,8 @@ static void __cam_isp_ctx_update_state_monitor_array( { int iterator = 0; iterator = INC_STATE_MONITOR_HEAD(&ctx_isp->state_monitor_head); iterator = INC_HEAD(&ctx_isp->state_monitor_head, CAM_ISP_CTX_STATE_MONITOR_MAX_ENTRIES); ctx_isp->cam_isp_ctx_state_monitor[iterator].curr_state = curr_state; ctx_isp->cam_isp_ctx_state_monitor[iterator].next_state = Loading Loading @@ -160,7 +271,11 @@ static void __cam_isp_ctx_dump_state_monitor_array( } } static void cam_isp_ctx_dump_req(struct cam_isp_ctx_req *req_isp) static void cam_isp_ctx_dump_req(struct cam_isp_ctx_req *req_isp, uintptr_t cpu_addr, size_t buf_len, uint32_t *offset, bool dump_to_buff) { int i = 0, rc = 0; size_t len = 0; Loading @@ -168,6 +283,7 @@ static void cam_isp_ctx_dump_req(struct cam_isp_ctx_req *req_isp) uint32_t *buf_start, *buf_end; size_t remain_len = 0; bool need_put = false; struct cam_cdm_cmd_buf_dump_info dump_info; for (i = 0; i < req_isp->num_cfg; i++) { rc = cam_packet_util_get_cmd_mem_addr( Loading Loading @@ -202,7 +318,21 @@ static void cam_isp_ctx_dump_req(struct cam_isp_ctx_req *req_isp) req_isp->cfg[i].offset); buf_end = (uint32_t *)((uint8_t *) buf_start + req_isp->cfg[i].len - 1); if (dump_to_buff) { if (!cpu_addr || !offset || !buf_len) { CAM_ERR(CAM_ISP, "Invalid args"); break; } dump_info.src_start = buf_start; dump_info.src_end = buf_end; dump_info.dst_start = cpu_addr; dump_info.dst_offset = *offset; dump_info.dst_max_size = buf_len; cam_cdm_util_dump_cmd_bufs_v2(&dump_info); *offset = dump_info.dst_offset; } else { cam_cdm_util_dump_cmd_buf(buf_start, buf_end); } if (cam_mem_put_cpu_buf(req_isp->cfg[i].handle)) CAM_WARN(CAM_ISP, "Failed to put cpu buf: 0x%x", req_isp->cfg[i].handle); Loading @@ -216,6 +346,7 @@ static int __cam_isp_ctx_enqueue_request_in_order( struct cam_ctx_request *req_current; struct cam_ctx_request *req_prev; struct list_head temp_list; struct cam_isp_context *ctx_isp; INIT_LIST_HEAD(&temp_list); spin_lock_bh(&ctx->lock); Loading Loading @@ -246,6 +377,9 @@ static int __cam_isp_ctx_enqueue_request_in_order( } } } ctx_isp = (struct cam_isp_context *) ctx->ctx_priv; __cam_isp_ctx_update_event_record(ctx_isp, CAM_ISP_CTX_EVENT_SUBMIT, req); spin_unlock_bh(&ctx->lock); return 0; } Loading Loading @@ -490,7 +624,6 @@ static int __cam_isp_ctx_handle_buf_done_in_activated_state( req_isp->fence_map_out[j].resource_handle, req_isp->fence_map_out[j].sync_id, ctx->ctx_id); rc = cam_sync_signal(req_isp->fence_map_out[j].sync_id, CAM_SYNC_STATE_SIGNALED_SUCCESS); if (rc) Loading Loading @@ -560,6 +693,8 @@ static int __cam_isp_ctx_handle_buf_done_in_activated_state( CAM_ISP_HW_EVENT_DONE, ctx_isp->substate_activated, ctx_isp->substate_activated); __cam_isp_ctx_update_event_record(ctx_isp, CAM_ISP_CTX_EVENT_BUFDONE, req); } else { list_del_init(&req->list); list_add_tail(&req->list, &ctx->free_req_list); Loading @@ -574,6 +709,8 @@ static int __cam_isp_ctx_handle_buf_done_in_activated_state( CAM_ISP_HW_EVENT_DONE, ctx_isp->substate_activated, ctx_isp->substate_activated); __cam_isp_ctx_update_event_record(ctx_isp, CAM_ISP_CTX_EVENT_BUFDONE, req); } if (ctx_isp->active_req_cnt && ctx_isp->irq_delay_detect) { Loading Loading @@ -742,6 +879,10 @@ static int __cam_isp_ctx_reg_upd_in_activated_state( 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); Loading Loading @@ -776,7 +917,7 @@ static int __cam_isp_ctx_notify_sof_in_activated_state( int rc = 0; struct cam_req_mgr_trigger_notify notify; struct cam_context *ctx = ctx_isp->base; struct cam_ctx_request *req; struct cam_ctx_request *req = NULL; uint64_t request_id = 0; /* Loading Loading @@ -807,6 +948,8 @@ static int __cam_isp_ctx_notify_sof_in_activated_state( ctx_isp->req_info.reported_req_id = request_id; ctx_isp->req_info.last_reported_id_time_stamp = jiffies_to_msecs(jiffies); __cam_isp_ctx_update_event_record(ctx_isp, CAM_ISP_CTX_EVENT_EPOCH, req); break; } } Loading Loading @@ -973,6 +1116,8 @@ static int __cam_isp_ctx_epoch_in_applied(struct cam_isp_context *ctx_isp, __cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id, CAM_REQ_MGR_SOF_EVENT_SUCCESS); __cam_isp_ctx_update_event_record(ctx_isp, CAM_ISP_CTX_EVENT_EPOCH, NULL); goto end; } Loading Loading @@ -1018,6 +1163,8 @@ static int __cam_isp_ctx_epoch_in_applied(struct cam_isp_context *ctx_isp, } __cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id, CAM_REQ_MGR_SOF_EVENT_ERROR); __cam_isp_ctx_update_event_record(ctx_isp, CAM_ISP_CTX_EVENT_EPOCH, req); ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_BUBBLE; CAM_DBG(CAM_ISP, "next substate %d", Loading Loading @@ -1128,7 +1275,8 @@ static int __cam_isp_ctx_epoch_in_bubble_applied( __cam_isp_ctx_dump_state_monitor_array(ctx_isp, true); __cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id, CAM_REQ_MGR_SOF_EVENT_SUCCESS); __cam_isp_ctx_update_event_record(ctx_isp, CAM_ISP_CTX_EVENT_EPOCH, NULL); ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_BUBBLE; goto end; } Loading Loading @@ -1175,13 +1323,20 @@ static int __cam_isp_ctx_epoch_in_bubble_applied( jiffies_to_msecs(jiffies); __cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id, CAM_REQ_MGR_SOF_EVENT_ERROR); } else __cam_isp_ctx_update_event_record(ctx_isp, CAM_ISP_CTX_EVENT_EPOCH, req); } else { __cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id, CAM_REQ_MGR_SOF_EVENT_SUCCESS); } else __cam_isp_ctx_update_event_record(ctx_isp, CAM_ISP_CTX_EVENT_EPOCH, NULL); } } else { __cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id, CAM_REQ_MGR_SOF_EVENT_SUCCESS); __cam_isp_ctx_update_event_record(ctx_isp, CAM_ISP_CTX_EVENT_EPOCH, NULL); } ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_BUBBLE; CAM_DBG(CAM_ISP, "next substate %d", ctx_isp->substate_activated); end: Loading Loading @@ -1253,7 +1408,7 @@ static int __cam_isp_ctx_handle_error(struct cam_isp_context *ctx_isp, req_isp = (struct cam_isp_ctx_req *) req_to_dump->req_priv; if (error_event_data->enable_reg_dump) cam_isp_ctx_dump_req(req_isp); cam_isp_ctx_dump_req(req_isp, 0, 0, NULL, false); list_for_each_entry_safe(req, req_temp, &ctx->active_req_list, list) { Loading Loading @@ -1916,6 +2071,8 @@ static int __cam_isp_ctx_apply_req_in_activated_state( CAM_DBG(CAM_ISP, "new substate state %d, applied req %lld", next_state, ctx_isp->req_info.last_applied_req_id); __cam_isp_ctx_update_event_record(ctx_isp, CAM_ISP_CTX_EVENT_APPLY, req); spin_unlock_bh(&ctx->lock); } end: Loading Loading @@ -1971,6 +2128,160 @@ static int __cam_isp_ctx_apply_req_in_bubble( return rc; } static int __cam_isp_ctx_dump_req_info(struct cam_context *ctx, struct cam_ctx_request *req, uintptr_t cpu_addr, size_t buf_len, uint32_t *offset) { int rc = 0; struct cam_isp_ctx_req *req_isp; struct cam_isp_context *ctx_isp; int i; struct cam_isp_context_dump_header *hdr; int32_t *addr, *start; uint8_t *dst; if (!req || !ctx || !offset || !cpu_addr || !buf_len) { CAM_ERR(CAM_ISP, "Invalid parameters %pK %pK %u %pK %pK %pK ", req, ctx, offset, cpu_addr, buf_len); return -EINVAL; } req_isp = (struct cam_isp_ctx_req *)req->req_priv; ctx_isp = (struct cam_isp_context *)ctx->ctx_priv; dst = (char *)cpu_addr + *offset; hdr = (struct cam_isp_context_dump_header *)dst; hdr->word_size = sizeof(int32_t); snprintf(hdr->tag, CAM_ISP_CONTEXT_DUMP_TAG_MAX_LEN, "ISP_OUT_FENCE:"); addr = (int32_t *)(dst + sizeof(struct cam_isp_context_dump_header)); start = addr; for (i = 0; i < req_isp->num_fence_map_out; i++) { if (req_isp->fence_map_out[i].sync_id != -1) { *addr++ = req_isp->fence_map_out[i].resource_handle; *addr++ = req_isp->fence_map_out[i].sync_id; } } hdr->size = hdr->word_size * (addr - start); *offset += hdr->size + sizeof(struct cam_isp_context_dump_header); cam_isp_ctx_dump_req(req_isp, cpu_addr, buf_len, offset, true); return rc; } static int __cam_isp_ctx_dump_in_top_state(struct cam_context *ctx, struct cam_req_mgr_dump_info *dump_info) { struct cam_ctx_request *req = NULL; struct cam_isp_ctx_req *req_isp; struct cam_ctx_request *req_temp; struct cam_hw_dump_args dump_args; struct cam_isp_context *ctx_isp; uint64_t diff = 0; struct timeval cur_time; int rc = 0; uintptr_t cpu_addr; size_t buf_len; struct cam_isp_context_dump_header *hdr; uint64_t *addr, *start; uint8_t *dst; bool is_dump_only_event_record = false; list_for_each_entry_safe(req, req_temp, &ctx->active_req_list, list) { if (req->request_id == dump_info->req_id) { CAM_DBG(CAM_ISP, "isp active dumping req: %lld", dump_info->req_id); goto hw_dump; } } list_for_each_entry_safe(req, req_temp, &ctx->wait_req_list, list) { if (req->request_id == dump_info->req_id) { CAM_ERR(CAM_ISP, "isp dumping wait req: %lld", dump_info->req_id); goto hw_dump; } } return rc; hw_dump: if (req) { req_isp = (struct cam_isp_ctx_req *) req->req_priv; cam_common_util_get_curr_timestamp(&cur_time); diff = cam_common_util_get_time_diff(&cur_time, &req_isp->event_timestamp[CAM_ISP_CTX_EVENT_APPLY]); if (diff < CAM_ISP_CTX_RESPONSE_TIME_THRESHOLD) { CAM_INFO(CAM_ISP, "req %lld found no error", req->request_id); is_dump_only_event_record = true; } ctx_isp = (struct cam_isp_context *) ctx->ctx_priv; rc = cam_mem_get_cpu_buf(dump_info->buf_handle, &cpu_addr, &buf_len); if (!cpu_addr || !buf_len || rc) { CAM_ERR(CAM_ISP, "lnvalid addr %u len %zu rc %d", dump_info->buf_handle, buf_len, rc); return rc; } /* we take for isp sw information to be max as 2048*/ if ((buf_len - dump_info->offset) < CAM_ISP_CTX_DUMP_MIN_LENGTH) { CAM_ERR(CAM_ISP, "Dump buffer exhaust %u %u", buf_len, dump_info->offset); goto end; } dst = (char *)cpu_addr + dump_info->offset; hdr = (struct cam_isp_context_dump_header *)dst; snprintf(hdr->tag, CAM_ISP_CONTEXT_DUMP_TAG_MAX_LEN, "ISP_CTX_DUMP:"); hdr->word_size = sizeof(uint64_t); addr = (uint64_t *)(dst + sizeof(struct cam_isp_context_dump_header)); start = addr; *addr++ = req->request_id; *addr++ = req_isp->event_timestamp [CAM_ISP_CTX_EVENT_APPLY].tv_sec; *addr++ = req_isp->event_timestamp [CAM_ISP_CTX_EVENT_APPLY].tv_usec; *addr++ = cur_time.tv_sec; *addr++ = cur_time.tv_usec; hdr->size = hdr->word_size * (addr - start); dump_info->offset += hdr->size + sizeof(struct cam_isp_context_dump_header); spin_lock_bh(&ctx->lock); __cam_isp_ctx_dump_event_record(ctx_isp, cpu_addr, buf_len, &dump_info->offset); spin_unlock_bh(&ctx->lock); if (is_dump_only_event_record) goto end; rc = __cam_isp_ctx_dump_req_info(ctx, req, cpu_addr, buf_len, &dump_info->offset); if (rc) { CAM_ERR(CAM_ISP, "Dump Req info fail %lld", req->request_id); goto end; } if (ctx->hw_mgr_intf->hw_dump) { dump_args.offset = dump_info->offset; dump_args.request_id = dump_info->req_id; dump_args.buf_handle = dump_info->buf_handle; dump_args.ctxt_to_hw_map = ctx_isp->hw_ctx; rc = ctx->hw_mgr_intf->hw_dump( ctx->hw_mgr_intf->hw_mgr_priv, &dump_args); dump_info->offset = dump_args.offset; } end: rc = cam_mem_put_cpu_buf(dump_info->buf_handle); if (rc) CAM_ERR(CAM_ISP, "Cpu put failed handle %u", dump_info->buf_handle); } return rc; } static int __cam_isp_ctx_flush_req(struct cam_context *ctx, struct list_head *req_list, struct cam_req_mgr_flush_request *flush_req) { Loading Loading @@ -2510,7 +2821,7 @@ static int __cam_isp_ctx_rdi_only_sof_in_bubble_state( static int __cam_isp_ctx_rdi_only_reg_upd_in_bubble_applied_state( struct cam_isp_context *ctx_isp, void *evt_data) { struct cam_ctx_request *req; struct cam_ctx_request *req = NULL; struct cam_context *ctx = ctx_isp->base; struct cam_isp_ctx_req *req_isp = NULL; struct cam_req_mgr_trigger_notify notify; Loading Loading @@ -2572,6 +2883,8 @@ static int __cam_isp_ctx_rdi_only_reg_upd_in_bubble_applied_state( __cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id, CAM_REQ_MGR_SOF_EVENT_SUCCESS); __cam_isp_ctx_update_event_record(ctx_isp, CAM_ISP_CTX_EVENT_RUP, req); CAM_DBG(CAM_ISP, "next substate %d", ctx_isp->substate_activated); return 0; Loading @@ -2579,6 +2892,8 @@ static int __cam_isp_ctx_rdi_only_reg_upd_in_bubble_applied_state( /* Send SOF event as idle frame*/ __cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id, CAM_REQ_MGR_SOF_EVENT_SUCCESS); __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 Loading Loading @@ -3839,6 +4154,7 @@ static struct cam_ctx_ops .unlink = __cam_isp_ctx_unlink_in_acquired, .get_dev_info = __cam_isp_ctx_get_dev_info_in_acquired, .flush_req = __cam_isp_ctx_flush_req_in_top_state, .dump_req = __cam_isp_ctx_dump_in_top_state, }, .irq_ops = NULL, .pagefault_ops = cam_isp_context_dump_active_request, Loading @@ -3854,6 +4170,7 @@ static struct cam_ctx_ops .crm_ops = { .unlink = __cam_isp_ctx_unlink_in_ready, .flush_req = __cam_isp_ctx_flush_req_in_ready, .dump_req = __cam_isp_ctx_dump_in_top_state, }, .irq_ops = NULL, .pagefault_ops = cam_isp_context_dump_active_request, Loading @@ -3871,6 +4188,7 @@ static struct cam_ctx_ops .apply_req = __cam_isp_ctx_apply_req, .flush_req = __cam_isp_ctx_flush_req_in_top_state, .process_evt = __cam_isp_ctx_process_evt, .dump_req = __cam_isp_ctx_dump_in_top_state, }, .irq_ops = __cam_isp_ctx_handle_irq_in_activated, .pagefault_ops = cam_isp_context_dump_active_request, Loading
drivers/media/platform/msm/camera/cam_isp/cam_isp_context.h +66 −0 File changed.Preview size limit exceeded, changes collapsed. Show changes
drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +109 −0 Original line number Diff line number Diff line Loading @@ -4576,6 +4576,114 @@ static int cam_ife_mgr_cmd(void *hw_mgr_priv, void *cmd_args) return rc; } static int cam_ife_mgr_dump(void *hw_mgr_priv, void *args) { struct cam_isp_hw_dump_args isp_hw_dump_args; struct cam_hw_dump_args *dump_args = (struct cam_hw_dump_args *)args; struct cam_ife_hw_mgr_res *hw_mgr_res; struct cam_hw_intf *hw_intf; struct cam_ife_hw_mgr_ctx *ife_ctx = (struct cam_ife_hw_mgr_ctx *) dump_args->ctxt_to_hw_map; int i; int rc = 0; rc = cam_mem_get_cpu_buf(dump_args->buf_handle, &isp_hw_dump_args.cpu_addr, &isp_hw_dump_args.buf_len); if (!isp_hw_dump_args.cpu_addr || !isp_hw_dump_args.buf_len || rc) { CAM_ERR(CAM_ISP, "lnvalid addr %u len %zu rc %d", dump_args->buf_handle, isp_hw_dump_args.buf_len, rc); return rc; } isp_hw_dump_args.offset = dump_args->offset; isp_hw_dump_args.req_id = dump_args->request_id; list_for_each_entry(hw_mgr_res, &ife_ctx->res_list_ife_csid, list) { for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) { if (!hw_mgr_res->hw_res[i]) continue; hw_intf = hw_mgr_res->hw_res[i]->hw_intf; switch (hw_mgr_res->hw_res[i]->res_id) { case CAM_IFE_PIX_PATH_RES_RDI_0: case CAM_IFE_PIX_PATH_RES_RDI_1: case CAM_IFE_PIX_PATH_RES_RDI_2: case CAM_IFE_PIX_PATH_RES_RDI_3: if (ife_ctx->is_rdi_only_context && hw_intf->hw_ops.process_cmd) { rc = hw_intf->hw_ops.process_cmd( hw_intf->hw_priv, CAM_ISP_HW_CMD_DUMP_HW, &isp_hw_dump_args, sizeof(struct cam_isp_hw_dump_args)); } break; case CAM_IFE_PIX_PATH_RES_IPP: if (hw_intf->hw_ops.process_cmd) { rc = hw_intf->hw_ops.process_cmd( hw_intf->hw_priv, CAM_ISP_HW_CMD_DUMP_HW, &isp_hw_dump_args, sizeof(struct cam_isp_hw_dump_args)); } break; default: CAM_DBG(CAM_ISP, "not a valid res %d", hw_mgr_res->res_id); break; } } } list_for_each_entry(hw_mgr_res, &ife_ctx->res_list_ife_src, list) { for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) { if (!hw_mgr_res->hw_res[i]) continue; hw_intf = hw_mgr_res->hw_res[i]->hw_intf; switch (hw_mgr_res->res_id) { case CAM_ISP_HW_VFE_IN_RDI0: case CAM_ISP_HW_VFE_IN_RDI1: case CAM_ISP_HW_VFE_IN_RDI2: case CAM_ISP_HW_VFE_IN_RDI3: if (ife_ctx->is_rdi_only_context && hw_intf->hw_ops.process_cmd) { rc = hw_intf->hw_ops.process_cmd( hw_intf->hw_priv, CAM_ISP_HW_CMD_DUMP_HW, &isp_hw_dump_args, sizeof(struct cam_isp_hw_dump_args)); } break; case CAM_ISP_HW_VFE_IN_CAMIF: if (hw_intf->hw_ops.process_cmd) { rc = hw_intf->hw_ops.process_cmd( hw_intf->hw_priv, CAM_ISP_HW_CMD_DUMP_HW, &isp_hw_dump_args, sizeof(struct cam_isp_hw_dump_args)); } break; default: CAM_DBG(CAM_ISP, "not a valid res %d", hw_mgr_res->res_id); break; } } } dump_args->offset = isp_hw_dump_args.offset; rc = cam_mem_put_cpu_buf(dump_args->buf_handle); if (rc) CAM_ERR(CAM_FD, "Cpu put failed handle %u", dump_args->buf_handle); return rc; } static int cam_ife_mgr_cmd_get_sof_timestamp( struct cam_ife_hw_mgr_ctx *ife_ctx, uint64_t *time_stamp, Loading Loading @@ -6190,6 +6298,7 @@ int cam_ife_hw_mgr_init(struct cam_hw_mgr_intf *hw_mgr_intf, int *iommu_hdl) hw_mgr_intf->hw_config = cam_ife_mgr_config_hw; hw_mgr_intf->hw_cmd = cam_ife_mgr_cmd; hw_mgr_intf->hw_reset = cam_ife_mgr_reset; hw_mgr_intf->hw_dump = cam_ife_mgr_dump; if (iommu_hdl) *iommu_hdl = g_ife_hw_mgr.mgr_common.img_iommu_hdl; Loading