osd: fix hotplug hdmi causes system crash [1/1]
authorPengcheng Chen <pengcheng.chen@amlogic.com>
Wed, 10 Apr 2019 04:21:38 +0000 (12:21 +0800)
committerTao Zeng <tao.zeng@amlogic.com>
Tue, 16 Apr 2019 06:14:41 +0000 (23:14 -0700)
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 <pengcheng.chen@amlogic.com>
drivers/amlogic/media/osd/osd_hw.c

index 01ac461..c2242e9 100644 (file)
@@ -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) {