Răsfoiți Sursa

msm: camera: isp: Add per request reg dump to command buffer

For debugging, user space may request a specified register range
values to be dumped to a command buffer every request. Add
support for reg dump every request during cdm callback. Add debugfs
flag for making sure per request dump is not enabled by mistake.

CRs-Fixed: 2501003
Change-Id: I01a0f3bb00dd122b8037d513ec331c5c08fdf372
Signed-off-by: Mukund Madhusudan Atre <[email protected]>
Mukund Madhusudan Atre 5 ani în urmă
părinte
comite
4329af66bd

+ 146 - 111
drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c

@@ -58,6 +58,117 @@ static int cam_ife_hw_mgr_event_handler(
 	uint32_t                             evt_id,
 	void                                *evt_info);
 
+static int cam_ife_mgr_regspace_data_cb(uint32_t reg_base_type,
+	void *hw_mgr_ctx, struct cam_hw_soc_info **soc_info_ptr,
+	uint32_t *reg_base_idx)
+{
+	int rc = 0;
+	struct cam_ife_hw_mgr_res *hw_mgr_res;
+	struct cam_ife_hw_mgr_res *hw_mgr_res_temp;
+	struct cam_hw_soc_info    *soc_info = NULL;
+	struct cam_ife_hw_mgr_ctx *ctx =
+		(struct cam_ife_hw_mgr_ctx *) hw_mgr_ctx;
+
+	*soc_info_ptr = NULL;
+	list_for_each_entry_safe(hw_mgr_res, hw_mgr_res_temp,
+		&ctx->res_list_ife_src, list) {
+		if (hw_mgr_res->res_id != CAM_ISP_HW_VFE_IN_CAMIF)
+			continue;
+
+		switch (reg_base_type) {
+		case CAM_REG_DUMP_BASE_TYPE_CAMNOC:
+		case CAM_REG_DUMP_BASE_TYPE_ISP_LEFT:
+			if (!hw_mgr_res->hw_res[CAM_ISP_HW_SPLIT_LEFT])
+				continue;
+
+			rc = hw_mgr_res->hw_res[
+				CAM_ISP_HW_SPLIT_LEFT]->process_cmd(
+				hw_mgr_res->hw_res[CAM_ISP_HW_SPLIT_LEFT],
+				CAM_ISP_HW_CMD_QUERY_REGSPACE_DATA, &soc_info,
+				sizeof(void *));
+			if (rc) {
+				CAM_ERR(CAM_ISP,
+					"Failed in regspace data query split idx: %d rc : %d",
+					CAM_ISP_HW_SPLIT_LEFT, rc);
+				return rc;
+			}
+
+			if (reg_base_type == CAM_REG_DUMP_BASE_TYPE_ISP_LEFT)
+				*reg_base_idx = 0;
+			else
+				*reg_base_idx = 1;
+
+			*soc_info_ptr = soc_info;
+			break;
+		case CAM_REG_DUMP_BASE_TYPE_ISP_RIGHT:
+			if (!hw_mgr_res->hw_res[CAM_ISP_HW_SPLIT_RIGHT])
+				continue;
+
+			rc = hw_mgr_res->hw_res[
+				CAM_ISP_HW_SPLIT_RIGHT]->process_cmd(
+				hw_mgr_res->hw_res[CAM_ISP_HW_SPLIT_RIGHT],
+				CAM_ISP_HW_CMD_QUERY_REGSPACE_DATA, &soc_info,
+				sizeof(void *));
+			if (rc) {
+				CAM_ERR(CAM_ISP,
+					"Failed in regspace data query split idx: %d rc : %d",
+					CAM_ISP_HW_SPLIT_RIGHT, rc);
+				return rc;
+			}
+
+			*reg_base_idx = 0;
+			*soc_info_ptr = soc_info;
+			break;
+		default:
+			CAM_ERR(CAM_ISP,
+				"Unrecognized reg base type: %u",
+				reg_base_type);
+			return -EINVAL;
+		}
+
+		break;
+	}
+
+	return rc;
+}
+
+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)
+{
+	int rc = 0, i;
+
+	if (!num_reg_dump_buf || !reg_dump_buf_desc) {
+		CAM_DBG(CAM_ISP,
+			"Invalid args for reg dump req_id: [%llu] ctx idx: [%u] meta_type: [%u]",
+			ctx->applied_req_id, ctx->ctx_index, meta_type);
+		return rc;
+	}
+
+	if (!atomic_read(&ctx->cdm_done))
+		CAM_WARN_RATE_LIMIT(CAM_ISP,
+			"Reg dump values might be from more than one request");
+
+	for (i = 0; i < num_reg_dump_buf; i++) {
+		CAM_DBG(CAM_ISP, "Reg dump cmd meta data: %u req_type: %u",
+			reg_dump_buf_desc[i].meta_data, meta_type);
+		if (reg_dump_buf_desc[i].meta_data == meta_type) {
+			rc = cam_soc_util_reg_dump_to_cmd_buf(ctx,
+				&reg_dump_buf_desc[i],
+				ctx->applied_req_id,
+				cam_ife_mgr_regspace_data_cb);
+			if (rc) {
+				CAM_ERR(CAM_ISP,
+					"Reg dump failed at idx: %d, rc: %d req_id: %llu meta type: %u",
+					i, rc, ctx->applied_req_id, meta_type);
+				return rc;
+			}
+		}
+	}
+
+	return rc;
+}
+
 static int cam_ife_notify_safe_lut_scm(bool safe_trigger)
 {
 	uint32_t camera_hw_version, rc = 0;
@@ -2289,6 +2400,7 @@ err:
 void cam_ife_cam_cdm_callback(uint32_t handle, void *userdata,
 	enum cam_cdm_cb_status status, uint64_t cookie)
 {
+	struct cam_isp_prepare_hw_update_data *hw_update_data = NULL;
 	struct cam_ife_hw_mgr_ctx *ctx = NULL;
 
 	if (!userdata) {
@@ -2296,11 +2408,18 @@ void cam_ife_cam_cdm_callback(uint32_t handle, void *userdata,
 		return;
 	}
 
-	ctx = userdata;
+	hw_update_data = (struct cam_isp_prepare_hw_update_data *)userdata;
+	ctx = (struct cam_ife_hw_mgr_ctx *)hw_update_data->ife_mgr_ctx;
 
 	if (status == CAM_CDM_CB_STATUS_BL_SUCCESS) {
 		complete_all(&ctx->config_done_complete);
 		atomic_set(&ctx->cdm_done, 1);
+		if (g_ife_hw_mgr.debug_cfg.per_req_reg_dump)
+			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_DBG(CAM_ISP,
 			"Called by CDM hdl=%x, udata=%pK, status=%d, cookie=%llu ctx_index=%d",
 			 handle, userdata, status, cookie, ctx->ctx_index);
@@ -3237,6 +3356,7 @@ static int cam_ife_mgr_config_hw(void *hw_mgr_priv,
 		return -EINVAL;
 
 	hw_update_data = (struct cam_isp_prepare_hw_update_data  *) cfg->priv;
+	hw_update_data->ife_mgr_ctx = ctx;
 
 	CAM_DBG(CAM_ISP, "Ctx[%pK][%d] : Applying Req %lld",
 		ctx, ctx->ctx_index, cfg->request_id);
@@ -3282,7 +3402,7 @@ static int cam_ife_mgr_config_hw(void *hw_mgr_priv,
 		cdm_cmd->cmd_arrary_count = cfg->num_hw_update_entries;
 		cdm_cmd->type = CAM_CDM_BL_CMD_TYPE_MEM_HANDLE;
 		cdm_cmd->flag = true;
-		cdm_cmd->userdata = ctx;
+		cdm_cmd->userdata = hw_update_data;
 		cdm_cmd->cookie = cfg->request_id;
 
 		for (i = 0 ; i <= cfg->num_hw_update_entries; i++) {
@@ -5374,8 +5494,18 @@ static int cam_ife_mgr_prepare_hw_update(void *hw_mgr_priv,
 		}
 
 		goto end;
-	} else
+	} else {
 		prepare_hw_data->packet_opcode_type = CAM_ISP_PACKET_UPDATE_DEV;
+		prepare_hw_data->num_reg_dump_buf = prepare->num_reg_dump_buf;
+		if ((prepare_hw_data->num_reg_dump_buf) &&
+			(prepare_hw_data->num_reg_dump_buf <
+			CAM_REG_DUMP_MAX_BUF_ENTRIES)) {
+			memcpy(prepare_hw_data->reg_dump_buf_desc,
+				prepare->reg_dump_buf_desc,
+				sizeof(struct cam_cmd_buf_desc) *
+				prepare_hw_data->num_reg_dump_buf);
+		}
+	}
 
 	/* add reg update commands */
 	for (i = 0; i < ctx->num_base; i++) {
@@ -5529,112 +5659,6 @@ static void cam_ife_mgr_print_io_bufs(struct cam_packet *packet,
 	}
 }
 
-static int cam_ife_mgr_regspace_data_cb(uint32_t reg_base_type,
-	void *hw_mgr_ctx, struct cam_hw_soc_info **soc_info_ptr,
-	uint32_t *reg_base_idx)
-{
-	int rc = 0;
-	struct cam_ife_hw_mgr_res *hw_mgr_res;
-	struct cam_hw_soc_info    *soc_info = NULL;
-	struct cam_ife_hw_mgr_ctx *ctx =
-		(struct cam_ife_hw_mgr_ctx *) hw_mgr_ctx;
-
-	*soc_info_ptr = NULL;
-	list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_src, list) {
-		if (hw_mgr_res->res_id != CAM_ISP_HW_VFE_IN_CAMIF)
-			continue;
-
-		switch (reg_base_type) {
-		case CAM_REG_DUMP_BASE_TYPE_CAMNOC:
-		case CAM_REG_DUMP_BASE_TYPE_ISP_LEFT:
-			if (!hw_mgr_res->hw_res[CAM_ISP_HW_SPLIT_LEFT])
-				continue;
-
-			rc = hw_mgr_res->hw_res[
-				CAM_ISP_HW_SPLIT_LEFT]->process_cmd(
-				hw_mgr_res->hw_res[CAM_ISP_HW_SPLIT_LEFT],
-				CAM_ISP_HW_CMD_QUERY_REGSPACE_DATA, &soc_info,
-				sizeof(void *));
-			if (rc) {
-				CAM_ERR(CAM_ISP,
-					"Failed in regspace data query split idx: %d rc : %d",
-					CAM_ISP_HW_SPLIT_LEFT, rc);
-				return rc;
-			}
-
-			if (reg_base_type == CAM_REG_DUMP_BASE_TYPE_ISP_LEFT)
-				*reg_base_idx = 0;
-			else
-				*reg_base_idx = 1;
-
-			*soc_info_ptr = soc_info;
-			break;
-		case CAM_REG_DUMP_BASE_TYPE_ISP_RIGHT:
-			if (!hw_mgr_res->hw_res[CAM_ISP_HW_SPLIT_RIGHT])
-				continue;
-
-			rc = hw_mgr_res->hw_res[
-				CAM_ISP_HW_SPLIT_RIGHT]->process_cmd(
-				hw_mgr_res->hw_res[CAM_ISP_HW_SPLIT_RIGHT],
-				CAM_ISP_HW_CMD_QUERY_REGSPACE_DATA, &soc_info,
-				sizeof(void *));
-			if (rc) {
-				CAM_ERR(CAM_ISP,
-					"Failed in regspace data query split idx: %d rc : %d",
-					CAM_ISP_HW_SPLIT_RIGHT, rc);
-				return rc;
-			}
-
-			*reg_base_idx = 0;
-			*soc_info_ptr = soc_info;
-			break;
-		default:
-			CAM_ERR(CAM_ISP,
-				"Unrecognized reg base type: %d",
-				reg_base_type);
-			return -EINVAL;
-		}
-	}
-
-	return rc;
-}
-
-static int cam_ife_mgr_handle_reg_dump(struct cam_ife_hw_mgr_ctx *ctx,
-	uint32_t meta_type)
-{
-	int rc, i;
-
-	if (!ctx->num_reg_dump_buf) {
-		CAM_DBG(CAM_ISP,
-			"Zero command buffers for reg dump req_id: [%llu] ctx idx: [%llu] meta_type: %d",
-			ctx->applied_req_id, ctx->ctx_index, meta_type);
-		return 0;
-	}
-
-	if (!atomic_read(&ctx->cdm_done))
-		CAM_WARN_RATE_LIMIT(CAM_ISP,
-			"Reg dump values might be from more than one request");
-
-	for (i = 0; i < ctx->num_reg_dump_buf; i++) {
-		CAM_DBG(CAM_ISP, "Reg dump cmd meta data: %d req_type: %d",
-			ctx->reg_dump_buf_desc[i].meta_data, meta_type);
-		if (ctx->reg_dump_buf_desc[i].meta_data == meta_type) {
-			rc = cam_soc_util_reg_dump_to_cmd_buf(ctx,
-				&ctx->reg_dump_buf_desc[i],
-				ctx->applied_req_id,
-				cam_ife_mgr_regspace_data_cb);
-			if (rc) {
-				CAM_ERR(CAM_ISP,
-					"Reg dump failed at idx: %d, rc: %d req_id: %llu meta type: %d",
-					i, rc, ctx->applied_req_id, meta_type);
-				return -EINVAL;
-			}
-		}
-	}
-
-	return 0;
-}
-
 static int cam_ife_mgr_cmd(void *hw_mgr_priv, void *cmd_args)
 {
 	int rc = 0;
@@ -5713,7 +5737,8 @@ 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,
+		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);
 		if (rc) {
 			CAM_ERR(CAM_ISP,
@@ -5728,7 +5753,8 @@ static int cam_ife_mgr_cmd(void *hw_mgr_priv, void *cmd_args)
 			return 0;
 
 		ctx->last_dump_err_req_id = ctx->applied_req_id;
-		rc = cam_ife_mgr_handle_reg_dump(ctx,
+		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);
 		if (rc) {
 			CAM_ERR(CAM_ISP,
@@ -6544,6 +6570,15 @@ static int cam_ife_hw_mgr_debug_register(void)
 		CAM_ERR(CAM_ISP, "failed to create cam_ife_camif_debug");
 		goto err;
 	}
+
+	if (!debugfs_create_bool("per_req_reg_dump",
+		0644,
+		g_ife_hw_mgr.debug_cfg.dentry,
+		&g_ife_hw_mgr.debug_cfg.per_req_reg_dump)) {
+		CAM_ERR(CAM_ISP, "failed to create per_req_reg_dump entry");
+		goto err;
+	}
+
 	g_ife_hw_mgr.debug_cfg.enable_recovery = 0;
 
 	return 0;

+ 2 - 0
drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h

@@ -83,6 +83,7 @@ struct ctx_base_info {
  * @enable_recovery:           enable recovery
  * @enable_diag_sensor_status: enable sensor diagnosis status
  * @enable_req_dump:           Enable request dump on HW errors
+ * @per_req_reg_dump:          Enable per request reg dump
  *
  */
 struct cam_ife_hw_mgr_debug {
@@ -91,6 +92,7 @@ struct cam_ife_hw_mgr_debug {
 	uint32_t       enable_recovery;
 	uint32_t       camif_debug;
 	bool           enable_req_dump;
+	bool           per_req_reg_dump;
 };
 
 /**

+ 2 - 0
drivers/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c

@@ -422,6 +422,7 @@ int cam_isp_add_command_buffers(
 			break;
 		case CAM_ISP_PACKET_META_REG_DUMP_ON_FLUSH:
 		case CAM_ISP_PACKET_META_REG_DUMP_ON_ERROR:
+		case CAM_ISP_PACKET_META_REG_DUMP_PER_REQUEST:
 			if (split_id == CAM_ISP_HW_SPLIT_LEFT) {
 				if (prepare->num_reg_dump_buf >=
 					CAM_REG_DUMP_MAX_BUF_ENTRIES) {
@@ -430,6 +431,7 @@ int cam_isp_add_command_buffers(
 					prepare->num_reg_dump_buf);
 					return -EINVAL;
 				}
+
 				prepare->reg_dump_buf_desc[
 					prepare->num_reg_dump_buf] =
 					cmd_desc[i];

+ 7 - 0
drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h

@@ -115,6 +115,7 @@ struct cam_isp_bw_config_internal {
 /**
  * struct cam_isp_prepare_hw_update_data - hw prepare data
  *
+ * @ife_mgr_ctx:            IFE HW manager Context for current request
  * @packet_opcode_type:     Packet header opcode in the packet header
  *                          this opcode defines, packet is init packet or
  *                          update packet
@@ -123,14 +124,20 @@ struct cam_isp_bw_config_internal {
  * @bw_config_v2:           BW config info for AXI bw voting v2
  * @bw_config_valid:        Flag indicating whether the bw_config at the index
  *                          is valid or not
+ * @reg_dump_buf_desc:     cmd buffer descriptors for reg dump
+ * @num_reg_dump_buf:      Count of descriptors in reg_dump_buf_desc
  *
  */
 struct cam_isp_prepare_hw_update_data {
+	struct cam_ife_hw_mgr_ctx            *ife_mgr_ctx;
 	uint32_t                              packet_opcode_type;
 	uint32_t                              bw_config_version;
 	struct cam_isp_bw_config_internal     bw_config[CAM_IFE_HW_NUM_MAX];
 	struct cam_isp_bw_config_internal_v2  bw_config_v2[CAM_IFE_HW_NUM_MAX];
 	bool                                bw_config_valid[CAM_IFE_HW_NUM_MAX];
+	struct cam_cmd_buf_desc               reg_dump_buf_desc[
+						CAM_REG_DUMP_MAX_BUF_ENTRIES];
+	uint32_t                              num_reg_dump_buf;
 };