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

Commit 41fbc5eb authored by Prakasha Nayak's avatar Prakasha Nayak Committed by Gerrit - the friendly Code Review server
Browse files

msm: camera: isp: Handle Dual VFE incase of event mismatch



Handle event counter mismatch comes due to scheduling issues

Change-Id: I2efc53e9487629b008f38502c58b641a2b68952c
Signed-off-by: default avatarPrakasha Nayak <pnayak@codeaurora.org>
parent d19081d5
Loading
Loading
Loading
Loading
+50 −3
Original line number Diff line number Diff line
@@ -2159,6 +2159,7 @@ static int cam_ife_mgr_restart_hw(void *start_hw_args)
	}

	CAM_DBG(CAM_ISP, "START CID SRC ... in ctx id:%d", ctx->ctx_index);
	ctx->dual_ife_irq_mismatch_cnt = 0;
	/* Start IFE root node: do nothing */
	CAM_DBG(CAM_ISP, "Exit...(success)");
	return 0;
@@ -2378,6 +2379,7 @@ static int cam_ife_mgr_release_hw(void *hw_mgr_priv,
	memset(ctx->base, 0, sizeof(ctx->base));

	/* release cdm handle */
	ctx->dual_ife_irq_mismatch_cnt = 0;
	cam_cdm_release(ctx->cdm_handle);

	/* clean context */
@@ -2968,6 +2970,36 @@ static void cam_ife_mgr_print_io_bufs(struct cam_packet *packet,
	}
}

static void cam_ife_mgr_ctx_irq_dump(struct cam_ife_hw_mgr_ctx *ctx)
{
	struct cam_ife_hw_mgr_res        *hw_mgr_res;
	struct cam_hw_intf               *hw_intf;
	struct cam_isp_hw_get_cmd_update  cmd_update;
	int i = 0;

	list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_src, list) {
		if (hw_mgr_res->res_type == CAM_IFE_HW_MGR_RES_UNINIT)
			continue;
		for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) {
			if (!hw_mgr_res->hw_res[i])
				continue;
			switch (hw_mgr_res->hw_res[i]->res_id) {
			case CAM_ISP_HW_VFE_IN_CAMIF:
				hw_intf = hw_mgr_res->hw_res[i]->hw_intf;
				cmd_update.res = hw_mgr_res->hw_res[i];
				cmd_update.cmd_type =
					CAM_ISP_HW_CMD_GET_IRQ_REGISTER_DUMP;
				hw_intf->hw_ops.process_cmd(hw_intf->hw_priv,
					CAM_ISP_HW_CMD_GET_IRQ_REGISTER_DUMP,
					&cmd_update, sizeof(cmd_update));
				break;
			default:
				break;
			}
		}
	}
}

static int cam_ife_mgr_cmd(void *hw_mgr_priv, void *cmd_args)
{
	int rc = 0;
@@ -3618,13 +3650,28 @@ static int cam_ife_hw_mgr_check_irq_for_dual_vfe(
		(event_cnt[core_idx1] &&
		(event_cnt[core_idx1] - event_cnt[core_idx0] > 1))) {

		CAM_ERR_RATE_LIMIT(CAM_ISP,
			"One of the VFE cound not generate hw event %d",
			hw_event_type);
		if (ife_hw_mgr_ctx->dual_ife_irq_mismatch_cnt > 10) {
			rc = -1;
			return rc;
		}

		CAM_ERR_RATE_LIMIT(CAM_ISP,
			"One of the VFE could not generate hw event %d",
			hw_event_type);
		if (event_cnt[core_idx0] >= 2) {
			event_cnt[core_idx0]--;
			ife_hw_mgr_ctx->dual_ife_irq_mismatch_cnt++;
		}
		if (event_cnt[core_idx1] >= 2) {
			event_cnt[core_idx1]--;
			ife_hw_mgr_ctx->dual_ife_irq_mismatch_cnt++;
		}

		if (ife_hw_mgr_ctx->dual_ife_irq_mismatch_cnt == 1)
			cam_ife_mgr_ctx_irq_dump(ife_hw_mgr_ctx);
		rc = 0;
	}

	CAM_DBG(CAM_ISP, "Only one core_index has given hw event %d",
			hw_event_type);

+34 −30
Original line number Diff line number Diff line
/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -121,11 +121,14 @@ struct cam_ife_hw_mgr_debug {
 * @sof_cnt                     sof count value per core, used for dual VFE
 * @epoch_cnt                   epoch count value per core, used for dual VFE
 * @eof_cnt                     eof count value per core, used for dual VFE
 * @overflow_pending        flat to specify the overflow is pending for the
 * @overflow_pending            flag to specify the overflow is pending for the
 *                              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
 * @init_done                   indicate whether init hw is done
 * @dual_ife_irq_mismatch_cnt   irq mismatch count value per core, used for
 *                              dual VFE
 */
struct cam_ife_hw_mgr_ctx {
	struct list_head                list;
@@ -160,6 +163,7 @@ struct cam_ife_hw_mgr_ctx {
	uint32_t                        is_rdi_only_context;
	struct completion               config_done_complete;
	bool                            init_done;
	uint32_t                        dual_ife_irq_mismatch_cnt;
};

/**
+2 −1
Original line number Diff line number Diff line
/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -97,6 +97,7 @@ enum cam_isp_hw_cmd_type {
	CAM_ISP_HW_CMD_GET_REG_DUMP,
	CAM_ISP_HW_CMD_SOF_IRQ_DEBUG,
	CAM_ISP_HW_CMD_SET_CAMIF_DEBUG,
	CAM_ISP_HW_CMD_GET_IRQ_REGISTER_DUMP,
	CAM_ISP_HW_CMD_MAX,
};

+2 −1
Original line number Diff line number Diff line
/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -696,6 +696,7 @@ int cam_vfe_process_cmd(void *hw_priv, uint32_t cmd_type,
	case CAM_ISP_HW_CMD_CLOCK_UPDATE:
	case CAM_ISP_HW_CMD_BW_UPDATE:
	case CAM_ISP_HW_CMD_BW_CONTROL:
	case CAM_ISP_HW_CMD_GET_IRQ_REGISTER_DUMP:
		rc = core_info->vfe_top->hw_ops.process_cmd(
			core_info->vfe_top->top_priv, cmd_type, cmd_args,
			arg_size);
+38 −1
Original line number Diff line number Diff line
/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -378,6 +378,40 @@ static int cam_vfe_camif_reg_dump(
	return rc;
}

static int cam_vfe_camif_irq_reg_dump(
	struct cam_isp_resource_node *camif_res)
{
	struct cam_vfe_mux_camif_data *camif_priv;
	struct cam_vfe_soc_private *soc_private;
	int rc = 0;

	if (!camif_res) {
		CAM_ERR(CAM_ISP, "Error! Invalid input arguments\n");
		return -EINVAL;
	}

	if ((camif_res->res_state == CAM_ISP_RESOURCE_STATE_RESERVED) ||
		(camif_res->res_state == CAM_ISP_RESOURCE_STATE_AVAILABLE)) {
		CAM_ERR(CAM_ISP, "Error! Invalid state\n");
		return 0;
	}

	camif_priv = (struct cam_vfe_mux_camif_data *)camif_res->res_priv;
	soc_private = camif_priv->soc_info->soc_private;

	CAM_INFO(CAM_ISP,
		"Core Id =%d Mask reg: offset 0x%x val 0x%x offset 0x%x val 0x%x",
		camif_priv->hw_intf->hw_idx,
		0x5c, cam_io_r_mb(camif_priv->mem_base + 0x5c),
		0x60, cam_io_r_mb(camif_priv->mem_base + 0x60));
	CAM_INFO(CAM_ISP,
		"Core Id =%d Status reg: offset 0x%x val 0x%x offset 0x%x val 0x%x",
		camif_priv->hw_intf->hw_idx,
		0x6c, cam_io_r_mb(camif_priv->mem_base + 0x6c),
		0x70, cam_io_r_mb(camif_priv->mem_base + 0x70));
	return rc;
}

static int cam_vfe_camif_resource_stop(
	struct cam_isp_resource_node        *camif_res)
{
@@ -465,6 +499,9 @@ static int cam_vfe_camif_process_cmd(struct cam_isp_resource_node *rsrc_node,
			(struct cam_vfe_mux_camif_data *)rsrc_node->res_priv;
		camif_priv->camif_debug = *((uint32_t *)cmd_args);
		break;
	case CAM_ISP_HW_CMD_GET_IRQ_REGISTER_DUMP:
		rc = cam_vfe_camif_irq_reg_dump(rsrc_node);
		break;
	default:
		CAM_ERR(CAM_ISP,
			"unsupported process command:%d", cmd_type);
Loading