From 3e463c33ea05e60c2deed74f2b8a7e0eba72f594 Mon Sep 17 00:00:00 2001 From: Pavan Kumar Chilamkurthi Date: Thu, 6 Feb 2020 13:58:09 -0800 Subject: [PATCH] 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: Pavan Kumar Chilamkurthi --- drivers/cam_cpas/cam_cpas_hw.c | 25 ++- .../icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c | 189 ++++++++++++------ .../icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h | 2 + 3 files changed, 149 insertions(+), 67 deletions(-) diff --git a/drivers/cam_cpas/cam_cpas_hw.c b/drivers/cam_cpas/cam_cpas_hw.c index 0486a0c2fccd..134b1638b2e2 100644 --- a/drivers/cam_cpas/cam_cpas_hw.c +++ b/drivers/cam_cpas/cam_cpas_hw.c @@ -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 @@ vote_start_clients: 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; diff --git a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c index 3f30bb6819d4..425cebafae75 100644 --- a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c +++ b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c @@ -415,73 +415,48 @@ done: 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,23 +524,20 @@ static int32_t cam_icp_ctx_timer(void *priv, void *data) * votes only. */ path_index = - ctx_data->clk_info.axi_path[i] - .transac_type - - CAM_AXI_TRANSACTION_READ; + 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 - - CAM_AXI_PATH_DATA_IPE_START_OFFSET; + 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, - CAM_AXI_PATH_DATA_IPE_START_OFFSET, - CAM_ICP_MAX_PER_PATH_VOTES); + "Invalid path %d, start offset=%d, max=%d", + 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); diff --git a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h index c438d438e892..a4b3817680e8 100644 --- a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h +++ b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h @@ -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