Loading drivers/cam_cdm/cam_cdm_util.c +169 −1 Original line number Diff line number Diff line // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include <linux/types.h> Loading Loading @@ -823,3 +823,171 @@ void cam_cdm_util_dump_cmd_buf( } } while (buf_now <= cmd_buf_end); } static uint32_t cam_cdm_util_dump_reg_cont_cmd_v2( uint32_t *cmd_buf_addr, struct cam_cdm_cmd_buf_dump_info *dump_info) { int i; long ret; uint8_t *dst; size_t remain_len; uint32_t *temp_ptr = cmd_buf_addr; uint32_t *addr, *start; uint32_t min_len; struct cdm_regcontinuous_cmd *p_regcont_cmd; struct cam_cdm_cmd_dump_header *hdr; p_regcont_cmd = (struct cdm_regcontinuous_cmd *)temp_ptr; temp_ptr += cdm_get_cmd_header_size(CAM_CDM_CMD_REG_CONT); ret = cdm_get_cmd_header_size(CAM_CDM_CMD_REG_CONT); min_len = (sizeof(uint32_t) * p_regcont_cmd->count) + sizeof(struct cam_cdm_cmd_dump_header) + (2 * sizeof(uint32_t)); remain_len = dump_info->dst_max_size - dump_info->dst_offset; if (remain_len < min_len) { CAM_WARN_RATE_LIMIT(CAM_CDM, "Dump buffer exhaust remain %zu min %u", remain_len, min_len); return ret; } dst = (char *)dump_info->dst_start + dump_info->dst_offset; hdr = (struct cam_cdm_cmd_dump_header *)dst; scnprintf(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 uint32_t cam_cdm_util_dump_reg_random_cmd_v2( uint32_t *cmd_buf_addr, struct cam_cdm_cmd_buf_dump_info *dump_info) { int i; long ret; uint8_t *dst; uint32_t *temp_ptr = cmd_buf_addr; uint32_t *addr, *start; size_t remain_len; uint32_t min_len; struct cdm_regrandom_cmd *p_regrand_cmd; struct cam_cdm_cmd_dump_header *hdr; p_regrand_cmd = (struct cdm_regrandom_cmd *)temp_ptr; temp_ptr += cdm_get_cmd_header_size(CAM_CDM_CMD_REG_RANDOM); ret = cdm_get_cmd_header_size(CAM_CDM_CMD_REG_RANDOM); min_len = (2 * sizeof(uint32_t) * p_regrand_cmd->count) + sizeof(struct cam_cdm_cmd_dump_header) + sizeof(uint32_t); remain_len = dump_info->dst_max_size - dump_info->dst_offset; if (remain_len < min_len) { CAM_WARN_RATE_LIMIT(CAM_CDM, "Dump buffer exhaust remain %zu min %u", remain_len, min_len); return ret; } dst = (char *)dump_info->dst_start + dump_info->dst_offset; hdr = (struct cam_cdm_cmd_dump_header *)dst; scnprintf(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; } int cam_cdm_util_dump_cmd_bufs_v2( struct cam_cdm_cmd_buf_dump_info *dump_info) { uint32_t cmd; uint32_t *buf_now; int rc = 0; if (!dump_info || !dump_info->src_start || !dump_info->src_end || !dump_info->dst_start) { CAM_INFO(CAM_CDM, "Invalid args"); return -EINVAL; } buf_now = dump_info->src_start; do { if (dump_info->dst_offset >= dump_info->dst_max_size) { CAM_WARN(CAM_CDM, "Dump overshoot offset %zu size %zu", dump_info->dst_offset, dump_info->dst_max_size); return -ENOSPC; } cmd = *buf_now; 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 += cdm_get_cmd_header_size(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 += cdm_get_cmd_header_size( CAM_CDM_CMD_BUFF_INDIRECT); break; case CAM_CDM_CMD_GEN_IRQ: buf_now += cdm_get_cmd_header_size( CAM_CDM_CMD_GEN_IRQ); break; case CAM_CDM_CMD_WAIT_EVENT: buf_now += cdm_get_cmd_header_size( CAM_CDM_CMD_WAIT_EVENT); break; case CAM_CDM_CMD_CHANGE_BASE: buf_now += cdm_get_cmd_header_size( CAM_CDM_CMD_CHANGE_BASE); break; case CAM_CDM_CMD_PERF_CTRL: buf_now += cdm_get_cmd_header_size( CAM_CDM_CMD_PERF_CTRL); break; default: CAM_ERR(CAM_CDM, "Invalid CMD: 0x%x", cmd); buf_now++; break; } } while (buf_now <= dump_info->src_end); return rc; } drivers/cam_cdm/cam_cdm_util.h +44 −1 Original line number Diff line number Diff line /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #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 @@ -178,6 +181,34 @@ uint32_t *(*cdm_write_wait_prefetch_disable)( uint32_t mask2); }; /** * struct cam_cdm_cmd_buf_dump_info; - Camera CDM dump info * @dst_offset: dst offset * @dst_max_size max size of destination buffer * @src_start: source start address * @src_end: source end address * @dst_start: dst start address */ struct cam_cdm_cmd_buf_dump_info { size_t dst_offset; size_t dst_max_size; uint32_t *src_start; uint32_t *src_end; uintptr_t dst_start; }; /** * 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 { uint8_t tag[CAM_CDM_CMD_TAG_MAX_LEN]; uint64_t size; uint32_t word_size; }; /** * cam_cdm_util_log_cmd_bufs() * Loading @@ -190,6 +221,18 @@ uint32_t *(*cdm_write_wait_prefetch_disable)( 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 cdm command buffers * to a buffer * * @dump_info: Information about source and destination buffers * * return SUCCESS/FAILURE */ int cam_cdm_util_dump_cmd_bufs_v2( struct cam_cdm_cmd_buf_dump_info *dump_info); #endif /* _CAM_CDM_UTIL_H_ */ drivers/cam_isp/cam_isp_context.c +430 −16 File changed.Preview size limit exceeded, changes collapsed. Show changes drivers/cam_isp/cam_isp_context.h +72 −1 Original line number Diff line number Diff line /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_ISP_CONTEXT_H_ Loading Loading @@ -33,6 +33,27 @@ */ #define CAM_ISP_CTX_STATE_MONITOR_MAX_ENTRIES 40 /* * Threshold response time in us beyond which a request is not expected * to be with IFE hw */ #define CAM_ISP_CTX_RESPONSE_TIME_THRESHOLD 100000 /* Number of words for dumping isp context */ #define CAM_ISP_CTX_DUMP_NUM_WORDS 5 /* Number of words for dumping isp context events*/ #define CAM_ISP_CTX_DUMP_EVENT_NUM_WORDS 3 /* Number of words for dumping request info*/ #define CAM_ISP_CTX_DUMP_REQUEST_NUM_WORDS 2 /* Maximum entries in event record */ #define CAM_ISP_CTX_EVENT_RECORD_MAX_ENTRIES 20 /* Maximum length of tag while dumping */ #define CAM_ISP_CONTEXT_DUMP_TAG_MAX_LEN 32 /* forward declaration */ struct cam_isp_context; Loading @@ -55,6 +76,19 @@ enum cam_isp_ctx_activated_substate { CAM_ISP_CTX_ACTIVATED_MAX, }; /** * enum cam_isp_ctx_event_type - events for a request * */ enum cam_isp_ctx_event { CAM_ISP_CTX_EVENT_SUBMIT, CAM_ISP_CTX_EVENT_APPLY, CAM_ISP_CTX_EVENT_EPOCH, CAM_ISP_CTX_EVENT_RUP, CAM_ISP_CTX_EVENT_BUFDONE, CAM_ISP_CTX_EVENT_MAX }; /** * enum cam_isp_state_change_trigger - Different types of ISP events * Loading Loading @@ -109,6 +143,7 @@ struct cam_isp_ctx_irq_ops { * @bubble_report: Flag to track if bubble report is active on * current request * @hw_update_data: HW update data for this request * @event_timestamp: Timestamp for different stage of request * @reapply: True if reapplying after bubble * */ Loading @@ -125,6 +160,8 @@ struct cam_isp_ctx_req { uint32_t num_acked; int32_t bubble_report; struct cam_isp_prepare_hw_update_data hw_update_data; ktime_t event_timestamp [CAM_ISP_CTX_EVENT_MAX]; bool bubble_detected; bool reapply; }; Loading Loading @@ -160,8 +197,23 @@ struct cam_isp_context_state_monitor { struct cam_isp_context_req_id_info { int64_t last_bufdone_req_id; }; /** * * * struct cam_isp_context_event_record - Information for last 20 Events * for a request; Submit, Apply, EPOCH, RUP, Buf done. * * @req_id: Last applied request id * @timestamp: Timestamp for the event * */ struct cam_isp_context_event_record { uint64_t req_id; ktime_t timestamp; }; /** * struct cam_isp_context - ISP context object * * @base: Common context object pointer Loading @@ -185,6 +237,8 @@ struct cam_isp_context_req_id_info { * @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 * @rdi_only_context: Get context type information. * true, if context is rdi only context * @hw_acquired: Indicate whether HW resources are acquired Loading Loading @@ -218,6 +272,10 @@ struct cam_isp_context { 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]; bool rdi_only_context; bool hw_acquired; bool init_received; Loading @@ -226,6 +284,19 @@ struct cam_isp_context { uint32_t isp_device_type; }; /** * struct cam_isp_context_dump_header - ISP context dump header * @tag: Tag name for the header * @word_size: Size of word * @size: Size of data * */ struct cam_isp_context_dump_header { uint8_t tag[CAM_ISP_CONTEXT_DUMP_TAG_MAX_LEN]; uint64_t size; uint32_t word_size; }; /** * cam_isp_context_init() * Loading drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +160 −5 Original line number Diff line number Diff line Loading @@ -134,7 +134,9 @@ static int cam_ife_mgr_regspace_data_cb(uint32_t reg_base_type, static int cam_ife_mgr_handle_reg_dump(struct cam_ife_hw_mgr_ctx *ctx, struct cam_cmd_buf_desc *reg_dump_buf_desc, uint32_t num_reg_dump_buf, uint32_t meta_type) uint32_t meta_type, void *soc_dump_args, bool user_triggered_dump) { int rc = 0, i; Loading @@ -157,7 +159,9 @@ static int cam_ife_mgr_handle_reg_dump(struct cam_ife_hw_mgr_ctx *ctx, rc = cam_soc_util_reg_dump_to_cmd_buf(ctx, ®_dump_buf_desc[i], ctx->applied_req_id, cam_ife_mgr_regspace_data_cb); cam_ife_mgr_regspace_data_cb, soc_dump_args, user_triggered_dump); if (rc) { CAM_ERR(CAM_ISP, "Reg dump failed at idx: %d, rc: %d req_id: %llu meta type: %u", Loading Loading @@ -2423,7 +2427,8 @@ void cam_ife_cam_cdm_callback(uint32_t handle, void *userdata, cam_ife_mgr_handle_reg_dump(ctx, hw_update_data->reg_dump_buf_desc, hw_update_data->num_reg_dump_buf, CAM_ISP_PACKET_META_REG_DUMP_PER_REQUEST); CAM_ISP_PACKET_META_REG_DUMP_PER_REQUEST, NULL, false); CAM_DBG(CAM_ISP, "Called by CDM hdl=%x, udata=%pK, status=%d, cookie=%llu ctx_index=%d", Loading Loading @@ -5859,7 +5864,7 @@ static int cam_ife_mgr_cmd(void *hw_mgr_priv, void *cmd_args) ctx->last_dump_flush_req_id = ctx->applied_req_id; rc = cam_ife_mgr_handle_reg_dump(ctx, ctx->reg_dump_buf_desc, ctx->num_reg_dump_buf, CAM_ISP_PACKET_META_REG_DUMP_ON_FLUSH); CAM_ISP_PACKET_META_REG_DUMP_ON_FLUSH, NULL, false); if (rc) { CAM_ERR(CAM_ISP, "Reg dump on flush failed req id: %llu rc: %d", Loading @@ -5875,7 +5880,7 @@ static int cam_ife_mgr_cmd(void *hw_mgr_priv, void *cmd_args) ctx->last_dump_err_req_id = ctx->applied_req_id; rc = cam_ife_mgr_handle_reg_dump(ctx, ctx->reg_dump_buf_desc, ctx->num_reg_dump_buf, CAM_ISP_PACKET_META_REG_DUMP_ON_ERROR); CAM_ISP_PACKET_META_REG_DUMP_ON_ERROR, NULL, false); if (rc) { CAM_ERR(CAM_ISP, "Reg dump on error failed req id: %llu rc: %d", Loading @@ -5894,6 +5899,155 @@ static int cam_ife_mgr_cmd(void *hw_mgr_priv, void *cmd_args) return rc; } static int cam_ife_mgr_user_dump_hw( struct cam_ife_hw_mgr_ctx *ife_ctx, struct cam_hw_dump_args *dump_args) { int rc = 0; struct cam_hw_soc_dump_args soc_dump_args; if (!ife_ctx || !dump_args) { CAM_ERR(CAM_ISP, "Invalid parameters %pK %pK", ife_ctx, dump_args); rc = -EINVAL; goto end; } soc_dump_args.buf_handle = dump_args->buf_handle; soc_dump_args.request_id = dump_args->request_id; soc_dump_args.offset = dump_args->offset; rc = cam_ife_mgr_handle_reg_dump(ife_ctx, ife_ctx->reg_dump_buf_desc, ife_ctx->num_reg_dump_buf, CAM_ISP_PACKET_META_REG_DUMP_ON_ERROR, &soc_dump_args, true); if (rc) { CAM_ERR(CAM_ISP, "Dump failed req: %lld handle %u offset %u", dump_args->request_id, dump_args->buf_handle, dump_args->offset); goto end; } dump_args->offset = soc_dump_args.offset; end: 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_isp_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; /* for some targets, information about the IFE registers to be dumped * is already submitted with the hw manager. In this case, we * can dump just the related registers and skip going to core files. */ if (ife_ctx->num_reg_dump_buf) { cam_ife_mgr_user_dump_hw(ife_ctx, dump_args); goto end; } rc = cam_mem_get_cpu_buf(dump_args->buf_handle, &isp_hw_dump_args.cpu_addr, &isp_hw_dump_args.buf_len); if (rc) { CAM_ERR(CAM_ISP, "Invalid handle %u rc %d", dump_args->buf_handle, 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; end: CAM_DBG(CAM_ISP, "offset %u", dump_args->offset); 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 @@ -6879,6 +7033,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/cam_cdm/cam_cdm_util.c +169 −1 Original line number Diff line number Diff line // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include <linux/types.h> Loading Loading @@ -823,3 +823,171 @@ void cam_cdm_util_dump_cmd_buf( } } while (buf_now <= cmd_buf_end); } static uint32_t cam_cdm_util_dump_reg_cont_cmd_v2( uint32_t *cmd_buf_addr, struct cam_cdm_cmd_buf_dump_info *dump_info) { int i; long ret; uint8_t *dst; size_t remain_len; uint32_t *temp_ptr = cmd_buf_addr; uint32_t *addr, *start; uint32_t min_len; struct cdm_regcontinuous_cmd *p_regcont_cmd; struct cam_cdm_cmd_dump_header *hdr; p_regcont_cmd = (struct cdm_regcontinuous_cmd *)temp_ptr; temp_ptr += cdm_get_cmd_header_size(CAM_CDM_CMD_REG_CONT); ret = cdm_get_cmd_header_size(CAM_CDM_CMD_REG_CONT); min_len = (sizeof(uint32_t) * p_regcont_cmd->count) + sizeof(struct cam_cdm_cmd_dump_header) + (2 * sizeof(uint32_t)); remain_len = dump_info->dst_max_size - dump_info->dst_offset; if (remain_len < min_len) { CAM_WARN_RATE_LIMIT(CAM_CDM, "Dump buffer exhaust remain %zu min %u", remain_len, min_len); return ret; } dst = (char *)dump_info->dst_start + dump_info->dst_offset; hdr = (struct cam_cdm_cmd_dump_header *)dst; scnprintf(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 uint32_t cam_cdm_util_dump_reg_random_cmd_v2( uint32_t *cmd_buf_addr, struct cam_cdm_cmd_buf_dump_info *dump_info) { int i; long ret; uint8_t *dst; uint32_t *temp_ptr = cmd_buf_addr; uint32_t *addr, *start; size_t remain_len; uint32_t min_len; struct cdm_regrandom_cmd *p_regrand_cmd; struct cam_cdm_cmd_dump_header *hdr; p_regrand_cmd = (struct cdm_regrandom_cmd *)temp_ptr; temp_ptr += cdm_get_cmd_header_size(CAM_CDM_CMD_REG_RANDOM); ret = cdm_get_cmd_header_size(CAM_CDM_CMD_REG_RANDOM); min_len = (2 * sizeof(uint32_t) * p_regrand_cmd->count) + sizeof(struct cam_cdm_cmd_dump_header) + sizeof(uint32_t); remain_len = dump_info->dst_max_size - dump_info->dst_offset; if (remain_len < min_len) { CAM_WARN_RATE_LIMIT(CAM_CDM, "Dump buffer exhaust remain %zu min %u", remain_len, min_len); return ret; } dst = (char *)dump_info->dst_start + dump_info->dst_offset; hdr = (struct cam_cdm_cmd_dump_header *)dst; scnprintf(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; } int cam_cdm_util_dump_cmd_bufs_v2( struct cam_cdm_cmd_buf_dump_info *dump_info) { uint32_t cmd; uint32_t *buf_now; int rc = 0; if (!dump_info || !dump_info->src_start || !dump_info->src_end || !dump_info->dst_start) { CAM_INFO(CAM_CDM, "Invalid args"); return -EINVAL; } buf_now = dump_info->src_start; do { if (dump_info->dst_offset >= dump_info->dst_max_size) { CAM_WARN(CAM_CDM, "Dump overshoot offset %zu size %zu", dump_info->dst_offset, dump_info->dst_max_size); return -ENOSPC; } cmd = *buf_now; 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 += cdm_get_cmd_header_size(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 += cdm_get_cmd_header_size( CAM_CDM_CMD_BUFF_INDIRECT); break; case CAM_CDM_CMD_GEN_IRQ: buf_now += cdm_get_cmd_header_size( CAM_CDM_CMD_GEN_IRQ); break; case CAM_CDM_CMD_WAIT_EVENT: buf_now += cdm_get_cmd_header_size( CAM_CDM_CMD_WAIT_EVENT); break; case CAM_CDM_CMD_CHANGE_BASE: buf_now += cdm_get_cmd_header_size( CAM_CDM_CMD_CHANGE_BASE); break; case CAM_CDM_CMD_PERF_CTRL: buf_now += cdm_get_cmd_header_size( CAM_CDM_CMD_PERF_CTRL); break; default: CAM_ERR(CAM_CDM, "Invalid CMD: 0x%x", cmd); buf_now++; break; } } while (buf_now <= dump_info->src_end); return rc; }
drivers/cam_cdm/cam_cdm_util.h +44 −1 Original line number Diff line number Diff line /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #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 @@ -178,6 +181,34 @@ uint32_t *(*cdm_write_wait_prefetch_disable)( uint32_t mask2); }; /** * struct cam_cdm_cmd_buf_dump_info; - Camera CDM dump info * @dst_offset: dst offset * @dst_max_size max size of destination buffer * @src_start: source start address * @src_end: source end address * @dst_start: dst start address */ struct cam_cdm_cmd_buf_dump_info { size_t dst_offset; size_t dst_max_size; uint32_t *src_start; uint32_t *src_end; uintptr_t dst_start; }; /** * 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 { uint8_t tag[CAM_CDM_CMD_TAG_MAX_LEN]; uint64_t size; uint32_t word_size; }; /** * cam_cdm_util_log_cmd_bufs() * Loading @@ -190,6 +221,18 @@ uint32_t *(*cdm_write_wait_prefetch_disable)( 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 cdm command buffers * to a buffer * * @dump_info: Information about source and destination buffers * * return SUCCESS/FAILURE */ int cam_cdm_util_dump_cmd_bufs_v2( struct cam_cdm_cmd_buf_dump_info *dump_info); #endif /* _CAM_CDM_UTIL_H_ */
drivers/cam_isp/cam_isp_context.c +430 −16 File changed.Preview size limit exceeded, changes collapsed. Show changes
drivers/cam_isp/cam_isp_context.h +72 −1 Original line number Diff line number Diff line /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_ISP_CONTEXT_H_ Loading Loading @@ -33,6 +33,27 @@ */ #define CAM_ISP_CTX_STATE_MONITOR_MAX_ENTRIES 40 /* * Threshold response time in us beyond which a request is not expected * to be with IFE hw */ #define CAM_ISP_CTX_RESPONSE_TIME_THRESHOLD 100000 /* Number of words for dumping isp context */ #define CAM_ISP_CTX_DUMP_NUM_WORDS 5 /* Number of words for dumping isp context events*/ #define CAM_ISP_CTX_DUMP_EVENT_NUM_WORDS 3 /* Number of words for dumping request info*/ #define CAM_ISP_CTX_DUMP_REQUEST_NUM_WORDS 2 /* Maximum entries in event record */ #define CAM_ISP_CTX_EVENT_RECORD_MAX_ENTRIES 20 /* Maximum length of tag while dumping */ #define CAM_ISP_CONTEXT_DUMP_TAG_MAX_LEN 32 /* forward declaration */ struct cam_isp_context; Loading @@ -55,6 +76,19 @@ enum cam_isp_ctx_activated_substate { CAM_ISP_CTX_ACTIVATED_MAX, }; /** * enum cam_isp_ctx_event_type - events for a request * */ enum cam_isp_ctx_event { CAM_ISP_CTX_EVENT_SUBMIT, CAM_ISP_CTX_EVENT_APPLY, CAM_ISP_CTX_EVENT_EPOCH, CAM_ISP_CTX_EVENT_RUP, CAM_ISP_CTX_EVENT_BUFDONE, CAM_ISP_CTX_EVENT_MAX }; /** * enum cam_isp_state_change_trigger - Different types of ISP events * Loading Loading @@ -109,6 +143,7 @@ struct cam_isp_ctx_irq_ops { * @bubble_report: Flag to track if bubble report is active on * current request * @hw_update_data: HW update data for this request * @event_timestamp: Timestamp for different stage of request * @reapply: True if reapplying after bubble * */ Loading @@ -125,6 +160,8 @@ struct cam_isp_ctx_req { uint32_t num_acked; int32_t bubble_report; struct cam_isp_prepare_hw_update_data hw_update_data; ktime_t event_timestamp [CAM_ISP_CTX_EVENT_MAX]; bool bubble_detected; bool reapply; }; Loading Loading @@ -160,8 +197,23 @@ struct cam_isp_context_state_monitor { struct cam_isp_context_req_id_info { int64_t last_bufdone_req_id; }; /** * * * struct cam_isp_context_event_record - Information for last 20 Events * for a request; Submit, Apply, EPOCH, RUP, Buf done. * * @req_id: Last applied request id * @timestamp: Timestamp for the event * */ struct cam_isp_context_event_record { uint64_t req_id; ktime_t timestamp; }; /** * struct cam_isp_context - ISP context object * * @base: Common context object pointer Loading @@ -185,6 +237,8 @@ struct cam_isp_context_req_id_info { * @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 * @rdi_only_context: Get context type information. * true, if context is rdi only context * @hw_acquired: Indicate whether HW resources are acquired Loading Loading @@ -218,6 +272,10 @@ struct cam_isp_context { 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]; bool rdi_only_context; bool hw_acquired; bool init_received; Loading @@ -226,6 +284,19 @@ struct cam_isp_context { uint32_t isp_device_type; }; /** * struct cam_isp_context_dump_header - ISP context dump header * @tag: Tag name for the header * @word_size: Size of word * @size: Size of data * */ struct cam_isp_context_dump_header { uint8_t tag[CAM_ISP_CONTEXT_DUMP_TAG_MAX_LEN]; uint64_t size; uint32_t word_size; }; /** * cam_isp_context_init() * Loading
drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +160 −5 Original line number Diff line number Diff line Loading @@ -134,7 +134,9 @@ static int cam_ife_mgr_regspace_data_cb(uint32_t reg_base_type, static int cam_ife_mgr_handle_reg_dump(struct cam_ife_hw_mgr_ctx *ctx, struct cam_cmd_buf_desc *reg_dump_buf_desc, uint32_t num_reg_dump_buf, uint32_t meta_type) uint32_t meta_type, void *soc_dump_args, bool user_triggered_dump) { int rc = 0, i; Loading @@ -157,7 +159,9 @@ static int cam_ife_mgr_handle_reg_dump(struct cam_ife_hw_mgr_ctx *ctx, rc = cam_soc_util_reg_dump_to_cmd_buf(ctx, ®_dump_buf_desc[i], ctx->applied_req_id, cam_ife_mgr_regspace_data_cb); cam_ife_mgr_regspace_data_cb, soc_dump_args, user_triggered_dump); if (rc) { CAM_ERR(CAM_ISP, "Reg dump failed at idx: %d, rc: %d req_id: %llu meta type: %u", Loading Loading @@ -2423,7 +2427,8 @@ void cam_ife_cam_cdm_callback(uint32_t handle, void *userdata, cam_ife_mgr_handle_reg_dump(ctx, hw_update_data->reg_dump_buf_desc, hw_update_data->num_reg_dump_buf, CAM_ISP_PACKET_META_REG_DUMP_PER_REQUEST); CAM_ISP_PACKET_META_REG_DUMP_PER_REQUEST, NULL, false); CAM_DBG(CAM_ISP, "Called by CDM hdl=%x, udata=%pK, status=%d, cookie=%llu ctx_index=%d", Loading Loading @@ -5859,7 +5864,7 @@ static int cam_ife_mgr_cmd(void *hw_mgr_priv, void *cmd_args) ctx->last_dump_flush_req_id = ctx->applied_req_id; rc = cam_ife_mgr_handle_reg_dump(ctx, ctx->reg_dump_buf_desc, ctx->num_reg_dump_buf, CAM_ISP_PACKET_META_REG_DUMP_ON_FLUSH); CAM_ISP_PACKET_META_REG_DUMP_ON_FLUSH, NULL, false); if (rc) { CAM_ERR(CAM_ISP, "Reg dump on flush failed req id: %llu rc: %d", Loading @@ -5875,7 +5880,7 @@ static int cam_ife_mgr_cmd(void *hw_mgr_priv, void *cmd_args) ctx->last_dump_err_req_id = ctx->applied_req_id; rc = cam_ife_mgr_handle_reg_dump(ctx, ctx->reg_dump_buf_desc, ctx->num_reg_dump_buf, CAM_ISP_PACKET_META_REG_DUMP_ON_ERROR); CAM_ISP_PACKET_META_REG_DUMP_ON_ERROR, NULL, false); if (rc) { CAM_ERR(CAM_ISP, "Reg dump on error failed req id: %llu rc: %d", Loading @@ -5894,6 +5899,155 @@ static int cam_ife_mgr_cmd(void *hw_mgr_priv, void *cmd_args) return rc; } static int cam_ife_mgr_user_dump_hw( struct cam_ife_hw_mgr_ctx *ife_ctx, struct cam_hw_dump_args *dump_args) { int rc = 0; struct cam_hw_soc_dump_args soc_dump_args; if (!ife_ctx || !dump_args) { CAM_ERR(CAM_ISP, "Invalid parameters %pK %pK", ife_ctx, dump_args); rc = -EINVAL; goto end; } soc_dump_args.buf_handle = dump_args->buf_handle; soc_dump_args.request_id = dump_args->request_id; soc_dump_args.offset = dump_args->offset; rc = cam_ife_mgr_handle_reg_dump(ife_ctx, ife_ctx->reg_dump_buf_desc, ife_ctx->num_reg_dump_buf, CAM_ISP_PACKET_META_REG_DUMP_ON_ERROR, &soc_dump_args, true); if (rc) { CAM_ERR(CAM_ISP, "Dump failed req: %lld handle %u offset %u", dump_args->request_id, dump_args->buf_handle, dump_args->offset); goto end; } dump_args->offset = soc_dump_args.offset; end: 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_isp_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; /* for some targets, information about the IFE registers to be dumped * is already submitted with the hw manager. In this case, we * can dump just the related registers and skip going to core files. */ if (ife_ctx->num_reg_dump_buf) { cam_ife_mgr_user_dump_hw(ife_ctx, dump_args); goto end; } rc = cam_mem_get_cpu_buf(dump_args->buf_handle, &isp_hw_dump_args.cpu_addr, &isp_hw_dump_args.buf_len); if (rc) { CAM_ERR(CAM_ISP, "Invalid handle %u rc %d", dump_args->buf_handle, 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; end: CAM_DBG(CAM_ISP, "offset %u", dump_args->offset); 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 @@ -6879,6 +7033,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