소스 검색

msm: camera: mem_mgr: Add refcount to track in use buffers

The function cam_mem_mgr_release can unmap the buffers when in use.

This change prevents unmapping the buffers when in use.

CRs-Fixed: 3489559
Change-Id: I2e72e795d39ac15abfa56c19043c419a03686966
Signed-off-by: Shivakumar Malke <[email protected]>
Shivakumar Malke 2 년 전
부모
커밋
6d99262523

+ 22 - 5
drivers/cam_cdm/cam_cdm_virtual_core.c

@@ -103,6 +103,11 @@ int cam_virtual_cdm_submit_bl(struct cam_hw_info *cdm_hw,
 			rc = cam_mem_get_cpu_buf(
 				cdm_cmd->cmd[i].bl_addr.mem_handle, &vaddr_ptr,
 				&len);
+			if (rc) {
+				CAM_ERR(CAM_CDM,
+					"Falied to get CPU addr_i[%d] req_type %d", i,
+					req->data->type);
+			}
 		} else if (req->data->type ==
 			CAM_CDM_BL_CMD_TYPE_KERNEL_IOVA) {
 			rc = 0;
@@ -113,7 +118,6 @@ int cam_virtual_cdm_submit_bl(struct cam_hw_info *cdm_hw,
 				"Only mem hdl/Kernel va type is supported %d",
 				req->data->type);
 			rc = -EINVAL;
-			break;
 		}
 
 		if ((!rc) && (vaddr_ptr) && (len) &&
@@ -124,7 +128,7 @@ int cam_virtual_cdm_submit_bl(struct cam_hw_info *cdm_hw,
 				cdm_cmd->cmd[i].len) {
 				CAM_ERR(CAM_CDM, "Not enough buffer");
 				rc = -EINVAL;
-				break;
+				goto put_cpu_buf;
 			}
 			CAM_DBG(CAM_CDM,
 				"hdl=%x vaddr=%pK offset=%d cmdlen=%d:%zu",
@@ -142,7 +146,7 @@ int cam_virtual_cdm_submit_bl(struct cam_hw_info *cdm_hw,
 					"write failed for cnt=%d:%d len %u",
 					i, req->data->cmd_arrary_count,
 					cdm_cmd->cmd[i].len);
-				break;
+				goto put_cpu_buf;
 			}
 		} else {
 			CAM_ERR(CAM_CDM,
@@ -153,7 +157,7 @@ int cam_virtual_cdm_submit_bl(struct cam_hw_info *cdm_hw,
 				"Sanity check failed for cmd_count=%d cnt=%d",
 				i, req->data->cmd_arrary_count);
 			rc = -EINVAL;
-			break;
+			goto err;
 		}
 		if (!rc) {
 			struct cam_cdm_work_payload *payload;
@@ -169,7 +173,7 @@ int cam_virtual_cdm_submit_bl(struct cam_hw_info *cdm_hw,
 					GFP_KERNEL);
 				if (!node) {
 					rc = -ENOMEM;
-					break;
+					goto err;
 				}
 				node->request_type = CAM_HW_CDM_BL_CB_CLIENT;
 				node->client_hdl = req->handle;
@@ -202,10 +206,23 @@ int cam_virtual_cdm_submit_bl(struct cam_hw_info *cdm_hw,
 				"Now commit the BL nothing for virtual");
 			if (!rc && (core->bl_tag == 63))
 				core->bl_tag = 0;
+
+			if (req->data->type == CAM_CDM_BL_CMD_TYPE_MEM_HANDLE)
+				cam_mem_put_cpu_buf(cdm_cmd->cmd[i].bl_addr.mem_handle);
 		}
+
 	}
 	mutex_unlock(&client->lock);
 	return rc;
+
+put_cpu_buf:
+	if (req->data->type == CAM_CDM_BL_CMD_TYPE_MEM_HANDLE)
+		cam_mem_put_cpu_buf(cdm_cmd->cmd[i].bl_addr.mem_handle);
+
+err:
+	mutex_unlock(&client->lock);
+	return rc;
+
 }
 
 int cam_virtual_cdm_probe(struct platform_device *pdev)

+ 14 - 2
drivers/cam_core/cam_context_utils.c

@@ -264,6 +264,9 @@ int cam_context_buf_done_from_hw(struct cam_context *ctx,
 		req->out_map_entries[j].sync_id = -1;
 	}
 
+	if (cam_presil_mode_enabled())
+		cam_packet_util_put_packet_addr(req->pf_data.packet_handle);
+
 	if (cam_debug_ctx_req_list & ctx->dev_id)
 		CAM_INFO(CAM_CTXT,
 			"[%s][%d] : Moving req[%llu] from active_list to free_list",
@@ -484,6 +487,7 @@ int32_t cam_context_config_dev_to_hw(
 		rc = -EFAULT;
 	}
 
+	cam_mem_put_cpu_buf((int32_t) cmd->packet_handle);
 	return rc;
 }
 
@@ -1502,6 +1506,7 @@ static int cam_context_user_dump(struct cam_context *ctx,
 	if (dump_args->offset >= buf_len) {
 		CAM_WARN(CAM_CTXT, "dump buffer overshoot offset %zu len %zu",
 			dump_args->offset, buf_len);
+		cam_mem_put_cpu_buf(dump_args->buf_handle);
 		return -ENOSPC;
 	}
 
@@ -1531,6 +1536,7 @@ static int cam_context_user_dump(struct cam_context *ctx,
 		if (remain_len < min_len) {
 			CAM_WARN(CAM_CTXT, "dump buffer exhaust remain %zu min %u",
 				remain_len, min_len);
+			cam_mem_put_cpu_buf(dump_args->buf_handle);
 			return -ENOSPC;
 		}
 	}
@@ -1678,6 +1684,7 @@ static int cam_context_user_dump(struct cam_context *ctx,
 		}
 	}
 
+	cam_mem_put_cpu_buf(dump_args->buf_handle);
 	return 0;
 }
 
@@ -1758,7 +1765,7 @@ size_t cam_context_parse_config_cmd(struct cam_context *ctx, struct cam_config_d
 		CAM_ERR(CAM_CTXT, "invalid buff length: %zu or offset: %zu", len,
 			(size_t)cmd->offset);
 		rc = -EINVAL;
-		goto err;
+		goto put_cpu_buf;
 	}
 
 	*packet = (struct cam_packet *) ((uint8_t *)packet_addr + (uint32_t)cmd->offset);
@@ -1768,12 +1775,15 @@ size_t cam_context_parse_config_cmd(struct cam_context *ctx, struct cam_config_d
 		cmd->packet_handle, packet_addr, cmd->offset, len, (*packet)->header.request_id,
 		(*packet)->header.size, (*packet)->header.op_code);
 
+	cam_mem_put_cpu_buf((int32_t) cmd->packet_handle);
 	return (len - (size_t)cmd->offset);
 
+put_cpu_buf:
+	if (cmd)
+		cam_mem_put_cpu_buf((int32_t) cmd->packet_handle);
 err:
 	if (packet)
 		*packet = ERR_PTR(rc);
-
 	return 0;
 }
 
@@ -1831,6 +1841,7 @@ static void __cam_context_req_mini_dump(struct cam_ctx_request *req,
 		req->pf_data.packet_offset);
 	if (rc)
 		return;
+
 	if (packet && packet->num_io_configs) {
 		bytes_required = packet->num_io_configs * sizeof(struct cam_buf_io_cfg);
 		if (start_addr + bytes_written + bytes_required > end_addr)
@@ -1844,6 +1855,7 @@ static void __cam_context_req_mini_dump(struct cam_ctx_request *req,
 		req_md->num_io_cfg = packet->num_io_configs;
 	}
 
+	cam_packet_util_put_packet_addr(req->pf_data.packet_handle);
 end:
 	*bytes_updated = bytes_written;
 }

+ 1 - 0
drivers/cam_cre/cam_cre_context.c

@@ -83,6 +83,7 @@ static int __cam_cre_ctx_config_dev_in_ready(struct cam_context *ctx,
 	if (rc)
 		CAM_ERR(CAM_CRE, "Failed to prepare device");
 
+	cam_mem_put_cpu_buf((int32_t) cmd->packet_handle);
 	return rc;
 }
 

+ 2 - 0
drivers/cam_cre/cam_cre_hw_mgr/cam_cre_hw_mgr.c

@@ -2434,6 +2434,8 @@ static void cam_cre_mgr_dump_pf_data(struct cam_cre_hw_mgr  *hw_mgr,
 
 	cam_packet_util_dump_patch_info(packet, hw_mgr->iommu_hdl,
 		hw_mgr->iommu_sec_hdl, pf_args);
+
+	cam_mem_put_cpu_buf(pf_cmd_args->pf_req_info->packet_handle);
 }
 
 static int cam_cre_mgr_cmd(void *hw_mgr_priv, void *cmd_args)

+ 7 - 0
drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw_mgr.c

@@ -1248,6 +1248,12 @@ static int cam_custom_mgr_prepare_hw_update(void *hw_mgr_priv,
 		prepare->packet->cmd_buf_offset);
 	rc = cam_packet_util_get_cmd_mem_addr(
 			cmd_desc->mem_handle, &ptr, &len);
+	if (rc == -EINVAL) {
+		CAM_ERR(CAM_CUSTOM, "Failed to get CPU addr handle 0x%x",
+			cmd_desc->mem_handle);
+		return -EINVAL;
+	}
+
 	if (!rc) {
 		ptr += (cmd_desc->offset / 4);
 		custom_buf_type1 =
@@ -1262,6 +1268,7 @@ static int cam_custom_mgr_prepare_hw_update(void *hw_mgr_priv,
 	ctx->scratch_buffer_addr = 0x0;
 	prepare_hw_data->num_cfg = 0;
 	cam_custom_add_io_buffers(hw_mgr->img_iommu_hdl, prepare);
+	cam_mem_put_cpu_buf(cmd_desc->mem_handle);
 	return 0;
 }
 

+ 45 - 3
drivers/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.c

@@ -542,6 +542,33 @@ static int cam_fd_mgr_util_get_buf_map_requirement(uint32_t direction,
 	return 0;
 }
 
+static int cam_fd_mgr_put_cpu_buf(struct cam_hw_prepare_update_args *prepare)
+{
+	int i, rc;
+	uint32_t plane;
+	bool need_io_map, need_cpu_map;
+	struct cam_buf_io_cfg *io_cfg;
+
+	io_cfg = (struct cam_buf_io_cfg *) ((uint8_t *)
+		&prepare->packet->payload + prepare->packet->io_configs_offset);
+
+	if (!io_cfg)
+		return -EINVAL;
+
+	for (i = 0; i < prepare->packet->num_io_configs; i++) {
+		rc = cam_fd_mgr_util_get_buf_map_requirement(
+			io_cfg[i].direction, io_cfg[i].resource_type,
+			&need_io_map, &need_cpu_map);
+
+		if (rc || !need_cpu_map)
+			continue;
+
+		for (plane = 0; plane < CAM_PACKET_MAX_PLANES; plane++)
+			cam_mem_put_cpu_buf(io_cfg[i].mem_handle[plane]);
+	}
+	return 0;
+}
+
 static int cam_fd_mgr_util_prepare_io_buf_info(int32_t iommu_hdl,
 	struct cam_hw_prepare_update_args *prepare,
 	struct cam_fd_hw_io_buffer *input_buf,
@@ -627,6 +654,7 @@ static int cam_fd_mgr_util_prepare_io_buf_info(int32_t iommu_hdl,
 					&cpu_addr[plane], &size);
 				if (rc || ((io_addr[plane] & 0xFFFFFFFF)
 					!= io_addr[plane])) {
+					rc = -ENOSPC;
 					CAM_ERR(CAM_FD,
 						"Invalid cpu buf %d %d %d %d",
 						io_cfg[i].direction,
@@ -639,6 +667,7 @@ static int cam_fd_mgr_util_prepare_io_buf_info(int32_t iommu_hdl,
 						"Invalid cpu buf %d %d %d",
 						io_cfg[i].direction,
 						io_cfg[i].resource_type, plane);
+					cam_mem_put_cpu_buf(io_cfg[i].mem_handle[plane];
 					rc = -EINVAL;
 					return rc;
 				}
@@ -1628,6 +1657,7 @@ hw_dump:
 	if (fd_dump_args.buf_len <= dump_args->offset) {
 		CAM_WARN(CAM_FD, "dump offset overshoot len %zu offset %zu",
 			fd_dump_args.buf_len, dump_args->offset);
+		cam_mem_put_cpu_buf(dump_args->buf_handle);
 		return -ENOSPC;
 	}
 	remain_len = fd_dump_args.buf_len - dump_args->offset;
@@ -1637,6 +1667,7 @@ hw_dump:
 	if (remain_len < min_len) {
 		CAM_WARN(CAM_FD, "dump buffer exhaust remain %zu min %u",
 			remain_len, min_len);
+		cam_mem_put_cpu_buf(dump_args->buf_handle);
 		return -ENOSPC;
 	}
 
@@ -1668,12 +1699,14 @@ hw_dump:
 		if (rc) {
 			CAM_ERR(CAM_FD, "Hw Dump cmd fails req %lld rc %d",
 				frame_req->request_id, rc);
+			cam_mem_put_cpu_buf(dump_args->buf_handle);
 			return rc;
 		}
 	}
 	CAM_DBG(CAM_FD, "Offset before %zu after %zu",
 		dump_args->offset, fd_dump_args.offset);
 	dump_args->offset = fd_dump_args.offset;
+	cam_mem_put_cpu_buf(dump_args->buf_handle);
 	return rc;
 }
 
@@ -1798,16 +1831,20 @@ static int cam_fd_mgr_hw_prepare_update(void *hw_mgr_priv,
 		hw_mgr->device_iommu.non_secure, prepare,
 		prestart_args.input_buf, prestart_args.output_buf,
 		CAM_FD_MAX_IO_BUFFERS);
+
 	if (rc) {
 		CAM_ERR(CAM_FD, "Error in prepare IO Buf %d", rc);
-		goto error;
+
+		if (rc == -ENOSPC)
+			goto error;
+		goto put_cpu_buf;
 	}
 
 	rc = cam_fd_mgr_util_prepare_hw_update_entries(hw_mgr, prepare,
 		&prestart_args, &kmd_buf);
 	if (rc) {
 		CAM_ERR(CAM_FD, "Error in hw update entries %d", rc);
-		goto error;
+		goto put_cpu_buf;
 	}
 
 	/* get a free frame req from free list */
@@ -1816,7 +1853,8 @@ static int cam_fd_mgr_hw_prepare_update(void *hw_mgr_priv,
 	if (rc || !frame_req) {
 		CAM_ERR(CAM_FD, "Get frame_req failed, rc=%d, hw_ctx=%pK",
 			rc, hw_ctx);
-		return -ENOMEM;
+		rc = -ENOMEM;
+		goto put_cpu_buf;
 	}
 
 	/* Setup frame request info and queue to pending list */
@@ -1831,9 +1869,13 @@ static int cam_fd_mgr_hw_prepare_update(void *hw_mgr_priv,
 	 */
 	prepare->priv = frame_req;
 
+	cam_fd_mgr_put_cpu_buf(prepare);
 	CAM_DBG(CAM_FD, "FramePrepare : Frame[%lld]", frame_req->request_id);
 
 	return 0;
+
+put_cpu_buf:
+	cam_fd_mgr_put_cpu_buf(prepare);
 error:
 	return rc;
 }

+ 4 - 2
drivers/cam_icp/cam_icp_context.c

@@ -188,7 +188,7 @@ static int __cam_icp_config_dev_in_ready(struct cam_context *ctx,
 			"[%s] ctx[%u]: Invalid offset, len: %zu cmd offset: %llu sizeof packet: %zu",
 			ctx->dev_name, ctx->ctx_id,
 			len, cmd->offset, sizeof(struct cam_packet));
-		return -EINVAL;
+		goto put_cpu_buf;
 	}
 
 	remain_len -= (size_t)cmd->offset;
@@ -200,7 +200,7 @@ static int __cam_icp_config_dev_in_ready(struct cam_context *ctx,
 		CAM_ERR(CAM_CTXT, "[%s] ctx[%u]: Invalid packet params, remain length: %zu",
 			ctx->dev_name, ctx->ctx_id,
 			remain_len);
-		return rc;
+		goto put_cpu_buf;
 	}
 
 	if (((packet->header.op_code & 0xff) ==
@@ -217,6 +217,8 @@ static int __cam_icp_config_dev_in_ready(struct cam_context *ctx,
 		CAM_ERR(CAM_ICP, "[%s] ctx[%u]:Failed to prepare device",
 			ctx->dev_name, ctx->ctx_id);
 
+put_cpu_buf:
+	cam_mem_put_cpu_buf((int32_t) cmd->packet_handle);
 	return rc;
 }
 

+ 15 - 4
drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c

@@ -95,7 +95,7 @@ static int cam_icp_dump_io_cfg(struct cam_icp_hw_ctx_data *ctx_data,
 			used = 0;
 		}
 	}
-
+	cam_mem_put_cpu_buf(buf_handle);
 	return rc;
 }
 
@@ -5507,9 +5507,12 @@ static int cam_icp_mgr_process_cmd_desc(struct cam_icp_hw_mgr *hw_mgr,
 				cmd_desc[i].length)) {
 				CAM_ERR(CAM_ICP, "%s: Invalid offset or length",
 					ctx_data->ctx_id_string);
+				cam_mem_put_cpu_buf(cmd_desc[i].mem_handle);
 				return -EINVAL;
 			}
 			cpu_addr = cpu_addr + cmd_desc[i].offset;
+
+			cam_mem_put_cpu_buf(cmd_desc[i].mem_handle);
 		}
 	}
 
@@ -6508,7 +6511,8 @@ static int cam_icp_mgr_hw_dump(void *hw_priv, void *hw_dump_args)
 	if (icp_dump_args.buf_len <= dump_args->offset) {
 		CAM_WARN(CAM_ICP, "[%s] dump buffer overshoot len %zu offset %zu",
 			hw_mgr->hw_mgr_name, icp_dump_args.buf_len, dump_args->offset);
-		return -ENOSPC;
+		rc = -ENOSPC;
+		goto put_cpu_buf;
 	}
 
 	remain_len = icp_dump_args.buf_len - dump_args->offset;
@@ -6518,7 +6522,8 @@ static int cam_icp_mgr_hw_dump(void *hw_priv, void *hw_dump_args)
 	if (remain_len < min_len) {
 		CAM_WARN(CAM_ICP, "[%s] dump buffer exhaust remain %zu min %u",
 			hw_mgr->hw_mgr_name, remain_len, min_len);
-		return -ENOSPC;
+		rc = -ENOSPC;
+		goto put_cpu_buf;
 	}
 
 	/* Dumping clock and bandwidth info */
@@ -6581,7 +6586,8 @@ static int cam_icp_mgr_hw_dump(void *hw_priv, void *hw_dump_args)
 	if (!icp_dev_intf) {
 		CAM_ERR(CAM_ICP, "[%s] ICP device interface is NULL",
 			hw_mgr->hw_mgr_name);
-		return -EINVAL;
+		rc = -EINVAL;
+		goto put_cpu_buf;
 	}
 	rc = icp_dev_intf->hw_ops.process_cmd(
 		icp_dev_intf->hw_priv,
@@ -6590,6 +6596,9 @@ static int cam_icp_mgr_hw_dump(void *hw_priv, void *hw_dump_args)
 	CAM_DBG(CAM_ICP, "[%s] Offset before %zu after %zu",
 		hw_mgr->hw_mgr_name, dump_args->offset, icp_dump_args.offset);
 	dump_args->offset = icp_dump_args.offset;
+
+put_cpu_buf:
+	cam_mem_put_cpu_buf(dump_args->buf_handle);
 	return rc;
 }
 
@@ -7963,6 +7972,8 @@ static void cam_icp_mgr_dump_pf_data(struct cam_icp_hw_mgr *hw_mgr,
 
 	cam_packet_util_dump_patch_info(packet, hw_mgr->iommu_hdl,
 		hw_mgr->iommu_sec_hdl, pf_args);
+
+	cam_packet_util_put_packet_addr(pf_cmd_args->pf_req_info->packet_handle);
 }
 
 static int cam_icp_mgr_cmd(void *hw_mgr_priv, void *cmd_args)

+ 7 - 0
drivers/cam_isp/cam_isp_context.c

@@ -966,6 +966,7 @@ static int cam_isp_ctx_dump_req(
 				CAM_ERR(CAM_ISP,
 					"Invalid offset exp %u actual %u",
 					req_isp->cfg[i].offset, (uint32_t)len);
+				cam_mem_put_cpu_buf(req_isp->cfg[i].handle);
 				return -EINVAL;
 			}
 			remain_len = len - req_isp->cfg[i].offset;
@@ -976,6 +977,7 @@ static int cam_isp_ctx_dump_req(
 					"Invalid len exp %u remain_len %u",
 					req_isp->cfg[i].len,
 					(uint32_t)remain_len);
+				cam_mem_put_cpu_buf(req_isp->cfg[i].handle);
 				return -EINVAL;
 			}
 
@@ -1001,6 +1003,7 @@ static int cam_isp_ctx_dump_req(
 					return rc;
 			} else
 				cam_cdm_util_dump_cmd_buf(buf_start, buf_end);
+			cam_mem_put_cpu_buf(req_isp->cfg[i].handle);
 		}
 	}
 	return rc;
@@ -5294,6 +5297,7 @@ hw_dump:
 		CAM_WARN(CAM_ISP,
 		    "Dump buffer overshoot len %zu offset %zu, ctx_idx: %u, link: 0x%x",
 		    buf_len, dump_info->offset, ctx->ctx_id, ctx->link_hdl);
+		cam_mem_put_cpu_buf(dump_info->buf_handle);
 		return -ENOSPC;
 	}
 
@@ -5306,6 +5310,7 @@ hw_dump:
 		CAM_WARN(CAM_ISP,
 		    "Dump buffer exhaust remain %zu min %u, ctx_idx: %u, link: 0x%x",
 		    remain_len, min_len, ctx->ctx_id, ctx->link_hdl);
+		cam_mem_put_cpu_buf(dump_info->buf_handle);
 		return -ENOSPC;
 	}
 
@@ -5411,10 +5416,12 @@ hw_dump:
 			&ife_dump_args);
 		dump_info->offset = ife_dump_args.offset;
 	}
+	cam_mem_put_cpu_buf(dump_info->buf_handle);
 	return rc;
 
 end:
 	spin_unlock_bh(&ctx->lock);
+	cam_mem_put_cpu_buf(dump_info->buf_handle);
 	return rc;
 }
 

+ 24 - 10
drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c

@@ -12967,6 +12967,7 @@ static void cam_ife_mgr_dump_pf_data(
 outportlog:
 	cam_packet_util_dump_io_bufs(packet, hw_mgr->mgr_common.img_iommu_hdl,
 		hw_mgr->mgr_common.img_iommu_hdl_secure, pf_args, true);
+	cam_packet_util_put_packet_addr(pf_req_info->packet_handle);
 }
 
 int cam_isp_config_csid_rup_aup(
@@ -13553,7 +13554,8 @@ static int cam_ife_mgr_dump(void *hw_mgr_priv, void *args)
 		CAM_ERR(CAM_ISP,
 			"Dump offset overshoot offset %zu buf_len %zu ctx_idx: %u",
 			isp_hw_dump_args.offset, isp_hw_dump_args.buf_len, ife_ctx->ctx_index);
-		return -EINVAL;
+		rc = -EINVAL;
+		goto put_cpu_buf;
 	}
 
 	for (i = 0; i < ife_ctx->num_base; i++) {
@@ -13565,39 +13567,48 @@ static int cam_ife_mgr_dump(void *hw_mgr_priv, void *args)
 			if (!hw_intf) {
 				CAM_ERR(CAM_ISP, "hw_intf null, returning rc...ctx_idx: %u",
 					ife_ctx->ctx_index);
-				return -EINVAL;
+				rc = -EINVAL;
+				goto put_cpu_buf;
 			}
 			rc = hw_intf->hw_ops.process_cmd(hw_intf->hw_priv,
 				CAM_ISP_HW_USER_DUMP, &isp_hw_dump_args,
 				sizeof(struct cam_isp_hw_dump_args));
-			if (rc)
-				return rc;
+			if (rc) {
+				rc = -EINVAL;
+				goto put_cpu_buf;
+			}
 			break;
 		case CAM_ISP_HW_TYPE_VFE:
 			hw_intf = ife_ctx->hw_mgr->ife_devices[hw_idx]->hw_intf;
 			if (!hw_intf || !hw_intf->hw_priv) {
 				CAM_ERR(CAM_ISP, "hw_intf null, returning rc...ctx_idx: %u",
 					ife_ctx->ctx_index);
-				return -EINVAL;
+				rc = -EINVAL;
+				goto put_cpu_buf;
 			}
 			rc = hw_intf->hw_ops.process_cmd(hw_intf->hw_priv,
 				CAM_ISP_HW_USER_DUMP, &isp_hw_dump_args,
 				sizeof(struct cam_isp_hw_dump_args));
-			if (rc)
-				return rc;
+			if (rc) {
+				rc = -EINVAL;
+				goto put_cpu_buf;
+			}
 			break;
 		case CAM_ISP_HW_TYPE_SFE:
 			hw_intf = ife_ctx->hw_mgr->sfe_devices[hw_idx]->hw_intf;
 			if (!hw_intf || !hw_intf->hw_priv) {
 				CAM_ERR(CAM_ISP, "hw_intf null, returning rc...ctx_idx: %u",
 					ife_ctx->ctx_index);
-				return -EINVAL;
+				rc = -EINVAL;
+				goto put_cpu_buf;
 			}
 			rc = hw_intf->hw_ops.process_cmd(hw_intf->hw_priv,
 				CAM_ISP_HW_USER_DUMP, &isp_hw_dump_args,
 				sizeof(struct cam_isp_hw_dump_args));
-			if (rc)
-				return rc;
+			if (rc) {
+				rc = -EINVAL;
+				goto put_cpu_buf;
+			}
 			break;
 		default:
 			break;
@@ -13606,6 +13617,9 @@ static int cam_ife_mgr_dump(void *hw_mgr_priv, void *args)
 	}
 
 	dump_args->offset = isp_hw_dump_args.offset;
+
+put_cpu_buf:
+	cam_mem_put_cpu_buf(dump_args->buf_handle);
 	return rc;
 }
 

+ 6 - 0
drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c

@@ -1742,6 +1742,7 @@ void cam_tfe_cam_cdm_callback(uint32_t handle, void *userdata,
 				ctx->last_submit_bl_cmd.cmd[i].input_len - 1);
 
 			cam_cdm_util_dump_cmd_buf(buf_start, buf_end);
+			cam_mem_put_cpu_buf(ctx->last_submit_bl_cmd.cmd[i].mem_handle);
 		}
 		if (ctx->packet != NULL)
 			cam_packet_util_dump_patch_info(ctx->packet,
@@ -3540,6 +3541,7 @@ static int cam_tfe_mgr_dump(void *hw_mgr_priv, void *args)
 	}
 	dump_args->offset = isp_hw_dump_args.offset;
 	CAM_DBG(CAM_ISP, "offset %u", dump_args->offset);
+	cam_mem_put_cpu_buf(dump_args->buf_handle);
 	return rc;
 }
 
@@ -4130,6 +4132,7 @@ static int cam_tfe_update_dual_config(
 		(cmd_desc->offset >=
 			(len - sizeof(struct cam_isp_tfe_dual_config)))) {
 		CAM_ERR(CAM_ISP, "not enough buffer provided");
+		cam_mem_put_cpu_buf(cmd_desc->mem_handle);
 		return -EINVAL;
 	}
 
@@ -4142,6 +4145,7 @@ static int cam_tfe_update_dual_config(
 		(remain_len -
 			offsetof(struct cam_isp_tfe_dual_config, stripes))) {
 		CAM_ERR(CAM_ISP, "not enough buffer for all the dual configs");
+		cam_mem_put_cpu_buf(cmd_desc->mem_handle);
 		return -EINVAL;
 	}
 
@@ -4203,6 +4207,7 @@ static int cam_tfe_update_dual_config(
 	}
 
 end:
+	cam_mem_put_cpu_buf(cmd_desc->mem_handle);
 	return rc;
 }
 
@@ -4793,6 +4798,7 @@ static void cam_tfe_mgr_dump_pf_data(
 outportlog:
 	cam_packet_util_dump_io_bufs(packet, hw_mgr->mgr_common.img_iommu_hdl,
 		hw_mgr->mgr_common.img_iommu_hdl_secure, pf_cmd_args->pf_args, true);
+	cam_packet_util_put_packet_addr(pf_cmd_args->pf_req_info->packet_handle);
 
 }
 

+ 3 - 0
drivers/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c

@@ -171,6 +171,7 @@ static int cam_isp_update_dual_config(
 		(cmd_desc->offset >=
 		(len - sizeof(struct cam_isp_dual_config)))) {
 		CAM_ERR(CAM_ISP, "not enough buffer provided");
+		cam_mem_put_cpu_buf(cmd_desc->mem_handle);
 		return -EINVAL;
 	}
 	remain_len = len - cmd_desc->offset;
@@ -181,6 +182,7 @@ static int cam_isp_update_dual_config(
 		sizeof(struct cam_isp_dual_stripe_config)) >
 		(remain_len - offsetof(struct cam_isp_dual_config, stripes))) {
 		CAM_ERR(CAM_ISP, "not enough buffer for all the dual configs");
+		cam_mem_put_cpu_buf(cmd_desc->mem_handle);
 		return -EINVAL;
 	}
 	for (i = 0; i < dual_config->num_ports; i++) {
@@ -236,6 +238,7 @@ static int cam_isp_update_dual_config(
 	}
 
 end:
+	cam_mem_put_cpu_buf(cmd_desc->mem_handle);
 	return rc;
 }
 

+ 11 - 0
drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c

@@ -201,6 +201,7 @@ static int cam_jpeg_add_command_buffers(struct cam_packet *packet,
 			if ((cmd_desc[i].offset / sizeof(uint32_t)) >= len) {
 				CAM_ERR(CAM_JPEG, "Invalid offset: %u cmd buf len: %zu",
 					cmd_desc[i].offset, len);
+				cam_mem_put_cpu_buf(cmd_desc[i].mem_handle);
 				return -EINVAL;
 			}
 
@@ -210,6 +211,7 @@ static int cam_jpeg_add_command_buffers(struct cam_packet *packet,
 			jpeg_request_data->encode_size_buffer_ptr = &inout_params->output_size;
 			CAM_DBG(CAM_JPEG, "encode_size_buf_ptr: 0x%p",
 				jpeg_request_data->encode_size_buffer_ptr);
+			cam_mem_put_cpu_buf(cmd_desc[i].mem_handle);
 			break;
 		case CAM_JPEG_PACKET_GENERIC_BLOB:
 			rc = cam_packet_util_process_generic_cmd_buffer(&cmd_desc[i],
@@ -678,6 +680,8 @@ static int cam_jpeg_insert_cdm_change_base(
 		CAM_ERR(CAM_JPEG, "Not enough buf offset %d len %d",
 			config_args->hw_update_entries[CAM_JPEG_CHBASE_CMD_BUFF_IDX].offset,
 			ch_base_len);
+		cam_mem_put_cpu_buf(
+			config_args->hw_update_entries[CAM_JPEG_CHBASE_CMD_BUFF_IDX].handle);
 		return -EINVAL;
 	}
 
@@ -713,6 +717,9 @@ static int cam_jpeg_insert_cdm_change_base(
 	ch_base_iova_addr += size;
 	*ch_base_iova_addr = 0;
 
+	cam_mem_put_cpu_buf(
+		config_args->hw_update_entries[CAM_JPEG_CHBASE_CMD_BUFF_IDX].handle);
+
 	return rc;
 }
 
@@ -1899,6 +1906,7 @@ hw_dump:
 		CAM_WARN(CAM_JPEG, "dump offset overshoot len %zu offset %zu",
 			jpeg_dump_args.buf_len, dump_args->offset);
 		mutex_unlock(&hw_mgr->hw_mgr_mutex);
+		cam_mem_put_cpu_buf(dump_args->buf_handle);
 		return -ENOSPC;
 	}
 
@@ -1909,6 +1917,7 @@ hw_dump:
 		CAM_WARN(CAM_JPEG, "dump buffer exhaust remain %zu min %u",
 			remain_len, min_len);
 		mutex_unlock(&hw_mgr->hw_mgr_mutex);
+		cam_mem_put_cpu_buf(dump_args->buf_handle);
 		return -ENOSPC;
 	}
 
@@ -1941,6 +1950,7 @@ hw_dump:
 	CAM_DBG(CAM_JPEG, "Offset before %u after %u",
 		dump_args->offset, jpeg_dump_args.offset);
 	dump_args->offset = jpeg_dump_args.offset;
+	cam_mem_put_cpu_buf(dump_args->buf_handle);
 	return rc;
 }
 
@@ -1992,6 +2002,7 @@ static void cam_jpeg_mgr_dump_pf_data(
 iodump:
 	cam_packet_util_dump_io_bufs(packet, hw_mgr->iommu_hdl, hw_mgr->iommu_sec_hdl,
 		pf_args, hw_pid_support);
+	cam_packet_util_put_packet_addr(pf_req_info->packet_handle);
 }
 
 static int cam_jpeg_mgr_cmd(void *hw_mgr_priv, void *cmd_args)

+ 1 - 0
drivers/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.c

@@ -701,6 +701,7 @@ static int cam_lrme_mgr_hw_dump(void *hw_mgr_priv, void *hw_dump_args)
 	CAM_DBG(CAM_LRME, "Offset before %zu after %zu",
 		dump_args->offset, lrme_dump_args.offset);
 	dump_args->offset = lrme_dump_args.offset;
+	cam_mem_put_cpu_buf(dump_args->buf_handle);
 	return rc;
 }
 

+ 1 - 0
drivers/cam_ope/cam_ope_context.c

@@ -154,6 +154,7 @@ static int __cam_ope_config_dev_in_ready(struct cam_context *ctx,
 	if (rc)
 		CAM_ERR(CAM_OPE, "Failed to prepare device");
 
+	cam_mem_put_cpu_buf((int32_t) cmd->packet_handle);
 	return rc;
 }
 

+ 28 - 1
drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c

@@ -428,6 +428,25 @@ end:
 	return;
 }
 
+static int cam_ope_mgr_put_cmd_buf(struct cam_packet *packet)
+{
+	int i = 0;
+	struct cam_cmd_buf_desc *cmd_desc = NULL;
+
+	cmd_desc = (struct cam_cmd_buf_desc *)
+		((uint32_t *) &packet->payload + packet->cmd_buf_offset/4);
+
+	for (i = 0; i < packet->num_cmd_buf; i++) {
+		if (cmd_desc[i].type != CAM_CMD_BUF_GENERIC ||
+			cmd_desc[i].meta_data == OPE_CMD_META_GENERIC_BLOB)
+			continue;
+
+		cam_mem_put_cpu_buf(cmd_desc[i].mem_handle);
+	}
+
+	return 0;
+}
+
 static int cam_ope_dump_indirect(struct ope_cmd_buf_info *cmd_buf_info,
 	struct cam_ope_hang_dump *dump)
 {
@@ -457,6 +476,7 @@ static int cam_ope_dump_indirect(struct ope_cmd_buf_info *cmd_buf_info,
 			print_ptr += sizeof(struct cdm_dmi_cmd) /
 				sizeof(uint32_t);
 	}
+	cam_mem_put_cpu_buf((int32_t) cmd_buf_info->mem_handle);
 	return rc;
 }
 
@@ -559,6 +579,7 @@ static int cam_ope_dump_frame_process(struct cam_packet *packet,
 
 	cam_ope_mgr_dump_cmd_buf(cpu_addr, dump);
 	cam_ope_mgr_dump_frame_set(cpu_addr, dump);
+	cam_ope_mgr_put_cmd_buf(packet);
 	return rc;
 }
 
@@ -2208,6 +2229,7 @@ static int cam_ope_mgr_process_cmd_buf_req(struct cam_ope_hw_mgr *hw_mgr,
 					ope_request->ope_kmd_buf.cpu_addr,
 					ope_request->ope_kmd_buf.iova_addr,
 					ope_request->ope_kmd_buf.iova_cdm_addr);
+					cam_mem_put_cpu_buf(cmd_buf->mem_handle);
 					break;
 				} else if (cmd_buf->cmd_buf_usage ==
 					OPE_CMD_BUF_DEBUG) {
@@ -2223,8 +2245,10 @@ static int cam_ope_mgr_process_cmd_buf_req(struct cam_ope_hw_mgr *hw_mgr,
 						cmd_buf->offset;
 					CAM_DBG(CAM_OPE, "dbg buf = %x",
 					ope_request->ope_debug_buf.cpu_addr);
+					cam_mem_put_cpu_buf(cmd_buf->mem_handle);
 					break;
 				}
+				cam_mem_put_cpu_buf(cmd_buf->mem_handle);
 				break;
 			}
 			case OPE_CMD_BUF_SCOPE_STRIPE: {
@@ -3075,6 +3099,7 @@ static int cam_ope_mgr_release_hw(void *hw_priv, void *hw_release_args)
 	return rc;
 }
 
+
 static int cam_ope_packet_generic_blob_handler(void *user_data,
 	uint32_t blob_type, uint32_t blob_size, uint8_t *blob_data)
 {
@@ -3349,13 +3374,14 @@ static int cam_ope_mgr_prepare_hw_update(void *hw_priv,
 		ctx_data->last_req_time);
 	cam_ope_req_timer_modify(ctx_data, ctx_data->req_timer_timeout);
 	set_bit(request_idx, ctx_data->bitmap);
+	cam_ope_mgr_put_cmd_buf(packet);
 	mutex_unlock(&ctx_data->ctx_mutex);
-
 	CAM_DBG(CAM_REQ, "Prepare Hw update Successful request_id: %d  ctx: %d",
 		packet->header.request_id, ctx_data->ctx_id);
 	return rc;
 
 end:
+	cam_ope_mgr_put_cmd_buf(packet);
 	cam_free_clear((void *)ctx_data->req_list[request_idx]->cdm_cmd);
 	ctx_data->req_list[request_idx]->cdm_cmd = NULL;
 req_cdm_mem_alloc_failed:
@@ -4249,4 +4275,5 @@ iodump:
 			}
 		}
 	}
+	cam_packet_util_put_packet_addr(pf_req_info->packet_handle);
 }

+ 10 - 0
drivers/cam_ope/ope_hw_mgr/ope_hw/ope_core.c

@@ -585,6 +585,7 @@ static uint32_t *ope_create_frame_cmd_batch(struct cam_ope_hw_mgr *hw_mgr,
 				dmi_cmd = (struct cdm_dmi_cmd *)temp;
 				if (!dmi_cmd->addr) {
 					CAM_ERR(CAM_OPE, "Null dmi cmd addr");
+					cam_mem_put_cpu_buf(frm_proc->cmd_buf[i][j].mem_handle);
 					return NULL;
 				}
 
@@ -605,6 +606,8 @@ static uint32_t *ope_create_frame_cmd_batch(struct cam_ope_hw_mgr *hw_mgr,
 		if (hw_mgr->frame_dump_enable)
 			dump_frame_cmd(frm_proc, i, j,
 				iova_addr, kmd_buf, buf_len);
+
+		cam_mem_put_cpu_buf(frm_proc->cmd_buf[i][j].mem_handle);
 	}
 	return kmd_buf;
 
@@ -744,6 +747,8 @@ static uint32_t *ope_create_frame_cmd(struct cam_ope_hw_mgr *hw_mgr,
 					if (!dmi_cmd->addr) {
 						CAM_ERR(CAM_OPE,
 							"Null dmi cmd addr");
+						cam_mem_put_cpu_buf(
+							frm_proc->cmd_buf[i][j].mem_handle);
 						return NULL;
 					}
 
@@ -765,6 +770,8 @@ static uint32_t *ope_create_frame_cmd(struct cam_ope_hw_mgr *hw_mgr,
 			if (hw_mgr->frame_dump_enable)
 				dump_frame_cmd(frm_proc, i, j,
 					iova_addr, kmd_buf, buf_len);
+
+			cam_mem_put_cpu_buf(frm_proc->cmd_buf[i][j].mem_handle);
 		}
 	}
 	return kmd_buf;
@@ -859,6 +866,7 @@ static uint32_t *ope_create_stripe_cmd(struct cam_ope_hw_mgr *hw_mgr,
 				dmi_cmd = (struct cdm_dmi_cmd *)temp;
 				if (!dmi_cmd->addr) {
 					CAM_ERR(CAM_OPE, "Null dmi cmd addr");
+					cam_mem_put_cpu_buf(frm_proc->cmd_buf[i][k].mem_handle);
 					return NULL;
 				}
 
@@ -877,6 +885,8 @@ static uint32_t *ope_create_stripe_cmd(struct cam_ope_hw_mgr *hw_mgr,
 		if (hw_mgr->frame_dump_enable)
 			dump_stripe_cmd(frm_proc, stripe_idx, i, k,
 				iova_addr, kmd_buf, buf_len);
+
+		cam_mem_put_cpu_buf(frm_proc->cmd_buf[i][k].mem_handle);
 	}
 
 	ope_dev = hw_mgr->ope_dev_intf[0]->hw_priv;

+ 102 - 18
drivers/cam_req_mgr/cam_mem_mgr.c

@@ -491,6 +491,7 @@ int cam_mem_get_cpu_buf(int32_t buf_handle, uintptr_t *vaddr_ptr, size_t *len)
 		return -EINVAL;
 
 	idx = CAM_MEM_MGR_GET_HDL_IDX(buf_handle);
+
 	if (idx >= CAM_MEM_BUFQ_MAX || idx <= 0)
 		return -EINVAL;
 
@@ -500,18 +501,24 @@ int cam_mem_get_cpu_buf(int32_t buf_handle, uintptr_t *vaddr_ptr, size_t *len)
 		return -EPERM;
 	}
 
-	if (buf_handle != tbl.bufq[idx].buf_handle)
+	if (buf_handle != tbl.bufq[idx].buf_handle) {
+		CAM_ERR(CAM_MEM, "idx: %d Invalid buf handle %d",
+				idx, buf_handle);
 		return -EINVAL;
+	}
 
-	if (!(tbl.bufq[idx].flags & CAM_MEM_FLAG_KMD_ACCESS))
+	if (!(tbl.bufq[idx].flags & CAM_MEM_FLAG_KMD_ACCESS)) {
+		CAM_ERR(CAM_MEM, "idx: %d Invalid flag 0x%x",
+					idx, tbl.bufq[idx].flags);
 		return -EINVAL;
+	}
 
-	if (tbl.bufq[idx].kmdvaddr) {
+	if (tbl.bufq[idx].kmdvaddr && kref_get_unless_zero(&tbl.bufq[idx].krefcount)) {
 		*vaddr_ptr = tbl.bufq[idx].kmdvaddr;
 		*len = tbl.bufq[idx].len;
 	} else {
-		CAM_ERR(CAM_MEM, "No KMD access was requested for 0x%x handle",
-			buf_handle);
+		CAM_ERR(CAM_MEM, "No KMD access requested, kmdvddr= %p, idx= %d, buf_handle= %d",
+			tbl.bufq[idx].kmdvaddr, idx, buf_handle);
 		return -EINVAL;
 	}
 
@@ -1357,6 +1364,8 @@ int cam_mem_mgr_alloc_and_map(struct cam_mem_mgr_alloc_cmd_v2 *cmd)
 	tbl.bufq[idx].num_hdls = cmd->num_hdl;
 	cam_mem_mgr_reset_presil_params(idx);
 	tbl.bufq[idx].is_imported = false;
+	kref_init(&tbl.bufq[idx].krefcount);
+	tbl.bufq[idx].smmu_mapping_client = CAM_SMMU_MAPPING_USER;
 	mutex_unlock(&tbl.bufq[idx].q_lock);
 
 	cmd->out.buf_handle = tbl.bufq[idx].buf_handle;
@@ -1488,6 +1497,8 @@ int cam_mem_mgr_map(struct cam_mem_mgr_map_cmd_v2 *cmd)
 	tbl.bufq[idx].num_hdls = cmd->num_hdl;
 	tbl.bufq[idx].is_imported = true;
 	tbl.bufq[idx].is_internal = is_internal;
+	kref_init(&tbl.bufq[idx].krefcount);
+	tbl.bufq[idx].smmu_mapping_client = CAM_SMMU_MAPPING_USER;
 	mutex_unlock(&tbl.bufq[idx].q_lock);
 
 	cmd->out.buf_handle = tbl.bufq[idx].buf_handle;
@@ -1667,24 +1678,30 @@ void cam_mem_mgr_deinit(void)
 	mutex_destroy(&tbl.m_lock);
 }
 
-static int cam_mem_util_unmap(int32_t idx,
-	enum cam_smmu_mapping_client client)
+static void cam_mem_util_unmap(struct kref *kref)
 {
 	int rc = 0;
+	int32_t idx;
 	enum cam_smmu_region_id region = CAM_SMMU_REGION_SHARED;
+	enum cam_smmu_mapping_client client;
+	struct cam_mem_buf_queue *bufq =
+		container_of(kref, typeof(*bufq), krefcount);
 
+	idx = CAM_MEM_MGR_GET_HDL_IDX(bufq->buf_handle);
 	if (idx >= CAM_MEM_BUFQ_MAX || idx <= 0) {
 		CAM_ERR(CAM_MEM, "Incorrect index");
-		return -EINVAL;
+		return;
 	}
 
+	client = tbl.bufq[idx].smmu_mapping_client;
+
 	CAM_DBG(CAM_MEM, "Flags = %X idx %d", tbl.bufq[idx].flags, idx);
 
 	mutex_lock(&tbl.m_lock);
 	if (!tbl.bufq[idx].active) {
 		CAM_WARN(CAM_MEM, "Buffer at idx=%d is already unmapped", idx);
 		mutex_unlock(&tbl.m_lock);
-		return 0;
+		return;
 	}
 
 	/* Deactivate the buffer queue to prevent multiple unmap */
@@ -1750,13 +1767,50 @@ static int cam_mem_util_unmap(int32_t idx,
 	clear_bit(idx, tbl.bitmap);
 	mutex_unlock(&tbl.m_lock);
 
-	return rc;
 }
 
+void cam_mem_put_cpu_buf(int32_t buf_handle)
+{
+	int rc = 0;
+	int idx;
+
+	if (!buf_handle) {
+		CAM_ERR(CAM_MEM, "Invalid buf_handle");
+		return;
+	}
+
+	idx = CAM_MEM_MGR_GET_HDL_IDX(buf_handle);
+	if (idx >= CAM_MEM_BUFQ_MAX || idx <= 0) {
+		CAM_ERR(CAM_MEM, "idx: %d not valid", idx);
+		return;
+	}
+
+	if (!tbl.bufq[idx].active) {
+		CAM_ERR(CAM_MEM, "idx: %d not active", idx);
+		rc = -EPERM;
+		return;
+	}
+
+	if (buf_handle != tbl.bufq[idx].buf_handle) {
+		CAM_ERR(CAM_MEM, "idx: %d Invalid buf handle %d",
+				idx, buf_handle);
+		rc = -EINVAL;
+		return;
+	}
+
+	if (kref_put(&tbl.bufq[idx].krefcount, cam_mem_util_unmap))
+		CAM_DBG(CAM_MEM,
+			"Called unmap from here, buf_handle: %u, idx: %d",
+			buf_handle, idx);
+
+}
+EXPORT_SYMBOL(cam_mem_put_cpu_buf);
+
+
 int cam_mem_mgr_release(struct cam_mem_mgr_release_cmd *cmd)
 {
 	int idx;
-	int rc;
+	int rc = 0;
 
 	if (!atomic_read(&cam_mem_mgr_state)) {
 		CAM_ERR(CAM_MEM, "failed. mem_mgr not initialized");
@@ -1788,8 +1842,18 @@ int cam_mem_mgr_release(struct cam_mem_mgr_release_cmd *cmd)
 	}
 
 	CAM_DBG(CAM_MEM, "Releasing hdl = %x, idx = %d", cmd->buf_handle, idx);
-	rc = cam_mem_util_unmap(idx, CAM_SMMU_MAPPING_USER);
 
+	if (kref_put(&tbl.bufq[idx].krefcount, cam_mem_util_unmap)) {
+		CAM_DBG(CAM_MEM,
+			"Called unmap from here, buf_handle: %u, idx: %d",
+			cmd->buf_handle, idx);
+	} else {
+		rc = -EINVAL;
+		CAM_ERR(CAM_MEM,
+			"Unbalanced release Called buf_handle: %u, idx: %d",
+			cmd->buf_handle, idx);
+
+	}
 	return rc;
 }
 
@@ -1898,6 +1962,8 @@ int cam_mem_mgr_request_mem(struct cam_mem_mgr_request_desc *inp,
 	tbl.bufq[idx].len = inp->size;
 	tbl.bufq[idx].num_hdls = 1;
 	tbl.bufq[idx].is_imported = false;
+	kref_init(&tbl.bufq[idx].krefcount);
+	tbl.bufq[idx].smmu_mapping_client = CAM_SMMU_MAPPING_KERNEL;
 	mutex_unlock(&tbl.bufq[idx].q_lock);
 
 	out->kva = kvaddr;
@@ -1926,7 +1992,7 @@ EXPORT_SYMBOL(cam_mem_mgr_request_mem);
 int cam_mem_mgr_release_mem(struct cam_mem_mgr_memory_desc *inp)
 {
 	int32_t idx;
-	int rc;
+	int rc = 0;
 
 	if (!atomic_read(&cam_mem_mgr_state)) {
 		CAM_ERR(CAM_MEM, "failed. mem_mgr not initialized");
@@ -1956,7 +2022,16 @@ int cam_mem_mgr_release_mem(struct cam_mem_mgr_memory_desc *inp)
 	}
 
 	CAM_DBG(CAM_MEM, "Releasing hdl = %X", inp->mem_handle);
-	rc = cam_mem_util_unmap(idx, CAM_SMMU_MAPPING_KERNEL);
+	if (kref_put(&tbl.bufq[idx].krefcount, cam_mem_util_unmap))
+		CAM_DBG(CAM_MEM,
+			"Called unmap from here, buf_handle: %u, idx: %d",
+			tbl.bufq[idx].buf_handle, idx);
+	else {
+		CAM_ERR(CAM_MEM,
+			"Unbalanced release Called buf_handle: %u, idx: %d",
+			tbl.bufq[idx].buf_handle, idx);
+		rc = -EINVAL;
+	}
 
 	return rc;
 }
@@ -2049,6 +2124,8 @@ int cam_mem_mgr_reserve_memory_region(struct cam_mem_mgr_request_desc *inp,
 	tbl.bufq[idx].len = request_len;
 	tbl.bufq[idx].num_hdls = 1;
 	tbl.bufq[idx].is_imported = false;
+	kref_init(&tbl.bufq[idx].krefcount);
+	tbl.bufq[idx].smmu_mapping_client = CAM_SMMU_MAPPING_KERNEL;
 	mutex_unlock(&tbl.bufq[idx].q_lock);
 
 	out->kva = kvaddr;
@@ -2174,7 +2251,7 @@ int cam_mem_mgr_dump_user(struct cam_dump_req_cmd *dump_req)
 
 int cam_mem_mgr_free_memory_region(struct cam_mem_mgr_memory_desc *inp)
 {
-	int32_t rc, idx, entry_idx;
+	int32_t rc = 0, idx, entry_idx;
 
 	if (!atomic_read(&cam_mem_mgr_state)) {
 		CAM_ERR(CAM_MEM, "failed. mem_mgr not initialized");
@@ -2235,9 +2312,16 @@ int cam_mem_mgr_free_memory_region(struct cam_mem_mgr_memory_desc *inp)
 	}
 
 	CAM_DBG(CAM_MEM, "Releasing hdl = %X", inp->mem_handle);
-	rc = cam_mem_util_unmap(idx, CAM_SMMU_MAPPING_KERNEL);
-	if (rc)
-		CAM_ERR(CAM_MEM, "unmapping secondary heap failed");
+	if (kref_put(&tbl.bufq[idx].krefcount, cam_mem_util_unmap))
+		CAM_DBG(CAM_MEM,
+			"Called unmap from here, buf_handle: %u, idx: %d",
+			inp->mem_handle, idx);
+	else {
+		CAM_ERR(CAM_MEM,
+			"Unbalanced release Called buf_handle: %u, idx: %d",
+			inp->mem_handle, idx);
+		rc = -EINVAL;
+	}
 
 	return rc;
 }

+ 5 - 0
drivers/cam_req_mgr/cam_mem_mgr.h

@@ -80,6 +80,9 @@ struct cam_mem_buf_hw_hdl_info {
  * @is_imported:    Flag indicating if buffer is imported from an FD in user space
  * @is_internal:    Flag indicating kernel allocated buffer
  * @timestamp:      Timestamp at which this entry in tbl was made
+ * @krefcount:      Reference counter to track whether the buffer is
+ *                  mapped and in use
+ * @smmu_mapping_client: Client buffer (User or kernel)
  * @presil_params:  Parameters specific to presil environment
  */
 struct cam_mem_buf_queue {
@@ -98,6 +101,8 @@ struct cam_mem_buf_queue {
 	bool is_imported;
 	bool is_internal;
 	struct timespec64 timestamp;
+	struct kref krefcount;
+	enum cam_smmu_mapping_client smmu_mapping_client;
 
 #ifdef CONFIG_CAM_PRESIL
 	struct cam_presil_dmabuf_params presil_params;

+ 8 - 0
drivers/cam_req_mgr/cam_mem_mgr_api.h

@@ -93,6 +93,14 @@ int cam_mem_get_io_buf(int32_t buf_handle, int32_t mmu_handle,
 int cam_mem_get_cpu_buf(int32_t buf_handle, uintptr_t *vaddr_ptr,
 	size_t *len);
 
+/**
+ * @brief: This indicates end of CPU access
+ *
+ * @buf_handle: Handle for the buffer
+ *
+ */
+void cam_mem_put_cpu_buf(int32_t buf_handle);
+
 static inline bool cam_mem_is_secure_buf(int32_t buf_handle)
 {
 	return CAM_MEM_MGR_IS_SECURE_HDL(buf_handle);

+ 5 - 1
drivers/cam_req_mgr/cam_req_mgr_core.c

@@ -5543,11 +5543,13 @@ static int cam_req_mgr_dump_state_monitor_info(
 	if (rc) {
 		CAM_ERR(CAM_CRM, "Invalid handle %u rc %d",
 			dump_info->buf_handle, rc);
+		cam_mem_put_cpu_buf(dump_info->buf_handle);
 		return rc;
 	}
 	if (buf_len <= dump_info->offset) {
 		CAM_WARN(CAM_CRM, "Dump buffer overshoot len %zu offset %zu",
 			buf_len, dump_info->offset);
+		cam_mem_put_cpu_buf(dump_info->buf_handle);
 		return -ENOSPC;
 	}
 
@@ -5559,6 +5561,7 @@ static int cam_req_mgr_dump_state_monitor_info(
 	if (remain_len < min_len) {
 		CAM_WARN(CAM_CRM, "Dump buffer exhaust remain %zu min %u",
 			remain_len, min_len);
+		cam_mem_put_cpu_buf(dump_info->buf_handle);
 		return -ENOSPC;
 	}
 
@@ -5578,6 +5581,7 @@ static int cam_req_mgr_dump_state_monitor_info(
 				CAM_ERR(CAM_CRM,
 					"Dump state info failed, rc: %d",
 					rc);
+				cam_mem_put_cpu_buf(dump_info->buf_handle);
 				return rc;
 			}
 		}
@@ -5585,7 +5589,7 @@ static int cam_req_mgr_dump_state_monitor_info(
 	}
 
 	dump_info->offset = dump_args.offset;
-
+	cam_mem_put_cpu_buf(dump_info->buf_handle);
 	return rc;
 }
 

+ 21 - 4
drivers/cam_utils/cam_packet_util.c

@@ -48,6 +48,11 @@ int cam_packet_util_get_packet_addr(struct cam_packet **packet,
 	return rc;
 }
 
+void cam_packet_util_put_packet_addr(uint64_t packet_handle)
+{
+	cam_mem_put_cpu_buf(packet_handle);
+}
+
 int cam_packet_util_get_cmd_mem_addr(int handle, uint32_t **buf_addr,
 	size_t *len)
 {
@@ -57,6 +62,7 @@ int cam_packet_util_get_cmd_mem_addr(int handle, uint32_t **buf_addr,
 	rc = cam_mem_get_cpu_buf(handle, &kmd_buf_addr, len);
 	if (rc) {
 		CAM_ERR(CAM_UTIL, "Unable to get the virtual address %d", rc);
+		rc = -EINVAL;
 	} else {
 		if (kmd_buf_addr && *len) {
 			*buf_addr = (uint32_t *)kmd_buf_addr;
@@ -177,14 +183,16 @@ int cam_packet_util_get_kmd_buffer(struct cam_packet *packet,
 		((size_t)cmd_desc->size > (len - (size_t)cmd_desc->offset))) {
 		CAM_ERR(CAM_UTIL, "invalid memory len:%zd and cmd desc size:%d",
 			len, cmd_desc->size);
-		return -EINVAL;
+		rc = -EINVAL;
+		goto rel_kmd_buf;
 	}
 
 	remain_len -= (size_t)cmd_desc->offset;
 	if ((size_t)packet->kmd_cmd_buf_offset >= remain_len) {
 		CAM_ERR(CAM_UTIL, "Invalid kmd cmd buf offset: %zu",
 			(size_t)packet->kmd_cmd_buf_offset);
-		return -EINVAL;
+		rc = -EINVAL;
+		goto rel_kmd_buf;
 	}
 
 	cpu_addr += (cmd_desc->offset / 4) + (packet->kmd_cmd_buf_offset / 4);
@@ -201,6 +209,8 @@ int cam_packet_util_get_kmd_buffer(struct cam_packet *packet,
 	kmd_buf->size       = cmd_desc->size - cmd_desc->length;
 	kmd_buf->used_bytes = 0;
 
+rel_kmd_buf:
+	cam_mem_put_cpu_buf(cmd_desc->mem_handle);
 	return rc;
 }
 
@@ -287,6 +297,8 @@ void cam_packet_util_dump_patch_info(struct cam_packet *packet,
 
 		if (!(*dst_cpu_addr))
 			CAM_ERR(CAM_ICP, "Null at dst addr %p", dst_cpu_addr);
+
+		cam_mem_put_cpu_buf(patch_desc[i].dst_buf_hdl);
 	}
 }
 
@@ -418,6 +430,7 @@ int cam_packet_util_process_patches(struct cam_packet *packet,
 			(size_t)patch_desc[i].dst_offset)) {
 			CAM_ERR(CAM_UTIL,
 				"Invalid dst buf patch offset");
+			cam_mem_put_cpu_buf((int32_t)patch_desc[i].dst_buf_hdl);
 			return -EINVAL;
 		}
 
@@ -447,6 +460,7 @@ int cam_packet_util_process_patches(struct cam_packet *packet,
 			CAM_BOOL_TO_YESNO(flags & CAM_MEM_FLAG_HW_SHARED_ACCESS),
 			CAM_BOOL_TO_YESNO(flags & CAM_MEM_FLAG_CMD_BUF_TYPE),
 			CAM_BOOL_TO_YESNO(flags & CAM_MEM_FLAG_HW_AND_CDM_OR_SHARED));
+		cam_mem_put_cpu_buf((int32_t)patch_desc[i].dst_buf_hdl);
 	}
 
 	return rc;
@@ -578,14 +592,16 @@ int cam_packet_util_process_generic_cmd_buffer(
 		((size_t)cmd_buf->offset > (buf_size - sizeof(uint32_t)))) {
 		CAM_ERR(CAM_UTIL, "Invalid offset for cmd buf: %zu",
 			(size_t)cmd_buf->offset);
-		return -EINVAL;
+		rc = -EINVAL;
+		goto end;
 	}
 	remain_len -= (size_t)cmd_buf->offset;
 
 	if (remain_len < (size_t)cmd_buf->length) {
 		CAM_ERR(CAM_UTIL, "Invalid length for cmd buf: %zu",
 			(size_t)cmd_buf->length);
-		return -EINVAL;
+		rc = -EINVAL;
+		goto end;
 	}
 
 	blob_ptr = (uint32_t *)(((uint8_t *)cpu_addr) +
@@ -635,6 +651,7 @@ int cam_packet_util_process_generic_cmd_buffer(
 	}
 
 end:
+	cam_mem_put_cpu_buf(cmd_buf->mem_handle);
 	return rc;
 }
 

+ 8 - 0
drivers/cam_utils/cam_packet_util.h

@@ -44,6 +44,14 @@ typedef int (*cam_packet_generic_blob_handler)(void *user_data,
 int cam_packet_util_get_packet_addr(struct cam_packet **packet,
 	uint64_t packet_handle, uint32_t offset);
 
+
+/**
+ * @brief                  Put packet buffer address
+ *
+ * @packet_handle:         Buffer handle of the packet
+ */
+void cam_packet_util_put_packet_addr(uint64_t packet_handle);
+
 /**
  * cam_packet_util_get_cmd_mem_addr()
  *

+ 11 - 8
drivers/cam_utils/cam_soc_util.c

@@ -3692,8 +3692,7 @@ static int cam_soc_util_dump_dmi_reg_range_user_buf(
 		CAM_ERR(CAM_UTIL,
 			"Invalid input args soc_info: %pK, dump_args: %pK",
 			soc_info, dump_args);
-		rc = -EINVAL;
-		goto end;
+		return -EINVAL;
 	}
 
 	if (dmi_read->num_pre_writes > CAM_REG_DUMP_DMI_CONFIG_MAX ||
@@ -3701,15 +3700,14 @@ static int cam_soc_util_dump_dmi_reg_range_user_buf(
 		CAM_ERR(CAM_UTIL,
 			"Invalid number of requested writes, pre: %d post: %d",
 			dmi_read->num_pre_writes, dmi_read->num_post_writes);
-		rc = -EINVAL;
-		goto end;
+		return -EINVAL;
 	}
 
 	rc = cam_mem_get_cpu_buf(dump_args->buf_handle, &cpu_addr, &buf_len);
 	if (rc) {
 		CAM_ERR(CAM_UTIL, "Invalid handle %u rc %d",
 			dump_args->buf_handle, rc);
-		goto end;
+		return rc;
 	}
 
 	if (buf_len <= dump_args->offset) {
@@ -3795,6 +3793,7 @@ static int cam_soc_util_dump_dmi_reg_range_user_buf(
 		sizeof(struct cam_hw_soc_dump_header);
 
 end:
+	cam_mem_put_cpu_buf(dump_args->buf_handle);
 	return rc;
 }
 
@@ -3818,14 +3817,14 @@ static int cam_soc_util_dump_cont_reg_range_user_buf(
 		CAM_ERR(CAM_UTIL,
 			"Invalid input args soc_info: %pK, dump_out_buffer: %pK reg_read: %pK",
 			soc_info, dump_args, reg_read);
-		rc = -EINVAL;
-		goto end;
+		return -EINVAL;
 	}
+
 	rc = cam_mem_get_cpu_buf(dump_args->buf_handle, &cpu_addr, &buf_len);
 	if (rc) {
 		CAM_ERR(CAM_UTIL, "Invalid handle %u rc %d",
 			dump_args->buf_handle, rc);
-		goto end;
+		return rc;
 	}
 	if (buf_len <= dump_args->offset) {
 		CAM_WARN(CAM_UTIL, "Dump offset overshoot %zu %zu",
@@ -3875,6 +3874,7 @@ static int cam_soc_util_dump_cont_reg_range_user_buf(
 	dump_args->offset +=  hdr->size +
 		sizeof(struct cam_hw_soc_dump_header);
 end:
+	cam_mem_put_cpu_buf(dump_args->buf_handle);
 	return rc;
 }
 
@@ -3966,6 +3966,8 @@ int cam_soc_util_reg_dump_to_cmd_buf(void *ctx,
 	if (rc || !cpu_addr || (buf_size == 0)) {
 		CAM_ERR(CAM_UTIL, "Failed in Get cpu addr, rc=%d, cpu_addr=%pK",
 			rc, (void *)cpu_addr);
+		if (rc)
+			return rc;
 		goto end;
 	}
 
@@ -4167,6 +4169,7 @@ int cam_soc_util_reg_dump_to_cmd_buf(void *ctx,
 	}
 
 end:
+	cam_mem_put_cpu_buf(cmd_desc->mem_handle);
 	return rc;
 }