From 7e4424a1b5f6a6536066cca7aac2c3a23fd39f6f Mon Sep 17 00:00:00 2001 From: Krishnankutty Kolathappilly Date: Wed, 16 Nov 2016 15:10:18 -0800 Subject: msm: camera: Synchronize jpeg ISR and userspace call This will fix the race between jpeg dma ISR and userspace call. Without this fix jpeg dma may randomly crash due to invalid pointer access. Change-Id: I559ae08b9a46d5d3c35f8be509976a25faa967f9 CRs-Fixed: 1083323 Signed-off-by: Krishnankutty Kolathappilly --- .../platform/msm/camera_v2/jpeg_dma/msm_jpeg_dma_dev.c | 14 +++++++++++--- .../platform/msm/camera_v2/jpeg_dma/msm_jpeg_dma_dev.h | 1 + 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/drivers/media/platform/msm/camera_v2/jpeg_dma/msm_jpeg_dma_dev.c b/drivers/media/platform/msm/camera_v2/jpeg_dma/msm_jpeg_dma_dev.c index 3301fc4..4b48469 100644 --- a/drivers/media/platform/msm/camera_v2/jpeg_dma/msm_jpeg_dma_dev.c +++ b/drivers/media/platform/msm/camera_v2/jpeg_dma/msm_jpeg_dma_dev.c @@ -537,6 +537,7 @@ static int msm_jpegdma_open(struct file *file) if (!ctx) return -ENOMEM; + mutex_init(&ctx->lock); ctx->jdma_device = device; dev_dbg(ctx->jdma_device->dev, "Jpeg v4l2 dma open\n"); /* Set ctx defaults */ @@ -835,12 +836,13 @@ static int msm_jpegdma_qbuf(struct file *file, void *fh, int ret; msm_jpegdma_cast_long_to_buff_ptr(buf->m.userptr, &up_buff); - + mutex_lock(&ctx->lock); if (!access_ok(VERIFY_READ, up_buff, sizeof(struct msm_jpeg_dma_buff)) || get_user(kp_buff.fd, &up_buff->fd) || get_user(kp_buff.offset, &up_buff->offset)) { dev_err(ctx->jdma_device->dev, "Error getting user data\n"); + mutex_unlock(&ctx->lock); return -EFAULT; } @@ -849,6 +851,7 @@ static int msm_jpegdma_qbuf(struct file *file, void *fh, put_user(kp_buff.fd, &up_buff->fd) || put_user(kp_buff.offset, &up_buff->offset)) { dev_err(ctx->jdma_device->dev, "Error putting user data\n"); + mutex_unlock(&ctx->lock); return -EFAULT; } @@ -871,7 +874,7 @@ static int msm_jpegdma_qbuf(struct file *file, void *fh, ret = v4l2_m2m_qbuf(file, ctx->m2m_ctx, buf); if (ret < 0) dev_err(ctx->jdma_device->dev, "QBuf fail\n"); - + mutex_unlock(&ctx->lock); return ret; } @@ -1032,10 +1035,11 @@ static int msm_jpegdma_s_crop(struct file *file, void *fh, if (crop->c.height % formats[ctx->format_idx].v_align) return -EINVAL; + mutex_lock(&ctx->lock); ctx->crop = crop->c; if (atomic_read(&ctx->active)) ret = msm_jpegdma_update_hw_config(ctx); - + mutex_unlock(&ctx->lock); return ret; } @@ -1240,12 +1244,14 @@ void msm_jpegdma_isr_processing_done(struct msm_jpegdma_device *dma) ctx = v4l2_m2m_get_curr_priv(dma->m2m_dev); if (ctx) { + mutex_lock(&ctx->lock); ctx->plane_idx++; if (ctx->plane_idx >= formats[ctx->format_idx].num_planes) { src_buf = v4l2_m2m_src_buf_remove(ctx->m2m_ctx); dst_buf = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx); if (src_buf == NULL || dst_buf == NULL) { dev_err(ctx->jdma_device->dev, "Error, buffer list empty\n"); + mutex_unlock(&ctx->lock); mutex_unlock(&dma->lock); return; } @@ -1261,11 +1267,13 @@ void msm_jpegdma_isr_processing_done(struct msm_jpegdma_device *dma) src_buf = v4l2_m2m_next_src_buf(ctx->m2m_ctx); if (src_buf == NULL || dst_buf == NULL) { dev_err(ctx->jdma_device->dev, "Error, buffer list empty\n"); + mutex_unlock(&ctx->lock); mutex_unlock(&dma->lock); return; } msm_jpegdma_process_buffers(ctx, src_buf, dst_buf); } + mutex_unlock(&ctx->lock); } mutex_unlock(&dma->lock); } diff --git a/drivers/media/platform/msm/camera_v2/jpeg_dma/msm_jpeg_dma_dev.h b/drivers/media/platform/msm/camera_v2/jpeg_dma/msm_jpeg_dma_dev.h index 6a1205d..4911ce3 100644 --- a/drivers/media/platform/msm/camera_v2/jpeg_dma/msm_jpeg_dma_dev.h +++ b/drivers/media/platform/msm/camera_v2/jpeg_dma/msm_jpeg_dma_dev.h @@ -254,6 +254,7 @@ struct msm_jpegdma_buf_handle { * @format_idx: Current format index. */ struct jpegdma_ctx { + struct mutex lock; struct msm_jpegdma_device *jdma_device; atomic_t active; struct completion completion; -- cgit v1.1