From 799ba4c6f73c3f141a4b93c1f51fd770df3ca305 Mon Sep 17 00:00:00 2001 From: Pengcheng Chen Date: Wed, 10 Apr 2019 12:21:38 +0800 Subject: [PATCH] osd: fix hotplug hdmi causes system crash [1/1] PD#SWPL-7009 Problem: hotplug hdmi causes system crash when unplug hdmi display mode is null, hwc hasn't received event and post frame normal but osd vsync lost, which caused wait hw vsync timeout(1s), and fd leak. Solution: when process every frame, if display mode is null, exit frame process just process fence. Verify: verified on Raven, franklin Change-Id: Icbe7cd76776e46a6ed79c6cee3ea05772cc5f9d2 Signed-off-by: Pengcheng Chen --- drivers/amlogic/media/osd/osd_hw.c | 75 +++++++++++++++++++++++--------------- 1 file changed, 45 insertions(+), 30 deletions(-) diff --git a/drivers/amlogic/media/osd/osd_hw.c b/drivers/amlogic/media/osd/osd_hw.c index 01ac4611..c2242e9 100644 --- a/drivers/amlogic/media/osd/osd_hw.c +++ b/drivers/amlogic/media/osd/osd_hw.c @@ -1275,7 +1275,8 @@ static int sync_render_single_fence(u32 index, u32 yres, kthread_queue_work(&buffer_toggle_worker[output_index], &buffer_toggle_work[output_index]); request->out_fen_fd = out_fence_fd; - __close_fd(current->files, request->in_fen_fd); + if (request->in_fen_fd >= 0) + __close_fd(current->files, request->in_fen_fd); return out_fence_fd; } @@ -1342,8 +1343,10 @@ static int sync_render_layers_fence(u32 index, u32 yres, fence_map->layer_map[index].in_fd, fence_map->layer_map[index].out_fd); request->out_fen_fd = out_fence_fd; - __close_fd(current->files, in_fence_fd); - __close_fd(current->files, request->shared_fd); + if (in_fence_fd >= 0) + __close_fd(current->files, in_fence_fd); + if (request->shared_fd >= 0) + __close_fd(current->files, request->shared_fd); return out_fence_fd; } @@ -2184,8 +2187,16 @@ void osd_wait_vsync_hw(void) if (pxp_mode) timeout = msecs_to_jiffies(50); - else - timeout = msecs_to_jiffies(1000); + else { + struct vinfo_s *vinfo; + + vinfo = get_current_vinfo(); + if (vinfo && (!strcmp(vinfo->name, "invalid") || + !strcmp(vinfo->name, "null"))) { + timeout = msecs_to_jiffies(1); + } else + timeout = msecs_to_jiffies(1000); + } wait_event_interruptible_timeout( osd_vsync_wq, vsync_hit, timeout); } @@ -4211,6 +4222,14 @@ static void osd_pan_display_single_fence(struct osd_fence_map_s *fence_map) if (index >= OSD2) goto out; + vinfo = get_current_vinfo(); + if (vinfo && (!strcmp(vinfo->name, "invalid") || + !strcmp(vinfo->name, "null"))) + goto out; + + osd_hw.vinfo_width[output_index] = vinfo->width; + osd_hw.vinfo_height[output_index] = vinfo->height; + if (timeline_created[output_index]) { /* out fence created success. */ ret = osd_wait_buf_ready(fence_map); if (ret < 0) @@ -4232,15 +4251,6 @@ static void osd_pan_display_single_fence(struct osd_fence_map_s *fence_map) AFBC_EN | BLOCK_SPLIT | YUV_TRANSFORM | SUPER_BLOCK_ASPECT; } - vinfo = get_current_vinfo(); - if (vinfo) { - if ((strcmp(vinfo->name, "invalid")) && - (strcmp(vinfo->name, "null"))) { - osd_hw.vinfo_width[output_index] = vinfo->width; - osd_hw.vinfo_height[output_index] = - vinfo->height; - } - } /* Todo: */ if (fence_map->ext_addr && fence_map->width && fence_map->height) { @@ -4442,17 +4452,17 @@ static void osd_pan_display_single_fence(struct osd_fence_map_s *fence_map) osd_wait_vsync_hw(); } } +#ifdef CONFIG_AMLOGIC_MEDIA_FB_EXT + if (ret) + osd_ext_clone_pan(index); +#endif +out: if (timeline_created[output_index]) { if (ret) osd_timeline_increase(output_index); else osd_log_err("------NOT signal out_fence ERROR\n"); } -#ifdef CONFIG_AMLOGIC_MEDIA_FB_EXT - if (ret) - osd_ext_clone_pan(index); -#endif -out: if (fence_map->in_fence) osd_put_fenceobj(fence_map->in_fence); } @@ -4654,15 +4664,17 @@ static void _osd_pan_display_layers_fence( int ret; int start_index = 0; int backup_en = 0; - int osd_count; + int osd_count = 0; /* osd_count need -1 when VIU2 enable */ struct layer_fence_map_s *layer_map = NULL; - if (vinfo && (strcmp(vinfo->name, "invalid") && - strcmp(vinfo->name, "null"))) { - osd_hw.vinfo_width[output_index] = vinfo->width; - osd_hw.vinfo_height[output_index] = vinfo->field_height; - } + if (vinfo && (!strcmp(vinfo->name, "invalid") || + !strcmp(vinfo->name, "null"))) + /* vout is null, release fence */ + goto out; + + osd_hw.vinfo_width[output_index] = vinfo->width; + osd_hw.vinfo_height[output_index] = vinfo->field_height; memcpy(&osd_hw.disp_info[output_index], &fence_map->disp_info, sizeof(struct display_flip_info_s)); if (output_index == VIU1) { @@ -4708,6 +4720,7 @@ static void _osd_pan_display_layers_fence( /* set hw regs */ if (osd_hw.osd_display_debug != OSD_DISP_DEBUG) osd_setting_blend(output_index); +out: /* signal out fence */ if (timeline_created[output_index]) { if (osd_hw.osd_debug.osd_single_step_mode) { @@ -10669,12 +10682,14 @@ void osd_page_flip(struct osd_plane_map_s *plane_map) else if (output_index == VIU2) vinfo = get_current_vinfo2(); #endif - - if (vinfo && (strcmp(vinfo->name, "invalid") && - strcmp(vinfo->name, "null"))) { - osd_hw.vinfo_width[output_index] = vinfo->width; - osd_hw.vinfo_height[output_index] = vinfo->height; + vinfo = get_current_vinfo(); + if (vinfo && (!strcmp(vinfo->name, "invalid") || + !strcmp(vinfo->name, "null"))) { + return; } + osd_hw.vinfo_width[output_index] = vinfo->width; + osd_hw.vinfo_height[output_index] = vinfo->height; + osd_hw.osd_afbcd[index].enable = (plane_map->afbc_inter_format & AFBC_EN) >> 31; if (osd_hw.osd_meson_dev.osd_ver <= OSD_NORMAL) { -- 2.7.4