diff --git a/drivers/cam_req_mgr/cam_mem_mgr.c b/drivers/cam_req_mgr/cam_mem_mgr.c index d6d5fcc8e7e3..a2952787762e 100644 --- a/drivers/cam_req_mgr/cam_mem_mgr.c +++ b/drivers/cam_req_mgr/cam_mem_mgr.c @@ -238,8 +238,11 @@ int cam_mem_get_io_buf(int32_t buf_handle, int32_t mmu_handle, if (idx >= CAM_MEM_BUFQ_MAX || idx <= 0) return -ENOENT; - if (!tbl.bufq[idx].active) + if (!tbl.bufq[idx].active) { + CAM_ERR(CAM_MEM, "Buffer at idx=%d is already unmapped,", + idx); return -EAGAIN; + } mutex_lock(&tbl.bufq[idx].q_lock); if (buf_handle != tbl.bufq[idx].buf_handle) { @@ -294,8 +297,11 @@ int cam_mem_get_cpu_buf(int32_t buf_handle, uintptr_t *vaddr_ptr, size_t *len) if (idx >= CAM_MEM_BUFQ_MAX || idx <= 0) return -EINVAL; - if (!tbl.bufq[idx].active) + if (!tbl.bufq[idx].active) { + CAM_ERR(CAM_MEM, "Buffer at idx=%d is already unmapped,", + idx); return -EPERM; + } if (buf_handle != tbl.bufq[idx].buf_handle) return -EINVAL; @@ -337,6 +343,8 @@ int cam_mem_mgr_cache_ops(struct cam_mem_cache_ops_cmd *cmd) mutex_lock(&tbl.bufq[idx].q_lock); if (!tbl.bufq[idx].active) { + CAM_ERR(CAM_MEM, "Buffer at idx=%d is already unmapped,", + idx); rc = -EINVAL; goto end; } @@ -1053,6 +1061,13 @@ static int cam_mem_util_unmap(int32_t idx, return 0; } + /* Deactivate the buffer queue to prevent multiple unmap */ + mutex_lock(&tbl.bufq[idx].q_lock); + tbl.bufq[idx].active = false; + tbl.bufq[idx].vaddr = 0; + mutex_unlock(&tbl.bufq[idx].q_lock); + mutex_unlock(&tbl.m_lock); + if (tbl.bufq[idx].flags & CAM_MEM_FLAG_KMD_ACCESS) { if (tbl.bufq[idx].dma_buf && tbl.bufq[idx].kmdvaddr) { rc = cam_mem_util_unmap_cpu_va(tbl.bufq[idx].dma_buf, @@ -1083,10 +1098,10 @@ static int cam_mem_util_unmap(int32_t idx, tbl.bufq[idx].dma_buf = NULL; } + mutex_lock(&tbl.m_lock); mutex_lock(&tbl.bufq[idx].q_lock); tbl.bufq[idx].flags = 0; tbl.bufq[idx].buf_handle = -1; - tbl.bufq[idx].vaddr = 0; memset(tbl.bufq[idx].hdls, 0, sizeof(int32_t) * CAM_MEM_MMU_MAX_HANDLE); @@ -1105,7 +1120,6 @@ static int cam_mem_util_unmap(int32_t idx, tbl.bufq[idx].is_internal = false; tbl.bufq[idx].len = 0; tbl.bufq[idx].num_hdl = 0; - tbl.bufq[idx].active = false; memset(&tbl.bufq[idx].timestamp, 0, sizeof(struct timespec64)); mutex_unlock(&tbl.bufq[idx].q_lock); mutex_destroy(&tbl.bufq[idx].q_lock); diff --git a/drivers/cam_smmu/cam_smmu_api.c b/drivers/cam_smmu/cam_smmu_api.c index ef2ab698a035..4e3bc2a0c864 100644 --- a/drivers/cam_smmu/cam_smmu_api.c +++ b/drivers/cam_smmu/cam_smmu_api.c @@ -2210,6 +2210,26 @@ static enum cam_smmu_buf_state cam_smmu_check_fd_in_list(int idx, return CAM_SMMU_BUFF_NOT_EXIST; } +static enum cam_smmu_buf_state cam_smmu_user_reuse_fd_in_list(int idx, + int ion_fd, dma_addr_t *paddr_ptr, size_t *len_ptr, + struct timespec64 **ts_mapping) +{ + struct cam_dma_buff_info *mapping; + + list_for_each_entry(mapping, + &iommu_cb_set.cb_info[idx].smmu_buf_list, list) { + if (mapping->ion_fd == ion_fd) { + *paddr_ptr = mapping->paddr; + *len_ptr = mapping->len; + *ts_mapping = &mapping->ts; + mapping->ref_count++; + return CAM_SMMU_BUFF_EXIST; + } + } + + return CAM_SMMU_BUFF_NOT_EXIST; +} + static enum cam_smmu_buf_state cam_smmu_check_dma_buf_in_list(int idx, struct dma_buf *buf, dma_addr_t *paddr_ptr, size_t *len_ptr) { @@ -2973,7 +2993,7 @@ int cam_smmu_map_user_iova(int handle, int ion_fd, bool dis_delayed_unmap, goto get_addr_end; } - buf_state = cam_smmu_check_fd_in_list(idx, ion_fd, paddr_ptr, + buf_state = cam_smmu_user_reuse_fd_in_list(idx, ion_fd, paddr_ptr, len_ptr, &ts); if (buf_state == CAM_SMMU_BUFF_EXIST) { uint64_t ms = 0, tmp = 0, hrs = 0, min = 0, sec = 0; @@ -2990,7 +3010,7 @@ int cam_smmu_map_user_iova(int handle, int ion_fd, bool dis_delayed_unmap, ion_fd, hrs, min, sec, ms, iommu_cb_set.cb_info[idx].name[0], idx, handle, *len_ptr); - rc = -EALREADY; + rc = 0; goto get_addr_end; } @@ -3251,6 +3271,16 @@ int cam_smmu_unmap_user_iova(int handle, goto unmap_end; } + mapping_info->ref_count--; + if (mapping_info->ref_count > 0) { + CAM_DBG(CAM_SMMU, + "idx: %d fd = %d ref_count: %d", + idx, ion_fd, mapping_info->ref_count); + rc = 0; + goto unmap_end; + } + mapping_info->ref_count = 0; + /* Unmapping one buffer from device */ CAM_DBG(CAM_SMMU, "SMMU: removing buffer idx = %d", idx); rc = cam_smmu_unmap_buf_and_remove_from_list(mapping_info, idx);