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

Commit 3e463c33 authored by Pavan Kumar Chilamkurthi's avatar Pavan Kumar Chilamkurthi Committed by Gerrit - the friendly Code Review server
Browse files

msm: camera: icp: Remove bw vote of context in Release



Do not rely on timer expiry to remove bw of current context
if it is getting released. If context release is coming
before timer expiry (from last request submit), we are not
removing current context's vote from hw mgr and thus
from cpas. This will accumulate the bandwidth and causes
clocks to go to turbo and also into overflow issues if
the bw variables in cpas are wrapping around in long
hours testing.

CRs-Fixed: 2617278
Change-Id: I11d837bf7224ac4573fee32518f7f57ad9bf49f0
Signed-off-by: default avatarPavan Kumar Chilamkurthi <pchilamk@codeaurora.org>
parent 5619d4e9
Loading
Loading
Loading
Loading
+21 −4
Original line number Diff line number Diff line
@@ -403,6 +403,13 @@ static int cam_cpas_util_set_camnoc_axi_clk_rate(
		do_div(intermediate_result, 100);
		required_camnoc_bw += intermediate_result;

		if (cpas_core->streamon_clients && (required_camnoc_bw == 0)) {
			CAM_DBG(CAM_CPAS,
				"Set min vote if streamon_clients is non-zero : streamon_clients=%d",
				cpas_core->streamon_clients);
			required_camnoc_bw = CAM_CPAS_DEFAULT_AXI_BW;
		}

		if ((required_camnoc_bw > 0) &&
			(required_camnoc_bw <
			soc_private->camnoc_axi_min_ib_bw))
@@ -639,8 +646,12 @@ static int cam_cpas_camnoc_set_vote_axi_clk_rate(

		if (camnoc_axi_port->camnoc_bw)
			camnoc_bw = camnoc_axi_port->camnoc_bw;
		else
		else if (camnoc_axi_port->additional_bw)
			camnoc_bw = camnoc_axi_port->additional_bw;
		else if (cpas_core->streamon_clients)
			camnoc_bw = CAM_CPAS_DEFAULT_AXI_BW;
		else
			camnoc_bw = 0;

		rc = cam_cpas_util_vote_bus_client_bw(
			&camnoc_axi_port->bus_client,
@@ -816,14 +827,20 @@ static int cam_cpas_util_apply_client_axi_vote(
		else
			continue;

		CAM_DBG(CAM_PERF, "Port[%s] : ab=%lld ib=%lld additional=%lld",
		CAM_DBG(CAM_PERF,
			"Port[%s] : ab=%lld ib=%lld additional=%lld, streamon_clients=%d",
			mnoc_axi_port->axi_port_name, mnoc_axi_port->ab_bw,
			mnoc_axi_port->ib_bw, mnoc_axi_port->additional_bw);
			mnoc_axi_port->ib_bw, mnoc_axi_port->additional_bw,
			cpas_core->streamon_clients);

		if (mnoc_axi_port->ab_bw)
			mnoc_ab_bw = mnoc_axi_port->ab_bw;
		else
		else if (mnoc_axi_port->additional_bw)
			mnoc_ab_bw = mnoc_axi_port->additional_bw;
		else if (cpas_core->streamon_clients)
			mnoc_ab_bw = CAM_CPAS_DEFAULT_AXI_BW;
		else
			mnoc_ab_bw = 0;

		if (cpas_core->axi_port[i].ib_bw_voting_needed)
			mnoc_ib_bw = mnoc_axi_port->ib_bw;
+126 −63
Original line number Diff line number Diff line
@@ -415,73 +415,48 @@ static int32_t cam_icp_deinit_idle_clk(void *priv, void *data)
	return rc;
}

static int32_t cam_icp_ctx_timer(void *priv, void *data)
static int cam_icp_remove_ctx_bw(struct cam_icp_hw_mgr *hw_mgr,
	struct cam_icp_hw_ctx_data *ctx_data)
{
	struct clk_work_data *task_data = (struct clk_work_data *)data;
	struct cam_icp_hw_ctx_data *ctx_data =
		(struct cam_icp_hw_ctx_data *)task_data->data;
	struct cam_icp_hw_mgr *hw_mgr = &icp_hw_mgr;
	int rc = 0;
	struct cam_hw_intf *dev_intf = NULL;
	uint32_t id;
	uint64_t temp;
	struct cam_hw_intf *ipe0_dev_intf = NULL;
	struct cam_hw_intf *ipe1_dev_intf = NULL;
	struct cam_hw_intf *bps_dev_intf = NULL;
	struct cam_hw_intf *dev_intf = NULL;
	struct cam_icp_clk_info *clk_info;
	struct cam_icp_cpas_vote clk_update;
	int i = 0;
	int device_share_ratio = 1;
	uint64_t total_ab_bw = 0;

	if (!ctx_data) {
		CAM_ERR(CAM_ICP, "ctx_data is NULL, failed to update clk");
	if (!ctx_data->icp_dev_acquire_info) {
		CAM_WARN(CAM_ICP, "NULL acquire info");
		return -EINVAL;
	}

	mutex_lock(&ctx_data->ctx_mutex);
	if ((ctx_data->state != CAM_ICP_CTX_STATE_ACQUIRED) ||
		(ctx_data->watch_dog_reset_counter == 0)) {
		CAM_DBG(CAM_PERF, "state %d, counter=%d",
			ctx_data->state, ctx_data->watch_dog_reset_counter);
		mutex_unlock(&ctx_data->ctx_mutex);
		return 0;
	}

	if (cam_icp_frame_pending(ctx_data)) {
		cam_icp_ctx_timer_reset(ctx_data);
		mutex_unlock(&ctx_data->ctx_mutex);
		return -EBUSY;
	if ((!hw_mgr->ipe0_dev_intf) || (!hw_mgr->bps_dev_intf)) {
		CAM_ERR(CAM_ICP, "dev intfs are wrong, failed to update clk");
		return -EINVAL;
	}

	CAM_DBG(CAM_PERF,
		"E :ctx_id = %d ubw = %lld cbw = %lld curr_fc = %u bc = %u",
		"ctx_id = %d ubw = %lld cbw = %lld curr_fc = %u bc = %u",
		ctx_data->ctx_id,
		ctx_data->clk_info.uncompressed_bw,
		ctx_data->clk_info.compressed_bw,
		ctx_data->clk_info.curr_fc, ctx_data->clk_info.base_clk);

	ipe0_dev_intf = hw_mgr->ipe0_dev_intf;
	ipe1_dev_intf = hw_mgr->ipe1_dev_intf;
	bps_dev_intf = hw_mgr->bps_dev_intf;

	if ((!ipe0_dev_intf) || (!bps_dev_intf)) {
		CAM_ERR(CAM_ICP, "dev intfs are wrong, failed to update clk");
		mutex_unlock(&ctx_data->ctx_mutex);
		return -EINVAL;
	}

	if (!ctx_data->icp_dev_acquire_info) {
		CAM_WARN(CAM_ICP, "NULL acquire info");
		mutex_unlock(&ctx_data->ctx_mutex);
		return -EINVAL;
	if (!ctx_data->clk_info.bw_included) {
		CAM_DBG(CAM_PERF, "ctx_id = %d BW vote already removed",
			ctx_data->ctx_id);
		return 0;
	}

	if (ctx_data->icp_dev_acquire_info->dev_type == CAM_ICP_RES_TYPE_BPS) {
		dev_intf = bps_dev_intf;
		dev_intf = hw_mgr->bps_dev_intf;
		clk_info = &hw_mgr->clk_info[ICP_CLK_HW_BPS];
		id = CAM_ICP_BPS_CMD_VOTE_CPAS;
	} else {
		dev_intf = ipe0_dev_intf;
		dev_intf = hw_mgr->ipe0_dev_intf;
		clk_info = &hw_mgr->clk_info[ICP_CLK_HW_IPE];
		id = CAM_ICP_IPE_CMD_VOTE_CPAS;
	}
@@ -492,7 +467,7 @@ static int32_t cam_icp_ctx_timer(void *priv, void *data)
	 * to vote on each device
	 */
	if ((ctx_data->icp_dev_acquire_info->dev_type !=
		CAM_ICP_RES_TYPE_BPS) && (ipe1_dev_intf))
		CAM_ICP_RES_TYPE_BPS) && (hw_mgr->ipe1_dev_intf))
		device_share_ratio = 2;

	if (ctx_data->bw_config_version == CAM_ICP_BW_CONFIG_V1) {
@@ -549,21 +524,18 @@ static int32_t cam_icp_ctx_timer(void *priv, void *data)
				 * votes only.
				 */
				path_index =
					ctx_data->clk_info.axi_path[i]
					.transac_type -
				ctx_data->clk_info.axi_path[i].transac_type -
				CAM_AXI_TRANSACTION_READ;
			} else {
				path_index =
					ctx_data->clk_info.axi_path[i]
					.path_data_type -
				ctx_data->clk_info.axi_path[i].path_data_type -
				CAM_AXI_PATH_DATA_IPE_START_OFFSET;
			}

			if (path_index >= CAM_ICP_MAX_PER_PATH_VOTES) {
				CAM_WARN(CAM_PERF,
				"Invalid path %d, start offset=%d, max=%d",
					ctx_data->clk_info.axi_path[i]
					.path_data_type,
				ctx_data->clk_info.axi_path[i].path_data_type,
				CAM_AXI_PATH_DATA_IPE_START_OFFSET,
				CAM_ICP_MAX_PER_PATH_VOTES);
				continue;
@@ -582,6 +554,30 @@ static int32_t cam_icp_ctx_timer(void *priv, void *data)

			total_ab_bw +=
				clk_info->axi_path[path_index].mnoc_ab_bw;

			CAM_DBG(CAM_PERF,
				"Removing ctx bw from path_type: %s, transac_type: %s, camnoc_bw = %lld mnoc_ab_bw = %lld, mnoc_ib_bw = %lld, device: %s",
				cam_cpas_axi_util_path_type_to_string(
				ctx_data->clk_info.axi_path[i].path_data_type),
				cam_cpas_axi_util_trans_type_to_string(
				ctx_data->clk_info.axi_path[i].transac_type),
				ctx_data->clk_info.axi_path[i].camnoc_bw,
				ctx_data->clk_info.axi_path[i].mnoc_ab_bw,
				ctx_data->clk_info.axi_path[i].mnoc_ib_bw,
				cam_icp_dev_type_to_name(
				ctx_data->icp_dev_acquire_info->dev_type));

			CAM_DBG(CAM_PERF,
				"Final HW bw for path_type: %s, transac_type: %s, camnoc_bw = %lld mnoc_ab_bw = %lld, mnoc_ib_bw = %lld, device: %s",
				cam_cpas_axi_util_path_type_to_string(
				clk_info->axi_path[i].path_data_type),
				cam_cpas_axi_util_trans_type_to_string(
				clk_info->axi_path[i].transac_type),
				clk_info->axi_path[i].camnoc_bw,
				clk_info->axi_path[i].mnoc_ab_bw,
				clk_info->axi_path[i].mnoc_ib_bw,
				cam_icp_dev_type_to_name(
				ctx_data->icp_dev_acquire_info->dev_type));
		}

		memset(&ctx_data->clk_info.axi_path[0], 0,
@@ -628,22 +624,76 @@ static int32_t cam_icp_ctx_timer(void *priv, void *data)
		clk_update.ahb_vote_valid = false;
	}

	dev_intf->hw_ops.process_cmd(dev_intf->hw_priv, id,
	rc = dev_intf->hw_ops.process_cmd(dev_intf->hw_priv, id,
		&clk_update, sizeof(clk_update));
	if (rc)
		CAM_ERR(CAM_PERF, "Failed in updating cpas vote, rc=%d", rc);

	/*
	 * Vote half bandwidth each on both devices.
	 * Total bw at mnoc - CPAS will take care of adding up.
	 * camnoc clk calculate is more accurate this way.
	 */
	if ((ctx_data->icp_dev_acquire_info->dev_type !=
		CAM_ICP_RES_TYPE_BPS) && (ipe1_dev_intf))
		ipe1_dev_intf->hw_ops.process_cmd(ipe1_dev_intf->hw_priv, id,
		&clk_update, sizeof(clk_update));
	if ((!rc) && (hw_mgr->ipe1_dev_intf) &&
		(ctx_data->icp_dev_acquire_info->dev_type !=
		CAM_ICP_RES_TYPE_BPS)) {
		dev_intf = hw_mgr->ipe1_dev_intf;
		rc = dev_intf->hw_ops.process_cmd(dev_intf->hw_priv,
			id, &clk_update, sizeof(clk_update));
		if (rc)
			CAM_ERR(CAM_PERF,
				"Failed in updating cpas vote for ipe 2, rc=%d",
				rc);
	}

	ctx_data->clk_info.bw_included = false;

	CAM_DBG(CAM_PERF, "X :ctx_id = %d curr_fc = %u bc = %u",
		ctx_data->ctx_id, ctx_data->clk_info.curr_fc,
		ctx_data->clk_info.base_clk);

	return rc;

}


static int32_t cam_icp_ctx_timer(void *priv, void *data)
{
	struct clk_work_data *task_data = (struct clk_work_data *)data;
	struct cam_icp_hw_ctx_data *ctx_data =
		(struct cam_icp_hw_ctx_data *)task_data->data;

	if (!ctx_data) {
		CAM_ERR(CAM_ICP, "ctx_data is NULL, failed to update clk");
		return -EINVAL;
	}

	mutex_lock(&ctx_data->ctx_mutex);

	CAM_DBG(CAM_PERF,
		"ctx_id = %d ubw = %lld cbw = %lld curr_fc = %u bc = %u",
		ctx_data->ctx_id,
		ctx_data->clk_info.uncompressed_bw,
		ctx_data->clk_info.compressed_bw,
		ctx_data->clk_info.curr_fc,
		ctx_data->clk_info.base_clk);

	if ((ctx_data->state != CAM_ICP_CTX_STATE_ACQUIRED) ||
		(ctx_data->watch_dog_reset_counter == 0)) {
		CAM_DBG(CAM_PERF, "state %d, counter=%d",
			ctx_data->state, ctx_data->watch_dog_reset_counter);
		mutex_unlock(&ctx_data->ctx_mutex);
		return 0;
	}

	if (cam_icp_frame_pending(ctx_data)) {
		cam_icp_ctx_timer_reset(ctx_data);
		mutex_unlock(&ctx_data->ctx_mutex);
		return -EBUSY;
	}

	cam_icp_remove_ctx_bw(&icp_hw_mgr, ctx_data);

	mutex_unlock(&ctx_data->ctx_mutex);

	return 0;
@@ -1184,6 +1234,8 @@ static bool cam_icp_update_bw_v2(struct cam_icp_hw_mgr *hw_mgr,
			hw_mgr_clk_info->axi_path[path_index].mnoc_ab_bw);
	}

	ctx_data->clk_info.bw_included = true;

	if (hw_mgr_clk_info->num_paths < ctx_data->clk_info.num_paths)
		hw_mgr_clk_info->num_paths = ctx_data->clk_info.num_paths;

@@ -1250,6 +1302,8 @@ static bool cam_icp_update_bw(struct cam_icp_hw_mgr *hw_mgr,
		}
	}

	ctx_data->clk_info.bw_included = true;

	return true;
}

@@ -1432,6 +1486,7 @@ static int cam_icp_update_clk_rate(struct cam_icp_hw_mgr *hw_mgr,
static int cam_icp_update_cpas_vote(struct cam_icp_hw_mgr *hw_mgr,
	struct cam_icp_hw_ctx_data *ctx_data)
{
	int rc = 0;
	uint32_t id;
	uint64_t temp;
	int i = 0;
@@ -1529,8 +1584,10 @@ static int cam_icp_update_cpas_vote(struct cam_icp_hw_mgr *hw_mgr,
	}

	clk_update.axi_vote_valid = true;
	dev_intf->hw_ops.process_cmd(dev_intf->hw_priv, id,
	rc = dev_intf->hw_ops.process_cmd(dev_intf->hw_priv, id,
		&clk_update, sizeof(clk_update));
	if (rc)
		CAM_ERR(CAM_PERF, "Failed in updating cpas vote, rc=%d", rc);

	/*
	 * Vote half bandwidth each on both devices.
@@ -1538,11 +1595,16 @@ static int cam_icp_update_cpas_vote(struct cam_icp_hw_mgr *hw_mgr,
	 * camnoc clk calculate is more accurate this way.
	 */
	if ((ctx_data->icp_dev_acquire_info->dev_type !=
		CAM_ICP_RES_TYPE_BPS) && (ipe1_dev_intf))
		ipe1_dev_intf->hw_ops.process_cmd(ipe1_dev_intf->hw_priv, id,
		&clk_update, sizeof(clk_update));
		CAM_ICP_RES_TYPE_BPS) && (ipe1_dev_intf)) {
		rc = ipe1_dev_intf->hw_ops.process_cmd(ipe1_dev_intf->hw_priv,
			id, &clk_update, sizeof(clk_update));
		if (rc)
			CAM_ERR(CAM_PERF,
				"Failed in updating cpas vote for ipe 2, rc=%d",
				rc);
	}

	return 0;
	return rc;
}

static int cam_icp_mgr_ipe_bps_clk_update(struct cam_icp_hw_mgr *hw_mgr,
@@ -3315,6 +3377,7 @@ static int cam_icp_mgr_release_ctx(struct cam_icp_hw_mgr *hw_mgr, int ctx_id)
	}

	mutex_lock(&hw_mgr->ctx_data[ctx_id].ctx_mutex);
	cam_icp_remove_ctx_bw(hw_mgr, &hw_mgr->ctx_data[ctx_id]);
	if (hw_mgr->ctx_data[ctx_id].state !=
		CAM_ICP_CTX_STATE_ACQUIRED) {
		mutex_unlock(&hw_mgr->ctx_data[ctx_id].ctx_mutex);
+2 −0
Original line number Diff line number Diff line
@@ -207,6 +207,7 @@ struct hfi_frame_process_info {
 * @clk_rate: Supported clock rates for the context
 * @num_paths: Number of valid AXI paths
 * @axi_path: ctx based per path bw vote
 * @bw_included: Whether bw of this context is included in overal voting
 */
struct cam_ctx_clk_info {
	uint32_t curr_fc;
@@ -218,6 +219,7 @@ struct cam_ctx_clk_info {
	int32_t clk_rate[CAM_MAX_VOTE];
	uint32_t num_paths;
	struct cam_axi_per_path_bw_vote axi_path[CAM_ICP_MAX_PER_PATH_VOTES];
	bool bw_included;
};
/**
 * struct cam_icp_hw_ctx_data