Procházet zdrojové kódy

msm: camera: icp: LDAR Dump ICP Extension

Extension of Let's do a reset (LDAR) for ICP to include more info.

CRs-Fixed: 3105929
Change-Id: I5fee181d009a8d69e8d3e673a552b289f72fb4aa
Signed-off-by: Joshua Florez <[email protected]>
Joshua Florez před 3 roky
rodič
revize
5ce71f412e

+ 2 - 1
drivers/cam_core/cam_context.h

@@ -1,6 +1,7 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /*
  * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
  */
 
 #ifndef _CAM_CONTEXT_H_
@@ -27,7 +28,7 @@ struct cam_context;
 #define CAM_CTX_RES_MAX              20
 
 /* max tag  dump header string length*/
-#define CAM_CTXT_DUMP_TAG_MAX_LEN 32
+#define CAM_CTXT_DUMP_TAG_MAX_LEN 64
 
 /* Number of words to be dumped for context*/
 #define CAM_CTXT_DUMP_NUM_WORDS 10

+ 107 - 35
drivers/cam_core/cam_context_utils.c

@@ -1217,19 +1217,17 @@ end:
 	return rc;
 }
 
-static int cam_context_dump_context(struct cam_context *ctx,
+static int cam_context_user_dump(struct cam_context *ctx,
 	struct cam_hw_dump_args *dump_args)
 {
-	int                             rc;
-	int                             i;
-	size_t                          buf_len;
-	size_t                          remain_len;
-	uint8_t                        *dst;
-	uint64_t                       *addr, *start;
-	uint32_t                        min_len;
-	uintptr_t                       cpu_addr;
-	struct cam_ctx_request         *req;
-	struct cam_context_dump_header *hdr;
+	int                              rc, i;
+	struct cam_ctx_request          *req, *req_temp;
+	struct cam_context_dump_header  *hdr;
+	uint8_t                         *dst;
+	uint64_t                        *addr, *start;
+	uint32_t                         min_len;
+	size_t                           buf_len, remain_len;
+	uintptr_t                        cpu_addr;
 
 	if (!ctx || !dump_args) {
 		CAM_ERR(CAM_CORE, "Invalid parameters %pK %pK",
@@ -1247,7 +1245,8 @@ static int cam_context_dump_context(struct cam_context *ctx,
 	req = list_first_entry(&ctx->active_req_list,
 		struct cam_ctx_request, list);
 	spin_unlock_bh(&ctx->lock);
-	rc  = cam_mem_get_cpu_buf(dump_args->buf_handle,
+
+	rc = cam_mem_get_cpu_buf(dump_args->buf_handle,
 		&cpu_addr, &buf_len);
 	if (rc) {
 		CAM_ERR(CAM_CTXT, "Invalid hdl %u rc %d",
@@ -1261,38 +1260,111 @@ static int cam_context_dump_context(struct cam_context *ctx,
 	}
 
 	remain_len = buf_len - dump_args->offset;
-	min_len =  sizeof(struct cam_context_dump_header) +
-		    (CAM_CTXT_DUMP_NUM_WORDS + req->num_in_map_entries +
-		    (req->num_out_map_entries * 2)) * sizeof(uint64_t);
+	min_len = sizeof(struct cam_context_dump_header) +
+		(CAM_CTXT_DUMP_NUM_WORDS + req->num_in_map_entries +
+		(req->num_out_map_entries * 2)) * sizeof(uint64_t);
 
 	if (remain_len < min_len) {
 		CAM_WARN(CAM_CTXT, "dump buffer exhaust remain %zu min %u",
 			remain_len, min_len);
 		return -ENOSPC;
 	}
+
+	/* Dump context info */
 	dst = (uint8_t *)cpu_addr + dump_args->offset;
 	hdr = (struct cam_context_dump_header *)dst;
 	scnprintf(hdr->tag, CAM_CTXT_DUMP_TAG_MAX_LEN,
-		"%s_CTXT_DUMP:", ctx->dev_name);
+		"%s_CTX_INFO:", ctx->dev_name);
 	hdr->word_size = sizeof(uint64_t);
 	addr = (uint64_t *)(dst + sizeof(struct cam_context_dump_header));
 	start = addr;
-	*addr++ = ctx->ctx_id;
+	*addr++ = ctx->hw_mgr_ctx_id;
+	*addr++ = ctx->dev_id;
+	*addr++ = ctx->dev_hdl;
+	*addr++ = ctx->link_hdl;
+	*addr++ = ctx->session_hdl;
 	*addr++ = refcount_read(&(ctx->refcount.refcount));
 	*addr++ = ctx->last_flush_req;
 	*addr++ = ctx->state;
-	*addr++ = req->num_out_map_entries;
-	for (i = 0; i < req->num_out_map_entries; i++) {
-		*addr++ = req->out_map_entries[i].resource_handle;
-		*addr++ = req->out_map_entries[i].sync_id;
+	hdr->size = hdr->word_size * (addr - start);
+	dump_args->offset += hdr->size +
+		sizeof(struct cam_context_dump_header);
+
+	/* Dump pending request IDs */
+	dst = (uint8_t *)cpu_addr + dump_args->offset;
+	hdr = (struct cam_context_dump_header *)dst;
+	scnprintf(hdr->tag, CAM_CTXT_DUMP_TAG_MAX_LEN,
+		"%s_OUT_FENCE_PENDING_REQUESTS:", ctx->dev_name);
+	hdr->word_size = sizeof(uint64_t);
+	addr = (uint64_t *)(dst + sizeof(struct cam_context_dump_header));
+	start = addr;
+	if (!list_empty(&ctx->wait_req_list)) {
+		list_for_each_entry_safe(req, req_temp, &ctx->wait_req_list, list) {
+			*addr++ = req->request_id;
+		}
 	}
-	*addr++ = req->num_in_map_entries;
-	for (i = 0; i < req->num_in_map_entries; i++)
-		*addr++ = req->in_map_entries[i].sync_id;
 	hdr->size = hdr->word_size * (addr - start);
 	dump_args->offset += hdr->size +
 		sizeof(struct cam_context_dump_header);
-	return rc;
+
+	/* Dump applied request IDs */
+	dst = (uint8_t *)cpu_addr + dump_args->offset;
+	hdr = (struct cam_context_dump_header *)dst;
+	scnprintf(hdr->tag, CAM_CTXT_DUMP_TAG_MAX_LEN,
+		"%s_OUT_FENCE_APPLIED_REQUESTS:", ctx->dev_name);
+	hdr->word_size = sizeof(uint64_t);
+	addr = (uint64_t *)(dst + sizeof(struct cam_context_dump_header));
+	start = addr;
+	if (!list_empty(&ctx->pending_req_list)) {
+		list_for_each_entry_safe(req, req_temp, &ctx->pending_req_list, list) {
+			*addr++ = req->request_id;
+		}
+	}
+	hdr->size = hdr->word_size * (addr - start);
+	dump_args->offset += hdr->size +
+		sizeof(struct cam_context_dump_header);
+
+	/* Dump active request IDs */
+	dst = (uint8_t *)cpu_addr + dump_args->offset;
+	hdr = (struct cam_context_dump_header *)dst;
+	scnprintf(hdr->tag, CAM_CTXT_DUMP_TAG_MAX_LEN,
+		"%s_OUT_FENCE_ACTIVE_REQUESTS:", ctx->dev_name);
+	hdr->word_size = sizeof(uint64_t);
+	addr = (uint64_t *)(dst + sizeof(struct cam_context_dump_header));
+	start = addr;
+	if (!list_empty(&ctx->active_req_list)) {
+		list_for_each_entry_safe(req, req_temp, &ctx->active_req_list, list) {
+			*addr++ = req->request_id;
+		}
+	}
+	hdr->size = hdr->word_size * (addr - start);
+	dump_args->offset += hdr->size +
+		sizeof(struct cam_context_dump_header);
+
+	/* Dump active requests */
+	if (!list_empty(&ctx->active_req_list)) {
+		list_for_each_entry_safe(req, req_temp, &ctx->active_req_list, list) {
+			for (i = 0; i < req->num_out_map_entries; i++) {
+				dst = (uint8_t *)cpu_addr + dump_args->offset;
+				hdr = (struct cam_context_dump_header *)dst;
+				scnprintf(hdr->tag, CAM_CTXT_DUMP_TAG_MAX_LEN,
+					"%s_OUT_FENCE_REQUEST_ACTIVE.%d.%d.%d:",
+					ctx->dev_name,
+					req->out_map_entries[i].resource_handle,
+					&(req->out_map_entries[i].image_buf_addr),
+					req->out_map_entries[i].sync_id);
+				hdr->word_size = sizeof(uint64_t);
+				addr = (uint64_t *)(dst + sizeof(struct cam_context_dump_header));
+				start = addr;
+				*addr++ = req->request_id;
+				hdr->size = hdr->word_size * (addr - start);
+				dump_args->offset += hdr->size +
+					sizeof(struct cam_context_dump_header);
+			}
+		}
+	}
+
+	return 0;
 }
 
 int32_t cam_context_dump_dev_to_hw(struct cam_context *ctx,
@@ -1317,6 +1389,14 @@ int32_t cam_context_dump_dev_to_hw(struct cam_context *ctx,
 		dump_args.offset = cmd->offset;
 		dump_args.request_id = cmd->issue_req_id;
 		dump_args.error_type = cmd->error_type;
+
+		rc = cam_context_user_dump(ctx, &dump_args);
+		if (rc) {
+			CAM_ERR(CAM_CTXT, "[%s][%d] handle[%u] failed",
+				ctx->dev_name, ctx->ctx_id, dump_args.buf_handle);
+			return rc;
+		}
+
 		rc  = ctx->hw_mgr_intf->hw_dump(
 			ctx->hw_mgr_intf->hw_mgr_priv,
 			&dump_args);
@@ -1325,17 +1405,9 @@ int32_t cam_context_dump_dev_to_hw(struct cam_context *ctx,
 			    ctx->dev_name, ctx->ctx_id, dump_args.buf_handle);
 			return rc;
 		}
-		/* Offset will change if the issue request id is found with
-		 * the hw and has been lying with it beyond threshold time.
-		 * If offset does not change, do not dump the context
-		 * information as the current context has no problem with
-		 * the provided request id.
-		 */
+
+
 		if (dump_args.offset > cmd->offset) {
-			cam_context_dump_context(ctx, &dump_args);
-			CAM_INFO(CAM_CTXT, "[%s] ctx: %d Filled Length %u",
-				 ctx->dev_name, ctx->ctx_id,
-				 dump_args.offset - cmd->offset);
 			cmd->offset  = dump_args.offset;
 		}
 	} else {

+ 53 - 4
drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c

@@ -5763,17 +5763,19 @@ static int cam_icp_mgr_enqueue_abort(
 static int cam_icp_mgr_hw_dump(void *hw_priv, void *hw_dump_args)
 {
 	int                              rc;
-	int                              i;
+	int                              i, j;
 	size_t                           remain_len;
 	uint8_t                         *dst;
 	uint32_t                         min_len;
 	uint64_t                         diff;
 	uint64_t                        *addr, *start;
+	uint64_t                        *clk_addr, *clk_start;
+	uint32_t                        *mgr_addr, *mgr_start;
 	struct timespec64                cur_ts;
 	struct timespec64                req_ts;
 	ktime_t                          cur_time;
 	struct cam_hw_intf              *icp_dev_intf;
-	struct cam_icp_hw_mgr           *hw_mgr;
+	struct cam_icp_hw_mgr           *hw_mgr, *icp_mgr;
 	struct cam_hw_dump_args         *dump_args;
 	struct cam_icp_hw_ctx_data      *ctx_data;
 	struct cam_icp_dump_header      *hdr;
@@ -5843,6 +5845,52 @@ hw_dump:
 		return -ENOSPC;
 	}
 
+	/* Dumping clock and bandwidth info */
+	dst = (uint8_t *)icp_dump_args.cpu_addr + dump_args->offset;
+	hdr = (struct cam_icp_dump_header *)dst;
+	scnprintf(hdr->tag, CAM_ICP_DUMP_TAG_MAX_LEN, "ICP_HW_CLK:");
+	hdr->word_size = sizeof(uint64_t);
+	clk_addr = (uint64_t *)(dst + sizeof(struct cam_icp_dump_header));
+	clk_start = clk_addr;
+	*clk_addr++ = hw_mgr->clk_info[ICP_CLK_HW_BPS].prev_clk;
+	*clk_addr++ = hw_mgr->clk_info[ICP_CLK_HW_BPS].curr_clk;
+	*clk_addr++ = hw_mgr->clk_info[ICP_CLK_HW_IPE].prev_clk;
+	*clk_addr++ = hw_mgr->clk_info[ICP_CLK_HW_IPE].curr_clk;
+	for (j = 0; j < ctx_data->clk_info.num_paths; j++) {
+		*clk_addr++ = ctx_data->clk_info.axi_path[j].camnoc_bw;
+		*clk_addr++ = ctx_data->clk_info.axi_path[j].mnoc_ab_bw;
+		*clk_addr++ = ctx_data->clk_info.axi_path[j].mnoc_ib_bw;
+		*clk_addr++ = ctx_data->clk_info.axi_path[j].ddr_ab_bw;
+		*clk_addr++ = ctx_data->clk_info.axi_path[j].ddr_ib_bw;
+	}
+	hdr->size = hdr->word_size * (clk_addr - clk_start);
+	dump_args->offset += (hdr->size + sizeof(struct cam_icp_dump_header));
+
+	/* Dumping hw mgr info */
+	icp_mgr = &icp_hw_mgr;
+	dst = (uint8_t *)icp_dump_args.cpu_addr + dump_args->offset;
+	hdr = (struct cam_icp_dump_header *)dst;
+	scnprintf(hdr->tag, CAM_ICP_DUMP_TAG_MAX_LEN, "ICP_HW_MGR.%s:",
+		cam_icp_dev_type_to_name(ctx_data->icp_dev_acquire_info->dev_type));
+	hdr->word_size = sizeof(uint32_t);
+	mgr_addr = (uint32_t *)(dst + sizeof(struct cam_icp_dump_header));
+	mgr_start = mgr_addr;
+	*mgr_addr++ = atomic_read(&hw_mgr->recovery);
+	*mgr_addr++ = icp_mgr->icp_booted;
+	*mgr_addr++ = icp_mgr->icp_resumed;
+	*mgr_addr++ = icp_mgr->ipe_clk_state;
+	*mgr_addr++ = icp_mgr->bps_clk_state;
+	*mgr_addr++ = icp_mgr->disable_ubwc_comp;
+	*mgr_addr++ = icp_mgr->ipe0_enable;
+	*mgr_addr++ = icp_mgr->ipe1_enable;
+	*mgr_addr++ = icp_mgr->bps_enable;
+	*mgr_addr++ = icp_mgr->icp_pc_flag;
+	*mgr_addr++ = icp_mgr->ipe_bps_pc_flag;
+	*mgr_addr++ = icp_mgr->icp_use_pil;
+	hdr->size = hdr->word_size * (mgr_addr - mgr_start);
+	dump_args->offset += (hdr->size + sizeof(struct cam_icp_dump_header));
+
+	/* Dumping time info */
 	dst = (uint8_t *)icp_dump_args.cpu_addr + dump_args->offset;
 	hdr = (struct cam_icp_dump_header *)dst;
 	scnprintf(hdr->tag, CAM_ICP_DUMP_TAG_MAX_LEN, "ICP_REQ:");
@@ -5851,11 +5899,12 @@ hw_dump:
 	start = addr;
 	*addr++ = frm_process->request_id[i];
 	*addr++ = req_ts.tv_sec;
-	*addr++ = req_ts.tv_nsec/NSEC_PER_USEC;
+	*addr++ = req_ts.tv_nsec / NSEC_PER_USEC;
 	*addr++ = cur_ts.tv_sec;
-	*addr++ = cur_ts.tv_nsec/NSEC_PER_USEC;
+	*addr++ = cur_ts.tv_nsec / NSEC_PER_USEC;
 	hdr->size = hdr->word_size * (addr - start);
 	dump_args->offset += (hdr->size + sizeof(struct cam_icp_dump_header));
+
 	/* Dumping the fw image*/
 	icp_dump_args.offset = dump_args->offset;
 	icp_dev_intf = hw_mgr->icp_dev_intf;

+ 2 - 1
drivers/cam_icp/icp_hw/include/cam_icp_hw_mgr_intf.h

@@ -1,6 +1,7 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /*
  * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
  */
 
 #ifndef CAM_ICP_HW_MGR_INTF_H
@@ -27,7 +28,7 @@
 #define CAM_ICP_DEFAULT_AXI_PATH    CAM_AXI_PATH_DATA_ALL
 #define CAM_ICP_DEFAULT_AXI_TRANSAC CAM_AXI_TRANSACTION_READ
 
-#define CAM_ICP_DUMP_TAG_MAX_LEN 32
+#define CAM_ICP_DUMP_TAG_MAX_LEN 64
 #define CAM_ICP_DUMP_NUM_WORDS   5
 
 typedef void(*cam_icp_mini_dump_cb)(void *priv,