745 lines
27 KiB
Diff
745 lines
27 KiB
Diff
From 79c89cfdef8e9f3b2cbc53dbbd29e00635bf0023 Mon Sep 17 00:00:00 2001
|
|
From: "zongren.yin" <zongren.yin@amlogic.com>
|
|
Date: Mon, 26 Oct 2026 19:54:27 +0800
|
|
Subject: [PATCH 2/4] video display: add protect for NULL pointer [1/1]
|
|
|
|
PD#SWPL-
|
|
|
|
Problem:
|
|
|
|
Solution:
|
|
|
|
Fixed conflicts:
|
|
|
|
Verify:
|
|
t
|
|
|
|
Change-Id: Id8e88ef66bec35727344edf5d25df208f457baaf
|
|
Signed-off-by: zongren.yin <zongren.yin@amlogic.com>
|
|
---
|
|
drivers/drm/meson_plane.c | 9 +-
|
|
drivers/drm/vpu-hw/meson_vpu_video_wrapper.c | 73 ++++-
|
|
.../videodisplay/videodisplay_process.c | 286 +++++++++++++++++-
|
|
3 files changed, 340 insertions(+), 28 deletions(-)
|
|
|
|
diff --git a/drivers/drm/meson_plane.c b/drivers/drm/meson_plane.c
|
|
index 99b2e068f7..3f50b73f74 100644
|
|
--- a/drivers/drm/meson_plane.c
|
|
+++ b/drivers/drm/meson_plane.c
|
|
@@ -3463,10 +3463,17 @@ void meson_video_plane_async_update(struct drm_plane *plane,
|
|
return;
|
|
|
|
mvbs = meson_vpu_block_get_new_state(&mvv->base, state);
|
|
- if (!mvbs)
|
|
+ if (!mvbs) {
|
|
+ DRM_ERROR("async_update: plane%d get video new state failed\n",
|
|
+ video_plane->plane_index);
|
|
return;
|
|
+ }
|
|
mvvs = to_video_state(mvbs);
|
|
|
|
+ DRM_DEBUG_DRIVER("async_update: plane%d fb(%px) mvvs_new(%px) dmabuf(%px,%px)\n",
|
|
+ video_plane->plane_index, new_state->fb, mvvs,
|
|
+ mvvs->slices[0].dmabuf[0], mvvs->slices[0].dmabuf[1]);
|
|
+
|
|
DRM_DEBUG_DRIVER("plane_index=%d,crtc=%px,crtc_index=%d,fb=%px,src=%dx%d,dst=%dx%d\n",
|
|
plane->index, new_state->crtc,
|
|
crtc_index, new_state->fb,
|
|
diff --git a/drivers/drm/vpu-hw/meson_vpu_video_wrapper.c b/drivers/drm/vpu-hw/meson_vpu_video_wrapper.c
|
|
index 42f2bc0ae6..e92fbd718a 100644
|
|
--- a/drivers/drm/vpu-hw/meson_vpu_video_wrapper.c
|
|
+++ b/drivers/drm/vpu-hw/meson_vpu_video_wrapper.c
|
|
@@ -191,6 +191,11 @@ void video_dummy_data_set(u64 crtc_bgcolor, bool crtc_bgcolor_flag)
|
|
set_post_blend_dummy_data(vpp_index, 1 << 24 | y << 16 | u << 8 | v, alpha);
|
|
}
|
|
|
|
+static bool meson_dmabuf_is_stale(struct dma_buf *dmabuf)
|
|
+{
|
|
+ return dmabuf && !dmabuf->file;
|
|
+}
|
|
+
|
|
static void meson_vpu_update_video_info(struct meson_vpu_video_layer_info *plane_info,
|
|
struct meson_vpu_slice_state *mvss)
|
|
{
|
|
@@ -198,6 +203,11 @@ static void meson_vpu_update_video_info(struct meson_vpu_video_layer_info *plane
|
|
mvss->dmabuf[0], mvss->dmabuf[1],
|
|
plane_info->dmabuf[0], plane_info->dmabuf[1]);
|
|
|
|
+ if (meson_dmabuf_is_stale(mvss->dmabuf[0]) || meson_dmabuf_is_stale(mvss->dmabuf[1]))
|
|
+ DRM_INFO("%s: overwrite stale mvss dmabuf(%px,%px) with plane_info(%px,%px)\n",
|
|
+ __func__, mvss->dmabuf[0], mvss->dmabuf[1],
|
|
+ plane_info->dmabuf[0], plane_info->dmabuf[1]);
|
|
+
|
|
mvss->src_x = plane_info->src_x;
|
|
mvss->src_y = plane_info->src_y;
|
|
mvss->src_w = plane_info->src_w;
|
|
@@ -218,11 +228,8 @@ static void meson_vpu_update_video_info(struct meson_vpu_video_layer_info *plane
|
|
mvss->fb_size[1] = plane_info->fb_size[1];
|
|
mvss->vf = plane_info->vf;
|
|
mvss->is_uvm = plane_info->is_uvm;
|
|
- if (mvss->dmabuf[0] != plane_info->dmabuf[0] &&
|
|
- plane_info->dmabuf[0]) {
|
|
- mvss->dmabuf[0] = plane_info->dmabuf[0];
|
|
- mvss->dmabuf[1] = plane_info->dmabuf[1];
|
|
- }
|
|
+ mvss->dmabuf[0] = plane_info->dmabuf[0];
|
|
+ mvss->dmabuf[1] = plane_info->dmabuf[1];
|
|
mvss->crtc_index = plane_info->crtc_index;
|
|
mvss->rotation = plane_info->rotation;
|
|
mvss->signal_fmt = video_signal_fmt_cov(plane_info->signal_fmt);
|
|
@@ -304,6 +311,13 @@ static void video_set_state_for_uvm(struct meson_vpu_block *vblk,
|
|
return;
|
|
}
|
|
|
|
+ if (meson_dmabuf_is_stale(mvss->dmabuf[0]) ||
|
|
+ meson_dmabuf_is_stale(mvss->dmabuf[1])) {
|
|
+ DRM_ERROR("%s: stale dmabuf(%px,%px) file released, skip uvm set_state.\n",
|
|
+ video->base.name, mvss->dmabuf[0], mvss->dmabuf[1]);
|
|
+ return;
|
|
+ }
|
|
+
|
|
memset(vf_info, 0, sizeof(*vf_info));
|
|
src_h = mvss->src_h;
|
|
byte_stride = mvss->byte_stride;
|
|
@@ -494,6 +508,13 @@ static void video_set_state_for_non_uvm(struct meson_vpu_block *vblk,
|
|
return;
|
|
}
|
|
|
|
+ if (meson_dmabuf_is_stale(mvss->dmabuf[0]) ||
|
|
+ meson_dmabuf_is_stale(mvss->dmabuf[1])) {
|
|
+ DRM_ERROR("%s: stale dmabuf(%px,%px) file released, skip non-uvm set_state.\n",
|
|
+ video->base.name, mvss->dmabuf[0], mvss->dmabuf[1]);
|
|
+ return;
|
|
+ }
|
|
+
|
|
memset(vf_info, 0, sizeof(*vf_info));
|
|
src_h = mvss->src_h;
|
|
byte_stride = mvss->byte_stride;
|
|
@@ -581,10 +602,14 @@ static void video_set_state(struct meson_vpu_block *vblk,
|
|
video_set_state_for_non_uvm(vblk, mvss, vf_info);
|
|
}
|
|
|
|
+ DRM_INFO("set_state: %s mvvs(%px) dmabuf(%px,%px) is_uvm(%d) vf(%px) num(%d)\n",
|
|
+ video->base.name, mvvs, mvss->dmabuf[0], mvss->dmabuf[1],
|
|
+ mvss->is_uvm, mvss->vf, num_frame);
|
|
+
|
|
#ifdef CONFIG_AMLOGIC_VIDEO_DISPLAY
|
|
if (video->slice_mode && mvvs->num_of_video == VIDEO_MAX_SLICE)
|
|
video_display_set_multiframe(vblk->index, info_para, num_frame, 0);
|
|
- else
|
|
+ else if (info_para[0]->dmabuf[0])
|
|
video_display_setframe(vblk->index, info_para[0], 0);
|
|
#endif
|
|
|
|
@@ -644,11 +669,19 @@ static void video_disable_work_func(struct work_struct *works)
|
|
num_frame = mvvs->num_of_video;
|
|
for (i = 0; i < num_frame; i++) {
|
|
mvss = &mvvs->slices[i];
|
|
- if (mvss->dmabuf[0]) {
|
|
+ if (mvss->dmabuf[0] && meson_dmabuf_is_stale(mvss->dmabuf[0])) {
|
|
+ DRM_ERROR("%s: stale dmabuf[0](%px) file released, skip put.\n",
|
|
+ worker->video->base.name, mvss->dmabuf[0]);
|
|
+ mvss->dmabuf[0] = NULL;
|
|
+ } else if (mvss->dmabuf[0]) {
|
|
dma_buf_put(mvss->dmabuf[0]);
|
|
mvss->dmabuf[0] = NULL;
|
|
}
|
|
- if (mvss->dmabuf[1]) {
|
|
+ if (mvss->dmabuf[1] && meson_dmabuf_is_stale(mvss->dmabuf[1])) {
|
|
+ DRM_ERROR("%s: stale dmabuf[1](%px) file released, skip put.\n",
|
|
+ worker->video->base.name, mvss->dmabuf[1]);
|
|
+ mvss->dmabuf[1] = NULL;
|
|
+ } else if (mvss->dmabuf[1]) {
|
|
dma_buf_put(mvss->dmabuf[1]);
|
|
mvss->dmabuf[1] = NULL;
|
|
}
|
|
@@ -696,10 +729,18 @@ static void video_hw_disable(struct meson_vpu_block *vblk,
|
|
num_frame = mvvs->num_of_video;
|
|
for (i = 0; i < num_frame; i++) {
|
|
mvss = &mvvs->slices[i];
|
|
- if (mvss->dmabuf[0])
|
|
+ if (mvss->dmabuf[0] && meson_dmabuf_is_stale(mvss->dmabuf[0])) {
|
|
+ DRM_ERROR("%s: stale dmabuf[0](%px) file released, skip get.\n",
|
|
+ video->base.name, mvss->dmabuf[0]);
|
|
+ } else if (mvss->dmabuf[0]) {
|
|
get_dma_buf(mvss->dmabuf[0]);
|
|
- if (mvss->dmabuf[1])
|
|
+ }
|
|
+ if (mvss->dmabuf[1] && meson_dmabuf_is_stale(mvss->dmabuf[1])) {
|
|
+ DRM_ERROR("%s: stale dmabuf[1](%px) file released, skip get.\n",
|
|
+ video->base.name, mvss->dmabuf[1]);
|
|
+ } else if (mvss->dmabuf[1]) {
|
|
get_dma_buf(mvss->dmabuf[1]);
|
|
+ }
|
|
|
|
DRM_INFO("dmabuf(%px %px), release_fence(%px),present_fence(%px),\n"
|
|
"video_name(%s),frame_cnt(%llu)\n",
|
|
@@ -730,11 +771,19 @@ static void video_hw_disable(struct meson_vpu_block *vblk,
|
|
#endif
|
|
for (i = 0; i < num_frame; i++) {
|
|
mvss = &mvvs->slices[i];
|
|
- if (mvss->dmabuf[0]) {
|
|
+ if (mvss->dmabuf[0] && meson_dmabuf_is_stale(mvss->dmabuf[0])) {
|
|
+ DRM_ERROR("%s: stale dmabuf[0](%px) file released, skip put.\n",
|
|
+ video->base.name, mvss->dmabuf[0]);
|
|
+ mvss->dmabuf[0] = NULL;
|
|
+ } else if (mvss->dmabuf[0]) {
|
|
dma_buf_put(mvss->dmabuf[0]);
|
|
mvss->dmabuf[0] = NULL;
|
|
}
|
|
- if (mvss->dmabuf[1]) {
|
|
+ if (mvss->dmabuf[1] && meson_dmabuf_is_stale(mvss->dmabuf[1])) {
|
|
+ DRM_ERROR("%s: stale dmabuf[1](%px) file released, skip put.\n",
|
|
+ video->base.name, mvss->dmabuf[1]);
|
|
+ mvss->dmabuf[1] = NULL;
|
|
+ } else if (mvss->dmabuf[1]) {
|
|
dma_buf_put(mvss->dmabuf[1]);
|
|
mvss->dmabuf[1] = NULL;
|
|
}
|
|
diff --git a/drivers/media/video_processor/videodisplay/videodisplay_process.c b/drivers/media/video_processor/videodisplay/videodisplay_process.c
|
|
index 1425bf552d..f09e87093f 100644
|
|
--- a/drivers/media/video_processor/videodisplay/videodisplay_process.c
|
|
+++ b/drivers/media/video_processor/videodisplay/videodisplay_process.c
|
|
@@ -766,6 +766,18 @@ static void detect_vf_type(struct frame_info_t *frame_info, bool *is_dec_vf_ptr,
|
|
pr_info("is_dec_vf or is_v4l_vf err.\n");
|
|
return;
|
|
}
|
|
+ if (!frame_info) {
|
|
+ pr_err("%s: frame_info is NULL.\n", __func__);
|
|
+ *is_dec_vf_ptr = false;
|
|
+ *is_v4l_vf_ptr = false;
|
|
+ return;
|
|
+ }
|
|
+ if (!frame_info->dmabuf[0]) {
|
|
+ pr_err("%s: frame_info(%px)->dmabuf[0] is NULL.\n", __func__, frame_info);
|
|
+ *is_dec_vf_ptr = false;
|
|
+ *is_v4l_vf_ptr = false;
|
|
+ return;
|
|
+ }
|
|
if (frame_info->source_type == SOURCE_HWC_CREAT_ION) {
|
|
*is_dec_vf_ptr = false;
|
|
*is_v4l_vf_ptr = false;
|
|
@@ -1146,8 +1158,13 @@ static void display_q_uninit(struct videodisplay_dev *dev)
|
|
dma_buf_put((struct dma_buf *)file_vf);
|
|
if (file_vf_ext)
|
|
dma_buf_put((struct dma_buf *)file_vf_ext);
|
|
- dma_fence_signal(vd_prepare->release_fence[0]);
|
|
- dma_fence_put(vd_prepare->release_fence[0]);
|
|
+ if (vd_prepare->release_fence[0]) {
|
|
+ dma_fence_signal(vd_prepare->release_fence[0]);
|
|
+ dma_fence_put(vd_prepare->release_fence[0]);
|
|
+ } else {
|
|
+ pr_err("%s: release_fence[0] is NULL, frame_index=%d.\n",
|
|
+ __func__, vf->frame_index);
|
|
+ }
|
|
}
|
|
|
|
dev->fput_count++;
|
|
@@ -1166,7 +1183,26 @@ static void vd_get_input_dmabufs(struct frames_info_t *frames_info)
|
|
if (frames_info->frame_count != 1)
|
|
return;
|
|
|
|
+ if (frames_info->layer_index >= MAX_COMPOSER_COUNT) {
|
|
+ pr_err("%s: layer_index(%d) overflow.\n",
|
|
+ __func__, frames_info->layer_index);
|
|
+ return;
|
|
+ }
|
|
+
|
|
frame_info = &frames_info->frame_info[frames_info->layer_index];
|
|
+ if (!frame_info->dmabuf[0]) {
|
|
+ pr_err("%s: frame_info(%px)->dmabuf[0] is NULL.\n",
|
|
+ __func__, frame_info);
|
|
+ return;
|
|
+ }
|
|
+ if (!frame_info->dmabuf[0]->file ||
|
|
+ (frame_info->dmabuf[1] && !frame_info->dmabuf[1]->file)) {
|
|
+ pr_err("%s: stale dmabuf(%px,%px) file released, skip get.\n",
|
|
+ __func__, frame_info->dmabuf[0], frame_info->dmabuf[1]);
|
|
+ frame_info->dmabuf[0] = NULL;
|
|
+ frame_info->dmabuf[1] = NULL;
|
|
+ return;
|
|
+ }
|
|
get_dma_buf(frame_info->dmabuf[0]);
|
|
if (frame_info->dmabuf[1])
|
|
get_dma_buf(frame_info->dmabuf[1]);
|
|
@@ -1179,7 +1215,23 @@ static void vd_put_input_dmabufs(struct frames_info_t *frames_info)
|
|
if (frames_info->frame_count != 1)
|
|
return;
|
|
|
|
+ if (frames_info->layer_index >= MAX_COMPOSER_COUNT) {
|
|
+ pr_err("%s: layer_index(%d) overflow.\n",
|
|
+ __func__, frames_info->layer_index);
|
|
+ return;
|
|
+ }
|
|
+
|
|
frame_info = &frames_info->frame_info[frames_info->layer_index];
|
|
+ if (!frame_info->dmabuf[0])
|
|
+ return;
|
|
+ if (!frame_info->dmabuf[0]->file ||
|
|
+ (frame_info->dmabuf[1] && !frame_info->dmabuf[1]->file)) {
|
|
+ pr_err("%s: stale dmabuf(%px,%px) file released, skip put.\n",
|
|
+ __func__, frame_info->dmabuf[0], frame_info->dmabuf[1]);
|
|
+ frame_info->dmabuf[0] = NULL;
|
|
+ frame_info->dmabuf[1] = NULL;
|
|
+ return;
|
|
+ }
|
|
dma_buf_put(frame_info->dmabuf[0]);
|
|
if (frame_info->dmabuf[1])
|
|
dma_buf_put(frame_info->dmabuf[1]);
|
|
@@ -1202,11 +1254,20 @@ static void receive_q_uninit(struct videodisplay_dev *dev)
|
|
__func__, kfifo_len(&dev->receive_q));
|
|
if (kfifo_get(&dev->receive_q, &received_frames)) {
|
|
num = received_frames->frames_info.layer_index;
|
|
+ if (num >= MAX_COMPOSER_COUNT) {
|
|
+ pr_err("%s: layer_index(%d) overflow.\n", __func__, num);
|
|
+ num = 0;
|
|
+ }
|
|
release_fence = received_frames->frames_info.frame_info[num].release_fence;
|
|
present_fence = received_frames->frames_info.frame_info[num].present_fence;
|
|
vd_put_input_dmabufs(&received_frames->frames_info);
|
|
- dma_fence_signal(release_fence);
|
|
- dma_fence_put(release_fence);
|
|
+ if (release_fence) {
|
|
+ dma_fence_signal(release_fence);
|
|
+ dma_fence_put(release_fence);
|
|
+ } else {
|
|
+ pr_err("%s: release_fence is NULL, layer_index=%d.\n",
|
|
+ __func__, num);
|
|
+ }
|
|
if (present_fence) {
|
|
dma_fence_signal(present_fence);
|
|
dma_fence_put(present_fence);
|
|
@@ -1291,8 +1352,13 @@ static void ready_q_uninit(struct videodisplay_dev *dev)
|
|
dma_buf_put((struct dma_buf *)file_vf);
|
|
if (vf->file_vf_ext)
|
|
dma_buf_put((struct dma_buf *)vf->file_vf_ext);
|
|
- dma_fence_put(vd_prepare->release_fence[0]);
|
|
- dma_fence_signal(vd_prepare->release_fence[0]);
|
|
+ if (vd_prepare->release_fence[0]) {
|
|
+ dma_fence_signal(vd_prepare->release_fence[0]);
|
|
+ dma_fence_put(vd_prepare->release_fence[0]);
|
|
+ } else {
|
|
+ pr_err("%s: release_fence[0] is NULL, frame_index=%d.\n",
|
|
+ __func__, vf->frame_index);
|
|
+ }
|
|
}
|
|
|
|
dev->fput_count++;
|
|
@@ -1689,8 +1755,9 @@ static struct vframe_s *vd_get_vf_from_buf(struct videodisplay_dev *dev, struct
|
|
vd_print(dev->index, PRINT_OTHER, "vf is from decoder.\n");
|
|
vf = dmabuf_get_vframe(buf);
|
|
if (!vf) {
|
|
- vd_print(dev->index, PRINT_ERROR, "get vframe from decoder failed.\n");
|
|
- return vf;
|
|
+ pr_err("%s: dmabuf_get_vframe return NULL, buf=%px.\n",
|
|
+ __func__, buf);
|
|
+ return NULL;
|
|
}
|
|
vd_print(dev->index, PRINT_OTHER,
|
|
"vframe_type = 0x%x, vframe_flag = 0x%x.\n",
|
|
@@ -1791,7 +1858,9 @@ static int video_wait_dma_fence(struct videodisplay_dev *dev,
|
|
timestamp = local_clock();
|
|
ret = dma_fence_wait_timeout(fence_file, false, msecs_to_jiffies(3000));
|
|
if (ret == 0) {
|
|
- vd_print(dev->index, PRINT_ERROR, "fence wait timeout\n");
|
|
+ vd_print(dev->index, PRINT_ERROR,
|
|
+ "%s: fence(%px) wait timeout.\n", __func__, fence_file);
|
|
+ dma_fence_put(fence_file);
|
|
return 0;
|
|
}
|
|
|
|
@@ -1882,7 +1951,8 @@ static void vframe_do_mosaic_22(struct videodisplay_dev *dev,
|
|
u32 pic_w, pic_h;
|
|
|
|
if (IS_ERR_OR_NULL(dev) || IS_ERR_OR_NULL(received_frames)) {
|
|
- vd_print(dev->index, PRINT_ERROR, "%s: invalid param.\n", __func__);
|
|
+ pr_err("%s: invalid param, dev=%px, received_frames=%px.\n",
|
|
+ __func__, dev, received_frames);
|
|
return;
|
|
}
|
|
|
|
@@ -1904,6 +1974,7 @@ static void vframe_do_mosaic_22(struct videodisplay_dev *dev,
|
|
vc_private = vd_private_q_pop(dev);
|
|
if (!vc_private) {
|
|
vd_print(dev->index, PRINT_ERROR, "%s: get vc_private failed.\n", __func__);
|
|
+ vd_prepare_data_q_put(dev, vd_prepare);
|
|
return;
|
|
}
|
|
|
|
@@ -1916,6 +1987,11 @@ static void vframe_do_mosaic_22(struct videodisplay_dev *dev,
|
|
if (video_wait_dma_fence(dev, frame_info->input_fence) == 0)
|
|
continue;
|
|
}
|
|
+ if (!frame_info->dmabuf[0]) {
|
|
+ pr_err("%s: mosaic frame_info[%d]->dmabuf[0] is NULL.\n",
|
|
+ __func__, i);
|
|
+ continue;
|
|
+ }
|
|
|
|
get_dma_buf(frame_info->dmabuf[0]);
|
|
if (frame_info->dmabuf[1])
|
|
@@ -2067,6 +2143,11 @@ static void empty_ready_queue(struct videodisplay_dev *dev)
|
|
repeat_count, frame_index);
|
|
video_timeline_increase(dev, repeat_count + 1);
|
|
if (!is_composer) {
|
|
+ if (!file_vf) {
|
|
+ pr_err("%s: vf(%px) file_vf is NULL, frame_index=%d.\n",
|
|
+ __func__, vf, frame_index);
|
|
+ continue;
|
|
+ }
|
|
for (i = 0; i <= repeat_count; i++) {
|
|
fput(file_vf);
|
|
total_put_count++;
|
|
@@ -2817,6 +2898,8 @@ static inline int vd_perform_pulldown(struct videodisplay_dev *dev, struct vfram
|
|
/* Dont do anything if we have invalid data */
|
|
if (!vf || !vf->vc_private)
|
|
return -1;
|
|
+ if (vf->vc_private->vsync_index == 0)
|
|
+ return -1;
|
|
|
|
if (vf->vf_vrr_param.qms_plus_en || vf->vf_vrr_param.qms_en)
|
|
return -1;
|
|
@@ -2901,6 +2984,11 @@ static inline int vd_perform_pulldown(struct videodisplay_dev *dev, struct vfram
|
|
"patten_undetected: already hold:%d, need expire\n",
|
|
dev->cur_hold_count);
|
|
*expired = true;
|
|
+ } else if (!vf->vc_private) {
|
|
+ vd_print(dev->index, PRINT_ERROR,
|
|
+ "patten_undetected: vf(%px) vc_private is NULL.\n",
|
|
+ vf);
|
|
+ *expired = true;
|
|
} else {
|
|
expected_disp_vsync =
|
|
vf->vc_private->vsync_index - dev->last_vsync_index;
|
|
@@ -2928,6 +3016,11 @@ static inline int vd_perform_pulldown(struct videodisplay_dev *dev, struct vfram
|
|
"patten_undetected: already hold:%d, need expire\n",
|
|
dev->cur_hold_count);
|
|
*expired = true;
|
|
+ } else if (!vf->vc_private) {
|
|
+ vd_print(dev->index, PRINT_ERROR,
|
|
+ "patten_undetected: vf(%px) vc_private is NULL.\n",
|
|
+ vf);
|
|
+ *expired = true;
|
|
} else {
|
|
expected_disp_vsync =
|
|
vf->vc_private->vsync_index - dev->last_vsync_index;
|
|
@@ -2949,6 +3042,13 @@ static inline int vd_perform_pulldown(struct videodisplay_dev *dev, struct vfram
|
|
|
|
expected_disp_vsync = vf->vc_private->vsync_index - dev->last_vsync_index;
|
|
if (dev->is_tunnel_mode) {
|
|
+ if (!vf->vc_private) {
|
|
+ vd_print(dev->index, PRINT_ERROR,
|
|
+ "%s: tunnel mode vf(%px) vc_private is NULL.\n",
|
|
+ __func__, vf);
|
|
+ return -1;
|
|
+ }
|
|
+ expected_disp_vsync = vf->vc_private->vsync_index - dev->last_vsync_index;
|
|
vd_print(dev->index, PRINT_PATTERN,
|
|
"tunnel mode patten:%d: expected_disp_vsync:%d, patten_trace:%d\n",
|
|
dev->pattern_detected, expected_disp_vsync, patten_trace[dev->index]);
|
|
@@ -3261,6 +3361,11 @@ static int videodisplay_drop_frame(struct videodisplay_dev *dev,
|
|
struct timeval cur_time;
|
|
unsigned long time = 0;
|
|
|
|
+ if (!vf || !dmabuf) {
|
|
+ pr_err("%s: invalid param, vf=%px, dmabuf=%px.\n", __func__, vf, dmabuf);
|
|
+ return false;
|
|
+ }
|
|
+
|
|
if (vd_drop_org_i == 0)
|
|
return false;
|
|
|
|
@@ -3835,27 +3940,67 @@ static void vframe_display(struct videodisplay_dev *dev,
|
|
|
|
frames_info = &received_frames->frames_info;
|
|
num = frames_info->layer_index;
|
|
+ if (num >= MAX_COMPOSER_COUNT) {
|
|
+ pr_err("%s: received_frames(%px) layer_index(%d) overflow.\n",
|
|
+ __func__, received_frames, num);
|
|
+ return;
|
|
+ }
|
|
frame_info = &frames_info->frame_info[num];
|
|
time_us64 = received_frames->time_us64;
|
|
|
|
+ if (!frame_info->dmabuf[0]) {
|
|
+ pr_err("%s: frame_info(%px)->dmabuf[0] is NULL, frame_index=%d.\n",
|
|
+ __func__, frame_info, num);
|
|
+ if (frame_info->release_fence) {
|
|
+ dma_fence_signal(frame_info->release_fence);
|
|
+ dma_fence_put(frame_info->release_fence);
|
|
+ }
|
|
+ atomic_set(&received_frames->on_use, false);
|
|
+ return;
|
|
+ }
|
|
+
|
|
#ifdef CONFIG_AMLOGIC_MEDIA_DEINTERLACE
|
|
enable_prelink = dim_get_pre_link();
|
|
#endif
|
|
|
|
detect_vf_type(frame_info, &is_dec_vf, &is_v4l_vf);
|
|
+ get_dma_buf(frame_info->dmabuf[0]);
|
|
+ if (frame_info->dmabuf[1])
|
|
+ get_dma_buf(frame_info->dmabuf[1]);
|
|
|
|
if (dev->last_file == (struct file *)frame_info->dmabuf[0])
|
|
is_repeat_vf = true;
|
|
|
|
if (is_repeat_vf) {
|
|
vd_prepare = dev->vd_prepare_last;
|
|
+ if (!vd_prepare) {
|
|
+ pr_err("%s: dev(%px) vd_prepare_last is NULL for repeat frame, dmabuf=%px.\n",
|
|
+ __func__, dev, frame_info->dmabuf[0]);
|
|
+ dma_buf_put(frame_info->dmabuf[0]);
|
|
+ if (frame_info->dmabuf[1])
|
|
+ dma_buf_put(frame_info->dmabuf[1]);
|
|
+ if (frame_info->release_fence) {
|
|
+ dma_fence_signal(frame_info->release_fence);
|
|
+ dma_fence_put(frame_info->release_fence);
|
|
+ }
|
|
+ atomic_set(&received_frames->on_use, false);
|
|
+ dev->last_file = NULL;
|
|
+ return;
|
|
+ }
|
|
} else {
|
|
vd_prepare = vd_prepare_data_q_get(dev);
|
|
if (!vd_prepare) {
|
|
- vd_print(dev->index, PRINT_ERROR, "get prepare_data failed.\n");
|
|
+ pr_err("%s: dev(%px) vd_prepare_data_q_get return NULL, dmabuf=%px.\n",
|
|
+ __func__, dev, frame_info->dmabuf[0]);
|
|
dma_buf_put(frame_info->dmabuf[0]);
|
|
if (frame_info->dmabuf[1])
|
|
dma_buf_put(frame_info->dmabuf[1]);
|
|
+ if (frame_info->release_fence) {
|
|
+ dma_fence_signal(frame_info->release_fence);
|
|
+ dma_fence_put(frame_info->release_fence);
|
|
+ }
|
|
+ atomic_set(&received_frames->on_use, false);
|
|
+ dev->last_file = NULL;
|
|
return;
|
|
}
|
|
|
|
@@ -3866,6 +4011,13 @@ static void vframe_display(struct videodisplay_dev *dev,
|
|
dma_buf_put(frame_info->dmabuf[0]);
|
|
if (frame_info->dmabuf[1])
|
|
dma_buf_put(frame_info->dmabuf[1]);
|
|
+ if (frame_info->release_fence) {
|
|
+ dma_fence_signal(frame_info->release_fence);
|
|
+ dma_fence_put(frame_info->release_fence);
|
|
+ }
|
|
+ atomic_set(&received_frames->on_use, false);
|
|
+ vd_prepare_data_q_put(dev, vd_prepare);
|
|
+ dev->last_file = NULL;
|
|
return;
|
|
}
|
|
|
|
@@ -4156,7 +4308,18 @@ static void vframe_display(struct videodisplay_dev *dev,
|
|
dev->last_file = (struct file *)frame_info->dmabuf[0];
|
|
vf->vc_private = vd_private_q_pop(dev);
|
|
if (!vf->vc_private) {
|
|
- vd_print(dev->index, PRINT_ERROR, "vc_private is NULL.\n");
|
|
+ pr_err("%s: dev(%px) vd_private_q_pop return NULL, vf=%px, frame_index=%d.\n",
|
|
+ __func__, dev, vf, vf->frame_index);
|
|
+ dma_buf_put(frame_info->dmabuf[0]);
|
|
+ if (frame_info->dmabuf[1])
|
|
+ dma_buf_put(frame_info->dmabuf[1]);
|
|
+ if (frame_info->release_fence) {
|
|
+ dma_fence_signal(frame_info->release_fence);
|
|
+ dma_fence_put(frame_info->release_fence);
|
|
+ }
|
|
+ vd_prepare_data_q_put(dev, vd_prepare);
|
|
+ dev->last_file = NULL;
|
|
+ atomic_set(&received_frames->on_use, false);
|
|
return;
|
|
}
|
|
vf->vc_private->present_fence = frame_info->present_fence;
|
|
@@ -4214,6 +4377,21 @@ static void vframe_display(struct videodisplay_dev *dev,
|
|
|
|
if (!kfifo_put(&dev->ready_q, (const struct vframe_s *)vf)) {
|
|
vd_print(dev->index, PRINT_ERROR, "%s: put to ready_q failed.\n", __func__);
|
|
+ dma_buf_put(frame_info->dmabuf[0]);
|
|
+ if (frame_info->dmabuf[1])
|
|
+ dma_buf_put(frame_info->dmabuf[1]);
|
|
+ if (frame_info->release_fence) {
|
|
+ dma_fence_signal(frame_info->release_fence);
|
|
+ dma_fence_put(frame_info->release_fence);
|
|
+ }
|
|
+ if (vf->vc_private) {
|
|
+ vd_private_q_recycle(dev, vf->vc_private);
|
|
+ vf->vc_private = NULL;
|
|
+ }
|
|
+ vd_prepare_data_q_put(dev, vd_prepare);
|
|
+ dev->last_file = NULL;
|
|
+ dev->vd_prepare_last = NULL;
|
|
+ atomic_set(&received_frames->on_use, false);
|
|
return;
|
|
}
|
|
vf_notify_receiver(dev->vf_provider_name,
|
|
@@ -4288,10 +4466,36 @@ static void video_display_task(struct videodisplay_dev *dev)
|
|
|
|
dev->is_drm_enable = received_frames->is_drm;
|
|
num = received_frames->frames_info.layer_index;
|
|
+ if (num >= MAX_COMPOSER_COUNT ||
|
|
+ received_frames->frames_info.frame_count > MAX_COMPOSER_COUNT) {
|
|
+ pr_err("%s: received_frames(%px) invalid, layer_index=%d, frame_count=%d.\n",
|
|
+ __func__, received_frames,
|
|
+ received_frames->frames_info.layer_index,
|
|
+ received_frames->frames_info.frame_count);
|
|
+ if (received_frames->frames_info.frame_count >= 1 &&
|
|
+ received_frames->frames_info.frame_count <= MAX_COMPOSER_COUNT) {
|
|
+ fence_file = received_frames->frames_info.frame_info[0].release_fence;
|
|
+ if (fence_file) {
|
|
+ dma_fence_signal(fence_file);
|
|
+ dma_fence_put(fence_file);
|
|
+ }
|
|
+ }
|
|
+ atomic_set(&received_frames->on_use, false);
|
|
+ return;
|
|
+ }
|
|
fence_file = received_frames->frames_info.frame_info[num].input_fence;
|
|
|
|
if (video_wait_dma_fence(dev, fence_file) == 0) {
|
|
+ vd_print(dev->index, PRINT_ERROR,
|
|
+ "%s: input fence(%px) wait timeout, drop frame layer=%d count=%d.\n",
|
|
+ __func__, fence_file, num,
|
|
+ received_frames->frames_info.frame_count);
|
|
vd_put_input_dmabufs(&received_frames->frames_info);
|
|
+ fence_file = received_frames->frames_info.frame_info[num].release_fence;
|
|
+ if (fence_file) {
|
|
+ dma_fence_signal(fence_file);
|
|
+ dma_fence_put(fence_file);
|
|
+ }
|
|
atomic_set(&received_frames->on_use, false);
|
|
return;
|
|
}
|
|
@@ -4299,6 +4503,11 @@ static void video_display_task(struct videodisplay_dev *dev)
|
|
if (!detect_vf_usage(dev, received_frames, &need_composer, &do_mosaic_22)) {
|
|
vd_print(dev->index, PRINT_ERROR, "%s: fail to get vf usage.\n", __func__);
|
|
vd_put_input_dmabufs(&received_frames->frames_info);
|
|
+ fence_file = received_frames->frames_info.frame_info[num].release_fence;
|
|
+ if (fence_file) {
|
|
+ dma_fence_signal(fence_file);
|
|
+ dma_fence_put(fence_file);
|
|
+ }
|
|
atomic_set(&received_frames->on_use, false);
|
|
return;
|
|
}
|
|
@@ -4314,6 +4523,7 @@ static void video_display_task(struct videodisplay_dev *dev)
|
|
} else {
|
|
vd_print(dev->index, PRINT_INFO, "task: do display.\n");
|
|
vframe_display(dev, received_frames);
|
|
+ vd_put_input_dmabufs(&received_frames->frames_info);
|
|
}
|
|
}
|
|
|
|
@@ -4380,6 +4590,8 @@ static int video_display_thread(void *data)
|
|
}
|
|
if (kfifo_len(&dev->receive_q) > 0)
|
|
receive_q_uninit(dev);
|
|
+ vd_print(dev->index, PRINT_OTHER, "thread: stopped, receive_q len=%d\n",
|
|
+ kfifo_len(&dev->receive_q));
|
|
dev->thread_stopped = 1;
|
|
return 0;
|
|
}
|
|
@@ -4803,6 +5015,10 @@ static void vd_vf_put(struct vframe_s *vf, void *op_arg)
|
|
vf->canvas0_config[0].phy_addr,
|
|
vf->width,
|
|
vf->height);
|
|
+ if (!vf->enhance_vf) {
|
|
+ pr_err("%s: vf(%px) enhance_vf is NULL.\n", __func__, vf);
|
|
+ return;
|
|
+ }
|
|
vf = vf->enhance_vf;
|
|
display_vf = vf->enhance_vf;
|
|
vf->rendered = display_vf->rendered;
|
|
@@ -4939,8 +5155,13 @@ static void vd_vf_put(struct vframe_s *vf, void *op_arg)
|
|
dma_buf_put((struct dma_buf *)vf->file_vf);
|
|
if (vf->file_vf_ext)
|
|
dma_buf_put((struct dma_buf *)vf->file_vf_ext);
|
|
- dma_fence_signal(vd_prepare->release_fence[0]);
|
|
- dma_fence_put(vd_prepare->release_fence[0]);
|
|
+ if (vd_prepare->release_fence[0]) {
|
|
+ dma_fence_signal(vd_prepare->release_fence[0]);
|
|
+ dma_fence_put(vd_prepare->release_fence[0]);
|
|
+ } else {
|
|
+ pr_err("%s: release_fence[0] is NULL, frame_index=%d.\n",
|
|
+ __func__, vf->frame_index);
|
|
+ }
|
|
dev->fput_count++;
|
|
total_put_count++;
|
|
}
|
|
@@ -5345,7 +5566,9 @@ static int video_display_uninit(struct videodisplay_dev *dev)
|
|
dev->fget_count,
|
|
dev->fput_count);
|
|
}
|
|
- video_timeline_increase(dev, dev->fence_creat_count - dev->fence_release_count);
|
|
+ if (dev->fence_creat_count > dev->fence_release_count)
|
|
+ video_timeline_increase(dev,
|
|
+ dev->fence_creat_count - dev->fence_release_count);
|
|
dev->is_sideband = false;
|
|
dev->need_empty_ready = false;
|
|
dev_array[dev->index] = NULL;
|
|
@@ -5569,6 +5792,13 @@ int vd_set_frames(int index, struct frames_info_t *frames_info)
|
|
return -EINVAL;
|
|
}
|
|
|
|
+ pr_info("vd:%d %s: count=%d, layer=%d, dmabuf=(%px,%px), fi=%px\n",
|
|
+ index, __func__, frames_info->frame_count,
|
|
+ frames_info->layer_index,
|
|
+ frames_info->frame_info[frames_info->layer_index].dmabuf[0],
|
|
+ frames_info->frame_info[frames_info->layer_index].dmabuf[1],
|
|
+ frames_info);
|
|
+
|
|
vd_print(dev->index, PRINT_AXIS, "********src frame param********.\n");
|
|
vd_print(dev->index, PRINT_INFO,
|
|
"%s: count:%d, index:%d, z:%d, .\n",
|
|
@@ -5671,6 +5901,12 @@ int vd_mbd_setframe(int layer_index, struct mbd_video_frame_info_t *frame_info)
|
|
if (!dev)
|
|
return -1;
|
|
|
|
+ if (!frame_info->buffer_info) {
|
|
+ pr_err("%s: layer_index(%d) frame_info->buffer_info is NULL.\n",
|
|
+ __func__, layer_index);
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
dev->received_count++;
|
|
vd_print(layer_index, PRINT_OTHER | PRINT_PATTERN,
|
|
"%s: total receive_count is %lld.\n",
|
|
@@ -5681,6 +5917,11 @@ int vd_mbd_setframe(int layer_index, struct mbd_video_frame_info_t *frame_info)
|
|
|
|
if (is_repeat_vf) {
|
|
vd_prepare = dev->vd_prepare_last;
|
|
+ if (!vd_prepare) {
|
|
+ pr_err("%s: layer_index(%d) vd_prepare_last is NULL for repeat frame.\n",
|
|
+ __func__, layer_index);
|
|
+ return -ENOENT;
|
|
+ }
|
|
} else {
|
|
vd_prepare = vd_prepare_data_q_get(dev);
|
|
if (!vd_prepare) {
|
|
@@ -5735,6 +5976,21 @@ int vd_mbd_setframe(int layer_index, struct mbd_video_frame_info_t *frame_info)
|
|
}
|
|
|
|
vf->vc_private = vd_private_q_pop(dev);
|
|
+ if (!vf->vc_private) {
|
|
+ pr_err("%s: layer_index(%d) vd_private_q_pop return NULL.\n",
|
|
+ __func__, layer_index);
|
|
+ vd_prepare_data_q_put(dev, vd_prepare);
|
|
+ dev->vd_prepare_last = NULL;
|
|
+ return -ENOENT;
|
|
+ }
|
|
+ if (!frame_info->lock_buffer_cb || !frame_info->unlock_buffer_cb) {
|
|
+ pr_err("%s: layer_index(%d) mbd lock/unlock_buffer_cb is NULL, buffer_info=%px.\n",
|
|
+ __func__, layer_index, frame_info->buffer_info);
|
|
+ vd_prepare_data_q_put(dev, vd_prepare);
|
|
+ vd_private_q_recycle(dev, vf->vc_private);
|
|
+ vf->vc_private = NULL;
|
|
+ return -EINVAL;
|
|
+ }
|
|
vf->vc_private->lock_buffer_cb = frame_info->lock_buffer_cb;
|
|
vf->vc_private->unlock_buffer_cb = frame_info->unlock_buffer_cb;
|
|
vf->vc_private->lock_buffer_cb((void *)frame_info->buffer_info);
|
|
--
|
|
2.55.0
|
|
|