From 891c47b17e3fd2d734e4fb50ff68b18a4fc7c0a4 Mon Sep 17 00:00:00 2001 From: Haibin Liu Date: Fri, 27 Sep 2019 20:05:04 +0800 Subject: [PATCH] msm: camera: memmgr: reduce mutex lock duration Allow concurrent calls to unmap buffer by reducing the mutex lock duration, and allow same fd for mapping user iova, use book keeping for user smmu. CRs-Fixed: 2559879 Change-Id: Ic3c92d4fa0ca7d1c29e621172e0b058420e1501d Signed-off-by: Haibin Liu --- drivers/cam_req_mgr/cam_mem_mgr.c | 22 ++++++++++++++++---- drivers/cam_smmu/cam_smmu_api.c | 34 +++++++++++++++++++++++++++++-- 2 files changed, 50 insertions(+), 6 deletions(-) diff --git a/drivers/cam_req_mgr/cam_mem_mgr.c b/drivers/cam_req_mgr/cam_mem_mgr.c index ca6d671f46f2..5efd66b9eb82 100644 --- a/drivers/cam_req_mgr/cam_mem_mgr.c +++ b/drivers/cam_req_mgr/cam_mem_mgr.c @@ -254,8 +254,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) { @@ -310,8 +313,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; @@ -353,6 +359,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; } @@ -1061,6 +1069,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, @@ -1091,10 +1106,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); @@ -1113,7 +1128,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 b87972840021..6ff1775c3f63 100644 --- a/drivers/cam_smmu/cam_smmu_api.c +++ b/drivers/cam_smmu/cam_smmu_api.c @@ -2181,6 +2181,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) { @@ -2944,7 +2964,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; @@ -2961,7 +2981,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; } @@ -3222,6 +3242,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);