driver: video: rockchip: fix the memory leak of the encoder
1.when release buffer should call vpu_iommu_clear function. 2.before call vpu_iommu_clear that we should call vpu_drm_unmap_iommu&vpu_drm_free if there is through vpu_drm_alloc to allocate buffer. Change-Id: I01e7fac88c6da40e8cb4ee2199dd38283323783b Signed-off-by: Xinhuang Li <buluess.li@rock-chips.com>
This commit is contained in:
parent
aefc44dabb
commit
8486a3deec
4 changed files with 71 additions and 61 deletions
|
|
@ -687,14 +687,17 @@ static int mpp_dev_release(struct inode *inode, struct file *filp)
|
|||
}
|
||||
wake_up(&session->wait);
|
||||
|
||||
if (mpp->ops->release)
|
||||
mpp->ops->release(session);
|
||||
mpp_srv_lock(mpp->srv);
|
||||
/* remove this filp from the asynchronusly notified filp's */
|
||||
list_del_init(&session->list_session);
|
||||
mpp_dev_session_clear(mpp, session);
|
||||
vpu_iommu_clear(mpp->iommu_info, session);
|
||||
filp->private_data = NULL;
|
||||
mpp_srv_unlock(mpp->srv);
|
||||
if (mpp->ops->release)
|
||||
mpp->ops->release(session);
|
||||
if (mpp->ops->free)
|
||||
mpp->ops->free(session);
|
||||
else
|
||||
kfree(session);
|
||||
|
||||
|
|
@ -1054,7 +1057,6 @@ static struct platform_driver mpp_dev_driver = {
|
|||
.remove = mpp_dev_remove,
|
||||
.driver = {
|
||||
.name = "mpp_dev",
|
||||
.owner = THIS_MODULE,
|
||||
#if defined(CONFIG_OF)
|
||||
.of_match_table = of_match_ptr(mpp_dev_dt_ids),
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -244,6 +244,7 @@ struct mpp_dev_ops {
|
|||
unsigned int cmd, unsigned long arg);
|
||||
struct mpp_session *(*open)(struct rockchip_mpp_dev *mpp);
|
||||
void (*release)(struct mpp_session *session);
|
||||
void (*free)(struct mpp_session *session);
|
||||
};
|
||||
|
||||
void mpp_dump_reg(void __iomem *regs, int count);
|
||||
|
|
|
|||
|
|
@ -64,8 +64,10 @@ static ktime_t h265e_now, h265e_last;
|
|||
|
||||
static
|
||||
struct mpp_session *rockchip_mpp_h265e_open(struct rockchip_mpp_dev *mpp);
|
||||
static void rockchip_mpp_h265e_free(struct mpp_session *isession);
|
||||
static void rockchip_mpp_h265e_release(struct mpp_session *isession);
|
||||
static int rockchip_mpp_h265e_load_firmware(struct rockchip_mpp_dev *mpp);
|
||||
static int rockchip_mpp_h265e_load_firmware(struct rockchip_mpp_dev *mpp,
|
||||
struct mpp_session *session);
|
||||
static int rockchip_mpp_h265e_encode_one_frame(struct rockchip_mpp_dev *mpp,
|
||||
struct h265e_ctx *ctx,
|
||||
int index);
|
||||
|
|
@ -79,6 +81,16 @@ int rockchip_mpp_h265e_register_frame_buffer(struct rockchip_mpp_dev *mpp,
|
|||
static void rockchip_mpp_h265e_enable_clk(struct rockchip_mpp_dev *mpp);
|
||||
static void rockchip_mpp_h265e_disable_clk(struct rockchip_mpp_dev *mpp);
|
||||
|
||||
static void rockchip_mpp_h265e_dma_free(struct rockchip_mpp_dev *mpp,
|
||||
struct mpp_session *session,
|
||||
int hdl)
|
||||
{
|
||||
if (hdl >= 0) {
|
||||
vpu_iommu_unmap_iommu(mpp->iommu_info, session, hdl);
|
||||
vpu_iommu_free(mpp->iommu_info, session, hdl);
|
||||
}
|
||||
}
|
||||
|
||||
static int rockchip_mpp_h265e_dma_alloc(struct rockchip_mpp_dev *mpp,
|
||||
struct mpp_session *session,
|
||||
size_t len,
|
||||
|
|
@ -108,18 +120,6 @@ FAIL:
|
|||
return -1;
|
||||
}
|
||||
|
||||
static int rockchip_mpp_h265e_global_dma_alloc(struct rockchip_mpp_dev *mpp,
|
||||
size_t len,
|
||||
size_t align,
|
||||
unsigned long *addr)
|
||||
{
|
||||
struct mpp_session *session = list_first_entry(&mpp->srv->session,
|
||||
struct mpp_session,
|
||||
list_session);
|
||||
|
||||
return rockchip_mpp_h265e_dma_alloc(mpp, session, len, align, addr);
|
||||
}
|
||||
|
||||
static void rockchip_mpp_h265e_free_frame_buffer(struct rockchip_mpp_dev *mpp,
|
||||
struct rockchip_h265e_instance *instance)
|
||||
{
|
||||
|
|
@ -130,22 +130,18 @@ static void rockchip_mpp_h265e_free_frame_buffer(struct rockchip_mpp_dev *mpp,
|
|||
|
||||
mpp_debug_enter();
|
||||
buf = &instance->mv;
|
||||
if (buf->hdl >= 0)
|
||||
vpu_iommu_free(mpp->iommu_info, session, buf->hdl);
|
||||
rockchip_mpp_h265e_dma_free(mpp, session, buf->hdl);
|
||||
buf = &instance->fbc_luma;
|
||||
if (buf->hdl >= 0)
|
||||
vpu_iommu_free(mpp->iommu_info, session, buf->hdl);
|
||||
rockchip_mpp_h265e_dma_free(mpp, session, buf->hdl);
|
||||
buf = &instance->fbc_chroma;
|
||||
if (buf->hdl >= 0)
|
||||
vpu_iommu_free(mpp->iommu_info, session, buf->hdl);
|
||||
rockchip_mpp_h265e_dma_free(mpp, session, buf->hdl);
|
||||
buf = &instance->sub_sample;
|
||||
if (buf->hdl >= 0)
|
||||
vpu_iommu_free(mpp->iommu_info, session, buf->hdl);
|
||||
rockchip_mpp_h265e_dma_free(mpp, session, buf->hdl);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(instance->frame_buffer); i++) {
|
||||
fb = &instance->frame_buffer[i];
|
||||
buf = &fb->buffer;
|
||||
if (buf->hdl >= 0)
|
||||
vpu_iommu_free(mpp->iommu_info, session, buf->hdl);
|
||||
rockchip_mpp_h265e_dma_free(mpp, session, buf->hdl);
|
||||
fb->y = 0;
|
||||
fb->cb = 0;
|
||||
fb->cr = 0;
|
||||
|
|
@ -170,8 +166,7 @@ static void rockchip_mpp_h265e_free_instance(struct rockchip_mpp_dev *mpp,
|
|||
#endif
|
||||
if (!mpp || !instance)
|
||||
return;
|
||||
if (buf->hdl >= 0)
|
||||
vpu_iommu_free(mpp->iommu_info, session, buf->hdl);
|
||||
rockchip_mpp_h265e_dma_free(mpp, session, buf->hdl);
|
||||
rockchip_mpp_h265e_free_frame_buffer(mpp, instance);
|
||||
atomic_set(&enc->instance[index].is_used, 0);
|
||||
mpp_debug_leave();
|
||||
|
|
@ -252,7 +247,8 @@ static int rockchip_mpp_h265e_write_encoder_file(struct rockchip_mpp_dev *mpp)
|
|||
}
|
||||
#endif
|
||||
|
||||
static int rockchip_mpp_h265e_load_firmware(struct rockchip_mpp_dev *mpp)
|
||||
static int rockchip_mpp_h265e_load_firmware(struct rockchip_mpp_dev *mpp,
|
||||
struct mpp_session *session)
|
||||
{
|
||||
const struct firmware *firmware;
|
||||
u32 size = 0;
|
||||
|
|
@ -260,9 +256,6 @@ static int rockchip_mpp_h265e_load_firmware(struct rockchip_mpp_dev *mpp)
|
|||
container_of(mpp,
|
||||
struct rockchip_h265e_dev,
|
||||
dev);
|
||||
struct mpp_session *session = list_first_entry(&mpp->srv->session,
|
||||
struct mpp_session,
|
||||
list_session);
|
||||
|
||||
if (request_firmware(&firmware, H265E_FIRMWARE_NAME, mpp->dev) < 0) {
|
||||
mpp_err("firmware request failed\n");
|
||||
|
|
@ -273,10 +266,11 @@ static int rockchip_mpp_h265e_load_firmware(struct rockchip_mpp_dev *mpp)
|
|||
firmware->data, firmware->size);
|
||||
size = ALIGN(firmware->size, H265E_CODE_BUFFER_SIZE);
|
||||
enc->firmware.hdl =
|
||||
rockchip_mpp_h265e_global_dma_alloc(mpp,
|
||||
size,
|
||||
MPP_ALIGN_SIZE,
|
||||
&enc->firmware.dma_addr);
|
||||
rockchip_mpp_h265e_dma_alloc(mpp,
|
||||
session,
|
||||
size,
|
||||
MPP_ALIGN_SIZE,
|
||||
&enc->firmware.dma_addr);
|
||||
if (enc->firmware.hdl < 0) {
|
||||
mpp_err("error: alloc firmware buffer error\n");
|
||||
goto FAIL;
|
||||
|
|
@ -1340,7 +1334,7 @@ int rockchip_mpp_h265e_register_frame_buffer(struct rockchip_mpp_dev *mpp,
|
|||
stride;
|
||||
mpp_write(mpp, value, H265E_COMMON_PIC_INFO);
|
||||
|
||||
memset(&instance->frame_buffer, 0, sizeof(instance->frame_buffer));
|
||||
memset(&instance->frame_buffer, -1, sizeof(instance->frame_buffer));
|
||||
/* set frame buffer address*/
|
||||
for (i = 0; i < count; i++) {
|
||||
frame_buffer = &instance->frame_buffer[i];
|
||||
|
|
@ -1766,6 +1760,7 @@ struct mpp_dev_ops h265e_ops = {
|
|||
.ioctl = rockchip_mpp_h265e_ioctl,
|
||||
.open = rockchip_mpp_h265e_open,
|
||||
.release = rockchip_mpp_h265e_release,
|
||||
.free = rockchip_mpp_h265e_free,
|
||||
};
|
||||
|
||||
static void rockchip_mpp_h265e_enable_clk(struct rockchip_mpp_dev *mpp)
|
||||
|
|
@ -1843,31 +1838,17 @@ static struct mpp_session *rockchip_mpp_h265e_open(struct rockchip_mpp_dev *mpp)
|
|||
#endif
|
||||
mpp_dev_power_on(mpp);
|
||||
|
||||
if (!atomic_read(&enc->load_firmware)) {
|
||||
ret = rockchip_mpp_h265e_load_firmware(mpp);
|
||||
if (ret)
|
||||
goto NFREE_FAIL;
|
||||
atomic_inc(&enc->load_firmware);
|
||||
enc->temp.size = H265E_TEMP_BUFFER_SIZE;
|
||||
enc->temp.hdl =
|
||||
rockchip_mpp_h265e_global_dma_alloc(mpp,
|
||||
enc->temp.size,
|
||||
MPP_ALIGN_SIZE,
|
||||
&enc->temp.dma_addr);
|
||||
if (enc->temp.hdl < 0) {
|
||||
mpp_err("error: alloc temp buffer error\n");
|
||||
goto NFREE_FAIL;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < H265E_INSTANCE_NUM; i++) {
|
||||
instance = &enc->instance[i];
|
||||
instance->session = &session->isession;
|
||||
if (!atomic_read(&instance->is_used)) {
|
||||
instance->work.size = H265E_WORK_BUFFER_SIZE;
|
||||
instance->work.hdl =
|
||||
rockchip_mpp_h265e_global_dma_alloc(mpp,
|
||||
instance->work.size,
|
||||
MPP_ALIGN_SIZE,
|
||||
&instance->work.dma_addr);
|
||||
rockchip_mpp_h265e_dma_alloc(mpp,
|
||||
instance->session,
|
||||
instance->work.size,
|
||||
MPP_ALIGN_SIZE,
|
||||
&instance->work.dma_addr);
|
||||
instance->index = i;
|
||||
atomic_set(&instance->is_used, 1);
|
||||
break;
|
||||
|
|
@ -1877,11 +1858,29 @@ static struct mpp_session *rockchip_mpp_h265e_open(struct rockchip_mpp_dev *mpp)
|
|||
mpp_err("error: the num of instance up to H265E_INSTANCE_NUM\n");
|
||||
goto NFREE_FAIL;
|
||||
}
|
||||
|
||||
if (!atomic_read(&enc->load_firmware)) {
|
||||
ret = rockchip_mpp_h265e_load_firmware(mpp, instance->session);
|
||||
if (ret)
|
||||
goto FAIL;
|
||||
atomic_inc(&enc->load_firmware);
|
||||
enc->temp.size = H265E_TEMP_BUFFER_SIZE;
|
||||
enc->temp.hdl =
|
||||
rockchip_mpp_h265e_dma_alloc(mpp,
|
||||
instance->session,
|
||||
enc->temp.size,
|
||||
MPP_ALIGN_SIZE,
|
||||
&enc->temp.dma_addr);
|
||||
if (enc->temp.hdl < 0) {
|
||||
mpp_err("error: alloc temp buffer error\n");
|
||||
goto FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
index = instance->index;
|
||||
instance->status = H265E_INSTANCE_STATUS_ERROR;
|
||||
mpp_debug(DEBUG_H265E_INFO,
|
||||
"%s = %d\n", __func__, index);
|
||||
instance->session = &session->isession;
|
||||
session->instance_index = index;
|
||||
code_base = (u32)enc->firmware.dma_addr;
|
||||
mpp_debug(DEBUG_H265E_INFO, "h265e code_base = %x\n", code_base);
|
||||
|
|
@ -1980,6 +1979,15 @@ NFREE_FAIL:
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static void rockchip_mpp_h265e_free(struct mpp_session *isession)
|
||||
{
|
||||
struct h265e_session *session =
|
||||
container_of(isession,
|
||||
struct h265e_session,
|
||||
isession);
|
||||
kfree(session);
|
||||
}
|
||||
|
||||
static void rockchip_mpp_h265e_release(struct mpp_session *isession)
|
||||
{
|
||||
struct h265e_session *session =
|
||||
|
|
@ -2006,7 +2014,6 @@ static void rockchip_mpp_h265e_release(struct mpp_session *isession)
|
|||
if (mpp_read(mpp, H265E_RET_SUCCESS) == 0)
|
||||
mpp_err("h265e close instance %d ret fail\n", index);
|
||||
rockchip_mpp_h265e_free_instance(mpp, index);
|
||||
kfree(session);
|
||||
#if H265E_POWER_SAVE
|
||||
rockchip_mpp_h265e_disable_clk(mpp);
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -636,7 +636,7 @@ static struct mpp_session *mpp_dev_rkvenc_open(struct rockchip_mpp_dev *mpp)
|
|||
return &session->isession;
|
||||
}
|
||||
|
||||
static void mpp_dev_rkvenc_release(struct mpp_session *isession)
|
||||
static void mpp_dev_rkvenc_free(struct mpp_session *isession)
|
||||
{
|
||||
struct rkvenc_session *session = to_rkvenc_session(isession);
|
||||
|
||||
|
|
@ -652,7 +652,7 @@ struct mpp_dev_ops rkvenc_ops = {
|
|||
.result = rockchip_mpp_rkvenc_result,
|
||||
.ioctl = rockchip_mpp_rkvenc_ioctl,
|
||||
.open = mpp_dev_rkvenc_open,
|
||||
.release = mpp_dev_rkvenc_release,
|
||||
.free = mpp_dev_rkvenc_free,
|
||||
};
|
||||
|
||||
static void rockchip_mpp_rkvenc_power_on(struct rockchip_mpp_dev *mpp)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue