diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.c b/drivers/media/platform/msm/vidc/msm_vidc_common.c index 6778c1734b8c..c3e6d52d2430 100644 --- a/drivers/media/platform/msm/vidc/msm_vidc_common.c +++ b/drivers/media/platform/msm/vidc/msm_vidc_common.c @@ -2322,9 +2322,13 @@ struct vb2_buffer *msm_comm_get_vb_using_vidc_buffer( return NULL; } - q = &inst->bufq[port].vb2_bufq; mutex_lock(&inst->bufq[port].lock); found = false; + q = &inst->bufq[port].vb2_bufq; + if (!q->streaming) { + dprintk(VIDC_ERR, "port %d is not streaming", port); + goto unlock; + } list_for_each_entry(vb, &q->queued_list, queued_entry) { if (vb->state != VB2_BUF_STATE_ACTIVE) continue; @@ -2333,6 +2337,7 @@ struct vb2_buffer *msm_comm_get_vb_using_vidc_buffer( break; } } +unlock: mutex_unlock(&inst->bufq[port].lock); if (!found) { print_vidc_buffer(VIDC_ERR, "vb2 not found for", inst, mbuf); @@ -2343,28 +2348,52 @@ struct vb2_buffer *msm_comm_get_vb_using_vidc_buffer( } int msm_comm_vb2_buffer_done(struct msm_vidc_inst *inst, - struct vb2_buffer *vb) + struct msm_vidc_buffer *mbuf) { - u32 port; + struct vb2_buffer *vb2; + struct vb2_v4l2_buffer *vbuf; + u32 i, port; - if (!inst || !vb) { + if (!inst || !mbuf) { dprintk(VIDC_ERR, "%s: invalid params %pK %pK\n", - __func__, inst, vb); + __func__, inst, mbuf); return -EINVAL; } - if (vb->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { + if (mbuf->vvb.vb2_buf.type == + V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) port = CAPTURE_PORT; - } else if (vb->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { + else if (mbuf->vvb.vb2_buf.type == + V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) port = OUTPUT_PORT; - } else { - dprintk(VIDC_ERR, "%s: invalid type %d\n", - __func__, vb->type); + else return -EINVAL; - } + vb2 = msm_comm_get_vb_using_vidc_buffer(inst, mbuf); + if (!vb2) + return -EINVAL; + + /* + * access vb2 buffer under q->lock and if streaming only to + * ensure the buffer was not free'd by vb2 framework while + * we are accessing it here. + */ mutex_lock(&inst->bufq[port].lock); - vb2_buffer_done(vb, VB2_BUF_STATE_DONE); + if (inst->bufq[port].vb2_bufq.streaming) { + vbuf = to_vb2_v4l2_buffer(vb2); + vbuf->flags = mbuf->vvb.flags; + vb2->timestamp = mbuf->vvb.vb2_buf.timestamp; + for (i = 0; i < mbuf->vvb.vb2_buf.num_planes; i++) { + vb2->planes[i].bytesused = + mbuf->vvb.vb2_buf.planes[i].bytesused; + vb2->planes[i].data_offset = + mbuf->vvb.vb2_buf.planes[i].data_offset; + } + vb2_buffer_done(vb2, VB2_BUF_STATE_DONE); + } else { + dprintk(VIDC_ERR, "%s: port %d is not streaming\n", + __func__, port); + } mutex_unlock(&inst->bufq[port].lock); return 0; @@ -2438,12 +2467,11 @@ static void handle_ebd(enum hal_command_response cmd, void *data) { struct msm_vidc_cb_data_done *response = data; struct msm_vidc_buffer *mbuf; - struct vb2_buffer *vb, *vb2; + struct vb2_buffer *vb; struct msm_vidc_inst *inst; struct vidc_hal_ebd *empty_buf_done; - struct vb2_v4l2_buffer *vbuf; u32 planes[VIDEO_MAX_PLANES] = {0}; - u32 extra_idx = 0, i; + u32 extra_idx = 0; if (!response) { dprintk(VIDC_ERR, "Invalid response from vidc_hal\n"); @@ -2476,15 +2504,6 @@ static void handle_ebd(enum hal_command_response cmd, void *data) __func__, planes[0], planes[1]); goto exit; } - vb2 = msm_comm_get_vb_using_vidc_buffer(inst, mbuf); - - /* - * take registeredbufs.lock to update mbuf & vb2 variables together - * so that both are in sync else if mbuf and vb2 variables are not - * in sync msm_comm_compare_vb2_planes() returns false for the - * right buffer due to data_offset field mismatch. - */ - mutex_lock(&inst->registeredbufs.lock); vb = &mbuf->vvb.vb2_buf; vb->planes[0].bytesused = response->input_done.filled_len; @@ -2510,18 +2529,6 @@ static void handle_ebd(enum hal_command_response cmd, void *data) if (extra_idx && extra_idx < VIDEO_MAX_PLANES) vb->planes[extra_idx].bytesused = vb->planes[extra_idx].length; - if (vb2) { - vbuf = to_vb2_v4l2_buffer(vb2); - vbuf->flags |= mbuf->vvb.flags; - for (i = 0; i < mbuf->vvb.vb2_buf.num_planes; i++) { - vb2->planes[i].bytesused = - mbuf->vvb.vb2_buf.planes[i].bytesused; - vb2->planes[i].data_offset = - mbuf->vvb.vb2_buf.planes[i].data_offset; - } - } - mutex_unlock(&inst->registeredbufs.lock); - update_recon_stats(inst, &empty_buf_done->recon_stats); msm_vidc_clear_freq_entry(inst, mbuf->smem[0].device_addr); /* @@ -2535,7 +2542,7 @@ static void handle_ebd(enum hal_command_response cmd, void *data) * in put_buffer. */ msm_comm_put_vidc_buffer(inst, mbuf); - msm_comm_vb2_buffer_done(inst, vb2); + msm_comm_vb2_buffer_done(inst, mbuf); msm_vidc_debugfs_update(inst, MSM_VIDC_DEBUGFS_EVENT_EBD); kref_put_mbuf(mbuf); exit: @@ -2589,13 +2596,12 @@ static void handle_fbd(enum hal_command_response cmd, void *data) struct msm_vidc_cb_data_done *response = data; struct msm_vidc_buffer *mbuf; struct msm_vidc_inst *inst; - struct vb2_buffer *vb, *vb2; + struct vb2_buffer *vb; struct vidc_hal_fbd *fill_buf_done; - struct vb2_v4l2_buffer *vbuf; enum hal_buffer buffer_type; u64 time_usec = 0; u32 planes[VIDEO_MAX_PLANES] = {0}; - u32 extra_idx, i; + u32 extra_idx; if (!response) { dprintk(VIDC_ERR, "Invalid response from vidc_hal\n"); @@ -2623,7 +2629,6 @@ static void handle_fbd(enum hal_command_response cmd, void *data) __func__, planes[0], planes[1]); goto exit; } - vb2 = msm_comm_get_vb_using_vidc_buffer(inst, mbuf); } else { if (handle_multi_stream_buffers(inst, fill_buf_done->packet_buffer1)) @@ -2632,14 +2637,6 @@ static void handle_fbd(enum hal_command_response cmd, void *data) &fill_buf_done->packet_buffer1); goto exit; } - - /* - * take registeredbufs.lock to update mbuf & vb2 variables together - * so that both are in sync else if mbuf and vb2 variables are not - * in sync msm_comm_compare_vb2_planes() returns false for the - * right buffer due to data_offset field mismatch. - */ - mutex_lock(&inst->registeredbufs.lock); vb = &mbuf->vvb.vb2_buf; if (fill_buf_done->flags1 & HAL_BUFFERFLAG_DROP_FRAME) @@ -2698,19 +2695,6 @@ static void handle_fbd(enum hal_command_response cmd, void *data) break; } - if (vb2) { - vbuf = to_vb2_v4l2_buffer(vb2); - vbuf->flags = mbuf->vvb.flags; - vb2->timestamp = mbuf->vvb.vb2_buf.timestamp; - for (i = 0; i < mbuf->vvb.vb2_buf.num_planes; i++) { - vb2->planes[i].bytesused = - mbuf->vvb.vb2_buf.planes[i].bytesused; - vb2->planes[i].data_offset = - mbuf->vvb.vb2_buf.planes[i].data_offset; - } - } - mutex_unlock(&inst->registeredbufs.lock); - /* * dma cache operations need to be performed before dma_unmap * which is done inside msm_comm_put_vidc_buffer() @@ -2722,7 +2706,7 @@ static void handle_fbd(enum hal_command_response cmd, void *data) * in put_buffer. */ msm_comm_put_vidc_buffer(inst, mbuf); - msm_comm_vb2_buffer_done(inst, vb2); + msm_comm_vb2_buffer_done(inst, mbuf); msm_vidc_debugfs_update(inst, MSM_VIDC_DEBUGFS_EVENT_FBD); kref_put_mbuf(mbuf); @@ -6100,7 +6084,6 @@ bool msm_comm_compare_vb2_plane(struct msm_vidc_inst *inst, vb = &mbuf->vvb.vb2_buf; if (vb->planes[i].m.fd == vb2->planes[i].m.fd && - vb->planes[i].data_offset == vb2->planes[i].data_offset && vb->planes[i].length == vb2->planes[i].length) { return true; } @@ -6232,6 +6215,7 @@ int msm_comm_flush_vidc_buffer(struct msm_vidc_inst *inst, { int rc; struct vb2_buffer *vb; + u32 port; if (!inst || !mbuf) { dprintk(VIDC_ERR, "%s: invalid params %pK %pK\n", @@ -6246,11 +6230,24 @@ int msm_comm_flush_vidc_buffer(struct msm_vidc_inst *inst, return -EINVAL; } - vb->planes[0].bytesused = 0; - rc = msm_comm_vb2_buffer_done(inst, vb); - if (rc) - print_vidc_buffer(VIDC_ERR, - "vb2_buffer_done failed for", inst, mbuf); + if (mbuf->vvb.vb2_buf.type == + V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) + port = CAPTURE_PORT; + else if (mbuf->vvb.vb2_buf.type == + V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) + port = OUTPUT_PORT; + else + return -EINVAL; + + mutex_lock(&inst->bufq[port].lock); + if (inst->bufq[port].vb2_bufq.streaming) { + vb->planes[0].bytesused = 0; + vb2_buffer_done(vb, VB2_BUF_STATE_DONE); + } else { + dprintk(VIDC_ERR, "%s: port %d is not streaming\n", + __func__, port); + } + mutex_unlock(&inst->bufq[port].lock); return rc; } @@ -6415,23 +6412,24 @@ struct msm_vidc_buffer *msm_comm_get_vidc_buffer(struct msm_vidc_inst *inst, } mutex_lock(&inst->registeredbufs.lock); - if (inst->session_type == MSM_VIDC_DECODER) { + /* + * for encoder input, client may queue the same buffer with different + * fd before driver returned old buffer to the client. This buffer + * should be treated as new buffer Search the list with fd so that + * it will be treated as new msm_vidc_buffer. + */ + if (is_encode_session(inst) && vb2->type == + V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { list_for_each_entry(mbuf, &inst->registeredbufs.list, list) { - if (msm_comm_compare_dma_planes(inst, mbuf, - dma_planes)) { + if (msm_comm_compare_vb2_planes(inst, mbuf, vb2)) { found = true; break; } } } else { - /* - * for encoder, client may queue the same buffer with different - * fd before driver returned old buffer to the client. This - * buffer should be treated as new buffer. Search the list with - * fd so that it will be treated as new msm_vidc_buffer. - */ list_for_each_entry(mbuf, &inst->registeredbufs.list, list) { - if (msm_comm_compare_vb2_planes(inst, mbuf, vb2)) { + if (msm_comm_compare_dma_planes(inst, mbuf, + dma_planes)) { found = true; break; } diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.h b/drivers/media/platform/msm/vidc/msm_vidc_common.h index 01791b3a5bfa..6d329ca95012 100644 --- a/drivers/media/platform/msm/vidc/msm_vidc_common.h +++ b/drivers/media/platform/msm/vidc/msm_vidc_common.h @@ -214,7 +214,7 @@ void msm_comm_put_vidc_buffer(struct msm_vidc_inst *inst, void handle_release_buffer_reference(struct msm_vidc_inst *inst, struct msm_vidc_buffer *mbuf); int msm_comm_vb2_buffer_done(struct msm_vidc_inst *inst, - struct vb2_buffer *vb); + struct msm_vidc_buffer *mbuf); int msm_comm_flush_vidc_buffer(struct msm_vidc_inst *inst, struct msm_vidc_buffer *mbuf); int msm_comm_unmap_vidc_buffer(struct msm_vidc_inst *inst,