msm: eva: Use pool allocator to allocate wncc oobs

Keep wncc working in case of kernel heap leakage. wncc buffer
requires 128kb. Driver will pre-allocate and store 8 buffers
in the pool if wncc use case starts.

Save all recently de-register wncc buffer mappings through
deregister_buffer API.

Change-Id: Iaa422bed9d3dd6f6cfe349a4931bfde28a3e3a51
Signed-off-by: George Shen <quic_sqiao@quicinc.com>
This commit is contained in:
George Shen
2023-04-20 11:13:46 -07:00
parent d4e1c81dc6
commit 1f5a03e9a6
4 changed files with 127 additions and 6 deletions

View File

@@ -41,6 +41,8 @@
inst->dma_cache.usage_bitmap); \
} while (0)
struct cvp_oob_pool wncc_buf_pool;
static void _wncc_print_cvpwnccbufs_table(struct msm_cvp_inst* inst);
static int _wncc_unmap_metadata_bufs(struct eva_kmd_hfi_packet* in_pkt,
unsigned int num_layers, unsigned int metadata_bufs_offset,
@@ -626,6 +628,15 @@ int msm_cvp_unmap_buf_wncc(struct msm_cvp_inst *inst,
mutex_unlock(&inst->cvpwnccbufs.lock);
return -EINVAL;
}
if (cbuf->smem->device_addr) {
u64 idx = inst->unused_wncc_bufs.ktid;
inst->unused_wncc_bufs.smem[idx] = *(cbuf->smem);
inst->unused_wncc_bufs.nr++;
inst->unused_wncc_bufs.nr =
(inst->unused_wncc_bufs.nr > MAX_FRAME_BUFFER_NUMS)?
MAX_FRAME_BUFFER_NUMS : inst->unused_wncc_bufs.nr;
inst->unused_wncc_bufs.ktid = ++idx % MAX_FRAME_BUFFER_NUMS;
}
mutex_unlock(&inst->cvpwnccbufs.lock);
if (cbuf->smem->device_addr) {
@@ -957,11 +968,89 @@ static int _wncc_unmap_metadata_bufs(struct eva_kmd_hfi_packet* in_pkt,
return rc;
}
static int init_wncc_bufs(void)
{
int i;
for (i = 0; i < NUM_WNCC_BUFS; i++) {
wncc_buf_pool.bufs[i] = (struct eva_kmd_oob_wncc*)kzalloc(
sizeof(struct eva_kmd_oob_wncc), GFP_KERNEL);
if (!wncc_buf_pool.bufs[i]) {
i--;
goto exit_fail;
}
}
wncc_buf_pool.used_bitmap = 0;
wncc_buf_pool.allocated = true;
return 0;
exit_fail:
while (i >= 0) {
kfree(wncc_buf_pool.bufs[i]);
i--;
}
return -ENOMEM;
}
static int alloc_wncc_buf(struct wncc_oob_buf *wob)
{
int rc, i;
mutex_lock(&wncc_buf_pool.lock);
if (!wncc_buf_pool.allocated) {
rc = init_wncc_bufs();
if (rc) {
mutex_unlock(&wncc_buf_pool.lock);
return rc;
}
}
for (i = 0; i < NUM_WNCC_BUFS; i++) {
if (!(wncc_buf_pool.used_bitmap & BIT(i))) {
wncc_buf_pool.used_bitmap |= BIT(i);
wob->bitmap_idx = i;
wob->buf = wncc_buf_pool.bufs[i];
mutex_unlock(&wncc_buf_pool.lock);
return 0;
}
}
mutex_unlock(&wncc_buf_pool.lock);
wob->bitmap_idx = 0xff;
wob->buf = (struct eva_kmd_oob_wncc*)kzalloc(
sizeof(struct eva_kmd_oob_wncc), GFP_KERNEL);
if (!wob->buf)
rc = -ENOMEM;
else
rc = 0;
return rc;
}
static void free_wncc_buf(struct wncc_oob_buf *wob)
{
if (!wob)
return;
if (wob->bitmap_idx == 0xff) {
kfree(wob->buf);
return;
}
if (wob->bitmap_idx < NUM_WNCC_BUFS) {
mutex_lock(&wncc_buf_pool.lock);
wncc_buf_pool.used_bitmap &= ~BIT(wob->bitmap_idx);
memset(wob->buf, 0, sizeof(struct eva_kmd_oob_wncc));
wob->buf = NULL;
mutex_unlock(&wncc_buf_pool.lock);
}
}
static int msm_cvp_proc_oob_wncc(struct msm_cvp_inst* inst,
struct eva_kmd_hfi_packet* in_pkt)
{
int rc = 0;
struct eva_kmd_oob_wncc* wncc_oob;
struct wncc_oob_buf wob;
struct eva_kmd_wncc_metadata* wncc_metadata[EVA_KMD_WNCC_MAX_LAYERS];
unsigned int i, j;
bool empty = false;
@@ -972,12 +1061,11 @@ static int msm_cvp_proc_oob_wncc(struct msm_cvp_inst* inst,
return -EINVAL;
}
wncc_oob = (struct eva_kmd_oob_wncc*)kzalloc(
sizeof(struct eva_kmd_oob_wncc), GFP_KERNEL);
if (!wncc_oob) {
dprintk(CVP_ERR, "%s: OOB buf allocation failed", __func__);
rc = alloc_wncc_buf(&wob);
if (rc)
return -ENOMEM;
}
wncc_oob = wob.buf;
rc = _wncc_copy_oob_from_user(in_pkt, wncc_oob);
if (rc) {
dprintk(CVP_ERR, "%s: OOB buf copying failed", __func__);
@@ -1062,7 +1150,7 @@ static int msm_cvp_proc_oob_wncc(struct msm_cvp_inst* inst,
}
exit:
kfree(wncc_oob);
free_wncc_buf(&wob);
return rc;
}
@@ -1497,6 +1585,15 @@ static void backup_frame_buffers(struct msm_cvp_inst *inst,
do {
i--;
if (frame->bufs[i].smem->bitmap_index < MAX_DMABUF_NUMS) {
/*
* Frame buffer info can be found in dma_cache table,
* Skip saving
*/
inst->last_frame.nr = 0;
return;
}
inst->last_frame.smem[i] = *(frame->bufs[i].smem);
} while (i);
}
@@ -1846,6 +1943,11 @@ void msm_cvp_print_inst_bufs(struct msm_cvp_inst *inst, bool log)
dprintk(CVP_ERR, "last frame ktid %llx\n", inst->last_frame.ktid);
for (i = 0; i < inst->last_frame.nr; i++)
_log_smem(snap, inst, &inst->last_frame.smem[i], log);
dprintk(CVP_ERR, "unmapped wncc bufs\n");
for (i = 0; i < inst->unused_wncc_bufs.nr; i++)
_log_smem(snap, inst, &inst->unused_wncc_bufs.smem[i], log);
}
struct cvp_internal_buf *cvp_allocate_arp_bufs(struct msm_cvp_inst *inst,