diff --git a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c index 021c010824..81170e324f 100644 --- a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c +++ b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c @@ -2096,6 +2096,7 @@ static int cam_icp_mgr_handle_frame_process(uint32_t *msg_ptr, int flag) struct cam_hw_done_event_data buf_data; uint32_t clk_type; uint32_t event_id; + struct cam_hangdump_mem_regions *mem_regions = NULL; ioconfig_ack = (struct hfi_msg_ipebps_async_ack *)msg_ptr; request_id = ioconfig_ack->user_data2; @@ -2160,6 +2161,23 @@ static int cam_icp_mgr_handle_frame_process(uint32_t *msg_ptr, int flag) event_id = CAM_CTX_EVT_ID_SUCCESS; } + if (cam_presil_mode_enabled()) { + mem_regions = &hfi_frame_process->hangdump_mem_regions[idx]; + CAM_INFO(CAM_ICP, "Hangdump Num Regions %d", + mem_regions->num_mem_regions); + for (i = 0; i < mem_regions->num_mem_regions; i++) { + CAM_INFO(CAM_PRESIL, "Hangdump Mem %d handle 0x%08x offset 0x%08x len %u", + i, mem_regions->mem_info_array[i].mem_handle, + mem_regions->mem_info_array[i].offset, + mem_regions->mem_info_array[i].size); + cam_mem_mgr_retrieve_buffer_from_presil( + mem_regions->mem_info_array[i].mem_handle, + mem_regions->mem_info_array[i].size, + mem_regions->mem_info_array[i].offset, + icp_hw_mgr.iommu_hdl); + } + } + buf_data.request_id = hfi_frame_process->request_id[idx]; ctx_data->ctxt_event_cb(ctx_data->context_priv, event_id, &buf_data); hfi_frame_process->request_id[idx] = 0; @@ -4793,6 +4811,48 @@ end: return rc; } +static int cam_icp_process_presil_hangdump_info( + struct cam_icp_hw_ctx_data *ctx_data, + struct cam_cmd_mem_regions *cmd_mem_regions, + uint32_t index) +{ + int i = 0; + struct cam_hangdump_mem_regions *mem_regions = NULL; + + if (!ctx_data || !cmd_mem_regions) { + CAM_ERR(CAM_ICP, "Invalid hangdump info blob ctx %pK mem_region %pK", + ctx_data, cmd_mem_regions); + return -EINVAL; + } + + if ((cmd_mem_regions->num_regions == 0) || + (cmd_mem_regions->num_regions > HANG_DUMP_REGIONS_MAX)) { + CAM_ERR(CAM_ICP, "Invalid num hangdump mem regions %d ", + cmd_mem_regions->num_regions); + return -EINVAL; + } + + mem_regions = &ctx_data->hfi_frame_process.hangdump_mem_regions[index]; + CAM_INFO(CAM_ICP, "Hangdump Mem Num Regions %d index %d mem_regions 0x%pK", + cmd_mem_regions->num_regions, index, mem_regions); + + for (i = 0; i < cmd_mem_regions->num_regions; i++) { + mem_regions->mem_info_array[i].mem_handle = + cmd_mem_regions->map_info_array[i].mem_handle; + mem_regions->mem_info_array[i].offset = + cmd_mem_regions->map_info_array[i].offset; + mem_regions->mem_info_array[i].size = + cmd_mem_regions->map_info_array[i].size; + CAM_INFO(CAM_ICP, "Hangdump Mem Region %u mem_handle 0x%08x iova 0x%08x len %u", + i, cmd_mem_regions->map_info_array[i].mem_handle, + (uint32_t)cmd_mem_regions->map_info_array[i].offset, + (uint32_t)cmd_mem_regions->map_info_array[i].size); + } + mem_regions->num_mem_regions = cmd_mem_regions->num_regions; + + return 0; +} + static int cam_icp_packet_generic_blob_handler(void *user_data, uint32_t blob_type, uint32_t blob_size, uint8_t *blob_data) { @@ -4989,6 +5049,21 @@ static int cam_icp_packet_generic_blob_handler(void *user_data, } break; + case CAM_ICP_CMD_GENERIC_BLOB_PRESIL_HANGDUMP: + if (cam_presil_mode_enabled()) { + cmd_mem_regions = (struct cam_cmd_mem_regions *)blob_data; + if (cmd_mem_regions->num_regions <= 0) { + CAM_INFO(CAM_ICP, "Pre-sil Hangdump disabled %u", + cmd_mem_regions->num_regions); + } else { + CAM_INFO(CAM_ICP, "Pre-sil Hangdump enabled %u entries index %d", + cmd_mem_regions->num_regions, index); + rc = cam_icp_process_presil_hangdump_info(ctx_data, + cmd_mem_regions, index); + } + } + break; + default: CAM_WARN(CAM_ICP, "Invalid blob type %d", blob_type); break; @@ -6497,6 +6572,7 @@ int cam_icp_hw_mgr_init(struct device_node *of_node, uint64_t *hw_mgr_hdl, struct cam_hw_mgr_intf *hw_mgr_intf; struct cam_cpas_query_cap query; uint32_t cam_caps, camera_hw_version; + uint32_t size = 0; hw_mgr_intf = (struct cam_hw_mgr_intf *)hw_mgr_hdl; if (!of_node || !hw_mgr_intf) { @@ -6524,8 +6600,14 @@ int cam_icp_hw_mgr_init(struct device_node *of_node, uint64_t *hw_mgr_hdl, mutex_init(&icp_hw_mgr.hw_mgr_mutex); spin_lock_init(&icp_hw_mgr.hw_mgr_lock); - for (i = 0; i < CAM_ICP_CTX_MAX; i++) + for (i = 0; i < CAM_ICP_CTX_MAX; i++) { mutex_init(&icp_hw_mgr.ctx_data[i].ctx_mutex); + if (cam_presil_mode_enabled()) { + size = CAM_FRAME_CMD_MAX * sizeof(struct cam_hangdump_mem_regions); + icp_hw_mgr.ctx_data[i].hfi_frame_process.hangdump_mem_regions = + kzalloc(size, GFP_KERNEL); + } + } rc = cam_cpas_get_hw_info(&query.camera_family, &query.camera_version, &query.cpas_version, @@ -6602,8 +6684,11 @@ icp_get_hdl_failed: cam_icp_mgr_free_devs(); destroy_mutex: mutex_destroy(&icp_hw_mgr.hw_mgr_mutex); - for (i = 0; i < CAM_ICP_CTX_MAX; i++) + for (i = 0; i < CAM_ICP_CTX_MAX; i++) { mutex_destroy(&icp_hw_mgr.ctx_data[i].ctx_mutex); + if (cam_presil_mode_enabled()) + kfree(icp_hw_mgr.ctx_data[i].hfi_frame_process.hangdump_mem_regions); + } return rc; } @@ -6617,6 +6702,9 @@ void cam_icp_hw_mgr_deinit(void) cam_icp_mgr_destroy_wq(); cam_icp_mgr_free_devs(); mutex_destroy(&icp_hw_mgr.hw_mgr_mutex); - for (i = 0; i < CAM_ICP_CTX_MAX; i++) + for (i = 0; i < CAM_ICP_CTX_MAX; i++) { mutex_destroy(&icp_hw_mgr.ctx_data[i].ctx_mutex); + if (cam_presil_mode_enabled()) + kfree(icp_hw_mgr.ctx_data[i].hfi_frame_process.hangdump_mem_regions); + } } diff --git a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h index 39c75de3d5..3792241e92 100644 --- a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h +++ b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h @@ -173,6 +173,21 @@ struct cam_icp_clk_bw_req_internal_v2 { struct cam_axi_per_path_bw_vote axi_path[CAM_ICP_MAX_PER_PATH_VOTES]; }; +#define HANG_DUMP_REGIONS_MAX 10 + +/** + * struct cam_hangdump_mem_regions - + * List of multiple memory descriptors of different + * regions + * + * @num_regions : Number of regions + * @map_info_array : Array of all the regions + */ +struct cam_hangdump_mem_regions { + uint32_t num_mem_regions; + struct cam_cmd_mem_region_info mem_info_array[HANG_DUMP_REGIONS_MAX]; +}; + /** * struct hfi_frame_process_info * @hfi_frame_cmd: Frame process command info @@ -187,6 +202,7 @@ struct cam_icp_clk_bw_req_internal_v2 { * @clk_info_v2: Clock info for AXI bw voting v2 * @frame_info: information needed to process request * @submit_timestamp: Submit timestamp to hw + * @hangdump_mem_regions: Mem regions for hangdump */ struct hfi_frame_process_info { struct hfi_cmd_ipebps_async hfi_frame_cmd[CAM_FRAME_CMD_MAX]; @@ -203,6 +219,7 @@ struct hfi_frame_process_info { struct cam_icp_clk_bw_req_internal_v2 clk_info_v2[CAM_FRAME_CMD_MAX]; struct icp_frame_info frame_info[CAM_FRAME_CMD_MAX]; ktime_t submit_timestamp[CAM_FRAME_CMD_MAX]; + struct cam_hangdump_mem_regions *hangdump_mem_regions; }; /** @@ -230,6 +247,7 @@ struct cam_ctx_clk_info { struct cam_axi_per_path_bw_vote axi_path[CAM_ICP_MAX_PER_PATH_VOTES]; bool bw_included; }; + /** * struct cam_icp_hw_ctx_data * @context_priv: Context private data diff --git a/include/uapi/camera/media/cam_icp.h b/include/uapi/camera/media/cam_icp.h index b4975287b1..05ca77a472 100644 --- a/include/uapi/camera/media/cam_icp.h +++ b/include/uapi/camera/media/cam_icp.h @@ -74,11 +74,12 @@ #define CAM_ICP_CMD_META_GENERIC_BLOB 0x1 /* Generic blob types */ -#define CAM_ICP_CMD_GENERIC_BLOB_CLK 0x1 -#define CAM_ICP_CMD_GENERIC_BLOB_CFG_IO 0x2 -#define CAM_ICP_CMD_GENERIC_BLOB_FW_MEM_MAP 0x3 -#define CAM_ICP_CMD_GENERIC_BLOB_FW_MEM_UNMAP 0x4 -#define CAM_ICP_CMD_GENERIC_BLOB_CLK_V2 0x5 +#define CAM_ICP_CMD_GENERIC_BLOB_CLK 0x1 +#define CAM_ICP_CMD_GENERIC_BLOB_CFG_IO 0x2 +#define CAM_ICP_CMD_GENERIC_BLOB_FW_MEM_MAP 0x3 +#define CAM_ICP_CMD_GENERIC_BLOB_FW_MEM_UNMAP 0x4 +#define CAM_ICP_CMD_GENERIC_BLOB_CLK_V2 0x5 +#define CAM_ICP_CMD_GENERIC_BLOB_PRESIL_HANGDUMP 0x6 /** * struct cam_icp_clk_bw_request_v2