msm: vidc: free registered buffers when closing session

Free the registered buffers when closing instead of stopping
session to avoid NULL pointer access error if client tries to
dequeue buffer while stopping session.

Change-Id: Iecce727fe7f5afc0287e38904beb5855a6e11e02
Signed-off-by: Maheshwar Ajja <majja@codeaurora.org>
This commit is contained in:
Maheshwar Ajja 2015-07-25 23:26:10 +05:30 committed by Gerrit - the friendly Code Review server
parent c2b3e4d092
commit 0768bffc4c
3 changed files with 48 additions and 14 deletions

View File

@ -1,4 +1,4 @@
/* Copyright (c) 2012-2014, The Linux Foundation. All rights reserved.
/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@ -80,6 +80,12 @@ static int msm_v4l2_close(struct file *filp)
dprintk(VIDC_WARN,
"Failed in %s for release output buffers\n", __func__);
rc = msm_vidc_free_buffers(vidc_inst,
V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
if (rc)
dprintk(VIDC_WARN,
"%s: Failed to free output buffers\n", __func__);
rc = msm_vidc_close(vidc_inst);
trace_msm_v4l2_vidc_close_end("msm_v4l2_close end");
return rc;
@ -139,11 +145,18 @@ int msm_v4l2_reqbufs(struct file *file, void *fh,
{
struct msm_vidc_inst *vidc_inst = get_vidc_inst(file, fh);
int rc = 0;
if (b->count == 0)
if (b->count == 0) {
rc = msm_vidc_release_buffers(vidc_inst, b->type);
if (rc)
dprintk(VIDC_WARN,
"Failed in %s for release output buffers\n", __func__);
if (rc)
dprintk(VIDC_WARN,
"%s: failed to release output buffers\n",
__func__);
rc = msm_vidc_free_buffers(vidc_inst, b->type);
if (rc)
dprintk(VIDC_WARN,
"%s: failed to free output buffers\n",
__func__);
}
return msm_vidc_reqbufs((void *)vidc_inst, b);
}

View File

@ -763,7 +763,7 @@ EXPORT_SYMBOL(msm_vidc_prepare_buf);
int msm_vidc_release_buffers(void *instance, int buffer_type)
{
struct msm_vidc_inst *inst = instance;
struct buffer_info *bi, *dummy;
struct buffer_info *bi;
struct v4l2_buffer buffer_info;
struct v4l2_plane plane[VIDEO_MAX_PLANES];
int i, rc = 0;
@ -804,10 +804,12 @@ int msm_vidc_release_buffers(void *instance, int buffer_type)
plane[i].m.userptr = bi->device_addr[i];
buffer_info.m.planes = plane;
dprintk(VIDC_DBG,
"Releasing buffer: %d, %d, %d\n",
"Releasing buffer: device_addr %pa, fd %d, offset %d, size %d, buffer_type 0x%x\n",
&bi->device_addr[i],
buffer_info.m.planes[i].reserved[0],
buffer_info.m.planes[i].reserved[1],
buffer_info.m.planes[i].length);
buffer_info.m.planes[i].length,
buffer_info.type);
}
buffer_info.length = bi->num_planes;
release_buf = true;
@ -823,14 +825,31 @@ int msm_vidc_release_buffers(void *instance, int buffer_type)
&buffer_info);
if (rc)
dprintk(VIDC_ERR,
"Failed Release buffer: %d, %d, %d\n",
"Failed Release buffer: device_addr %pa, fd %d, offset %d, size %d, buffer_type 0x%x\n",
&bi->device_addr[0],
buffer_info.m.planes[0].reserved[0],
buffer_info.m.planes[0].reserved[1],
buffer_info.m.planes[0].length);
buffer_info.m.planes[0].length,
buffer_info.type);
}
mutex_unlock(&inst->registeredbufs.lock);
free_and_unmap:
return rc;
}
EXPORT_SYMBOL(msm_vidc_release_buffers);
int msm_vidc_free_buffers(void *instance, int buffer_type)
{
struct msm_vidc_inst *inst = instance;
struct buffer_info *bi, *dummy;
int i, rc = 0;
if (!inst) {
dprintk(VIDC_ERR, "%s: invalid instance\n", __func__);
return -EINVAL;
}
mutex_lock(&inst->registeredbufs.lock);
list_for_each_entry_safe(bi, dummy, &inst->registeredbufs.list, list) {
if (bi->type == buffer_type) {
@ -838,10 +857,11 @@ free_and_unmap:
for (i = 0; i < bi->num_planes; i++) {
if (bi->handle[i] && bi->mapped[i]) {
dprintk(VIDC_DBG,
"%s: [UNMAP] binfo = 0x%p, handle[%d] = %p, device_addr = 0x%pa, fd = %d, offset = %d, mapped = %d\n",
"%s: binfo = 0x%p, handle[%d] = %p, device_addr = %pa, fd = %d, offset = %d, buffer_type 0x%x, mapped = %d\n",
__func__, bi, i, bi->handle[i],
&bi->device_addr[i], bi->fd[i],
bi->buff_off[i], bi->mapped[i]);
bi->buff_off[i], bi->type,
bi->mapped[i]);
msm_comm_smem_free(inst,
bi->handle[i]);
}
@ -852,7 +872,7 @@ free_and_unmap:
mutex_unlock(&inst->registeredbufs.lock);
return rc;
}
EXPORT_SYMBOL(msm_vidc_release_buffers);
EXPORT_SYMBOL(msm_vidc_free_buffers);
int msm_vidc_encoder_cmd(void *instance, struct v4l2_encoder_cmd *enc)
{

View File

@ -1,4 +1,4 @@
/* Copyright (c) 2012-2014, The Linux Foundation. All rights reserved.
/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@ -90,6 +90,7 @@ int msm_vidc_g_ctrl(void *instance, struct v4l2_control *a);
int msm_vidc_reqbufs(void *instance, struct v4l2_requestbuffers *b);
int msm_vidc_prepare_buf(void *instance, struct v4l2_buffer *b);
int msm_vidc_release_buffers(void *instance, int buffer_type);
int msm_vidc_free_buffers(void *instance, int buffer_type);
int msm_vidc_qbuf(void *instance, struct v4l2_buffer *b);
int msm_vidc_dqbuf(void *instance, struct v4l2_buffer *b);
int msm_vidc_streamon(void *instance, enum v4l2_buf_type i);