msm: camera: icp: Optimize FW uncached region for ICP

Allocate memory based on what is configured to FW. Avoid
hardcoded allocations, thereby reducing the memory
footprint. The change also updates size check for a SMMU
mapping, if the size of the buffer is beyond the assigned
va range fail the mapping.

CRs-Fixed: 3477543
Change-Id: I3c2e262f57cdfdbd51255679b2405d855d7d5353
Signed-off-by: Karthik Anantha Ram <quic_kartanan@quicinc.com>
This commit is contained in:
Karthik Anantha Ram
2023-04-24 14:32:47 -07:00
committed by Camera Software Integration
parent d56214d30d
commit 6d25986b9f
4 changed files with 50 additions and 61 deletions

View File

@@ -39,11 +39,13 @@
#define ICP_QHDR_RX_TYPE_MASK 0x00FF0000 #define ICP_QHDR_RX_TYPE_MASK 0x00FF0000
#define ICP_QHDR_PRI_TYPE_MASK 0x0000FF00 #define ICP_QHDR_PRI_TYPE_MASK 0x0000FF00
#define ICP_QHDR_Q_ID_MASK 0x000000FF #define ICP_QHDR_Q_ID_MASK 0x000000FF
#define ICP_QTBL_SIZE_IN_BYTES sizeof(struct hfi_qtbl)
#define ICP_CMD_Q_SIZE_IN_BYTES 8192 #define ICP_CMD_Q_SIZE_IN_BYTES 8192
#define ICP_MSG_Q_SIZE_IN_BYTES 8192 #define ICP_MSG_Q_SIZE_IN_BYTES 8192
#define ICP_DBG_Q_SIZE_IN_BYTES 102400 #define ICP_DBG_Q_SIZE_IN_BYTES 102400
#define ICP_MSG_SFR_SIZE_IN_BYTES 4096 #define ICP_MSG_SFR_SIZE_IN_BYTES 4096
#define ICP_SEC_HEAP_SIZE_IN_BYTES 1048576
#define ICP_HFI_QTBL_HOSTID1 0x01000000 #define ICP_HFI_QTBL_HOSTID1 0x01000000
#define ICP_HFI_QTBL_STATUS_ENABLED 0x00000001 #define ICP_HFI_QTBL_STATUS_ENABLED 0x00000001

View File

@@ -928,7 +928,7 @@ int cam_hfi_init(int client_handle, struct hfi_mem_info *hfi_mem,
qtbl_hdr = &qtbl->q_tbl_hdr; qtbl_hdr = &qtbl->q_tbl_hdr;
qtbl_hdr->qtbl_version = 0xFFFFFFFF; qtbl_hdr->qtbl_version = 0xFFFFFFFF;
qtbl_hdr->qtbl_size = sizeof(struct hfi_qtbl); qtbl_hdr->qtbl_size = sizeof(struct hfi_qtbl);
qtbl_hdr->qtbl_qhdr0_offset = sizeof(struct hfi_qtbl_hdr); qtbl_hdr->qtbl_qhdr0_offset = offsetof(struct hfi_qtbl, q_hdr);
qtbl_hdr->qtbl_qhdr_size = sizeof(struct hfi_q_hdr); qtbl_hdr->qtbl_qhdr_size = sizeof(struct hfi_q_hdr);
qtbl_hdr->qtbl_num_q = ICP_HFI_NUMBER_OF_QS; qtbl_hdr->qtbl_num_q = ICP_HFI_NUMBER_OF_QS;
qtbl_hdr->qtbl_num_active_q = ICP_HFI_NUMBER_OF_QS; qtbl_hdr->qtbl_num_active_q = ICP_HFI_NUMBER_OF_QS;

View File

@@ -52,9 +52,6 @@
#define ICP_DEVICE_IDLE_TIMEOUT 400 #define ICP_DEVICE_IDLE_TIMEOUT 400
/* Memory required to setup all HFI queues and sec heap */
#define ICP_HFI_QUEUES_MEM_SIZE 0x700000
/* /*
* If synx fencing is enabled, send FW memory mapping * If synx fencing is enabled, send FW memory mapping
* for synx hw_mutex, ipc hw_mutex, synx global mem * for synx hw_mutex, ipc hw_mutex, synx global mem
@@ -3258,38 +3255,15 @@ static int cam_icp_alloc_secheap_mem(struct cam_icp_hw_mgr *hw_mgr,
return rc; return rc;
} }
static int cam_icp_alloc_sfr_mem(struct cam_icp_hw_mgr *hw_mgr, static int cam_icp_alloc_shared_mem(
struct cam_mem_mgr_memory_desc *sfr) struct cam_icp_hw_mgr *hw_mgr, size_t size_requested,
struct cam_mem_mgr_memory_desc *alloc_out)
{ {
int rc; int rc;
struct cam_mem_mgr_request_desc alloc; struct cam_mem_mgr_request_desc alloc;
struct cam_mem_mgr_memory_desc out; struct cam_mem_mgr_memory_desc out;
alloc.size = SZ_8K; alloc.size = size_requested;
alloc.align = 0;
alloc.flags = CAM_MEM_FLAG_HW_READ_WRITE |
CAM_MEM_FLAG_HW_SHARED_ACCESS;
alloc.smmu_hdl = hw_mgr->iommu_hdl;
rc = cam_mem_mgr_request_mem(&alloc, &out);
if (rc)
return rc;
*sfr = out;
CAM_DBG(CAM_ICP, "[%s] kva: %llX, iova: %x, hdl: %x, len: %lld",
hw_mgr->hw_mgr_name, out.kva, out.iova, out.mem_handle, out.len);
return rc;
}
static int cam_icp_alloc_shared_mem(struct cam_icp_hw_mgr *hw_mgr,
struct cam_mem_mgr_memory_desc *qtbl)
{
int rc;
struct cam_mem_mgr_request_desc alloc;
struct cam_mem_mgr_memory_desc out;
alloc.size = SZ_1M;
alloc.align = 0; alloc.align = 0;
alloc.flags = CAM_MEM_FLAG_HW_READ_WRITE | alloc.flags = CAM_MEM_FLAG_HW_READ_WRITE |
CAM_MEM_FLAG_HW_SHARED_ACCESS; CAM_MEM_FLAG_HW_SHARED_ACCESS;
@@ -3301,7 +3275,7 @@ static int cam_icp_alloc_shared_mem(struct cam_icp_hw_mgr *hw_mgr,
return rc; return rc;
} }
*qtbl = out; *alloc_out = out;
CAM_DBG(CAM_ICP, "[%s] kva: %llX, iova: %x, hdl: %x, len: %lld", CAM_DBG(CAM_ICP, "[%s] kva: %llX, iova: %x, hdl: %x, len: %lld",
hw_mgr->hw_mgr_name, hw_mgr->hw_mgr_name,
out.kva, out.iova, out.mem_handle, out.len); out.kva, out.iova, out.mem_handle, out.len);
@@ -3541,6 +3515,7 @@ static int cam_icp_allocate_hfi_mem(struct cam_icp_hw_mgr *hw_mgr)
int rc; int rc;
struct cam_smmu_region_info fwuncached_region_info = {0}; struct cam_smmu_region_info fwuncached_region_info = {0};
bool fwuncached_region_exists = false; bool fwuncached_region_exists = false;
size_t qtbl_size, cmdq_size, msgq_size, dbgq_size, sfr_size, sec_heap_size;
rc = cam_smmu_get_region_info(hw_mgr->iommu_hdl, rc = cam_smmu_get_region_info(hw_mgr->iommu_hdl,
CAM_SMMU_REGION_SHARED, &hw_mgr->hfi_mem.shmem); CAM_SMMU_REGION_SHARED, &hw_mgr->hfi_mem.shmem);
@@ -3564,6 +3539,17 @@ static int cam_icp_allocate_hfi_mem(struct cam_icp_hw_mgr *hw_mgr)
goto fw_alloc_failed; goto fw_alloc_failed;
} }
/*
* Compute sizes aligned to page size, and add a padding
* of a page between regions
*/
qtbl_size = ALIGN(ICP_QTBL_SIZE_IN_BYTES, PAGE_SIZE) + PAGE_SIZE;
cmdq_size = ALIGN(ICP_CMD_Q_SIZE_IN_BYTES, PAGE_SIZE) + PAGE_SIZE;
msgq_size = ALIGN(ICP_MSG_Q_SIZE_IN_BYTES, PAGE_SIZE) + PAGE_SIZE;
dbgq_size = ALIGN(ICP_DBG_Q_SIZE_IN_BYTES, PAGE_SIZE) + PAGE_SIZE;
sfr_size = ALIGN(ICP_MSG_SFR_SIZE_IN_BYTES, PAGE_SIZE) + PAGE_SIZE;
sec_heap_size = ALIGN(ICP_SEC_HEAP_SIZE_IN_BYTES, PAGE_SIZE) + PAGE_SIZE;
rc = cam_smmu_get_region_info(hw_mgr->iommu_hdl, rc = cam_smmu_get_region_info(hw_mgr->iommu_hdl,
CAM_SMMU_REGION_FWUNCACHED, &fwuncached_region_info); CAM_SMMU_REGION_FWUNCACHED, &fwuncached_region_info);
if (!rc) if (!rc)
@@ -3573,9 +3559,13 @@ static int cam_icp_allocate_hfi_mem(struct cam_icp_hw_mgr *hw_mgr)
struct cam_mem_mgr_request_desc alloc; struct cam_mem_mgr_request_desc alloc;
struct cam_mem_mgr_memory_desc out; struct cam_mem_mgr_memory_desc out;
uint32_t offset; uint32_t offset;
uint64_t size;
alloc.size = ICP_HFI_QUEUES_MEM_SIZE; /*
* FW uncached consists of the qtbl, HFI queues, SFR buffer
* and secondary heap
*/
alloc.size = qtbl_size + cmdq_size + msgq_size + dbgq_size +
sfr_size + sec_heap_size;
alloc.align = 0; alloc.align = 0;
alloc.flags = CAM_MEM_FLAG_KMD_ACCESS; alloc.flags = CAM_MEM_FLAG_KMD_ACCESS;
alloc.smmu_hdl = hw_mgr->iommu_hdl; alloc.smmu_hdl = hw_mgr->iommu_hdl;
@@ -3600,59 +3590,53 @@ static int cam_icp_allocate_hfi_mem(struct cam_icp_hw_mgr *hw_mgr)
offset = 0; offset = 0;
size = SZ_1M;
hw_mgr->hfi_mem.sec_heap.iova = out.iova + offset; hw_mgr->hfi_mem.sec_heap.iova = out.iova + offset;
hw_mgr->hfi_mem.sec_heap.kva = out.kva + offset; hw_mgr->hfi_mem.sec_heap.kva = out.kva + offset;
hw_mgr->hfi_mem.sec_heap.len = size; hw_mgr->hfi_mem.sec_heap.len = sec_heap_size;
hw_mgr->hfi_mem.sec_heap.smmu_hdl = out.smmu_hdl; hw_mgr->hfi_mem.sec_heap.smmu_hdl = out.smmu_hdl;
hw_mgr->hfi_mem.sec_heap.mem_handle = out.mem_handle; hw_mgr->hfi_mem.sec_heap.mem_handle = out.mem_handle;
hw_mgr->hfi_mem.sec_heap.region = out.region; hw_mgr->hfi_mem.sec_heap.region = out.region;
offset += (uint32_t)size; offset += (uint32_t)sec_heap_size;
size = SZ_1M;
hw_mgr->hfi_mem.qtbl.iova = out.iova + offset; hw_mgr->hfi_mem.qtbl.iova = out.iova + offset;
hw_mgr->hfi_mem.qtbl.kva = out.kva + offset; hw_mgr->hfi_mem.qtbl.kva = out.kva + offset;
hw_mgr->hfi_mem.qtbl.len = size; hw_mgr->hfi_mem.qtbl.len = qtbl_size;
hw_mgr->hfi_mem.qtbl.smmu_hdl = out.smmu_hdl; hw_mgr->hfi_mem.qtbl.smmu_hdl = out.smmu_hdl;
hw_mgr->hfi_mem.qtbl.mem_handle = out.mem_handle; hw_mgr->hfi_mem.qtbl.mem_handle = out.mem_handle;
hw_mgr->hfi_mem.qtbl.region = out.region; hw_mgr->hfi_mem.qtbl.region = out.region;
offset += (uint32_t)size; offset += (uint32_t)qtbl_size;
size = SZ_1M;
hw_mgr->hfi_mem.cmd_q.iova = out.iova + offset; hw_mgr->hfi_mem.cmd_q.iova = out.iova + offset;
hw_mgr->hfi_mem.cmd_q.kva = out.kva + offset; hw_mgr->hfi_mem.cmd_q.kva = out.kva + offset;
hw_mgr->hfi_mem.cmd_q.len = size; hw_mgr->hfi_mem.cmd_q.len = cmdq_size;
hw_mgr->hfi_mem.cmd_q.smmu_hdl = out.smmu_hdl; hw_mgr->hfi_mem.cmd_q.smmu_hdl = out.smmu_hdl;
hw_mgr->hfi_mem.cmd_q.mem_handle = out.mem_handle; hw_mgr->hfi_mem.cmd_q.mem_handle = out.mem_handle;
hw_mgr->hfi_mem.cmd_q.region = out.region; hw_mgr->hfi_mem.cmd_q.region = out.region;
offset += (uint32_t)size; offset += (uint32_t)cmdq_size;
size = SZ_1M;
hw_mgr->hfi_mem.msg_q.iova = out.iova + offset; hw_mgr->hfi_mem.msg_q.iova = out.iova + offset;
hw_mgr->hfi_mem.msg_q.kva = out.kva + offset; hw_mgr->hfi_mem.msg_q.kva = out.kva + offset;
hw_mgr->hfi_mem.msg_q.len = size; hw_mgr->hfi_mem.msg_q.len = msgq_size;
hw_mgr->hfi_mem.msg_q.smmu_hdl = out.smmu_hdl; hw_mgr->hfi_mem.msg_q.smmu_hdl = out.smmu_hdl;
hw_mgr->hfi_mem.msg_q.mem_handle = out.mem_handle; hw_mgr->hfi_mem.msg_q.mem_handle = out.mem_handle;
hw_mgr->hfi_mem.msg_q.region = out.region; hw_mgr->hfi_mem.msg_q.region = out.region;
offset += (uint32_t)size; offset += (uint32_t)msgq_size;
size = SZ_1M;
hw_mgr->hfi_mem.dbg_q.iova = out.iova + offset; hw_mgr->hfi_mem.dbg_q.iova = out.iova + offset;
hw_mgr->hfi_mem.dbg_q.kva = out.kva + offset; hw_mgr->hfi_mem.dbg_q.kva = out.kva + offset;
hw_mgr->hfi_mem.dbg_q.len = size; hw_mgr->hfi_mem.dbg_q.len = dbgq_size;
hw_mgr->hfi_mem.dbg_q.smmu_hdl = out.smmu_hdl; hw_mgr->hfi_mem.dbg_q.smmu_hdl = out.smmu_hdl;
hw_mgr->hfi_mem.dbg_q.mem_handle = out.mem_handle; hw_mgr->hfi_mem.dbg_q.mem_handle = out.mem_handle;
hw_mgr->hfi_mem.dbg_q.region = out.region; hw_mgr->hfi_mem.dbg_q.region = out.region;
offset += (uint32_t)size; offset += (uint32_t)dbgq_size;
size = SZ_8K;
hw_mgr->hfi_mem.sfr_buf.iova = out.iova + offset; hw_mgr->hfi_mem.sfr_buf.iova = out.iova + offset;
hw_mgr->hfi_mem.sfr_buf.kva = out.kva + offset; hw_mgr->hfi_mem.sfr_buf.kva = out.kva + offset;
hw_mgr->hfi_mem.sfr_buf.len = size; hw_mgr->hfi_mem.sfr_buf.len = sfr_size;
hw_mgr->hfi_mem.sfr_buf.smmu_hdl = out.smmu_hdl; hw_mgr->hfi_mem.sfr_buf.smmu_hdl = out.smmu_hdl;
hw_mgr->hfi_mem.sfr_buf.mem_handle = out.mem_handle; hw_mgr->hfi_mem.sfr_buf.mem_handle = out.mem_handle;
hw_mgr->hfi_mem.sfr_buf.region = out.region; hw_mgr->hfi_mem.sfr_buf.region = out.region;
offset += (uint32_t)size; offset += (uint32_t)sfr_size;
if (offset > out.len) { if (offset > out.len) {
CAM_ERR(CAM_ICP, CAM_ERR(CAM_ICP,
@@ -3662,35 +3646,35 @@ static int cam_icp_allocate_hfi_mem(struct cam_icp_hw_mgr *hw_mgr)
goto qtbl_alloc_failed; goto qtbl_alloc_failed;
} }
} else { } else {
rc = cam_icp_alloc_shared_mem(hw_mgr, &hw_mgr->hfi_mem.qtbl); rc = cam_icp_alloc_shared_mem(hw_mgr, qtbl_size, &hw_mgr->hfi_mem.qtbl);
if (rc) { if (rc) {
CAM_ERR(CAM_ICP, "[%s] Unable to allocate qtbl memory, rc %d", CAM_ERR(CAM_ICP, "[%s] Unable to allocate qtbl memory, rc %d",
hw_mgr->hw_mgr_name, rc); hw_mgr->hw_mgr_name, rc);
goto qtbl_alloc_failed; goto qtbl_alloc_failed;
} }
rc = cam_icp_alloc_shared_mem(hw_mgr, &hw_mgr->hfi_mem.cmd_q); rc = cam_icp_alloc_shared_mem(hw_mgr, cmdq_size, &hw_mgr->hfi_mem.cmd_q);
if (rc) { if (rc) {
CAM_ERR(CAM_ICP, "[%s] Unable to allocate cmd q memory rc %d", CAM_ERR(CAM_ICP, "[%s] Unable to allocate cmd q memory rc %d",
hw_mgr->hw_mgr_name, rc); hw_mgr->hw_mgr_name, rc);
goto cmd_q_alloc_failed; goto cmd_q_alloc_failed;
} }
rc = cam_icp_alloc_shared_mem(hw_mgr, &hw_mgr->hfi_mem.msg_q); rc = cam_icp_alloc_shared_mem(hw_mgr, msgq_size, &hw_mgr->hfi_mem.msg_q);
if (rc) { if (rc) {
CAM_ERR(CAM_ICP, "[%s] Unable to allocate msg q memory rc %d", CAM_ERR(CAM_ICP, "[%s] Unable to allocate msg q memory rc %d",
hw_mgr->hw_mgr_name, rc); hw_mgr->hw_mgr_name, rc);
goto msg_q_alloc_failed; goto msg_q_alloc_failed;
} }
rc = cam_icp_alloc_shared_mem(hw_mgr, &hw_mgr->hfi_mem.dbg_q); rc = cam_icp_alloc_shared_mem(hw_mgr, dbgq_size, &hw_mgr->hfi_mem.dbg_q);
if (rc) { if (rc) {
CAM_ERR(CAM_ICP, "[%s] Unable to allocate dbg q memory rc %d", CAM_ERR(CAM_ICP, "[%s] Unable to allocate dbg q memory rc %d",
hw_mgr->hw_mgr_name, rc); hw_mgr->hw_mgr_name, rc);
goto dbg_q_alloc_failed; goto dbg_q_alloc_failed;
} }
rc = cam_icp_alloc_sfr_mem(hw_mgr, &hw_mgr->hfi_mem.sfr_buf); rc = cam_icp_alloc_shared_mem(hw_mgr, sfr_size, &hw_mgr->hfi_mem.sfr_buf);
if (rc) { if (rc) {
CAM_ERR(CAM_ICP, "[%s] Unable to allocate sfr buffer rc %d", CAM_ERR(CAM_ICP, "[%s] Unable to allocate sfr buffer rc %d",
hw_mgr->hw_mgr_name, rc); hw_mgr->hw_mgr_name, rc);
@@ -3713,8 +3697,10 @@ static int cam_icp_allocate_hfi_mem(struct cam_icp_hw_mgr *hw_mgr)
fwuncached_region_info.iova_len); fwuncached_region_info.iova_len);
CAM_DBG(CAM_ICP, CAM_DBG(CAM_ICP,
"[%s] FwUncached[0x%x %p %lld] QTbl[0x%x %p %lld] CmdQ[0x%x %p %lld] MsgQ[0x%x %p %lld]", "[%s] FwUncached[0x%x %lld] FwUncached_Generic[0x%x %p %lld] QTbl[0x%x %p %lld] CmdQ[0x%x %p %lld] MsgQ[0x%x %p %lld]",
hw_mgr->hw_mgr_name, hw_mgr->hw_mgr_name,
hw_mgr->hfi_mem.fw_uncached.iova_start,
hw_mgr->hfi_mem.fw_uncached.iova_len,
hw_mgr->hfi_mem.fw_uncached_generic.iova, hw_mgr->hfi_mem.fw_uncached_generic.iova,
hw_mgr->hfi_mem.fw_uncached_generic.kva, hw_mgr->hfi_mem.fw_uncached_generic.kva,
hw_mgr->hfi_mem.fw_uncached_generic.len, hw_mgr->hfi_mem.fw_uncached_generic.len,

View File

@@ -2461,16 +2461,17 @@ int cam_smmu_reserve_buf_region(enum cam_smmu_region_id region,
buf_info->table->sgl, buf_info->table->sgl,
buf_info->table->orig_nents, buf_info->table->orig_nents,
prot); prot);
if (size != region_info->iova_len) { if (region_info->iova_len < size) {
CAM_ERR(CAM_SMMU, CAM_ERR(CAM_SMMU,
"IOMMU mapping failed size=%zu, iova_len=%zu", "IOMMU mapping failed for size=%zu available iova_len=%zu",
size, region_info->iova_len); size, region_info->iova_len);
rc = -EINVAL; rc = -EINVAL;
goto err_unmap_sg; goto err_unmap_sg;
} }
*iova = (uint32_t)region_info->iova_start; *iova = (uint32_t)region_info->iova_start;
*request_len = region_info->iova_len; /* Assign size mapped */
*request_len = size;
*is_buf_allocated = true; *is_buf_allocated = true;
mutex_unlock(&cb_info->lock); mutex_unlock(&cb_info->lock);