Explorar o código

msm: camera: common: Add a check for 0 reg-val pairs in cdm command

Add a check for reg-val count=0 in reg_random command. Count=0 in
reg_random cdm command will throw an invalid command HW error.

CRs-Fixed: 2916477
Change-Id: Idb8654c3752963cf5a52147d350e291208b917d0
Signed-off-by: Jigar Agrawal <[email protected]>
Jigar Agrawal %!s(int64=4) %!d(string=hai) anos
pai
achega
b5c4f91b83

+ 12 - 2
drivers/cam_cdm/cam_cdm_util.c

@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
- * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
  */
 
 #include <linux/types.h>
@@ -196,8 +196,13 @@ uint32_t cdm_required_size_dmi(void)
 	return cdm_get_cmd_header_size(CAM_CDM_CMD_DMI);
 }
 
-uint32_t cdm_required_size_reg_continuous(uint32_t  numVals)
+uint32_t cdm_required_size_reg_continuous(uint32_t numVals)
 {
+	if (!numVals) {
+		CAM_WARN(CAM_CDM, "numVals cant be 0");
+		return 0;
+	}
+
 	return cdm_get_cmd_header_size(CAM_CDM_CMD_REG_CONT) + numVals;
 }
 
@@ -300,6 +305,11 @@ uint32_t *cdm_write_regrandom(uint32_t *pCmdBuffer, uint32_t numRegVals,
 	struct cdm_regrandom_cmd *pHeader =
 		(struct cdm_regrandom_cmd *)pCmdBuffer;
 
+	if (!numRegVals) {
+		CAM_ERR(CAM_CDM, "Number of reg-val pairs can not be 0");
+		return pCmdBuffer;
+	}
+
 	pHeader->count = numRegVals;
 	pHeader->cmd = CAM_CDM_CMD_REG_RANDOM;
 	pHeader->reserved = 0;

+ 38 - 23
drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_core.c

@@ -173,6 +173,7 @@ static int cam_fd_hw_util_processcmd_prestart(struct cam_hw_info *fd_hw,
 	uint32_t *cmd_buf_addr = prestart_args->cmd_buf_addr;
 	uint32_t reg_val_pair[CAM_FD_REG_VAL_PAIR_SIZE];
 	uint32_t num_cmds = 0;
+	uint32_t num_regval_pairs = 0;
 	int i;
 	struct cam_fd_hw_io_buffer *io_buf;
 	struct cam_fd_hw_req_private *req_private;
@@ -364,19 +365,25 @@ static int cam_fd_hw_util_processcmd_prestart(struct cam_hw_info *fd_hw,
 	ctx_hw_private->cdm_ops->cdm_write_changebase(cmd_buf_addr, mem_base);
 	cmd_buf_addr += size;
 	available_size -= (size * 4);
+	num_regval_pairs = num_cmds / 2;
 
-	size = ctx_hw_private->cdm_ops->cdm_required_size_reg_random(
-		num_cmds/2);
-	/* cdm util returns dwords, need to convert to bytes */
-	if ((size * 4) > available_size) {
-		CAM_ERR(CAM_FD, "Insufficient size:%d , expected size:%d",
-			available_size, size);
-		return -ENOMEM;
+	if (num_regval_pairs) {
+		size = ctx_hw_private->cdm_ops->cdm_required_size_reg_random(
+			num_regval_pairs);
+		/* cdm util returns dwords, need to convert to bytes */
+		if ((size * 4) > available_size) {
+			CAM_ERR(CAM_FD,
+				"Insufficient size:%d , expected size:%d",
+				available_size, size);
+			return -ENOMEM;
+		}
+		ctx_hw_private->cdm_ops->cdm_write_regrandom(cmd_buf_addr,
+			num_regval_pairs, reg_val_pair);
+		cmd_buf_addr += size;
+		available_size -= (size * 4);
+	} else {
+		CAM_DBG(CAM_FD, "No reg val pairs");
 	}
-	ctx_hw_private->cdm_ops->cdm_write_regrandom(cmd_buf_addr, num_cmds/2,
-		reg_val_pair);
-	cmd_buf_addr += size;
-	available_size -= (size * 4);
 
 	/* Update pre_config_buf_size in bytes */
 	prestart_args->pre_config_buf_size =
@@ -385,19 +392,27 @@ static int cam_fd_hw_util_processcmd_prestart(struct cam_hw_info *fd_hw,
 	/* Insert start trigger command into CDM as post config commands. */
 	num_cmds = cam_fd_cdm_write_reg_val_pair(reg_val_pair, 0,
 		hw_static_info->core_regs.control, 0x2);
-	size = ctx_hw_private->cdm_ops->cdm_required_size_reg_random(
-		num_cmds/2);
-	if ((size * 4) > available_size) {
-		CAM_ERR(CAM_FD, "Insufficient size:%d , expected size:%d",
-			available_size, size);
-		return -ENOMEM;
-	}
-	ctx_hw_private->cdm_ops->cdm_write_regrandom(cmd_buf_addr, num_cmds/2,
-		reg_val_pair);
-	cmd_buf_addr += size;
-	available_size -= (size * 4);
 
-	prestart_args->post_config_buf_size = size * 4;
+	num_regval_pairs = num_cmds / 2;
+
+	if (num_regval_pairs) {
+		size = ctx_hw_private->cdm_ops->cdm_required_size_reg_random(
+			num_regval_pairs);
+		if ((size * 4) > available_size) {
+			CAM_ERR(CAM_FD,
+				"Insufficient size:%d , expected size:%d",
+				available_size, size);
+			return -ENOMEM;
+		}
+		ctx_hw_private->cdm_ops->cdm_write_regrandom(cmd_buf_addr,
+			num_regval_pairs, reg_val_pair);
+		cmd_buf_addr += size;
+		available_size -= (size * 4);
+		prestart_args->post_config_buf_size = size * 4;
+	} else {
+		CAM_DBG(CAM_FD, "No reg val pairs");
+		prestart_args->post_config_buf_size = 0;
+	}
 
 	CAM_DBG(CAM_FD, "PreConfig [%pK %d], PostConfig[%pK %d]",
 		prestart_args->cmd_buf_addr, prestart_args->pre_config_buf_size,

+ 27 - 13
drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_bus/cam_sfe_bus_rd.c

@@ -1208,7 +1208,9 @@ static int cam_sfe_bus_rd_update_rm(void *priv, void *cmd_args,
 	struct cam_buf_io_cfg                  *io_cfg = NULL;
 	struct cam_sfe_bus_rd_data             *sfe_bus_rd_data = NULL;
 	struct cam_sfe_bus_rd_rm_resource_data *rm_data = NULL;
+	struct cam_cdm_utils_ops               *cdm_util_ops;
 	uint32_t *reg_val_pair;
+	uint32_t num_regval_pairs = 0;
 	uint32_t width = 0, height = 0, stride = 0;
 	uint32_t  i, j, size = 0;
 
@@ -1218,7 +1220,9 @@ static int cam_sfe_bus_rd_update_rm(void *priv, void *cmd_args,
 	sfe_bus_rd_data = (struct cam_sfe_bus_rd_data *)
 		update_buf->res->res_priv;
 
-	if (!sfe_bus_rd_data || !sfe_bus_rd_data->cdm_util_ops) {
+	cdm_util_ops = sfe_bus_rd_data->cdm_util_ops;
+
+	if (!sfe_bus_rd_data || !cdm_util_ops) {
 		CAM_ERR(CAM_SFE, "Failed! Invalid data");
 		return -EINVAL;
 	}
@@ -1287,21 +1291,31 @@ static int cam_sfe_bus_rd_update_rm(void *priv, void *cmd_args,
 		rm_data->img_addr = reg_val_pair[j-1];
 	}
 
-	size = sfe_bus_rd_data->cdm_util_ops->cdm_required_size_reg_random(j/2);
+	num_regval_pairs = j / 2;
+	if (num_regval_pairs) {
+		size = cdm_util_ops->cdm_required_size_reg_random(
+			num_regval_pairs);
 
-	/* cdm util returns dwords, need to convert to bytes */
-	if ((size * 4) > update_buf->cmd.size) {
-		CAM_ERR(CAM_SFE,
-			"Failed! Buf size:%d insufficient, expected size:%d",
-			update_buf->cmd.size, size);
-		return -ENOMEM;
-	}
+		/* cdm util returns dwords, need to convert to bytes */
+		if ((size * 4) > update_buf->cmd.size) {
+			CAM_ERR(CAM_SFE,
+				"Failed! Buf size:%d insufficient, expected size:%d",
+				update_buf->cmd.size, size);
+			return -ENOMEM;
+		}
 
-	sfe_bus_rd_data->cdm_util_ops->cdm_write_regrandom(
-		update_buf->cmd.cmd_buf_addr, j/2, reg_val_pair);
+		cdm_util_ops->cdm_write_regrandom(
+			update_buf->cmd.cmd_buf_addr, num_regval_pairs,
+			reg_val_pair);
 
-	/* cdm util returns dwords, need to convert to bytes */
-	update_buf->cmd.used_bytes = size * 4;
+		/* cdm util returns dwords, need to convert to bytes */
+		update_buf->cmd.used_bytes = size * 4;
+	} else {
+		update_buf->cmd.used_bytes = 0;
+		CAM_DBG(CAM_SFE,
+			"No reg val pairs. num_rms: %u",
+			sfe_bus_rd_data->num_rm);
+	}
 
 	return 0;
 }

+ 55 - 26
drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_bus/cam_sfe_bus_wr.c

@@ -1987,8 +1987,10 @@ static int cam_sfe_bus_wr_update_wm(void *priv, void *cmd_args,
 	struct cam_isp_hw_get_cmd_update       *update_buf;
 	struct cam_buf_io_cfg                  *io_cfg = NULL;
 	struct cam_sfe_bus_wr_out_data         *sfe_out_data = NULL;
+	struct cam_cdm_utils_ops               *cdm_util_ops;
 	struct cam_sfe_bus_wr_wm_resource_data *wm_data = NULL;
 	uint32_t *reg_val_pair;
+	uint32_t num_regval_pairs = 0;
 	uint32_t  i, j, k, size = 0;
 	uint32_t  frame_inc = 0, val;
 	uint32_t loop_size = 0, stride = 0, slice_h = 0;
@@ -1999,7 +2001,9 @@ static int cam_sfe_bus_wr_update_wm(void *priv, void *cmd_args,
 	sfe_out_data = (struct cam_sfe_bus_wr_out_data *)
 		update_buf->res->res_priv;
 
-	if (!sfe_out_data || !sfe_out_data->cdm_util_ops) {
+	cdm_util_ops = sfe_out_data->cdm_util_ops;
+
+	if (!sfe_out_data || !cdm_util_ops) {
 		CAM_ERR(CAM_SFE, "Failed! Invalid data");
 		return -EINVAL;
 	}
@@ -2110,21 +2114,32 @@ static int cam_sfe_bus_wr_update_wm(void *priv, void *cmd_args,
 			wm_data->init_cfg_done = true;
 	}
 
-	size = sfe_out_data->cdm_util_ops->cdm_required_size_reg_random(j/2);
+	num_regval_pairs = j / 2;
 
-	/* cdm util returns dwords, need to convert to bytes */
-	if ((size * 4) > update_buf->cmd.size) {
-		CAM_ERR(CAM_SFE,
-			"Failed! Buf size:%d insufficient, expected size:%d",
-			update_buf->cmd.size, size);
-		return -ENOMEM;
-	}
+	if (num_regval_pairs) {
+		size = cdm_util_ops->cdm_required_size_reg_random(
+			num_regval_pairs);
+
+		/* cdm util returns dwords, need to convert to bytes */
+		if ((size * 4) > update_buf->cmd.size) {
+			CAM_ERR(CAM_SFE,
+				"Failed! Buf size:%d insufficient, expected size:%d",
+				update_buf->cmd.size, size);
+			return -ENOMEM;
+		}
 
-	sfe_out_data->cdm_util_ops->cdm_write_regrandom(
-		update_buf->cmd.cmd_buf_addr, j/2, reg_val_pair);
+		cdm_util_ops->cdm_write_regrandom(
+			update_buf->cmd.cmd_buf_addr, num_regval_pairs,
+			reg_val_pair);
 
-	/* cdm util returns dwords, need to convert to bytes */
-	update_buf->cmd.used_bytes = size * 4;
+		/* cdm util returns dwords, need to convert to bytes */
+		update_buf->cmd.used_bytes = size * 4;
+	} else {
+		CAM_DBG(CAM_SFE,
+			"No reg val pairs. num_wms: %u",
+			sfe_out_data->num_wm);
+		update_buf->cmd.used_bytes = 0;
+	}
 
 	return 0;
 }
@@ -2252,7 +2267,9 @@ static int cam_sfe_bus_wr_update_hfr(void *priv, void *cmd_args,
 	struct cam_sfe_bus_wr_out_data         *sfe_out_data = NULL;
 	struct cam_sfe_bus_wr_wm_resource_data *wm_data = NULL;
 	struct cam_isp_port_hfr_config         *hfr_cfg = NULL;
+	struct cam_cdm_utils_ops               *cdm_util_ops;
 	uint32_t *reg_val_pair;
+	uint32_t num_regval_pairs = 0;
 	uint32_t  i, j, size = 0;
 
 	bus_priv = (struct cam_sfe_bus_wr_priv  *) priv;
@@ -2261,7 +2278,8 @@ static int cam_sfe_bus_wr_update_hfr(void *priv, void *cmd_args,
 	sfe_out_data = (struct cam_sfe_bus_wr_out_data *)
 		update_hfr->res->res_priv;
 
-	if (!sfe_out_data || !sfe_out_data->cdm_util_ops) {
+	cdm_util_ops = sfe_out_data->cdm_util_ops;
+	if (!sfe_out_data || !cdm_util_ops) {
 		CAM_ERR(CAM_SFE, "Failed! Invalid data");
 		return -EINVAL;
 	}
@@ -2326,21 +2344,32 @@ static int cam_sfe_bus_wr_update_hfr(void *priv, void *cmd_args,
 			wm_data->hfr_cfg_done = true;
 	}
 
-	size = sfe_out_data->cdm_util_ops->cdm_required_size_reg_random(j/2);
+	num_regval_pairs = j / 2;
 
-	/* cdm util returns dwords, need to convert to bytes */
-	if ((size * 4) > update_hfr->cmd.size) {
-		CAM_ERR(CAM_SFE,
-			"Failed! Buf size:%d insufficient, expected size:%d",
-			update_hfr->cmd.size, size);
-		return -ENOMEM;
-	}
+	if (num_regval_pairs) {
+		size = cdm_util_ops->cdm_required_size_reg_random(
+			num_regval_pairs);
 
-	sfe_out_data->cdm_util_ops->cdm_write_regrandom(
-		update_hfr->cmd.cmd_buf_addr, j/2, reg_val_pair);
+		/* cdm util returns dwords, need to convert to bytes */
+		if ((size * 4) > update_hfr->cmd.size) {
+			CAM_ERR(CAM_SFE,
+				"Failed! Buf size:%d insufficient, expected size:%d",
+				update_hfr->cmd.size, size);
+			return -ENOMEM;
+		}
+
+		cdm_util_ops->cdm_write_regrandom(
+			update_hfr->cmd.cmd_buf_addr, num_regval_pairs,
+			reg_val_pair);
 
-	/* cdm util returns dwords, need to convert to bytes */
-	update_hfr->cmd.used_bytes = size * 4;
+		/* cdm util returns dwords, need to convert to bytes */
+		update_hfr->cmd.used_bytes = size * 4;
+	} else {
+		CAM_DBG(CAM_SFE,
+			"No reg val pairs. num_wms: %u",
+			sfe_out_data->num_wm);
+		update_hfr->cmd.used_bytes = 0;
+	}
 
 	return 0;
 }

+ 56 - 26
drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.c

@@ -1972,7 +1972,9 @@ static int cam_tfe_bus_update_wm(void *priv, void *cmd_args,
 	struct cam_buf_io_cfg                *io_cfg;
 	struct cam_tfe_bus_tfe_out_data      *tfe_out_data = NULL;
 	struct cam_tfe_bus_wm_resource_data  *wm_data = NULL;
+	struct cam_cdm_utils_ops             *cdm_util_ops;
 	uint32_t *reg_val_pair;
+	uint32_t num_regval_pairs = 0;
 	uint32_t i, j, size = 0;
 	uint32_t frame_inc = 0, val;
 
@@ -1982,7 +1984,9 @@ static int cam_tfe_bus_update_wm(void *priv, void *cmd_args,
 	tfe_out_data = (struct cam_tfe_bus_tfe_out_data *)
 		update_buf->res->res_priv;
 
-	if (!tfe_out_data || !tfe_out_data->cdm_util_ops) {
+	cdm_util_ops = tfe_out_data->cdm_util_ops;
+
+	if (!tfe_out_data || !cdm_util_ops) {
 		CAM_ERR(CAM_ISP, "Failed! Invalid data");
 		return -EINVAL;
 	}
@@ -2051,21 +2055,32 @@ static int cam_tfe_bus_update_wm(void *priv, void *cmd_args,
 			wm_data->en_cfg);
 	}
 
-	size = tfe_out_data->cdm_util_ops->cdm_required_size_reg_random(j/2);
+	num_regval_pairs = j / 2;
 
-	/* cdm util returns dwords, need to convert to bytes */
-	if ((size * 4) > update_buf->cmd.size) {
-		CAM_ERR(CAM_ISP,
-			"Failed! Buf size:%d insufficient, expected size:%d",
-			update_buf->cmd.size, size);
-		return -ENOMEM;
-	}
+	if (num_regval_pairs) {
+		size = cdm_util_ops->cdm_required_size_reg_random(
+			num_regval_pairs);
+
+		/* cdm util returns dwords, need to convert to bytes */
+		if ((size * 4) > update_buf->cmd.size) {
+			CAM_ERR(CAM_ISP,
+				"Failed! Buf size:%d insufficient, expected size:%d",
+				update_buf->cmd.size, size);
+			return -ENOMEM;
+		}
 
-	tfe_out_data->cdm_util_ops->cdm_write_regrandom(
-		update_buf->cmd.cmd_buf_addr, j/2, reg_val_pair);
+		cdm_util_ops->cdm_write_regrandom(
+			update_buf->cmd.cmd_buf_addr,
+			num_regval_pairs, reg_val_pair);
 
-	/* cdm util returns dwords, need to convert to bytes */
-	update_buf->cmd.used_bytes = size * 4;
+		/* cdm util returns dwords, need to convert to bytes */
+		update_buf->cmd.used_bytes = size * 4;
+	} else {
+		update_buf->cmd.used_bytes = 0;
+		CAM_DBG(CAM_ISP,
+			"No reg val pairs. num_wms: %u",
+			tfe_out_data->num_wm);
+	}
 
 	return 0;
 }
@@ -2077,8 +2092,10 @@ static int cam_tfe_bus_update_hfr(void *priv, void *cmd_args,
 	struct cam_isp_hw_get_cmd_update         *update_hfr;
 	struct cam_tfe_bus_tfe_out_data          *tfe_out_data = NULL;
 	struct cam_tfe_bus_wm_resource_data      *wm_data = NULL;
+	struct cam_cdm_utils_ops                 *cdm_util_ops;
 	struct cam_isp_tfe_port_hfr_config       *hfr_cfg = NULL;
 	uint32_t *reg_val_pair;
+	uint32_t num_regval_pairs = 0;
 	uint32_t  i, j, size = 0;
 
 	bus_priv = (struct cam_tfe_bus_priv  *) priv;
@@ -2087,7 +2104,9 @@ static int cam_tfe_bus_update_hfr(void *priv, void *cmd_args,
 	tfe_out_data = (struct cam_tfe_bus_tfe_out_data *)
 		update_hfr->res->res_priv;
 
-	if (!tfe_out_data || !tfe_out_data->cdm_util_ops) {
+	cdm_util_ops = tfe_out_data->cdm_util_ops;
+
+	if (!tfe_out_data || !cdm_util_ops) {
 		CAM_ERR(CAM_ISP, "Failed! Invalid data");
 		return -EINVAL;
 	}
@@ -2133,21 +2152,32 @@ static int cam_tfe_bus_update_hfr(void *priv, void *cmd_args,
 			wm_data->index, wm_data->irq_subsample_pattern);
 	}
 
-	size = tfe_out_data->cdm_util_ops->cdm_required_size_reg_random(j/2);
+	num_regval_pairs = j / 2;
 
-	/* cdm util returns dwords, need to convert to bytes */
-	if ((size * 4) > update_hfr->cmd.size) {
-		CAM_ERR(CAM_ISP,
-			"Failed! Buf size:%d insufficient, expected size:%d",
-			update_hfr->cmd.size, size);
-		return -ENOMEM;
-	}
+	if (num_regval_pairs) {
+		size = cdm_util_ops->cdm_required_size_reg_random(
+			num_regval_pairs);
+
+		/* cdm util returns dwords, need to convert to bytes */
+		if ((size * 4) > update_hfr->cmd.size) {
+			CAM_ERR(CAM_ISP,
+				"Failed! Buf size:%d insufficient, expected size:%d",
+				update_hfr->cmd.size, size);
+			return -ENOMEM;
+		}
 
-	tfe_out_data->cdm_util_ops->cdm_write_regrandom(
-		update_hfr->cmd.cmd_buf_addr, j/2, reg_val_pair);
+		cdm_util_ops->cdm_write_regrandom(
+			update_hfr->cmd.cmd_buf_addr,
+			num_regval_pairs, reg_val_pair);
 
-	/* cdm util returns dwords, need to convert to bytes */
-	update_hfr->cmd.used_bytes = size * 4;
+		/* cdm util returns dwords, need to convert to bytes */
+		update_hfr->cmd.used_bytes = size * 4;
+	} else {
+		update_hfr->cmd.used_bytes = 0;
+		CAM_DBG(CAM_ISP,
+			"No reg val pairs. num_wms: %u",
+			tfe_out_data->num_wm);
+	}
 
 	return 0;
 }

+ 29 - 14
drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_rd_ver1.c

@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
- * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2018-2021, The Linux Foundation. All rights reserved.
  */
 
 #include <linux/ratelimit.h>
@@ -860,9 +860,11 @@ static int cam_vfe_bus_rd_update_rm(void *priv, void *cmd_args,
 	struct cam_vfe_bus_rd_ver1_priv          *bus_priv;
 	struct cam_isp_hw_get_cmd_update         *update_buf;
 	struct cam_buf_io_cfg                    *io_cfg;
-	struct cam_vfe_bus_rd_ver1_vfe_bus_rd_data     *vfe_bus_rd_data = NULL;
+	struct cam_vfe_bus_rd_ver1_vfe_bus_rd_data  *vfe_bus_rd_data = NULL;
 	struct cam_vfe_bus_rd_ver1_rm_resource_data *rm_data = NULL;
+	struct cam_cdm_utils_ops                    *cdm_util_ops;
 	uint32_t *reg_val_pair;
+	uint32_t num_regval_pairs = 0;
 	uint32_t  i, j, size = 0;
 	uint32_t buf_size = 0;
 
@@ -872,6 +874,8 @@ static int cam_vfe_bus_rd_update_rm(void *priv, void *cmd_args,
 	vfe_bus_rd_data = (struct cam_vfe_bus_rd_ver1_vfe_bus_rd_data *)
 		update_buf->res->res_priv;
 
+	cdm_util_ops = vfe_bus_rd_data->cdm_util_ops;
+
 	if (!vfe_bus_rd_data || !vfe_bus_rd_data->cdm_util_ops) {
 		CAM_ERR(CAM_ISP, "Failed! Invalid data");
 		return -EINVAL;
@@ -931,21 +935,32 @@ static int cam_vfe_bus_rd_update_rm(void *priv, void *cmd_args,
 
 	}
 
-	size = vfe_bus_rd_data->cdm_util_ops->cdm_required_size_reg_random(j/2);
+	num_regval_pairs = j / 2;
 
-	/* cdm util returns dwords, need to convert to bytes */
-	if ((size * 4) > update_buf->cmd.size) {
-		CAM_ERR(CAM_ISP,
-			"Failed! Buf size:%d insufficient, expected size:%d",
-			update_buf->cmd.size, size);
-		return -ENOMEM;
-	}
+	if (num_regval_pairs) {
+		size = cdm_util_ops->cdm_required_size_reg_random(
+			num_regval_pairs);
 
-	vfe_bus_rd_data->cdm_util_ops->cdm_write_regrandom(
-		update_buf->cmd.cmd_buf_addr, j/2, reg_val_pair);
+		/* cdm util returns dwords, need to convert to bytes */
+		if ((size * 4) > update_buf->cmd.size) {
+			CAM_ERR(CAM_ISP,
+				"Failed! Buf size:%d insufficient, expected size:%d",
+				update_buf->cmd.size, size);
+			return -ENOMEM;
+		}
+
+		cdm_util_ops->cdm_write_regrandom(
+			update_buf->cmd.cmd_buf_addr,
+			num_regval_pairs, reg_val_pair);
 
-	/* cdm util returns dwords, need to convert to bytes */
-	update_buf->cmd.used_bytes = size * 4;
+		/* cdm util returns dwords, need to convert to bytes */
+		update_buf->cmd.used_bytes = size * 4;
+	} else {
+		update_buf->cmd.used_bytes = 0;
+		CAM_DBG(CAM_ISP,
+			"No reg val pairs. num_rms: %u",
+			vfe_bus_rd_data->num_rm);
+	}
 
 	return 0;
 }

+ 56 - 26
drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c

@@ -2915,7 +2915,9 @@ static int cam_vfe_bus_update_wm(void *priv, void *cmd_args,
 	struct cam_vfe_bus_ver2_vfe_out_data     *vfe_out_data = NULL;
 	struct cam_vfe_bus_ver2_wm_resource_data *wm_data = NULL;
 	struct cam_vfe_bus_ver2_reg_offset_ubwc_client *ubwc_client = NULL;
+	struct cam_cdm_utils_ops                       *cdm_util_ops;
 	uint32_t *reg_val_pair;
+	uint32_t num_regval_pairs = 0;
 	uint32_t  i, j, k, size = 0;
 	uint32_t  frame_inc = 0, val;
 	uint32_t loop_size = 0;
@@ -2926,7 +2928,9 @@ static int cam_vfe_bus_update_wm(void *priv, void *cmd_args,
 	vfe_out_data = (struct cam_vfe_bus_ver2_vfe_out_data *)
 		update_buf->res->res_priv;
 
-	if (!vfe_out_data || !vfe_out_data->cdm_util_ops) {
+	cdm_util_ops = vfe_out_data->cdm_util_ops;
+
+	if (!vfe_out_data || !cdm_util_ops) {
 		CAM_ERR(CAM_ISP, "Failed! Invalid data");
 		return -EINVAL;
 	}
@@ -3054,21 +3058,32 @@ static int cam_vfe_bus_update_wm(void *priv, void *cmd_args,
 			wm_data->init_cfg_done = true;
 	}
 
-	size = vfe_out_data->cdm_util_ops->cdm_required_size_reg_random(j/2);
+	num_regval_pairs = j / 2;
 
-	/* cdm util returns dwords, need to convert to bytes */
-	if ((size * 4) > update_buf->cmd.size) {
-		CAM_ERR(CAM_ISP,
-			"Failed! Buf size:%d insufficient, expected size:%d",
-			update_buf->cmd.size, size);
-		return -ENOMEM;
-	}
+	if (num_regval_pairs) {
+		size = cdm_util_ops->cdm_required_size_reg_random(
+			num_regval_pairs);
+
+		/* cdm util returns dwords, need to convert to bytes */
+		if ((size * 4) > update_buf->cmd.size) {
+			CAM_ERR(CAM_ISP,
+				"Failed! Buf size:%d insufficient, expected size:%d",
+				update_buf->cmd.size, size);
+			return -ENOMEM;
+		}
 
-	vfe_out_data->cdm_util_ops->cdm_write_regrandom(
-		update_buf->cmd.cmd_buf_addr, j/2, reg_val_pair);
+		cdm_util_ops->cdm_write_regrandom(
+			update_buf->cmd.cmd_buf_addr,
+			num_regval_pairs, reg_val_pair);
 
-	/* cdm util returns dwords, need to convert to bytes */
-	update_buf->cmd.used_bytes = size * 4;
+		/* cdm util returns dwords, need to convert to bytes */
+		update_buf->cmd.used_bytes = size * 4;
+	} else {
+		update_buf->cmd.used_bytes = 0;
+		CAM_DBG(CAM_ISP,
+			"No reg val pairs. num_wms: %u",
+			vfe_out_data->num_wm);
+	}
 
 	return 0;
 }
@@ -3081,7 +3096,9 @@ static int cam_vfe_bus_update_hfr(void *priv, void *cmd_args,
 	struct cam_vfe_bus_ver2_vfe_out_data     *vfe_out_data = NULL;
 	struct cam_vfe_bus_ver2_wm_resource_data *wm_data = NULL;
 	struct cam_isp_port_hfr_config           *hfr_cfg = NULL;
+	struct cam_cdm_utils_ops                 *cdm_util_ops;
 	uint32_t *reg_val_pair;
+	uint32_t num_regval_pairs = 0;
 	uint32_t  i, j, size = 0;
 
 	bus_priv = (struct cam_vfe_bus_ver2_priv  *) priv;
@@ -3090,7 +3107,9 @@ static int cam_vfe_bus_update_hfr(void *priv, void *cmd_args,
 	vfe_out_data = (struct cam_vfe_bus_ver2_vfe_out_data *)
 		update_hfr->res->res_priv;
 
-	if (!vfe_out_data || !vfe_out_data->cdm_util_ops) {
+	cdm_util_ops = vfe_out_data->cdm_util_ops;
+
+	if (!vfe_out_data || !cdm_util_ops) {
 		CAM_ERR(CAM_ISP, "Failed! Invalid data");
 		return -EINVAL;
 	}
@@ -3163,21 +3182,32 @@ static int cam_vfe_bus_update_hfr(void *priv, void *cmd_args,
 			wm_data->hfr_cfg_done = true;
 	}
 
-	size = vfe_out_data->cdm_util_ops->cdm_required_size_reg_random(j/2);
+	num_regval_pairs = j / 2;
 
-	/* cdm util returns dwords, need to convert to bytes */
-	if ((size * 4) > update_hfr->cmd.size) {
-		CAM_ERR(CAM_ISP,
-			"Failed! Buf size:%d insufficient, expected size:%d",
-			update_hfr->cmd.size, size);
-		return -ENOMEM;
-	}
+	if (num_regval_pairs) {
+		size = cdm_util_ops->cdm_required_size_reg_random(
+			num_regval_pairs);
+
+		/* cdm util returns dwords, need to convert to bytes */
+		if ((size * 4) > update_hfr->cmd.size) {
+			CAM_ERR(CAM_ISP,
+				"Failed! Buf size:%d insufficient, expected size:%d",
+				update_hfr->cmd.size, size);
+			return -ENOMEM;
+		}
 
-	vfe_out_data->cdm_util_ops->cdm_write_regrandom(
-		update_hfr->cmd.cmd_buf_addr, j/2, reg_val_pair);
+		cdm_util_ops->cdm_write_regrandom(
+			update_hfr->cmd.cmd_buf_addr,
+			num_regval_pairs, reg_val_pair);
 
-	/* cdm util returns dwords, need to convert to bytes */
-	update_hfr->cmd.used_bytes = size * 4;
+		/* cdm util returns dwords, need to convert to bytes */
+		update_hfr->cmd.used_bytes = size * 4;
+	} else {
+		update_hfr->cmd.used_bytes = 0;
+		CAM_DBG(CAM_ISP,
+			"No reg val pairs. num_wms: %u",
+			vfe_out_data->num_wm);
+	}
 
 	return 0;
 }

+ 54 - 26
drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c

@@ -2945,7 +2945,9 @@ static int cam_vfe_bus_ver3_update_wm(void *priv, void *cmd_args,
 	struct cam_vfe_bus_ver3_vfe_out_data     *vfe_out_data = NULL;
 	struct cam_vfe_bus_ver3_wm_resource_data *wm_data = NULL;
 	struct cam_vfe_bus_ver3_reg_offset_ubwc_client *ubwc_client = NULL;
+	struct cam_cdm_utils_ops                       *cdm_util_ops;
 	uint32_t *reg_val_pair;
+	uint32_t num_regval_pairs = 0;
 	uint32_t  i, j, k, size = 0;
 	uint32_t  frame_inc = 0, val;
 	uint32_t loop_size = 0;
@@ -2956,7 +2958,9 @@ static int cam_vfe_bus_ver3_update_wm(void *priv, void *cmd_args,
 	vfe_out_data = (struct cam_vfe_bus_ver3_vfe_out_data *)
 		update_buf->res->res_priv;
 
-	if (!vfe_out_data || !vfe_out_data->cdm_util_ops) {
+	cdm_util_ops = vfe_out_data->cdm_util_ops;
+
+	if (!vfe_out_data || !cdm_util_ops) {
 		CAM_ERR(CAM_ISP, "Failed! Invalid data");
 		return -EINVAL;
 	}
@@ -3128,21 +3132,31 @@ static int cam_vfe_bus_ver3_update_wm(void *priv, void *cmd_args,
 			wm_data->init_cfg_done = true;
 	}
 
-	size = vfe_out_data->cdm_util_ops->cdm_required_size_reg_random(j/2);
+	num_regval_pairs = j / 2;
+	if (num_regval_pairs) {
+		size = cdm_util_ops->cdm_required_size_reg_random(
+			num_regval_pairs);
 
-	/* cdm util returns dwords, need to convert to bytes */
-	if ((size * 4) > update_buf->cmd.size) {
-		CAM_ERR(CAM_ISP,
-			"Failed! Buf size:%d insufficient, expected size:%d",
-			update_buf->cmd.size, size);
-		return -ENOMEM;
-	}
+		/* cdm util returns dwords, need to convert to bytes */
+		if ((size * 4) > update_buf->cmd.size) {
+			CAM_ERR(CAM_ISP,
+				"Failed! Buf size:%d insufficient, expected size:%d",
+				update_buf->cmd.size, size);
+			return -ENOMEM;
+		}
 
-	vfe_out_data->cdm_util_ops->cdm_write_regrandom(
-		update_buf->cmd.cmd_buf_addr, j/2, reg_val_pair);
+		cdm_util_ops->cdm_write_regrandom(
+			update_buf->cmd.cmd_buf_addr,
+			num_regval_pairs, reg_val_pair);
 
-	/* cdm util returns dwords, need to convert to bytes */
-	update_buf->cmd.used_bytes = size * 4;
+		/* cdm util returns dwords, need to convert to bytes */
+		update_buf->cmd.used_bytes = size * 4;
+	} else {
+		CAM_DBG(CAM_ISP,
+			"No reg val pairs. num_wms: %u",
+			vfe_out_data->num_wm);
+		update_buf->cmd.used_bytes = 0;
+	}
 
 	return 0;
 }
@@ -3155,7 +3169,9 @@ static int cam_vfe_bus_ver3_update_hfr(void *priv, void *cmd_args,
 	struct cam_vfe_bus_ver3_vfe_out_data     *vfe_out_data = NULL;
 	struct cam_vfe_bus_ver3_wm_resource_data *wm_data = NULL;
 	struct cam_isp_port_hfr_config           *hfr_cfg = NULL;
+	struct cam_cdm_utils_ops                 *cdm_util_ops;
 	uint32_t *reg_val_pair;
+	uint32_t num_regval_pairs = 0;
 	uint32_t  i, j, size = 0;
 
 	bus_priv = (struct cam_vfe_bus_ver3_priv  *) priv;
@@ -3164,7 +3180,8 @@ static int cam_vfe_bus_ver3_update_hfr(void *priv, void *cmd_args,
 	vfe_out_data = (struct cam_vfe_bus_ver3_vfe_out_data *)
 		update_hfr->res->res_priv;
 
-	if (!vfe_out_data || !vfe_out_data->cdm_util_ops) {
+	cdm_util_ops = vfe_out_data->cdm_util_ops;
+	if (!vfe_out_data || !cdm_util_ops) {
 		CAM_ERR(CAM_ISP, "Failed! Invalid data");
 		return -EINVAL;
 	}
@@ -3239,21 +3256,32 @@ static int cam_vfe_bus_ver3_update_hfr(void *priv, void *cmd_args,
 			wm_data->hfr_cfg_done = true;
 	}
 
-	size = vfe_out_data->cdm_util_ops->cdm_required_size_reg_random(j/2);
+	num_regval_pairs = j / 2;
 
-	/* cdm util returns dwords, need to convert to bytes */
-	if ((size * 4) > update_hfr->cmd.size) {
-		CAM_ERR(CAM_ISP,
-			"Failed! Buf size:%d insufficient, expected size:%d",
-			update_hfr->cmd.size, size);
-		return -ENOMEM;
-	}
+	if (num_regval_pairs) {
+		size = cdm_util_ops->cdm_required_size_reg_random(
+			num_regval_pairs);
 
-	vfe_out_data->cdm_util_ops->cdm_write_regrandom(
-		update_hfr->cmd.cmd_buf_addr, j/2, reg_val_pair);
+		/* cdm util returns dwords, need to convert to bytes */
+		if ((size * 4) > update_hfr->cmd.size) {
+			CAM_ERR(CAM_ISP,
+				"Failed! Buf size:%d insufficient, expected size:%d",
+				update_hfr->cmd.size, size);
+			return -ENOMEM;
+		}
+
+		cdm_util_ops->cdm_write_regrandom(
+			update_hfr->cmd.cmd_buf_addr,
+			num_regval_pairs, reg_val_pair);
 
-	/* cdm util returns dwords, need to convert to bytes */
-	update_hfr->cmd.used_bytes = size * 4;
+		/* cdm util returns dwords, need to convert to bytes */
+		update_hfr->cmd.used_bytes = size * 4;
+	} else {
+		update_hfr->cmd.used_bytes = 0;
+		CAM_DBG(CAM_ISP,
+			"No reg val pairs. num_wms: %u",
+			vfe_out_data->num_wm);
+	}
 
 	return 0;
 }

+ 20 - 13
drivers/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_core.c

@@ -296,6 +296,7 @@ static int cam_lrme_hw_util_process_config_hw(struct cam_hw_info *lrme_hw,
 	struct cam_lrme_hw_info *hw_info =
 		((struct cam_lrme_core *)lrme_hw->core_info)->hw_info;
 	uint32_t num_cmd = 0;
+	uint32_t num_regval_pairs = 0;
 	uint32_t size;
 	uint32_t mem_base, available_size = config_args->size;
 	uint32_t output_res_mask = 0, input_res_mask = 0;
@@ -409,22 +410,28 @@ static int cam_lrme_hw_util_process_config_hw(struct cam_hw_info *lrme_hw,
 	cmd_buf_addr += size;
 	available_size -= (size * 4);
 
-	size = hw_cdm_info->cdm_ops->cdm_required_size_reg_random(
-		num_cmd / 2);
+	num_regval_pairs = num_cmd / 2;
 
-	if ((size * 4) > available_size) {
-		CAM_ERR(CAM_LRME, "buf size:%d is not sufficient, expected: %d",
-			available_size, size);
-		return -ENOMEM;
-	}
+	if (num_regval_pairs) {
+		size = hw_cdm_info->cdm_ops->cdm_required_size_reg_random(
+			num_regval_pairs);
 
-	hw_cdm_info->cdm_ops->cdm_write_regrandom(cmd_buf_addr, num_cmd / 2,
-		reg_val_pair);
-	cmd_buf_addr += size;
-	available_size -= (size * 4);
+		if ((size * 4) > available_size) {
+			CAM_ERR(CAM_LRME, "buf size:%d is not sufficient, expected: %d",
+				available_size, size);
+			return -ENOMEM;
+		}
+
+		hw_cdm_info->cdm_ops->cdm_write_regrandom(cmd_buf_addr,
+			num_regval_pairs, reg_val_pair);
+		cmd_buf_addr += size;
+		available_size -= (size * 4);
+
+	} else {
+		CAM_DBG(CAM_LRME, "No reg val pairs");
+	}
 
-	config_args->config_buf_size =
-		config_args->size - available_size;
+	config_args->config_buf_size = config_args->size - available_size;
 
 	return 0;
 }

+ 18 - 10
drivers/cam_ope/ope_hw_mgr/ope_hw/bus_rd/ope_bus_rd.c

@@ -154,6 +154,7 @@ static uint32_t *cam_ope_bus_rd_update(struct ope_hw *ope_hw_info,
 	uint32_t temp_reg[128] = {0};
 	uint32_t rm_id, header_size;
 	uint32_t rsc_type;
+	uint32_t *next_buff_addr = NULL;
 	struct cam_hw_prepare_update_args *prepare_args;
 	struct cam_ope_ctx *ctx_data;
 	struct cam_ope_request *ope_request;
@@ -306,10 +307,12 @@ static uint32_t *cam_ope_bus_rd_update(struct ope_hw *ope_hw_info,
 			io_port_cdm->s_cdm_info[l][idx].addr = kmd_buf;
 			io_port_cdm->num_s_cmd_bufs[l]++;
 
-			kmd_buf = cdm_ops->cdm_write_regrandom(
+			next_buff_addr = cdm_ops->cdm_write_regrandom(
 				kmd_buf, count/2, temp_reg);
-			prepare->kmd_buf_offset += ((count + header_size) *
-				sizeof(temp));
+			if (next_buff_addr > kmd_buf)
+				prepare->kmd_buf_offset +=
+					((count + header_size) * sizeof(temp));
+			kmd_buf = next_buff_addr;
 			CAM_DBG(CAM_OPE, "b:%d io:%d p:%d s:%d",
 				batch_idx, io_idx, k, l);
 			for (m = 0; m < count; m += 2)
@@ -340,6 +343,7 @@ static uint32_t *cam_ope_bus_rm_disable(struct ope_hw *ope_hw_info,
 	uint32_t count = 0;
 	uint32_t temp = 0;
 	uint32_t header_size;
+	uint32_t *next_buff_addr = NULL;
 	struct cam_ope_ctx *ctx_data;
 	struct ope_bus_rd_ctx *bus_rd_ctx;
 	struct cam_ope_bus_rd_reg *rd_reg;
@@ -398,11 +402,12 @@ static uint32_t *cam_ope_bus_rm_disable(struct ope_hw *ope_hw_info,
 		io_port_cdm->s_cdm_info[l][idx].addr = kmd_buf;
 		io_port_cdm->num_s_cmd_bufs[l]++;
 
-		kmd_buf = cdm_ops->cdm_write_regrandom(
+		next_buff_addr = cdm_ops->cdm_write_regrandom(
 			kmd_buf, count/2, temp_reg);
-		prepare->kmd_buf_offset += ((count + header_size) *
-			sizeof(temp));
-
+		if (next_buff_addr > kmd_buf)
+			prepare->kmd_buf_offset += ((count + header_size) *
+				sizeof(temp));
+		kmd_buf = next_buff_addr;
 		CAM_DBG(CAM_OPE, "RD cmd bufs = %d",
 			io_port_cdm->num_s_cmd_bufs[l]);
 		CAM_DBG(CAM_OPE, "stripe %d off:%d len:%d",
@@ -426,6 +431,7 @@ static int cam_ope_bus_rd_prepare(struct ope_hw *ope_hw_info,
 	uint32_t temp_reg[32] = {0};
 	uint32_t header_size;
 	uint32_t *kmd_buf;
+	uint32_t *next_buff_addr = NULL;
 	int is_rm_enabled;
 	struct cam_ope_dev_prepare_req *prepare;
 	struct cam_ope_ctx *ctx_data;
@@ -537,10 +543,12 @@ static int cam_ope_bus_rd_prepare(struct ope_hw *ope_hw_info,
 		io_port_cdm->go_cmd_offset =
 			prepare->kmd_buf_offset;
 	}
-	kmd_buf = cdm_ops->cdm_write_regrandom(
+	next_buff_addr = cdm_ops->cdm_write_regrandom(
 		kmd_buf, count/2, temp_reg);
-	prepare->kmd_buf_offset +=
-		((count + header_size) * sizeof(temp));
+	if (next_buff_addr > kmd_buf)
+		prepare->kmd_buf_offset +=
+			((count + header_size) * sizeof(temp));
+	kmd_buf = next_buff_addr;
 	CAM_DBG(CAM_OPE, "kmd_buf:%x,offset:%d",
 		kmd_buf, prepare->kmd_buf_offset);
 	CAM_DBG(CAM_OPE, "t_reg:%xcount: %d size:%d",

+ 14 - 7
drivers/cam_ope/ope_hw_mgr/ope_hw/bus_wr/ope_bus_wr.c

@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
- * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2019-2021, The Linux Foundation. All rights reserved.
  */
 
 #include <linux/of.h>
@@ -179,6 +179,7 @@ static uint32_t *cam_ope_bus_wr_update(struct ope_hw *ope_hw_info,
 	uint32_t temp = 0;
 	uint32_t wm_port_id;
 	uint32_t header_size;
+	uint32_t *next_buff_addr = NULL;
 	struct cam_hw_prepare_update_args *prepare_args;
 	struct cam_ope_ctx *ctx_data;
 	struct cam_ope_request *ope_request;
@@ -328,10 +329,12 @@ static uint32_t *cam_ope_bus_wr_update(struct ope_hw *ope_hw_info,
 			io_port_cdm->s_cdm_info[l][idx].addr = kmd_buf;
 			io_port_cdm->num_s_cmd_bufs[l]++;
 
-			kmd_buf = cdm_ops->cdm_write_regrandom(
+			next_buff_addr = cdm_ops->cdm_write_regrandom(
 				kmd_buf, count/2, temp_reg);
-			prepare->kmd_buf_offset += ((count + header_size) *
-				sizeof(temp));
+			if (next_buff_addr > kmd_buf)
+				prepare->kmd_buf_offset +=
+					((count + header_size) * sizeof(temp));
+			kmd_buf = next_buff_addr;
 
 			CAM_DBG(CAM_OPE, "b:%d io:%d p:%d s:%d",
 				batch_idx, io_idx, k, l);
@@ -366,6 +369,7 @@ static uint32_t *cam_ope_bus_wm_disable(struct ope_hw *ope_hw_info,
 	uint32_t temp = 0;
 	uint32_t wm_port_id;
 	uint32_t header_size;
+	uint32_t *next_buff_addr = NULL;
 	struct cam_ope_ctx *ctx_data;
 	struct ope_bus_wr_ctx *bus_wr_ctx;
 	struct cam_ope_bus_wr_reg *wr_reg;
@@ -426,10 +430,13 @@ static uint32_t *cam_ope_bus_wm_disable(struct ope_hw *ope_hw_info,
 			io_port_cdm->s_cdm_info[l][idx].addr = kmd_buf;
 			io_port_cdm->num_s_cmd_bufs[l]++;
 
-			kmd_buf = cdm_ops->cdm_write_regrandom(
+			next_buff_addr = cdm_ops->cdm_write_regrandom(
 				kmd_buf, count/2, temp_reg);
-			prepare->kmd_buf_offset += ((count + header_size) *
-				sizeof(temp));
+
+			if (next_buff_addr > kmd_buf)
+				prepare->kmd_buf_offset +=
+					((count + header_size) * sizeof(temp));
+			kmd_buf = next_buff_addr;
 
 			CAM_DBG(CAM_OPE, "WR cmd bufs = %d",
 				io_port_cdm->num_s_cmd_bufs[l]);