Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 897e9cd7 authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm: camera: Add support for reg dump to command buffers"

parents 606ad96f f52e68be
Loading
Loading
Loading
Loading
+10 −0
Original line number Original line Diff line number Diff line
@@ -21,6 +21,9 @@
/* maximum buf done irqs */
/* maximum buf done irqs */
#define CAM_NUM_OUT_PER_COMP_IRQ_MAX        12
#define CAM_NUM_OUT_PER_COMP_IRQ_MAX        12


/* Maximum reg dump cmd buffer entries in a context */
#define CAM_REG_DUMP_MAX_BUF_ENTRIES        10

/* hardware event callback function type */
/* hardware event callback function type */
typedef int (*cam_hw_event_cb_func)(void *context, uint32_t evt_id,
typedef int (*cam_hw_event_cb_func)(void *context, uint32_t evt_id,
	void *evt_data);
	void *evt_data);
@@ -166,6 +169,8 @@ struct cam_hw_mgr_dump_pf_data {
 * @max_in_map_entries:    Maximum input fence mapping supported
 * @max_in_map_entries:    Maximum input fence mapping supported
 * @in_map_entries:        Actual input fence mapping list (returned)
 * @in_map_entries:        Actual input fence mapping list (returned)
 * @num_in_map_entries:    Number of acutal input fence mapping (returned)
 * @num_in_map_entries:    Number of acutal input fence mapping (returned)
 * @reg_dump_buf_desc:     cmd buffer descriptors for reg dump
 * @num_reg_dump_buf:      Count of descriptors in reg_dump_buf_desc
 * @priv:                  Private pointer of hw update
 * @priv:                  Private pointer of hw update
 * @pf_data:               Debug data for page fault
 * @pf_data:               Debug data for page fault
 *
 *
@@ -183,6 +188,9 @@ struct cam_hw_prepare_update_args {
	uint32_t                        max_in_map_entries;
	uint32_t                        max_in_map_entries;
	struct cam_hw_fence_map_entry  *in_map_entries;
	struct cam_hw_fence_map_entry  *in_map_entries;
	uint32_t                        num_in_map_entries;
	uint32_t                        num_in_map_entries;
	struct cam_cmd_buf_desc         reg_dump_buf_desc[
					CAM_REG_DUMP_MAX_BUF_ENTRIES];
	uint32_t                        num_reg_dump_buf;
	void                           *priv;
	void                           *priv;
	struct cam_hw_mgr_dump_pf_data *pf_data;
	struct cam_hw_mgr_dump_pf_data *pf_data;
};
};
@@ -266,6 +274,8 @@ struct cam_hw_dump_pf_args {
enum cam_hw_mgr_command {
enum cam_hw_mgr_command {
	CAM_HW_MGR_CMD_INTERNAL,
	CAM_HW_MGR_CMD_INTERNAL,
	CAM_HW_MGR_CMD_DUMP_PF_INFO,
	CAM_HW_MGR_CMD_DUMP_PF_INFO,
	CAM_HW_MGR_CMD_REG_DUMP_ON_FLUSH,
	CAM_HW_MGR_CMD_REG_DUMP_ON_ERROR,
};
};


/**
/**
+28 −0
Original line number Original line Diff line number Diff line
@@ -1116,6 +1116,22 @@ static int __cam_isp_ctx_handle_error(struct cam_isp_context *ctx_isp,
		(error_type == CAM_ISP_HW_ERROR_BUSIF_OVERFLOW))
		(error_type == CAM_ISP_HW_ERROR_BUSIF_OVERFLOW))
		notify.error = CRM_KMD_ERR_OVERFLOW;
		notify.error = CRM_KMD_ERR_OVERFLOW;



	if ((error_type == CAM_ISP_HW_ERROR_OVERFLOW) ||
		(error_type == CAM_ISP_HW_ERROR_BUSIF_OVERFLOW) ||
		(error_type == CAM_ISP_HW_ERROR_VIOLATION)) {
		struct cam_hw_cmd_args hw_cmd_args;

		memset(&hw_cmd_args, 0, sizeof(hw_cmd_args));
		hw_cmd_args.ctxt_to_hw_map = ctx->ctxt_to_hw_map;
		hw_cmd_args.cmd_type = CAM_HW_MGR_CMD_REG_DUMP_ON_ERROR;
		rc = ctx->hw_mgr_intf->hw_cmd(ctx->hw_mgr_intf->hw_mgr_priv,
			&hw_cmd_args);
		if (rc) {
			CAM_ERR(CAM_ISP, "Reg dump on error failed rc: %d", rc);
			rc = 0;
		}
	}
	/*
	/*
	 * The error is likely caused by first request on the active list.
	 * The error is likely caused by first request on the active list.
	 * If active list is empty check wait list (maybe error hit as soon
	 * If active list is empty check wait list (maybe error hit as soon
@@ -1932,6 +1948,8 @@ static int __cam_isp_ctx_flush_req_in_top_state(
{
{
	int rc = 0;
	int rc = 0;
	struct cam_isp_context *ctx_isp;
	struct cam_isp_context *ctx_isp;
	struct cam_hw_cmd_args hw_cmd_args;



	ctx_isp = (struct cam_isp_context *) ctx->ctx_priv;
	ctx_isp = (struct cam_isp_context *) ctx->ctx_priv;
	if (flush_req->type == CAM_REQ_MGR_FLUSH_TYPE_ALL) {
	if (flush_req->type == CAM_REQ_MGR_FLUSH_TYPE_ALL) {
@@ -1945,6 +1963,16 @@ static int __cam_isp_ctx_flush_req_in_top_state(
	rc = __cam_isp_ctx_flush_req(ctx, &ctx->pending_req_list, flush_req);
	rc = __cam_isp_ctx_flush_req(ctx, &ctx->pending_req_list, flush_req);
	spin_unlock_bh(&ctx->lock);
	spin_unlock_bh(&ctx->lock);


	memset(&hw_cmd_args, 0, sizeof(hw_cmd_args));
	hw_cmd_args.ctxt_to_hw_map = ctx->ctxt_to_hw_map;
	hw_cmd_args.cmd_type = CAM_HW_MGR_CMD_REG_DUMP_ON_FLUSH;
	rc = ctx->hw_mgr_intf->hw_cmd(ctx->hw_mgr_intf->hw_mgr_priv,
		&hw_cmd_args);
	if (rc) {
		CAM_ERR(CAM_ISP, "Reg dump on flush failed rc: %d", rc);
		rc = 0;
	}

	atomic_set(&ctx_isp->process_bubble, 0);
	atomic_set(&ctx_isp->process_bubble, 0);
	return rc;
	return rc;
}
}
+156 −3
Original line number Original line Diff line number Diff line
@@ -2077,7 +2077,7 @@ void cam_ife_cam_cdm_callback(uint32_t handle, void *userdata,
	ctx = userdata;
	ctx = userdata;


	if (status == CAM_CDM_CB_STATUS_BL_SUCCESS) {
	if (status == CAM_CDM_CB_STATUS_BL_SUCCESS) {
		complete(&ctx->config_done_complete);
		complete_all(&ctx->config_done_complete);
		CAM_DBG(CAM_ISP,
		CAM_DBG(CAM_ISP,
			"Called by CDM hdl=%x, udata=%pK, status=%d, cookie=%llu ctx_index=%d",
			"Called by CDM hdl=%x, udata=%pK, status=%d, cookie=%llu ctx_index=%d",
			 handle, userdata, status, cookie, ctx->ctx_index);
			 handle, userdata, status, cookie, ctx->ctx_index);
@@ -3059,8 +3059,8 @@ static int cam_ife_mgr_config_hw(void *hw_mgr_priv,
			cdm_cmd->cmd[i].len = cmd->len;
			cdm_cmd->cmd[i].len = cmd->len;
		}
		}


		if (cfg->init_packet)
		reinit_completion(&ctx->config_done_complete);
			init_completion(&ctx->config_done_complete);
		ctx->applied_req_id = cfg->request_id;


		CAM_DBG(CAM_ISP, "Submit to CDM");
		CAM_DBG(CAM_ISP, "Submit to CDM");
		rc = cam_cdm_submit_bls(ctx->cdm_handle, cdm_cmd);
		rc = cam_cdm_submit_bls(ctx->cdm_handle, cdm_cmd);
@@ -5058,6 +5058,7 @@ static int cam_ife_mgr_prepare_hw_update(void *hw_mgr_priv,
	prepare->num_hw_update_entries = 0;
	prepare->num_hw_update_entries = 0;
	prepare->num_in_map_entries = 0;
	prepare->num_in_map_entries = 0;
	prepare->num_out_map_entries = 0;
	prepare->num_out_map_entries = 0;
	prepare->num_reg_dump_buf = 0;


	memset(&prepare_hw_data->bw_config[0], 0x0,
	memset(&prepare_hw_data->bw_config[0], 0x0,
		sizeof(prepare_hw_data->bw_config[0]) *
		sizeof(prepare_hw_data->bw_config[0]) *
@@ -5123,6 +5124,15 @@ static int cam_ife_mgr_prepare_hw_update(void *hw_mgr_priv,
	if (((prepare->packet->header.op_code + 1) & 0xF) ==
	if (((prepare->packet->header.op_code + 1) & 0xF) ==
		CAM_ISP_PACKET_INIT_DEV) {
		CAM_ISP_PACKET_INIT_DEV) {
		prepare_hw_data->packet_opcode_type = CAM_ISP_PACKET_INIT_DEV;
		prepare_hw_data->packet_opcode_type = CAM_ISP_PACKET_INIT_DEV;
		ctx->num_reg_dump_buf = prepare->num_reg_dump_buf;
		if ((ctx->num_reg_dump_buf) && (ctx->num_reg_dump_buf <
			CAM_REG_DUMP_MAX_BUF_ENTRIES)) {
			memcpy(ctx->reg_dump_buf_desc,
				prepare->reg_dump_buf_desc,
				sizeof(struct cam_cmd_buf_desc) *
				prepare->num_reg_dump_buf);
		}

		goto end;
		goto end;
	} else
	} else
		prepare_hw_data->packet_opcode_type = CAM_ISP_PACKET_UPDATE_DEV;
		prepare_hw_data->packet_opcode_type = CAM_ISP_PACKET_UPDATE_DEV;
@@ -5279,6 +5289,118 @@ 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;
	}

	rc = wait_for_completion_timeout(
		&ctx->config_done_complete,
		msecs_to_jiffies(30));
	if (rc <= 0) {
		CAM_ERR(CAM_ISP,
			"config done completion timeout rc=%d ctx_index %d",
			rc, ctx->ctx_index);
		rc = 0;
	}

	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)
static int cam_ife_mgr_cmd(void *hw_mgr_priv, void *cmd_args)
{
{
	int rc = 0;
	int rc = 0;
@@ -5342,6 +5464,37 @@ static int cam_ife_mgr_cmd(void *hw_mgr_priv, void *cmd_args)
			hw_cmd_args->u.pf_args.buf_info,
			hw_cmd_args->u.pf_args.buf_info,
			hw_cmd_args->u.pf_args.mem_found);
			hw_cmd_args->u.pf_args.mem_found);
		break;
		break;
	case CAM_HW_MGR_CMD_REG_DUMP_ON_FLUSH:
		if (ctx->last_dump_flush_req_id == ctx->applied_req_id)
			return 0;

		ctx->last_dump_flush_req_id = ctx->applied_req_id;

		rc = cam_ife_mgr_handle_reg_dump(ctx,
			CAM_ISP_PACKET_META_REG_DUMP_ON_FLUSH);
		if (rc) {
			CAM_ERR(CAM_ISP,
				"Reg dump on flush failed req id: %llu rc: %d",
				ctx->applied_req_id, rc);
			return rc;
		}

		break;
	case CAM_HW_MGR_CMD_REG_DUMP_ON_ERROR:
		if (ctx->last_dump_err_req_id == ctx->applied_req_id)
			return 0;

		ctx->last_dump_err_req_id = ctx->applied_req_id;
		rc = cam_ife_mgr_handle_reg_dump(ctx,
			CAM_ISP_PACKET_META_REG_DUMP_ON_ERROR);
		if (rc) {
			CAM_ERR(CAM_ISP,
				"Reg dump on error failed req id: %llu rc: %d",
				ctx->applied_req_id, rc);
			return rc;
		}

		break;
	default:
	default:
		CAM_ERR(CAM_ISP, "Invalid cmd");
		CAM_ERR(CAM_ISP, "Invalid cmd");
	}
	}
+11 −0
Original line number Original line Diff line number Diff line
@@ -124,6 +124,11 @@ struct cam_ife_hw_mgr_debug {
 *                          context
 *                          context
 * @is_rdi_only_context     flag to specify the context has only rdi resource
 * @is_rdi_only_context     flag to specify the context has only rdi resource
 * @config_done_complete    indicator for configuration complete
 * @config_done_complete    indicator for configuration complete
 * @reg_dump_buf_desc:      cmd buffer descriptors for reg dump
 * @num_reg_dump_buf:       Count of descriptors in reg_dump_buf_desc
 * @applied_req_id:         Last request id to be applied
 * @last_dump_flush_req_id  Last req id for which reg dump on flush was called
 * @last_dump_err_req_id    Last req id for which reg dump on error was called
 * @init_done               indicate whether init hw is done
 * @init_done               indicate whether init hw is done
 * @is_fe_enable            indicate whether fetch engine\read path is enabled
 * @is_fe_enable            indicate whether fetch engine\read path is enabled
 * @is_dual                 indicate whether context is in dual VFE mode
 * @is_dual                 indicate whether context is in dual VFE mode
@@ -161,6 +166,12 @@ struct cam_ife_hw_mgr_ctx {
	atomic_t                        overflow_pending;
	atomic_t                        overflow_pending;
	uint32_t                        is_rdi_only_context;
	uint32_t                        is_rdi_only_context;
	struct completion               config_done_complete;
	struct completion               config_done_complete;
	struct cam_cmd_buf_desc         reg_dump_buf_desc[
						CAM_REG_DUMP_MAX_BUF_ENTRIES];
	uint32_t                        num_reg_dump_buf;
	uint64_t                        applied_req_id;
	uint64_t                        last_dump_flush_req_id;
	uint64_t                        last_dump_err_req_id;
	bool                            init_done;
	bool                            init_done;
	bool                            is_fe_enable;
	bool                            is_fe_enable;
	bool                            is_dual;
	bool                            is_dual;
+20 −0
Original line number Original line Diff line number Diff line
@@ -420,6 +420,26 @@ int cam_isp_add_command_buffers(
			num_ent = prepare->num_hw_update_entries;
			num_ent = prepare->num_hw_update_entries;
		}
		}
			break;
			break;
		case CAM_ISP_PACKET_META_REG_DUMP_ON_FLUSH:
		case CAM_ISP_PACKET_META_REG_DUMP_ON_ERROR:
			if (split_id == CAM_ISP_HW_SPLIT_LEFT) {
				if (prepare->num_reg_dump_buf >=
					CAM_REG_DUMP_MAX_BUF_ENTRIES) {
					CAM_ERR(CAM_ISP,
					"Descriptor count out of bounds: %d",
					prepare->num_reg_dump_buf);
					return -EINVAL;
				}
				prepare->reg_dump_buf_desc[
					prepare->num_reg_dump_buf] =
					cmd_desc[i];
				prepare->num_reg_dump_buf++;
				CAM_DBG(CAM_ISP,
					"Added command buffer: %d desc_count: %d",
					cmd_desc[i].meta_data,
					prepare->num_reg_dump_buf);
			}
			break;
		default:
		default:
			CAM_ERR(CAM_ISP, "invalid cdm command meta data %d",
			CAM_ERR(CAM_ISP, "invalid cdm command meta data %d",
				cmd_meta_data);
				cmd_meta_data);
Loading