From 0768bffc4c8f9921a8aa9e58e66a35fa6f1186ef Mon Sep 17 00:00:00 2001 From: Maheshwar Ajja Date: Sat, 25 Jul 2015 23:26:10 +0530 Subject: [PATCH] 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 --- .../media/platform/msm/vidc/msm_v4l2_vidc.c | 23 +++++++++--- drivers/media/platform/msm/vidc/msm_vidc.c | 36 ++++++++++++++----- include/media/msm_vidc.h | 3 +- 3 files changed, 48 insertions(+), 14 deletions(-) diff --git a/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c b/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c index b57104354a50..faf01a1ab8fa 100644 --- a/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c +++ b/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c @@ -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); } diff --git a/drivers/media/platform/msm/vidc/msm_vidc.c b/drivers/media/platform/msm/vidc/msm_vidc.c index a999a3902ea4..9513a7db4495 100644 --- a/drivers/media/platform/msm/vidc/msm_vidc.c +++ b/drivers/media/platform/msm/vidc/msm_vidc.c @@ -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) { diff --git a/include/media/msm_vidc.h b/include/media/msm_vidc.h index fe1086878e7d..dd26797272e7 100644 --- a/include/media/msm_vidc.h +++ b/include/media/msm_vidc.h @@ -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);