• Qiuxu Zhuo's avatar
    drm/fb-helper: Don't schedule_work() to flush frame buffer during panic() · 833cd3e9
    Qiuxu Zhuo authored
    Sometimes the system [1] hangs on x86 I/O machine checks. However, the
    expected behavior is to reboot the system, as the machine check handler
    ultimately triggers a panic(), initiating a reboot in the last step.
    
    The root cause is that sometimes the panic() is blocked when
    drm_fb_helper_damage() invoking schedule_work() to flush the frame buffer.
    This occurs during the process of flushing all messages to the frame
    buffer driver as shown in the following call trace:
    
      Machine check occurs [2]:
        panic()
          console_flush_on_panic()
            console_flush_all()
              console_emit_next_record()
                con->write()
                  vt_console_print()
                    hide_cursor()
                      vc->vc_sw->con_cursor()
                        fbcon_cursor()
                          ops->cursor()
                            bit_cursor()
                              soft_cursor()
                                info->fbops->fb_imageblit()
                                  drm_fbdev_generic_defio_imageblit()
                                    drm_fb_helper_damage_area()
                                      drm_fb_helper_damage()
                                        schedule_work() // <--- blocked here
        ...
        emergency_restart()  // wasn't invoked, so no reboot.
    
    During panic(), except the panic CPU, all the other CPUs are stopped.
    In schedule_work(), the panic CPU requires the lock of worker_pool to
    queue the work on that pool, while the lock may have been token by some
    other stopped CPU. So schedule_work() is blocked.
    
    Additionally, during a panic(), since there is no opportunity to execute
    any scheduled work, it's safe to fix this issue by skipping schedule_work()
    on 'oops_in_progress' in drm_fb_helper_damage().
    
    [1] Enable the kernel option CONFIG_FRAMEBUFFER_CONSOLE,
        CONFIG_DRM_FBDEV_EMULATION, and boot with the 'console=tty0'
        kernel command line parameter.
    
    [2] Set 'panic_timeout' to a non-zero value before calling panic().
    Acked-by: default avatarThomas Zimmermann <tzimmermann@suse.de>
    Reported-by: default avatarYudong Wang <yudong.wang@intel.com>
    Tested-by: default avatarYudong Wang <yudong.wang@intel.com>
    Signed-off-by: default avatarQiuxu Zhuo <qiuxu.zhuo@intel.com>
    Link: https://patchwork.freedesktop.org/patch/msgid/20240703141737.75378-1-qiuxu.zhuo@intel.comSigned-off-by: default avatarMaarten Lankhorst,,, <maarten.lankhorst@linux.intel.com>
    833cd3e9
drm_fb_helper.c 58.7 KB