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

Commit 87838509 authored by Mangalaram ARCHANA's avatar Mangalaram ARCHANA
Browse files

msm: camera: ife: IFE debug enhancement for overflow debugging



In many error cases it is required to know the
bandwidth applied on axi ports and camnoc axi
clock rate values. Added cpas api to print the
current axi bus votes, camnoc axi clock and ahb
vote level.This api can be called for isp errors
such as bus overflow, pxl overflow cases.
On RDI overflow printing last applied IFE clock,
dumping the CAMNOC fill-level registers to know
the pending and queued transactions, SOF EPOCH
and EOF timing to know exactly at what time the
RDI overflow came, Width and height of specific
Write master.

CRs-Fixed: 2623885
Change-Id: I92a9097efe9f6726748ec27ca39dd51c8c6de1b6
Signed-off-by: default avatarMangalaram ARCHANA <mangar@codeaurora.org>
parent 01bb6065
Loading
Loading
Loading
Loading
+66 −5
Original line number Diff line number Diff line
@@ -83,7 +83,7 @@ static int cam_cpas_util_vote_bus_client_level(

static int cam_cpas_util_vote_bus_client_bw(
	struct cam_cpas_bus_client *bus_client, uint64_t ab, uint64_t ib,
	bool camnoc_bw)
	bool camnoc_bw, uint64_t *applied_ab, uint64_t *applied_ib)
{
	struct msm_bus_paths *path;
	struct msm_bus_scale_pdata *pdata;
@@ -146,6 +146,10 @@ static int cam_cpas_util_vote_bus_client_bw(
	CAM_DBG(CAM_CPAS, "Bus client=[%d][%s] :ab[%llu] ib[%llu], index[%d]",
		bus_client->client_id, bus_client->name, ab, ib, idx);
	msm_bus_scale_client_update_request(bus_client->client_id, idx);
	if (applied_ab)
		*applied_ab = ab;
	if (applied_ib)
		*applied_ib = ib;

	return 0;
}
@@ -221,7 +225,8 @@ static int cam_cpas_util_unregister_bus_client(
		return -EINVAL;

	if (bus_client->dyn_vote)
		cam_cpas_util_vote_bus_client_bw(bus_client, 0, 0, false);
		cam_cpas_util_vote_bus_client_bw(bus_client, 0, 0, false,
		NULL, NULL);
	else
		cam_cpas_util_vote_bus_client_level(bus_client, 0);

@@ -309,6 +314,7 @@ static int cam_cpas_util_vote_default_ahb_axi(struct cam_hw_info *cpas_hw,
	int rc, i = 0;
	struct cam_cpas *cpas_core = (struct cam_cpas *)cpas_hw->core_info;
	uint64_t ab_bw, ib_bw;
	uint64_t applied_ab_bw = 0, applied_ib_bw = 0;

	rc = cam_cpas_util_vote_bus_client_level(&cpas_core->ahb_bus_client,
		(enable == true) ? CAM_SVS_VOTE : CAM_SUSPEND_VOTE);
@@ -329,13 +335,15 @@ static int cam_cpas_util_vote_default_ahb_axi(struct cam_hw_info *cpas_hw,
	for (i = 0; i < cpas_core->num_axi_ports; i++) {
		rc = cam_cpas_util_vote_bus_client_bw(
			&cpas_core->axi_port[i].bus_client,
			ab_bw, ib_bw, false);
			ab_bw, ib_bw, false, &applied_ab_bw, &applied_ib_bw);
		if (rc) {
			CAM_ERR(CAM_CPAS,
				"Failed in mnoc vote, enable=%d, rc=%d",
				enable, rc);
			goto remove_ahb_vote;
		}
		cpas_core->axi_port[i].applied_ab_bw = applied_ab_bw;
		cpas_core->axi_port[i].applied_ib_bw = applied_ib_bw;
	}

	return 0;
@@ -494,6 +502,8 @@ static int cam_cpas_util_set_camnoc_axi_clk_rate(
				CAM_ERR(CAM_CPAS,
				"Failed in setting camnoc axi clk %llu %lld %d",
				required_camnoc_bw, clk_rate, rc);

			cpas_core->applied_camnoc_axi_rate = clk_rate;
		}
	}

@@ -675,6 +685,7 @@ static int cam_cpas_camnoc_set_vote_axi_clk_rate(
	int rc = 0;
	struct cam_cpas_axi_port *camnoc_axi_port = NULL;
	uint64_t camnoc_bw;
	uint64_t applied_ab = 0, applied_ib = 0;

	if (soc_private->control_camnoc_axi_clk) {
		rc = cam_cpas_util_set_camnoc_axi_clk_rate(cpas_hw);
@@ -711,7 +722,7 @@ static int cam_cpas_camnoc_set_vote_axi_clk_rate(

		rc = cam_cpas_util_vote_bus_client_bw(
			&camnoc_axi_port->bus_client,
			0, camnoc_bw, true);
			0, camnoc_bw, true, &applied_ab, &applied_ib);

		CAM_DBG(CAM_CPAS,
			"camnoc vote camnoc_bw[%llu] rc=%d %s",
@@ -722,6 +733,8 @@ static int cam_cpas_camnoc_set_vote_axi_clk_rate(
				camnoc_bw, rc);
			break;
		}
		camnoc_axi_port->applied_ab_bw = applied_ab;
		camnoc_axi_port->applied_ib_bw = applied_ib;
	}
	return rc;
}
@@ -744,6 +757,7 @@ static int cam_cpas_util_apply_client_axi_vote(
		curr_camnoc_old = 0, curr_mnoc_ab_old = 0, curr_mnoc_ib_old = 0,
		par_camnoc_old = 0, par_mnoc_ab_old = 0, par_mnoc_ib_old = 0;
	int rc = 0, i = 0;
	uint64_t applied_ab = 0, applied_ib = 0;

	mutex_lock(&cpas_core->tree_lock);
	if (!cpas_client->tree_node_valid) {
@@ -899,13 +913,16 @@ static int cam_cpas_util_apply_client_axi_vote(

		rc = cam_cpas_util_vote_bus_client_bw(
			&mnoc_axi_port->bus_client,
			mnoc_ab_bw, mnoc_ib_bw, false);
			mnoc_ab_bw, mnoc_ib_bw, false, &applied_ab,
			&applied_ib);
		if (rc) {
			CAM_ERR(CAM_CPAS,
				"Failed in mnoc vote ab[%llu] ib[%llu] rc=%d",
				mnoc_ab_bw, mnoc_ib_bw, rc);
			goto unlock_tree;
		}
		mnoc_axi_port->applied_ab_bw = applied_ab;
		mnoc_axi_port->applied_ib_bw = applied_ib;
	}
	rc = cam_cpas_camnoc_set_vote_axi_clk_rate(
		cpas_hw, camnoc_axi_port_updated);
@@ -1652,6 +1669,46 @@ static int cam_cpas_hw_get_hw_info(void *hw_priv,
	return 0;
}

static int cam_cpas_log_vote(struct cam_hw_info *cpas_hw)
{
	struct cam_cpas *cpas_core = (struct cam_cpas *) cpas_hw->core_info;
	struct cam_cpas_private_soc *soc_private =
		(struct cam_cpas_private_soc *) cpas_hw->soc_info.soc_private;
	int rc = 0;
	uint32_t i;

	for (i = 0; i < cpas_core->num_axi_ports; i++) {
		CAM_INFO(CAM_CPAS,
			"[%s] ab_bw[%lld] ib_bw[%lld] additional_bw[%lld] applied_ab[%lld] applied_ib[%lld]",
			cpas_core->axi_port[i].axi_port_name,
			cpas_core->axi_port[i].ab_bw,
			cpas_core->axi_port[i].ib_bw,
			cpas_core->axi_port[i].additional_bw,
			cpas_core->axi_port[i].applied_ab_bw,
			cpas_core->axi_port[i].applied_ib_bw);
	}

	if (soc_private->control_camnoc_axi_clk) {
		CAM_INFO(CAM_CPAS, "applied camnoc axi clk[%lld]",
			cpas_core->applied_camnoc_axi_rate);
	} else {
		for (i = 0; i < cpas_core->num_camnoc_axi_ports; i++) {
			CAM_INFO(CAM_CPAS,
				"[%s] ab_bw[%lld] ib_bw[%lld] additional_bw[%lld] applied_ab[%lld] applied_ib[%lld]",
				cpas_core->camnoc_axi_port[i].axi_port_name,
				cpas_core->camnoc_axi_port[i].ab_bw,
				cpas_core->camnoc_axi_port[i].ib_bw,
				cpas_core->camnoc_axi_port[i].additional_bw,
				cpas_core->camnoc_axi_port[i].applied_ab_bw,
				cpas_core->camnoc_axi_port[i].applied_ib_bw);
		}
	}

	CAM_INFO(CAM_CPAS, "ahb client curr vote level[%d]",
		cpas_core->ahb_bus_client.curr_vote_level);

	return rc;
}

static int cam_cpas_hw_process_cmd(void *hw_priv,
	uint32_t cmd_type, void *cmd_args, uint32_t arg_size)
@@ -1755,6 +1812,10 @@ static int cam_cpas_hw_process_cmd(void *hw_priv,
			cmd_axi_vote->client_handle, cmd_axi_vote->axi_vote);
		break;
	}
	case CAM_CPAS_HW_CMD_LOG_VOTE: {
		rc = cam_cpas_log_vote(hw_priv);
		break;
	}
	default:
		CAM_ERR(CAM_CPAS, "CPAS HW command not valid =%d", cmd_type);
		break;
+6 −0
Original line number Diff line number Diff line
@@ -155,6 +155,8 @@ struct cam_cpas_bus_client {
 * @ib_bw: IB bw value for this port
 * @camnoc_bw: CAMNOC bw value for this port
 * @additional_bw: Additional bandwidth to cover non-hw cpas clients
 * @applied_ab_bw: applied ab bw for this port
 * @applied_ib_bw: applied ib bw for this port
 */
struct cam_cpas_axi_port {
	const char *axi_port_name;
@@ -165,6 +167,8 @@ struct cam_cpas_axi_port {
	uint64_t ib_bw;
	uint64_t camnoc_bw;
	uint64_t additional_bw;
	uint64_t applied_ab_bw;
	uint64_t applied_ib_bw;
};

/**
@@ -189,6 +193,7 @@ struct cam_cpas_axi_port {
 * @irq_count_wq: wait variable to ensure all irq's are handled
 * @dentry: debugfs file entry
 * @ahb_bus_scaling_disable: ahb scaling based on src clk corner for bus
 * @applied_camnoc_axi_rate: applied camnoc axi clock rate
 */
struct cam_cpas {
	struct cam_cpas_hw_caps hw_caps;
@@ -210,6 +215,7 @@ struct cam_cpas {
	wait_queue_head_t irq_count_wq;
	struct dentry *dentry;
	bool ahb_bus_scaling_disable;
	uint64_t applied_camnoc_axi_rate;
};

int cam_camsstop_get_internal_ops(struct cam_cpas_internal_ops *internal_ops);
+2 −1
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
 * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
 */

#ifndef _CAM_CPAS_HW_INTF_H_
@@ -38,6 +38,7 @@ enum cam_cpas_hw_cmd_process {
	CAM_CPAS_HW_CMD_REG_READ,
	CAM_CPAS_HW_CMD_AHB_VOTE,
	CAM_CPAS_HW_CMD_AXI_VOTE,
	CAM_CPAS_HW_CMD_LOG_VOTE,
	CAM_CPAS_HW_CMD_INVALID,
};

+25 −1
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
 * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
 */

#include <linux/of.h>
@@ -392,6 +392,30 @@ int cam_cpas_start(uint32_t client_handle,
}
EXPORT_SYMBOL(cam_cpas_start);

void cam_cpas_log_votes(void)
{
	uint32_t dummy_args;
	int rc;

	if (!CAM_CPAS_INTF_INITIALIZED()) {
		CAM_ERR(CAM_CPAS, "cpas intf not initialized");
		return;
	}

	if (g_cpas_intf->hw_intf->hw_ops.process_cmd) {
		rc = g_cpas_intf->hw_intf->hw_ops.process_cmd(
			g_cpas_intf->hw_intf->hw_priv,
			CAM_CPAS_HW_CMD_LOG_VOTE, &dummy_args,
			sizeof(dummy_args));
		if (rc)
			CAM_ERR(CAM_CPAS, "Failed in process_cmd, rc=%d", rc);
	} else {
		CAM_ERR(CAM_CPAS, "Invalid process_cmd ops");
	}

}
EXPORT_SYMBOL(cam_cpas_log_votes);

int cam_cpas_unregister_client(uint32_t client_handle)
{
	int rc;
+10 −0
Original line number Diff line number Diff line
@@ -617,5 +617,15 @@ const char *cam_cpas_axi_util_path_type_to_string(
const char *cam_cpas_axi_util_trans_type_to_string(
	uint32_t path_data_type);

/**
 * cam_cpas_log_votes()
 *
 * @brief: API to print the all bw votes of axi client. It also print the
 *     applied camnoc axi clock vote value and ahb vote value
 *
 * @return 0 on success.
 *
 */
void cam_cpas_log_votes(void);

#endif /* _CAM_CPAS_API_H_ */
Loading