Bladeren bron

msm: camera: isp: Fix the logic to disable TFE WM clients dynamically

TFE disable WM client logic is broken due to ISP common framework
changes and last consume address changes in ISP common framework.

Fixed the logic to disable WM dynamically. This change add the
fix for invalid pointer access in last consume address logic
as well.

CRs-Fixed: 3696470
Signed-off-by: Alok Chauhan <[email protected]>
Change-Id: I31d06e0dfe17ef660e7ff023b41ada1d713ff92f
Alok Chauhan 1 jaar geleden
bovenliggende
commit
0595a89841

+ 14 - 10
drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c

@@ -901,17 +901,19 @@ static void cam_tfe_hw_mgr_dump_all_ctx(void)
 static void cam_tfe_mgr_add_base_info(
 	struct cam_tfe_hw_mgr_ctx       *ctx,
 	enum cam_isp_hw_split_id         split_id,
-	uint32_t                         base_idx)
+	uint32_t                         base_idx,
+	enum cam_isp_hw_type             hw_type)
 {
 	uint32_t    i;
 
 	if (!ctx->num_base) {
 		ctx->base[0].split_id = split_id;
 		ctx->base[0].idx      = base_idx;
+		ctx->base[0].hw_type  = hw_type;
 		ctx->num_base++;
 		CAM_DBG(CAM_ISP,
-			"Add split id = %d for base idx = %d num_base=%d",
-			split_id, base_idx, ctx->num_base);
+			"Add split id = %d for base idx = %d num_base=%d hw_type=%d",
+			split_id, base_idx, ctx->num_base, hw_type);
 	} else {
 		/*Check if base index already exists in the list */
 		for (i = 0; i < ctx->num_base; i++) {
@@ -928,10 +930,11 @@ static void cam_tfe_mgr_add_base_info(
 		if (i == ctx->num_base) {
 			ctx->base[ctx->num_base].split_id = split_id;
 			ctx->base[ctx->num_base].idx      = base_idx;
+			ctx->base[ctx->num_base].hw_type  = hw_type;
 			ctx->num_base++;
 			CAM_DBG(CAM_ISP,
-				"Add split_id=%d for base idx=%d num_base=%d",
-				 split_id, base_idx, ctx->num_base);
+				"Add split_id=%d for base idx=%d num_base=%d hw_type=%d",
+				 split_id, base_idx, ctx->num_base, hw_type);
 		}
 	}
 }
@@ -959,12 +962,13 @@ static int cam_tfe_mgr_process_base_info(
 
 			res = hw_mgr_res->hw_res[i];
 			cam_tfe_mgr_add_base_info(ctx, i,
-					res->hw_intf->hw_idx);
-			CAM_DBG(CAM_ISP, "add base info for hw %d",
-				res->hw_intf->hw_idx);
+					res->hw_intf->hw_idx,
+					CAM_ISP_HW_TYPE_TFE);
+			CAM_DBG(CAM_ISP, "add base info for hw %d ctx_idx: %u",
+				res->hw_intf->hw_idx, ctx->ctx_index);
 		}
 	}
-	CAM_DBG(CAM_ISP, "ctx base num = %d", ctx->num_base);
+	CAM_DBG(CAM_ISP, "ctx base num = %d, ctx_idx: %u", ctx->num_base, ctx->ctx_index);
 
 	return 0;
 }
@@ -5682,7 +5686,7 @@ static int cam_tfe_mgr_cmd_get_last_consumed_addr(
 	}
 
 	hw_mgr_res =
-		&ctx->res_list_tfe_out[res_id_out];
+		&ctx->res_list_tfe_out[ctx->tfe_out_map[res_id_out]];
 
 	for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) {
 		if (!hw_mgr_res->hw_res[i])

+ 26 - 21
drivers/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c

@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
  * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
- * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
  */
 
 #include <media/cam_defs.h>
@@ -767,8 +767,8 @@ static int cam_isp_io_buf_get_entries_util(
 				&buf_info->scratch_check_cfg->ife_scratch_res_info,
 				io_cfg->resource_type);
 		}
-
 		*hw_mgr_res = &buf_info->res_list_isp_out[buf_info->out_map[res_id]];
+
 		if ((*hw_mgr_res)->res_type == CAM_ISP_RESOURCE_UNINT) {
 			CAM_ERR(CAM_ISP, "io res id:%d not valid",
 				io_cfg->resource_type);
@@ -1220,13 +1220,14 @@ int cam_isp_add_io_buffers(struct cam_isp_io_buf_info   *io_info)
 	}
 
 	disabled_wm_mask = (prepare_hw_data->wm_bitmask ^ cfg_io_mask);
+
 	if ((io_info->base->hw_type == CAM_ISP_HW_TYPE_TFE) && disabled_wm_mask) {
 		for (j = 0; j < io_info->out_max; j++) {
 			rc = cam_isp_add_disable_wm_update(io_info->prepare,
-					&io_info->res_list_isp_out[j],
+					&io_info->res_list_isp_out[io_info->out_map[j]],
 					io_info->base->idx, io_info->kmd_buf_info,
-					disabled_wm_mask,
-					&io_info->kmd_buf_info->used_bytes);
+					&disabled_wm_mask,
+					io_info);
 			if (rc) {
 				CAM_ERR_RATE_LIMIT(CAM_ISP, "Disable out res %d failed",
 						j, rc);
@@ -1263,8 +1264,8 @@ int cam_isp_add_disable_wm_update(
 	struct cam_isp_hw_mgr_res            *isp_hw_res,
 	uint32_t                              base_idx,
 	struct cam_kmd_buf_info              *kmd_buf_info,
-	uint64_t                              wm_mask,
-	uint32_t                             *io_cfg_used_bytes)
+	uint64_t                              *wm_mask,
+	struct cam_isp_io_buf_info *io_info)
 {
 	int rc = 0;
 	struct cam_hw_intf                 *hw_intf;
@@ -1281,23 +1282,25 @@ int cam_isp_add_disable_wm_update(
 		res = isp_hw_res->hw_res[i];
 		if (res->hw_intf->hw_idx != base_idx)
 			continue;
-		if (!(wm_mask & (1 << res->res_id))) {
+		if (!(*wm_mask & (1 << res->res_id))) {
 			CAM_DBG(CAM_ISP, "No need to disable out res %d", res->res_id);
 			continue;
 		}
-		if (kmd_buf_info->size > (kmd_buf_info->used_bytes +
-			(*io_cfg_used_bytes))) {
-			kmd_buf_remain_size =  kmd_buf_info->size -
-			(kmd_buf_info->used_bytes +
-			(*io_cfg_used_bytes));
+
+		*wm_mask &= ~BIT(res->res_id);
+
+		if (kmd_buf_info->used_bytes < kmd_buf_info->size) {
+			kmd_buf_remain_size = kmd_buf_info->size - kmd_buf_info->used_bytes;
 		} else {
-			CAM_ERR(CAM_ISP, "no free mem %d %d", kmd_buf_info->size,
-				kmd_buf_info->used_bytes + (*io_cfg_used_bytes));
-			rc = -EINVAL;
-			return rc;
+			CAM_ERR(CAM_ISP,
+				"no free kmd memory for base=%d bytes_used=%u buf_size=%u",
+				base_idx, kmd_buf_info->used_bytes, kmd_buf_info->size);
+				rc = -EINVAL;
+				return rc;
 		}
+
 		wm_update.cmd.cmd_buf_addr = kmd_buf_info->cpu_addr +
-			kmd_buf_info->used_bytes/4 + (*io_cfg_used_bytes)/4;
+			kmd_buf_info->used_bytes/4;
 		wm_update.cmd.size = kmd_buf_remain_size;
 		wm_update.cmd_type = CAM_ISP_HW_CMD_BUS_WM_DISABLE;
 		wm_update.res = res;
@@ -1311,9 +1314,11 @@ int cam_isp_add_disable_wm_update(
 			return rc;
 		}
 		CAM_DBG(CAM_ISP,
-			"Out res %d disable update added hw_id %d cdm_idx %d",
-			res->res_id, res->hw_intf->hw_idx, base_idx);
-		(*io_cfg_used_bytes) += wm_update.cmd.used_bytes;
+			"Out res %d disable update added hw_id %d cdm_idx %d split id: %d",
+			res->res_id, res->hw_intf->hw_idx, base_idx, i);
+
+		io_info->kmd_buf_info->used_bytes += wm_update.cmd.used_bytes;
+		io_info->kmd_buf_info->offset += wm_update.cmd.used_bytes;
 	}
 	return rc;
 }

+ 4 - 4
drivers/cam_isp/isp_hw_mgr/hw_utils/include/cam_isp_packet_parser.h

@@ -1,7 +1,7 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /*
  * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
- * Copyright (c) 2022-2023, Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022-2024, Qualcomm Innovation Center, Inc. All rights reserved.
  */
 
 #ifndef _CAM_ISP_HW_PARSER_H_
@@ -288,7 +288,7 @@ int cam_isp_add_io_buffers(struct cam_isp_io_buf_info   *io_info);
  * @base_idx:              Base or dev index of the IFE/VFE HW instance
  * @kmd_buf_info:          Kmd buffer to store the change base command
  * @wm_mask                Bit mask of unconfigured resource
- * @io_cfg_used_bytes      IO cfg size used in bytes
+ * @io_info                IO buf info
  *
  */
 int cam_isp_add_disable_wm_update(
@@ -296,8 +296,8 @@ int cam_isp_add_disable_wm_update(
 	struct cam_isp_hw_mgr_res            *isp_hw_res,
 	uint32_t                              base_idx,
 	struct cam_kmd_buf_info              *kmd_buf_info,
-	uint64_t                              wm_mask,
-	uint32_t                             *io_cfg_used_bytes);
+	uint64_t                              *wm_mask,
+	struct cam_isp_io_buf_info *io_info);
 
 /*
  * cam_isp_add_reg_update()

+ 16 - 6
drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.c

@@ -1988,13 +1988,15 @@ static uint32_t cam_tfe_bus_get_last_consumed_addr(
 	struct cam_isp_resource_node        *rsrc_node = NULL;
 	struct cam_tfe_bus_tfe_out_data     *rsrc_data = NULL;
 	struct cam_tfe_bus_wm_resource_data *wm_rsrc_data = NULL;
+	enum cam_tfe_bus_tfe_out_id             tfe_out_res_id;
 
-	if (out_id >= CAM_TFE_BUS_TFE_OUT_MAX) {
+	tfe_out_res_id = cam_tfe_bus_get_out_res_id(out_id);
+	if (tfe_out_res_id >= CAM_TFE_BUS_TFE_OUT_MAX) {
 		CAM_ERR(CAM_ISP, "invalid out_id:%u", out_id);
 		return 0;
 	}
 
-	rsrc_node = &bus_priv->tfe_out[out_id];
+	rsrc_node = &bus_priv->tfe_out[tfe_out_res_id];
 	rsrc_data = rsrc_node->res_priv;
 	wm_rsrc_data = rsrc_data->wm_res[PLANE_Y]->res_priv;
 
@@ -2002,6 +2004,9 @@ static uint32_t cam_tfe_bus_get_last_consumed_addr(
 		wm_rsrc_data->common_data->mem_base +
 		wm_rsrc_data->hw_regs->addr_status_0);
 
+	CAM_DBG(CAM_ISP, "TFE:%u res_type:0x%x res_id:0x%x last_consumed_addr:0x%x",
+		bus_priv->common_data.core_index, out_id, tfe_out_res_id, val);
+
 	return val;
 }
 
@@ -2016,6 +2021,7 @@ static int cam_tfe_bus_bufdone_bottom_half(
 	struct cam_tfe_bus_comp_grp_data     *comp_rsrc_data;
 	struct cam_isp_hw_bufdone_event_info  bufdone_evt_info = {0};
 	uint32_t i;
+	struct cam_tfe_bus_wm_resource_data *wm_rsrc_data = NULL;
 
 	common_data = &bus_priv->common_data;
 
@@ -2027,6 +2033,10 @@ static int cam_tfe_bus_bufdone_bottom_half(
 		comp_rsrc_data = (struct cam_tfe_bus_comp_grp_data  *)
 			bus_priv->comp_grp[i].res_priv;
 
+		CAM_DBG(CAM_ISP, "i: %d irq: 0x%x comm_done: 0x%x com_grp: %d",
+			i, evt_payload->bus_irq_val[0], bus_priv->common_data.comp_done_shift,
+			comp_rsrc_data->comp_grp_id);
+
 		if (evt_payload->bus_irq_val[0] &
 			BIT(comp_rsrc_data->comp_grp_id +
 			bus_priv->common_data.comp_done_shift)) {
@@ -2037,10 +2047,10 @@ static int cam_tfe_bus_bufdone_bottom_half(
 				evt_info.res_id = out_rsrc->res_id;
 				bufdone_evt_info.res_id = out_rsrc->res_id;
 				bufdone_evt_info.comp_grp_id = comp_rsrc_data->comp_grp_id;
-				bufdone_evt_info.last_consumed_addr =
-					cam_tfe_bus_get_last_consumed_addr(
-						out_rsrc_data->bus_priv,
-						out_rsrc_data->out_id);
+				wm_rsrc_data = out_rsrc_data->wm_res[PLANE_Y]->res_priv;
+				bufdone_evt_info.last_consumed_addr = cam_io_r_mb(
+					wm_rsrc_data->common_data->mem_base +
+					wm_rsrc_data->hw_regs->addr_status_0);
 				evt_info.event_data = (void *)&bufdone_evt_info;
 
 				if (out_rsrc_data->event_cb)