Loading drivers/cam_icp/fw_inc/hfi_intf.h +2 −0 Original line number Diff line number Diff line Loading @@ -32,6 +32,7 @@ struct hfi_mem { * @sec_heap: secondary heap hfi memory for firmware * @qdss: qdss mapped memory for fw * @io_mem: io memory info * @io_mem2: 2nd io memory info * @icp_base: icp base address */ struct hfi_mem_info { Loading @@ -44,6 +45,7 @@ struct hfi_mem_info { struct hfi_mem shmem; struct hfi_mem qdss; struct hfi_mem io_mem; struct hfi_mem io_mem2; void __iomem *icp_base; }; Loading drivers/cam_icp/fw_inc/hfi_reg.h +2 −0 Original line number Diff line number Diff line Loading @@ -39,6 +39,8 @@ #define HFI_REG_QDSS_IOVA_SIZE 0x70 #define HFI_REG_IO_REGION_IOVA 0x74 #define HFI_REG_IO_REGION_SIZE 0x78 #define HFI_REG_IO2_REGION_IOVA 0x7C #define HFI_REG_IO2_REGION_SIZE 0x80 /* end of ICP CSR registers */ Loading drivers/cam_icp/hfi.c +17 −0 Original line number Diff line number Diff line Loading @@ -669,6 +669,15 @@ int cam_hfi_resume(struct hfi_mem_info *hfi_mem, cam_io_w_mb((uint32_t)hfi_mem->io_mem.len, icp_base + HFI_REG_IO_REGION_SIZE); cam_io_w_mb((uint32_t)hfi_mem->io_mem2.iova, icp_base + HFI_REG_IO2_REGION_IOVA); cam_io_w_mb((uint32_t)hfi_mem->io_mem2.len, icp_base + HFI_REG_IO2_REGION_SIZE); CAM_INFO(CAM_HFI, "Resume IO1 : [0x%x 0x%x] IO2 [0x%x 0x%x]", hfi_mem->io_mem.iova, hfi_mem->io_mem.len, hfi_mem->io_mem2.iova, hfi_mem->io_mem2.len); return rc; } Loading Loading @@ -859,6 +868,14 @@ int cam_hfi_init(uint8_t event_driven_mode, struct hfi_mem_info *hfi_mem, icp_base + HFI_REG_IO_REGION_IOVA); cam_io_w_mb((uint32_t)hfi_mem->io_mem.len, icp_base + HFI_REG_IO_REGION_SIZE); cam_io_w_mb((uint32_t)hfi_mem->io_mem2.iova, icp_base + HFI_REG_IO2_REGION_IOVA); cam_io_w_mb((uint32_t)hfi_mem->io_mem2.len, icp_base + HFI_REG_IO2_REGION_SIZE); CAM_INFO(CAM_HFI, "Init IO1 : [0x%x 0x%x] IO2 [0x%x 0x%x]", hfi_mem->io_mem.iova, hfi_mem->io_mem.len, hfi_mem->io_mem2.iova, hfi_mem->io_mem2.len); hw_version = cam_io_r(icp_base + HFI_REG_A5_HW_VERSION); Loading drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c +63 −11 Original line number Diff line number Diff line Loading @@ -2794,18 +2794,21 @@ static int cam_icp_allocate_qdss_mem(void) static int cam_icp_get_io_mem_info(void) { int rc; size_t len; dma_addr_t iova; size_t len, discard_iova_len; dma_addr_t iova, discard_iova_start; rc = cam_smmu_get_io_region_info(icp_hw_mgr.iommu_hdl, &iova, &len); &iova, &len, &discard_iova_start, &discard_iova_len); if (rc) return rc; icp_hw_mgr.hfi_mem.io_mem.iova_len = len; icp_hw_mgr.hfi_mem.io_mem.iova_start = iova; icp_hw_mgr.hfi_mem.io_mem.discard_iova_start = discard_iova_start; icp_hw_mgr.hfi_mem.io_mem.discard_iova_len = discard_iova_len; CAM_DBG(CAM_ICP, "iova: %llx, len: %zu", iova, len); CAM_DBG(CAM_ICP, "iova: %llx, len: %zu discard iova %llx len %llx", iova, len, discard_iova_start, discard_iova_len); return rc; } Loading Loading @@ -3098,12 +3101,38 @@ static int cam_icp_mgr_hfi_resume(struct cam_icp_hw_mgr *hw_mgr) hfi_mem.qdss.iova = icp_hw_mgr.hfi_mem.qdss_buf.iova; hfi_mem.qdss.len = icp_hw_mgr.hfi_mem.qdss_buf.len; if (icp_hw_mgr.hfi_mem.io_mem.discard_iova_start && icp_hw_mgr.hfi_mem.io_mem.discard_iova_len) { /* IO Region 1 */ hfi_mem.io_mem.iova = icp_hw_mgr.hfi_mem.io_mem.iova_start; hfi_mem.io_mem.len = icp_hw_mgr.hfi_mem.io_mem.discard_iova_start - icp_hw_mgr.hfi_mem.io_mem.iova_start; /* IO Region 2 */ hfi_mem.io_mem2.iova = icp_hw_mgr.hfi_mem.io_mem.discard_iova_start + icp_hw_mgr.hfi_mem.io_mem.discard_iova_len; hfi_mem.io_mem2.len = icp_hw_mgr.hfi_mem.io_mem.iova_start + icp_hw_mgr.hfi_mem.io_mem.iova_len - hfi_mem.io_mem2.iova; } else { /* IO Region 1 */ hfi_mem.io_mem.iova = icp_hw_mgr.hfi_mem.io_mem.iova_start; hfi_mem.io_mem.len = icp_hw_mgr.hfi_mem.io_mem.iova_len; CAM_DBG(CAM_ICP, "IO region IOVA = %X length = %lld", /* IO Region 2 */ hfi_mem.io_mem2.iova = 0x0; hfi_mem.io_mem2.len = 0x0; } CAM_DBG(CAM_ICP, "IO region1 IOVA = %X length = %lld, IO region2 IOVA = %X length = %lld", hfi_mem.io_mem.iova, hfi_mem.io_mem.len); hfi_mem.io_mem.len, hfi_mem.io_mem2.iova, hfi_mem.io_mem2.len); return cam_hfi_resume(&hfi_mem, a5_dev->soc_info.reg_map[A5_SIERRA_BASE].mem_base, Loading Loading @@ -3572,9 +3601,32 @@ static int cam_icp_mgr_hfi_init(struct cam_icp_hw_mgr *hw_mgr) hfi_mem.qdss.iova = icp_hw_mgr.hfi_mem.qdss_buf.iova; hfi_mem.qdss.len = icp_hw_mgr.hfi_mem.qdss_buf.len; if (icp_hw_mgr.hfi_mem.io_mem.discard_iova_start && icp_hw_mgr.hfi_mem.io_mem.discard_iova_len) { /* IO Region 1 */ hfi_mem.io_mem.iova = icp_hw_mgr.hfi_mem.io_mem.iova_start; hfi_mem.io_mem.len = icp_hw_mgr.hfi_mem.io_mem.discard_iova_start - icp_hw_mgr.hfi_mem.io_mem.iova_start; /* IO Region 2 */ hfi_mem.io_mem2.iova = icp_hw_mgr.hfi_mem.io_mem.discard_iova_start + icp_hw_mgr.hfi_mem.io_mem.discard_iova_len; hfi_mem.io_mem2.len = icp_hw_mgr.hfi_mem.io_mem.iova_start + icp_hw_mgr.hfi_mem.io_mem.iova_len - hfi_mem.io_mem2.iova; } else { /* IO Region 1 */ hfi_mem.io_mem.iova = icp_hw_mgr.hfi_mem.io_mem.iova_start; hfi_mem.io_mem.len = icp_hw_mgr.hfi_mem.io_mem.iova_len; /* IO Region 2 */ hfi_mem.io_mem2.iova = 0x0; hfi_mem.io_mem2.len = 0x0; } return cam_hfi_init(0, &hfi_mem, a5_dev->soc_info.reg_map[A5_SIERRA_BASE].mem_base, hw_mgr->a5_jtag_debug); Loading drivers/cam_smmu/cam_smmu_api.c +132 −4 Original line number Diff line number Diff line Loading @@ -14,6 +14,8 @@ #include <linux/workqueue.h> #include <linux/genalloc.h> #include <linux/debugfs.h> #include <linux/dma-iommu.h> #include <soc/qcom/scm.h> #include <soc/qcom/secure_buffer.h> #include <media/cam_req_mgr.h> Loading Loading @@ -134,6 +136,10 @@ struct cam_context_bank_info { size_t io_mapping_size; size_t shared_mapping_size; /* discard iova - non-zero values are valid */ dma_addr_t discard_iova_start; size_t discard_iova_len; }; struct cam_iommu_cb_set { Loading Loading @@ -1421,11 +1427,13 @@ int cam_smmu_dealloc_qdss(int32_t smmu_hdl) EXPORT_SYMBOL(cam_smmu_dealloc_qdss); int cam_smmu_get_io_region_info(int32_t smmu_hdl, dma_addr_t *iova, size_t *len) dma_addr_t *iova, size_t *len, dma_addr_t *discard_iova_start, size_t *discard_iova_len) { int32_t idx; if (!iova || !len || (smmu_hdl == HANDLE_INIT)) { if (!iova || !len || !discard_iova_start || !discard_iova_len || (smmu_hdl == HANDLE_INIT)) { CAM_ERR(CAM_SMMU, "Error: Input args are invalid"); return -EINVAL; } Loading @@ -1447,10 +1455,15 @@ int cam_smmu_get_io_region_info(int32_t smmu_hdl, mutex_lock(&iommu_cb_set.cb_info[idx].lock); *iova = iommu_cb_set.cb_info[idx].io_info.iova_start; *len = iommu_cb_set.cb_info[idx].io_info.iova_len; *discard_iova_start = iommu_cb_set.cb_info[idx].io_info.discard_iova_start; *discard_iova_len = iommu_cb_set.cb_info[idx].io_info.discard_iova_len; CAM_DBG(CAM_SMMU, "I/O area for hdl = %x start addr = %pK len = %zu", smmu_hdl, *iova, *len); "I/O area for hdl = %x Region:[%pK %zu] Discard:[%pK %zu]", smmu_hdl, *iova, *len, *discard_iova_start, *discard_iova_len); mutex_unlock(&iommu_cb_set.cb_info[idx].lock); return 0; Loading Loading @@ -3281,6 +3294,11 @@ static int cam_smmu_setup_cb(struct cam_context_bank_info *cb, rc = -ENODEV; goto end; } if (cb->discard_iova_start) iommu_dma_reserve_iova(dev, cb->discard_iova_start, cb->discard_iova_len); cb->state = CAM_SMMU_ATTACH; } else { CAM_ERR(CAM_SMMU, "Context bank does not have IO region"); Loading Loading @@ -3347,6 +3365,52 @@ static int cam_alloc_smmu_context_banks(struct device *dev) return 0; } static int cam_smmu_get_discard_memory_regions(struct device_node *of_node, dma_addr_t *discard_iova_start, size_t *discard_iova_len) { uint32_t discard_iova[2] = { 0 }; int num_values = 0; int rc = 0; if (!discard_iova_start || !discard_iova_len) return -EINVAL; *discard_iova_start = 0; *discard_iova_len = 0; num_values = of_property_count_u32_elems(of_node, "iova-region-discard"); if (num_values <= 0) { CAM_DBG(CAM_UTIL, "No discard region specified"); return 0; } else if (num_values != 2) { CAM_ERR(CAM_UTIL, "Invalid discard region specified %d", num_values); return -EINVAL; } rc = of_property_read_u32_array(of_node, "iova-region-discard", discard_iova, num_values); if (rc) { CAM_ERR(CAM_UTIL, "Can not read discard region %d", num_values); return rc; } else if (!discard_iova[0] || !discard_iova[1]) { CAM_ERR(CAM_UTIL, "Incorrect Discard region specified [0x%x 0x%x]", discard_iova[0], discard_iova[1]); return -EINVAL; } CAM_DBG(CAM_UTIL, "Discard region [0x%x 0x%x]", discard_iova[0], discard_iova[0] + discard_iova[1]); *discard_iova_start = discard_iova[0]; *discard_iova_len = discard_iova[1]; return 0; } static int cam_smmu_get_memory_regions_info(struct device_node *of_node, struct cam_context_bank_info *cb) { Loading Loading @@ -3445,6 +3509,16 @@ static int cam_smmu_get_memory_regions_info(struct device_node *of_node, cb->io_support = 1; cb->io_info.iova_start = region_start; cb->io_info.iova_len = region_len; rc = cam_smmu_get_discard_memory_regions(child_node, &cb->io_info.discard_iova_start, &cb->io_info.discard_iova_len); if (rc) { CAM_ERR(CAM_SMMU, "Invalid Discard region specified in IO region, rc=%d", rc); of_node_put(mem_map_node); return -EINVAL; } break; case CAM_SMMU_REGION_SECHEAP: cb->secheap_support = 1; Loading @@ -3469,6 +3543,60 @@ static int cam_smmu_get_memory_regions_info(struct device_node *of_node, CAM_DBG(CAM_SMMU, "region_len -> %X", region_len); CAM_DBG(CAM_SMMU, "region_id -> %X", region_id); } if (cb->io_support) { rc = cam_smmu_get_discard_memory_regions(of_node, &cb->discard_iova_start, &cb->discard_iova_len); if (rc) { CAM_ERR(CAM_SMMU, "Invalid Discard region specified in CB, rc=%d", rc); of_node_put(mem_map_node); return -EINVAL; } /* Make sure Discard region is properly specified */ if ((cb->discard_iova_start != cb->io_info.discard_iova_start) || (cb->discard_iova_len != cb->io_info.discard_iova_len)) { CAM_ERR(CAM_SMMU, "Mismatch Discard region specified, [0x%x 0x%x] [0x%x 0x%x]", cb->discard_iova_start, cb->discard_iova_len, cb->io_info.discard_iova_start, cb->io_info.discard_iova_len); of_node_put(mem_map_node); return -EINVAL; } else if (cb->discard_iova_start && cb->discard_iova_len) { if ((cb->discard_iova_start <= cb->io_info.iova_start) || (cb->discard_iova_start >= cb->io_info.iova_start + cb->io_info.iova_len) || (cb->discard_iova_start + cb->discard_iova_len >= cb->io_info.iova_start + cb->io_info.iova_len)) { CAM_ERR(CAM_SMMU, "[%s] : Incorrect Discard region specified [0x%x 0x%x] in [0x%x 0x%x]", cb->name, cb->discard_iova_start, cb->discard_iova_start + cb->discard_iova_len, cb->io_info.iova_start, cb->io_info.iova_start + cb->io_info.iova_len); of_node_put(mem_map_node); return -EINVAL; } CAM_INFO(CAM_SMMU, "[%s] : Discard region specified [0x%x 0x%x] in [0x%x 0x%x]", cb->name, cb->discard_iova_start, cb->discard_iova_start + cb->discard_iova_len, cb->io_info.iova_start, cb->io_info.iova_start + cb->io_info.iova_len); } } of_node_put(mem_map_node); if (!num_regions) { Loading Loading
drivers/cam_icp/fw_inc/hfi_intf.h +2 −0 Original line number Diff line number Diff line Loading @@ -32,6 +32,7 @@ struct hfi_mem { * @sec_heap: secondary heap hfi memory for firmware * @qdss: qdss mapped memory for fw * @io_mem: io memory info * @io_mem2: 2nd io memory info * @icp_base: icp base address */ struct hfi_mem_info { Loading @@ -44,6 +45,7 @@ struct hfi_mem_info { struct hfi_mem shmem; struct hfi_mem qdss; struct hfi_mem io_mem; struct hfi_mem io_mem2; void __iomem *icp_base; }; Loading
drivers/cam_icp/fw_inc/hfi_reg.h +2 −0 Original line number Diff line number Diff line Loading @@ -39,6 +39,8 @@ #define HFI_REG_QDSS_IOVA_SIZE 0x70 #define HFI_REG_IO_REGION_IOVA 0x74 #define HFI_REG_IO_REGION_SIZE 0x78 #define HFI_REG_IO2_REGION_IOVA 0x7C #define HFI_REG_IO2_REGION_SIZE 0x80 /* end of ICP CSR registers */ Loading
drivers/cam_icp/hfi.c +17 −0 Original line number Diff line number Diff line Loading @@ -669,6 +669,15 @@ int cam_hfi_resume(struct hfi_mem_info *hfi_mem, cam_io_w_mb((uint32_t)hfi_mem->io_mem.len, icp_base + HFI_REG_IO_REGION_SIZE); cam_io_w_mb((uint32_t)hfi_mem->io_mem2.iova, icp_base + HFI_REG_IO2_REGION_IOVA); cam_io_w_mb((uint32_t)hfi_mem->io_mem2.len, icp_base + HFI_REG_IO2_REGION_SIZE); CAM_INFO(CAM_HFI, "Resume IO1 : [0x%x 0x%x] IO2 [0x%x 0x%x]", hfi_mem->io_mem.iova, hfi_mem->io_mem.len, hfi_mem->io_mem2.iova, hfi_mem->io_mem2.len); return rc; } Loading Loading @@ -859,6 +868,14 @@ int cam_hfi_init(uint8_t event_driven_mode, struct hfi_mem_info *hfi_mem, icp_base + HFI_REG_IO_REGION_IOVA); cam_io_w_mb((uint32_t)hfi_mem->io_mem.len, icp_base + HFI_REG_IO_REGION_SIZE); cam_io_w_mb((uint32_t)hfi_mem->io_mem2.iova, icp_base + HFI_REG_IO2_REGION_IOVA); cam_io_w_mb((uint32_t)hfi_mem->io_mem2.len, icp_base + HFI_REG_IO2_REGION_SIZE); CAM_INFO(CAM_HFI, "Init IO1 : [0x%x 0x%x] IO2 [0x%x 0x%x]", hfi_mem->io_mem.iova, hfi_mem->io_mem.len, hfi_mem->io_mem2.iova, hfi_mem->io_mem2.len); hw_version = cam_io_r(icp_base + HFI_REG_A5_HW_VERSION); Loading
drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c +63 −11 Original line number Diff line number Diff line Loading @@ -2794,18 +2794,21 @@ static int cam_icp_allocate_qdss_mem(void) static int cam_icp_get_io_mem_info(void) { int rc; size_t len; dma_addr_t iova; size_t len, discard_iova_len; dma_addr_t iova, discard_iova_start; rc = cam_smmu_get_io_region_info(icp_hw_mgr.iommu_hdl, &iova, &len); &iova, &len, &discard_iova_start, &discard_iova_len); if (rc) return rc; icp_hw_mgr.hfi_mem.io_mem.iova_len = len; icp_hw_mgr.hfi_mem.io_mem.iova_start = iova; icp_hw_mgr.hfi_mem.io_mem.discard_iova_start = discard_iova_start; icp_hw_mgr.hfi_mem.io_mem.discard_iova_len = discard_iova_len; CAM_DBG(CAM_ICP, "iova: %llx, len: %zu", iova, len); CAM_DBG(CAM_ICP, "iova: %llx, len: %zu discard iova %llx len %llx", iova, len, discard_iova_start, discard_iova_len); return rc; } Loading Loading @@ -3098,12 +3101,38 @@ static int cam_icp_mgr_hfi_resume(struct cam_icp_hw_mgr *hw_mgr) hfi_mem.qdss.iova = icp_hw_mgr.hfi_mem.qdss_buf.iova; hfi_mem.qdss.len = icp_hw_mgr.hfi_mem.qdss_buf.len; if (icp_hw_mgr.hfi_mem.io_mem.discard_iova_start && icp_hw_mgr.hfi_mem.io_mem.discard_iova_len) { /* IO Region 1 */ hfi_mem.io_mem.iova = icp_hw_mgr.hfi_mem.io_mem.iova_start; hfi_mem.io_mem.len = icp_hw_mgr.hfi_mem.io_mem.discard_iova_start - icp_hw_mgr.hfi_mem.io_mem.iova_start; /* IO Region 2 */ hfi_mem.io_mem2.iova = icp_hw_mgr.hfi_mem.io_mem.discard_iova_start + icp_hw_mgr.hfi_mem.io_mem.discard_iova_len; hfi_mem.io_mem2.len = icp_hw_mgr.hfi_mem.io_mem.iova_start + icp_hw_mgr.hfi_mem.io_mem.iova_len - hfi_mem.io_mem2.iova; } else { /* IO Region 1 */ hfi_mem.io_mem.iova = icp_hw_mgr.hfi_mem.io_mem.iova_start; hfi_mem.io_mem.len = icp_hw_mgr.hfi_mem.io_mem.iova_len; CAM_DBG(CAM_ICP, "IO region IOVA = %X length = %lld", /* IO Region 2 */ hfi_mem.io_mem2.iova = 0x0; hfi_mem.io_mem2.len = 0x0; } CAM_DBG(CAM_ICP, "IO region1 IOVA = %X length = %lld, IO region2 IOVA = %X length = %lld", hfi_mem.io_mem.iova, hfi_mem.io_mem.len); hfi_mem.io_mem.len, hfi_mem.io_mem2.iova, hfi_mem.io_mem2.len); return cam_hfi_resume(&hfi_mem, a5_dev->soc_info.reg_map[A5_SIERRA_BASE].mem_base, Loading Loading @@ -3572,9 +3601,32 @@ static int cam_icp_mgr_hfi_init(struct cam_icp_hw_mgr *hw_mgr) hfi_mem.qdss.iova = icp_hw_mgr.hfi_mem.qdss_buf.iova; hfi_mem.qdss.len = icp_hw_mgr.hfi_mem.qdss_buf.len; if (icp_hw_mgr.hfi_mem.io_mem.discard_iova_start && icp_hw_mgr.hfi_mem.io_mem.discard_iova_len) { /* IO Region 1 */ hfi_mem.io_mem.iova = icp_hw_mgr.hfi_mem.io_mem.iova_start; hfi_mem.io_mem.len = icp_hw_mgr.hfi_mem.io_mem.discard_iova_start - icp_hw_mgr.hfi_mem.io_mem.iova_start; /* IO Region 2 */ hfi_mem.io_mem2.iova = icp_hw_mgr.hfi_mem.io_mem.discard_iova_start + icp_hw_mgr.hfi_mem.io_mem.discard_iova_len; hfi_mem.io_mem2.len = icp_hw_mgr.hfi_mem.io_mem.iova_start + icp_hw_mgr.hfi_mem.io_mem.iova_len - hfi_mem.io_mem2.iova; } else { /* IO Region 1 */ hfi_mem.io_mem.iova = icp_hw_mgr.hfi_mem.io_mem.iova_start; hfi_mem.io_mem.len = icp_hw_mgr.hfi_mem.io_mem.iova_len; /* IO Region 2 */ hfi_mem.io_mem2.iova = 0x0; hfi_mem.io_mem2.len = 0x0; } return cam_hfi_init(0, &hfi_mem, a5_dev->soc_info.reg_map[A5_SIERRA_BASE].mem_base, hw_mgr->a5_jtag_debug); Loading
drivers/cam_smmu/cam_smmu_api.c +132 −4 Original line number Diff line number Diff line Loading @@ -14,6 +14,8 @@ #include <linux/workqueue.h> #include <linux/genalloc.h> #include <linux/debugfs.h> #include <linux/dma-iommu.h> #include <soc/qcom/scm.h> #include <soc/qcom/secure_buffer.h> #include <media/cam_req_mgr.h> Loading Loading @@ -134,6 +136,10 @@ struct cam_context_bank_info { size_t io_mapping_size; size_t shared_mapping_size; /* discard iova - non-zero values are valid */ dma_addr_t discard_iova_start; size_t discard_iova_len; }; struct cam_iommu_cb_set { Loading Loading @@ -1421,11 +1427,13 @@ int cam_smmu_dealloc_qdss(int32_t smmu_hdl) EXPORT_SYMBOL(cam_smmu_dealloc_qdss); int cam_smmu_get_io_region_info(int32_t smmu_hdl, dma_addr_t *iova, size_t *len) dma_addr_t *iova, size_t *len, dma_addr_t *discard_iova_start, size_t *discard_iova_len) { int32_t idx; if (!iova || !len || (smmu_hdl == HANDLE_INIT)) { if (!iova || !len || !discard_iova_start || !discard_iova_len || (smmu_hdl == HANDLE_INIT)) { CAM_ERR(CAM_SMMU, "Error: Input args are invalid"); return -EINVAL; } Loading @@ -1447,10 +1455,15 @@ int cam_smmu_get_io_region_info(int32_t smmu_hdl, mutex_lock(&iommu_cb_set.cb_info[idx].lock); *iova = iommu_cb_set.cb_info[idx].io_info.iova_start; *len = iommu_cb_set.cb_info[idx].io_info.iova_len; *discard_iova_start = iommu_cb_set.cb_info[idx].io_info.discard_iova_start; *discard_iova_len = iommu_cb_set.cb_info[idx].io_info.discard_iova_len; CAM_DBG(CAM_SMMU, "I/O area for hdl = %x start addr = %pK len = %zu", smmu_hdl, *iova, *len); "I/O area for hdl = %x Region:[%pK %zu] Discard:[%pK %zu]", smmu_hdl, *iova, *len, *discard_iova_start, *discard_iova_len); mutex_unlock(&iommu_cb_set.cb_info[idx].lock); return 0; Loading Loading @@ -3281,6 +3294,11 @@ static int cam_smmu_setup_cb(struct cam_context_bank_info *cb, rc = -ENODEV; goto end; } if (cb->discard_iova_start) iommu_dma_reserve_iova(dev, cb->discard_iova_start, cb->discard_iova_len); cb->state = CAM_SMMU_ATTACH; } else { CAM_ERR(CAM_SMMU, "Context bank does not have IO region"); Loading Loading @@ -3347,6 +3365,52 @@ static int cam_alloc_smmu_context_banks(struct device *dev) return 0; } static int cam_smmu_get_discard_memory_regions(struct device_node *of_node, dma_addr_t *discard_iova_start, size_t *discard_iova_len) { uint32_t discard_iova[2] = { 0 }; int num_values = 0; int rc = 0; if (!discard_iova_start || !discard_iova_len) return -EINVAL; *discard_iova_start = 0; *discard_iova_len = 0; num_values = of_property_count_u32_elems(of_node, "iova-region-discard"); if (num_values <= 0) { CAM_DBG(CAM_UTIL, "No discard region specified"); return 0; } else if (num_values != 2) { CAM_ERR(CAM_UTIL, "Invalid discard region specified %d", num_values); return -EINVAL; } rc = of_property_read_u32_array(of_node, "iova-region-discard", discard_iova, num_values); if (rc) { CAM_ERR(CAM_UTIL, "Can not read discard region %d", num_values); return rc; } else if (!discard_iova[0] || !discard_iova[1]) { CAM_ERR(CAM_UTIL, "Incorrect Discard region specified [0x%x 0x%x]", discard_iova[0], discard_iova[1]); return -EINVAL; } CAM_DBG(CAM_UTIL, "Discard region [0x%x 0x%x]", discard_iova[0], discard_iova[0] + discard_iova[1]); *discard_iova_start = discard_iova[0]; *discard_iova_len = discard_iova[1]; return 0; } static int cam_smmu_get_memory_regions_info(struct device_node *of_node, struct cam_context_bank_info *cb) { Loading Loading @@ -3445,6 +3509,16 @@ static int cam_smmu_get_memory_regions_info(struct device_node *of_node, cb->io_support = 1; cb->io_info.iova_start = region_start; cb->io_info.iova_len = region_len; rc = cam_smmu_get_discard_memory_regions(child_node, &cb->io_info.discard_iova_start, &cb->io_info.discard_iova_len); if (rc) { CAM_ERR(CAM_SMMU, "Invalid Discard region specified in IO region, rc=%d", rc); of_node_put(mem_map_node); return -EINVAL; } break; case CAM_SMMU_REGION_SECHEAP: cb->secheap_support = 1; Loading @@ -3469,6 +3543,60 @@ static int cam_smmu_get_memory_regions_info(struct device_node *of_node, CAM_DBG(CAM_SMMU, "region_len -> %X", region_len); CAM_DBG(CAM_SMMU, "region_id -> %X", region_id); } if (cb->io_support) { rc = cam_smmu_get_discard_memory_regions(of_node, &cb->discard_iova_start, &cb->discard_iova_len); if (rc) { CAM_ERR(CAM_SMMU, "Invalid Discard region specified in CB, rc=%d", rc); of_node_put(mem_map_node); return -EINVAL; } /* Make sure Discard region is properly specified */ if ((cb->discard_iova_start != cb->io_info.discard_iova_start) || (cb->discard_iova_len != cb->io_info.discard_iova_len)) { CAM_ERR(CAM_SMMU, "Mismatch Discard region specified, [0x%x 0x%x] [0x%x 0x%x]", cb->discard_iova_start, cb->discard_iova_len, cb->io_info.discard_iova_start, cb->io_info.discard_iova_len); of_node_put(mem_map_node); return -EINVAL; } else if (cb->discard_iova_start && cb->discard_iova_len) { if ((cb->discard_iova_start <= cb->io_info.iova_start) || (cb->discard_iova_start >= cb->io_info.iova_start + cb->io_info.iova_len) || (cb->discard_iova_start + cb->discard_iova_len >= cb->io_info.iova_start + cb->io_info.iova_len)) { CAM_ERR(CAM_SMMU, "[%s] : Incorrect Discard region specified [0x%x 0x%x] in [0x%x 0x%x]", cb->name, cb->discard_iova_start, cb->discard_iova_start + cb->discard_iova_len, cb->io_info.iova_start, cb->io_info.iova_start + cb->io_info.iova_len); of_node_put(mem_map_node); return -EINVAL; } CAM_INFO(CAM_SMMU, "[%s] : Discard region specified [0x%x 0x%x] in [0x%x 0x%x]", cb->name, cb->discard_iova_start, cb->discard_iova_start + cb->discard_iova_len, cb->io_info.iova_start, cb->io_info.iova_start + cb->io_info.iova_len); } } of_node_put(mem_map_node); if (!num_regions) { Loading