diff --git a/drivers/cam_req_mgr/cam_mem_mgr.c b/drivers/cam_req_mgr/cam_mem_mgr.c index d07ee455b5..5fff0cf2f0 100644 --- a/drivers/cam_req_mgr/cam_mem_mgr.c +++ b/drivers/cam_req_mgr/cam_mem_mgr.c @@ -22,6 +22,7 @@ #include "cam_debug_util.h" #include "cam_trace.h" #include "cam_common_util.h" +#include "cam_presil_hw_access.h" #define CAM_MEM_SHARED_BUFFER_PAD_4K (4 * 1024) @@ -33,6 +34,19 @@ static void cam_mem_mgr_put_dma_heaps(void); static int cam_mem_mgr_get_dma_heaps(void); #endif +#ifdef CONFIG_CAM_PRESIL +static inline void cam_mem_mgr_reset_presil_params(int idx) +{ + tbl.bufq[idx].presil_params.fd_for_umd_daemon = -1; + tbl.bufq[idx].presil_params.refcount = 0; +} +#else +static inline void cam_mem_mgr_reset_presil_params(int idx) +{ + return; +} +#endif + static unsigned long cam_mem_mgr_mini_dump_cb(void *dst, unsigned long len) { struct cam_mem_table_mini_dump *md; @@ -220,6 +234,7 @@ int cam_mem_mgr_init(void) for (i = 1; i < CAM_MEM_BUFQ_MAX; i++) { tbl.bufq[i].fd = -1; tbl.bufq[i].buf_handle = -1; + cam_mem_mgr_reset_presil_params(i); } mutex_init(&tbl.m_lock); @@ -1020,6 +1035,7 @@ int cam_mem_mgr_alloc_and_map(struct cam_mem_mgr_alloc_cmd *cmd) tbl.bufq[idx].dma_buf = dmabuf; tbl.bufq[idx].len = len; tbl.bufq[idx].num_hdl = cmd->num_hdl; + cam_mem_mgr_reset_presil_params(idx); memcpy(tbl.bufq[idx].hdls, cmd->mmu_hdls, sizeof(int32_t) * cmd->num_hdl); tbl.bufq[idx].is_imported = false; @@ -1297,6 +1313,7 @@ static int cam_mem_mgr_cleanup_table(void) tbl.bufq[i].dma_buf = NULL; tbl.bufq[i].active = false; tbl.bufq[i].is_internal = false; + cam_mem_mgr_reset_presil_params(i); mutex_unlock(&tbl.bufq[i].q_lock); mutex_destroy(&tbl.bufq[i].q_lock); } @@ -1408,6 +1425,7 @@ 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; + cam_mem_mgr_reset_presil_params(idx); memset(&tbl.bufq[idx].timestamp, 0, sizeof(struct timespec64)); mutex_unlock(&tbl.bufq[idx].q_lock); mutex_destroy(&tbl.bufq[idx].q_lock); @@ -1821,8 +1839,268 @@ int cam_mem_mgr_free_memory_region(struct cam_mem_mgr_memory_desc *inp) } EXPORT_SYMBOL(cam_mem_mgr_free_memory_region); -#ifndef CONFIG_CAM_PRESIL +#ifdef CONFIG_CAM_PRESIL +struct dma_buf *cam_mem_mgr_get_dma_buf(int fd) +{ + struct dma_buf *dmabuf = NULL; + dmabuf = dma_buf_get(fd); + if (IS_ERR_OR_NULL((void *)(dmabuf))) { + CAM_ERR(CAM_MEM, "Failed to import dma_buf for fd"); + return NULL; + } + + CAM_INFO(CAM_PRESIL, "Received DMA Buf* %pK", dmabuf); + + return dmabuf; +} + +int cam_presil_put_dmabuf_from_fd(uint64_t input_dmabuf) +{ + struct dma_buf *dmabuf = (struct dma_buf *)(uint64_t)input_dmabuf; + int idx = 0; + + CAM_INFO(CAM_PRESIL, "Received dma_buf :%pK", dmabuf); + + if (!dmabuf) { + CAM_ERR(CAM_PRESIL, "NULL to import dma_buf fd"); + return -EINVAL; + } + + for (idx = 0; idx < CAM_MEM_BUFQ_MAX; idx++) { + if ((tbl.bufq[idx].dma_buf != NULL) && (tbl.bufq[idx].dma_buf == dmabuf)) { + if (tbl.bufq[idx].presil_params.refcount) + tbl.bufq[idx].presil_params.refcount--; + else + CAM_ERR(CAM_PRESIL, "Unbalanced dmabuf put: %pK", dmabuf); + + if (!tbl.bufq[idx].presil_params.refcount) { + dma_buf_put(dmabuf); + cam_mem_mgr_reset_presil_params(idx); + CAM_DBG(CAM_PRESIL, "Done dma_buf_put for %pK", dmabuf); + } + } + } + + return 0; +} +EXPORT_SYMBOL(cam_presil_put_dmabuf_from_fd); + +int cam_presil_get_fd_from_dmabuf(uint64_t input_dmabuf) +{ + int fd_for_dmabuf = -1; + struct dma_buf *dmabuf = (struct dma_buf *)(uint64_t)input_dmabuf; + int idx = 0; + + CAM_DBG(CAM_PRESIL, "Received dma_buf :%pK", dmabuf); + + if (!dmabuf) { + CAM_ERR(CAM_PRESIL, "NULL to import dma_buf fd"); + return -EINVAL; + } + + for (idx = 0; idx < CAM_MEM_BUFQ_MAX; idx++) { + if ((tbl.bufq[idx].dma_buf != NULL) && (tbl.bufq[idx].dma_buf == dmabuf)) { + CAM_DBG(CAM_PRESIL, + "Found entry for request from Presil UMD Daemon at %d, dmabuf %pK fd_for_umd_daemon %d refcount: %d", + idx, tbl.bufq[idx].dma_buf, + tbl.bufq[idx].presil_params.fd_for_umd_daemon, + tbl.bufq[idx].presil_params.refcount); + + if (tbl.bufq[idx].presil_params.fd_for_umd_daemon < 0) { + fd_for_dmabuf = dma_buf_fd(dmabuf, O_CLOEXEC); + if (fd_for_dmabuf < 0) { + CAM_ERR(CAM_PRESIL, "get fd fail, fd_for_dmabuf=%d", + fd_for_dmabuf); + return -EINVAL; + } + + tbl.bufq[idx].presil_params.fd_for_umd_daemon = fd_for_dmabuf; + CAM_INFO(CAM_PRESIL, + "Received generated idx %d fd_for_dmabuf Buf* %lld", idx, + fd_for_dmabuf); + } else { + fd_for_dmabuf = tbl.bufq[idx].presil_params.fd_for_umd_daemon; + CAM_INFO(CAM_PRESIL, + "Received existing at idx %d fd_for_dmabuf Buf* %lld", idx, + fd_for_dmabuf); + } + + tbl.bufq[idx].presil_params.refcount++; + } else { + CAM_DBG(CAM_MEM, + "Not found dmabuf at idx=%d, dma_buf %pK handle 0x%0x active %d ", + idx, tbl.bufq[idx].dma_buf, tbl.bufq[idx].buf_handle, + tbl.bufq[idx].active); + } + } + + return (int)fd_for_dmabuf; +} +EXPORT_SYMBOL(cam_presil_get_fd_from_dmabuf); + +int cam_mem_mgr_send_buffer_to_presil(int32_t iommu_hdl, int32_t buf_handle) +{ + int rc = 0; + + /* Sending Presil IO Buf to PC side ( as iova start address indicates) */ + uint64_t io_buf_addr; + size_t io_buf_size; + int i, fd = -1, idx = 0; + uint8_t *iova_ptr = NULL; + uint64_t dmabuf = 0; + bool is_mapped_in_cb = false; + + + CAM_DBG(CAM_PRESIL, "buf handle 0x%0x", buf_handle); + + idx = CAM_MEM_MGR_GET_HDL_IDX(buf_handle); + for (i = 0; i < tbl.bufq[idx].num_hdl; i++) { + if (tbl.bufq[idx].hdls[i] == iommu_hdl) + is_mapped_in_cb = true; + } + + if (!is_mapped_in_cb) + return 0; + + if ((tbl.bufq[idx].buf_handle != 0) && (tbl.bufq[idx].active) && + (tbl.bufq[idx].buf_handle == buf_handle)) { + CAM_DBG(CAM_PRESIL, + "Found dmabuf in bufq idx %d, FD %d handle 0x%0x dmabuf %pK", + idx, tbl.bufq[idx].fd, tbl.bufq[idx].buf_handle, tbl.bufq[idx].dma_buf); + dmabuf = (uint64_t)tbl.bufq[idx].dma_buf; + fd = tbl.bufq[idx].fd; + } else { + CAM_ERR(CAM_PRESIL, + "Could not find dmabuf Invalid Mem idx=%d, FD %d handle 0x%0x active %d", + idx, tbl.bufq[idx].fd, tbl.bufq[idx].buf_handle, tbl.bufq[idx].active); + return -EINVAL; + } + + rc = cam_mem_get_io_buf(buf_handle, iommu_hdl, &io_buf_addr, &io_buf_size, NULL); + if (rc || NULL == (void *)io_buf_addr) { + CAM_DBG(CAM_PRESIL, "Invalid ioaddr : 0x%x, fd = %d, dmabuf = %pK", + io_buf_addr, fd, dmabuf); + return -EINVAL; + } + + iova_ptr = (uint8_t *)io_buf_addr; + CAM_INFO(CAM_PRESIL, "Sending buffer with ioaddr : 0x%x, fd = %d, dmabuf = %pK", + io_buf_addr, fd, dmabuf); + + rc = cam_presil_send_buffer(dmabuf, 0, 0, (uint32_t)io_buf_size, (uint64_t)iova_ptr); + + return rc; +} + +int cam_mem_mgr_send_all_buffers_to_presil(int32_t iommu_hdl) +{ + int idx = 0; + int rc = 0; + int32_t fd_already_sent[128]; + int fd_already_sent_count = 0; + int fd_already_index = 0; + int fd_already_sent_found = 0; + + + memset(&fd_already_sent, 0x0, sizeof(fd_already_sent)); + + for (idx = 0; idx < CAM_MEM_BUFQ_MAX; idx++) { + if ((tbl.bufq[idx].buf_handle != 0) && (tbl.bufq[idx].active)) { + CAM_DBG(CAM_PRESIL, "Sending %d, FD %d handle 0x%0x", idx, tbl.bufq[idx].fd, + tbl.bufq[idx].buf_handle); + fd_already_sent_found = 0; + + for (fd_already_index = 0; fd_already_index < fd_already_sent_count; + fd_already_index++) { + + if (fd_already_sent[fd_already_index] == tbl.bufq[idx].fd) { + fd_already_sent_found = 1; + CAM_DBG(CAM_PRESIL, + "fd_already_sent %d, FD %d handle 0x%0x flags=0x%0x", + idx, tbl.bufq[idx].fd, tbl.bufq[idx].buf_handle, + tbl.bufq[idx].flags); + } + } + + if (fd_already_sent_found) + continue; + + CAM_DBG(CAM_PRESIL, "Sending %d, FD %d handle 0x%0x flags=0x%0x", idx, + tbl.bufq[idx].fd, tbl.bufq[idx].buf_handle, tbl.bufq[idx].flags); + + rc = cam_mem_mgr_send_buffer_to_presil(iommu_hdl, tbl.bufq[idx].buf_handle); + fd_already_sent[fd_already_sent_count++] = tbl.bufq[idx].fd; + + } else { + CAM_DBG(CAM_PRESIL, "Invalid Mem idx=%d, FD %d handle 0x%0x active %d", + idx, tbl.bufq[idx].fd, tbl.bufq[idx].buf_handle, + tbl.bufq[idx].active); + } + } + + return rc; +} +EXPORT_SYMBOL(cam_mem_mgr_send_all_buffers_to_presil); + +int cam_mem_mgr_retrieve_buffer_from_presil(int32_t buf_handle, uint32_t buf_size, + uint32_t offset, int32_t iommu_hdl) +{ + int rc = 0; + + /* Receive output buffer from Presil IO Buf to PC side (as iova start address indicates) */ + uint64_t io_buf_addr; + size_t io_buf_size; + uint64_t dmabuf = 0; + int fd = 0; + uint8_t *iova_ptr = NULL; + int idx = 0; + + + CAM_DBG(CAM_PRESIL, "buf handle 0x%0x ", buf_handle); + rc = cam_mem_get_io_buf(buf_handle, iommu_hdl, &io_buf_addr, &io_buf_size, NULL); + if (rc) { + CAM_ERR(CAM_PRESIL, "Unable to get IOVA for buffer buf_hdl: 0x%0x iommu_hdl: 0x%0x", + buf_handle, iommu_hdl); + return -EINVAL; + } + + iova_ptr = (uint8_t *)io_buf_addr; + iova_ptr += offset; // correct target address to start writing buffer to. + + if (!buf_size) { + buf_size = io_buf_size; + CAM_DBG(CAM_PRESIL, "Updated buf_size from Zero to 0x%0x", buf_size); + } + + fd = GET_FD_FROM_HANDLE(buf_handle); + + idx = CAM_MEM_MGR_GET_HDL_IDX(buf_handle); + if ((tbl.bufq[idx].buf_handle != 0) && (tbl.bufq[idx].active) && + (tbl.bufq[idx].buf_handle == buf_handle)) { + CAM_DBG(CAM_PRESIL, "Found dmabuf in bufq idx %d, FD %d handle 0x%0x dmabuf %pK", + idx, tbl.bufq[idx].fd, tbl.bufq[idx].buf_handle, tbl.bufq[idx].dma_buf); + dmabuf = (uint64_t)tbl.bufq[idx].dma_buf; + } else { + CAM_ERR(CAM_PRESIL, + "Could not find dmabuf Invalid Mem idx=%d, FD %d handle 0x%0x active %d ", + idx, tbl.bufq[idx].fd, tbl.bufq[idx].buf_handle, tbl.bufq[idx].active); + } + + CAM_DBG(CAM_PRESIL, + "Retrieving buffer with ioaddr : 0x%x, offset = %d, size = %d, fd = %d, dmabuf = %pK", + io_buf_addr, offset, buf_size, fd, dmabuf); + + rc = cam_presil_retrieve_buffer(dmabuf, 0, 0, (uint32_t)buf_size, (uint64_t)io_buf_addr); + + CAM_INFO(CAM_PRESIL, + "Retrieved buffer with ioaddr : 0x%x, offset = %d, size = %d, fd = %d, dmabuf = %pK", + io_buf_addr, 0, buf_size, fd, dmabuf); + + return rc; +} + +#else /* ifdef CONFIG_CAM_PRESIL */ struct dma_buf * cam_mem_mgr_get_dma_buf(int fd) { return NULL; @@ -1845,4 +2123,4 @@ int cam_mem_mgr_retrieve_buffer_from_presil(int32_t buf_handle, { return 0; } -#endif +#endif /* ifdef CONFIG_CAM_PRESIL */ diff --git a/drivers/cam_req_mgr/cam_mem_mgr.h b/drivers/cam_req_mgr/cam_mem_mgr.h index f53c4ca7b5..20bdf75657 100644 --- a/drivers/cam_req_mgr/cam_mem_mgr.h +++ b/drivers/cam_req_mgr/cam_mem_mgr.h @@ -26,25 +26,33 @@ enum cam_smmu_mapping_client { CAM_SMMU_MAPPING_KERNEL, }; +#ifdef CONFIG_CAM_PRESIL +struct cam_presil_dmabuf_params { + int32_t fd_for_umd_daemon; + uint32_t refcount; +}; +#endif + /** * struct cam_mem_buf_queue * - * @dma_buf: pointer to the allocated dma_buf in the table - * @q_lock: mutex lock for buffer - * @hdls: list of mapped handles - * @num_hdl: number of handles - * @fd: file descriptor of buffer - * @i_ino: inode number of this dmabuf. Uniquely identifies a buffer - * @buf_handle: unique handle for buffer - * @align: alignment for allocation - * @len: size of buffer - * @flags: attributes of buffer - * @vaddr: IOVA of buffer - * @kmdvaddr: Kernel virtual address - * @active: state of the buffer - * @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 + * @dma_buf: pointer to the allocated dma_buf in the table + * @q_lock: mutex lock for buffer + * @hdls: list of mapped handles + * @num_hdl: number of handles + * @fd: file descriptor of buffer + * @i_ino: inode number of this dmabuf. Uniquely identifies a buffer + * @buf_handle: unique handle for buffer + * @align: alignment for allocation + * @len: size of buffer + * @flags: attributes of buffer + * @vaddr: IOVA of buffer + * @kmdvaddr: Kernel virtual address + * @active: state of the buffer + * @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 + * @presil_params: Parameters specific to presil environment */ struct cam_mem_buf_queue { struct dma_buf *dma_buf; @@ -63,6 +71,10 @@ struct cam_mem_buf_queue { bool is_imported; bool is_internal; struct timespec64 timestamp; + +#ifdef CONFIG_CAM_PRESIL + struct cam_presil_dmabuf_params presil_params; +#endif }; /**