diff options
Diffstat (limited to '0004-console-fbcon-Add-support-for-deferred-console-takeo.patch')
-rw-r--r-- | 0004-console-fbcon-Add-support-for-deferred-console-takeo.patch | 322 |
1 files changed, 322 insertions, 0 deletions
diff --git a/0004-console-fbcon-Add-support-for-deferred-console-takeo.patch b/0004-console-fbcon-Add-support-for-deferred-console-takeo.patch new file mode 100644 index 000000000..36d625ef3 --- /dev/null +++ b/0004-console-fbcon-Add-support-for-deferred-console-takeo.patch @@ -0,0 +1,322 @@ +From 83d83bebf40132e2d55ec58af666713cc76f9764 Mon Sep 17 00:00:00 2001 +From: Hans de Goede <hdegoede@redhat.com> +Date: Thu, 28 Jun 2018 15:20:30 +0200 +Subject: [PATCH 4/7] console/fbcon: Add support for deferred console takeover + +Currently fbcon claims fbdevs as soon as they are registered and takes over +the console as soon as the first fbdev gets registered. + +This behavior is undesirable in cases where a smooth graphical bootup is +desired, in such cases we typically want the contents of the framebuffer +(typically a vendor logo) to stay in place as is. + +The current solution for this problem (on embedded systems) is to not +enable fbcon. + +This commit adds a new FRAMEBUFFER_CONSOLE_DEFERRED_TAKEOVER config option, +which when enabled defers fbcon taking over the console from the dummy +console until the first text is displayed on the console. Together with the +"quiet" kernel commandline option, this allows fbcon to still be used +together with a smooth graphical bootup, having it take over the console as +soon as e.g. an error message is logged. + +Note the choice to detect the first console output in the dummycon driver, +rather then handling this entirely inside the fbcon code, was made after +2 failed attempts to handle this entirely inside the fbcon code. The fbcon +code is woven quite tightly into the console code, making this to only +feasible option. + +Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch> +Signed-off-by: Hans de Goede <hdegoede@redhat.com> +Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com> +--- + Documentation/fb/fbcon.txt | 7 ++++ + drivers/video/console/Kconfig | 11 +++++ + drivers/video/console/dummycon.c | 67 +++++++++++++++++++++++++---- + drivers/video/fbdev/core/fbcon.c | 72 ++++++++++++++++++++++++++++++++ + include/linux/console.h | 5 +++ + 5 files changed, 154 insertions(+), 8 deletions(-) + +diff --git a/Documentation/fb/fbcon.txt b/Documentation/fb/fbcon.txt +index 79c22d096bbc..d4d642e1ce9c 100644 +--- a/Documentation/fb/fbcon.txt ++++ b/Documentation/fb/fbcon.txt +@@ -155,6 +155,13 @@ C. Boot options + used by text. By default, this area will be black. The 'color' value + is an integer number that depends on the framebuffer driver being used. + ++6. fbcon=nodefer ++ ++ If the kernel is compiled with deferred fbcon takeover support, normally ++ the framebuffer contents, left in place by the firmware/bootloader, will ++ be preserved until there actually is some text is output to the console. ++ This option causes fbcon to bind immediately to the fbdev device. ++ + C. Attaching, Detaching and Unloading + + Before going on how to attach, detach and unload the framebuffer console, an +diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig +index 4110ba7d7ca9..e91edef98633 100644 +--- a/drivers/video/console/Kconfig ++++ b/drivers/video/console/Kconfig +@@ -150,6 +150,17 @@ config FRAMEBUFFER_CONSOLE_ROTATION + such that other users of the framebuffer will remain normally + oriented. + ++config FRAMEBUFFER_CONSOLE_DEFERRED_TAKEOVER ++ bool "Framebuffer Console Deferred Takeover" ++ depends on FRAMEBUFFER_CONSOLE=y && DUMMY_CONSOLE=y ++ help ++ If enabled this defers the framebuffer console taking over the ++ console from the dummy console until the first text is displayed on ++ the console. This is useful in combination with the "quiet" kernel ++ commandline option to keep the framebuffer contents initially put up ++ by the firmware in place, rather then replacing the contents with a ++ black screen as soon as fbcon loads. ++ + config STI_CONSOLE + bool "STI text console" + depends on PARISC && HAS_IOMEM +diff --git a/drivers/video/console/dummycon.c b/drivers/video/console/dummycon.c +index f2eafe2ed980..45ad925ad5f8 100644 +--- a/drivers/video/console/dummycon.c ++++ b/drivers/video/console/dummycon.c +@@ -26,6 +26,65 @@ + #define DUMMY_ROWS CONFIG_DUMMY_CONSOLE_ROWS + #endif + ++#ifdef CONFIG_FRAMEBUFFER_CONSOLE_DEFERRED_TAKEOVER ++/* These are both protected by the console_lock */ ++static RAW_NOTIFIER_HEAD(dummycon_output_nh); ++static bool dummycon_putc_called; ++ ++void dummycon_register_output_notifier(struct notifier_block *nb) ++{ ++ raw_notifier_chain_register(&dummycon_output_nh, nb); ++ ++ if (dummycon_putc_called) ++ nb->notifier_call(nb, 0, NULL); ++} ++ ++void dummycon_unregister_output_notifier(struct notifier_block *nb) ++{ ++ raw_notifier_chain_unregister(&dummycon_output_nh, nb); ++} ++ ++static void dummycon_putc(struct vc_data *vc, int c, int ypos, int xpos) ++{ ++ dummycon_putc_called = true; ++ raw_notifier_call_chain(&dummycon_output_nh, 0, NULL); ++} ++ ++static void dummycon_putcs(struct vc_data *vc, const unsigned short *s, ++ int count, int ypos, int xpos) ++{ ++ int i; ++ ++ if (!dummycon_putc_called) { ++ /* Ignore erases */ ++ for (i = 0 ; i < count; i++) { ++ if (s[i] != vc->vc_video_erase_char) ++ break; ++ } ++ if (i == count) ++ return; ++ ++ dummycon_putc_called = true; ++ } ++ ++ raw_notifier_call_chain(&dummycon_output_nh, 0, NULL); ++} ++ ++static int dummycon_blank(struct vc_data *vc, int blank, int mode_switch) ++{ ++ /* Redraw, so that we get putc(s) for output done while blanked */ ++ return 1; ++} ++#else ++static void dummycon_putc(struct vc_data *vc, int c, int ypos, int xpos) { } ++static void dummycon_putcs(struct vc_data *vc, const unsigned short *s, ++ int count, int ypos, int xpos) { } ++static int dummycon_blank(struct vc_data *vc, int blank, int mode_switch) ++{ ++ return 0; ++} ++#endif ++ + static const char *dummycon_startup(void) + { + return "dummy device"; +@@ -44,9 +103,6 @@ static void dummycon_init(struct vc_data *vc, int init) + static void dummycon_deinit(struct vc_data *vc) { } + static void dummycon_clear(struct vc_data *vc, int sy, int sx, int height, + int width) { } +-static void dummycon_putc(struct vc_data *vc, int c, int ypos, int xpos) { } +-static void dummycon_putcs(struct vc_data *vc, const unsigned short *s, +- int count, int ypos, int xpos) { } + static void dummycon_cursor(struct vc_data *vc, int mode) { } + + static bool dummycon_scroll(struct vc_data *vc, unsigned int top, +@@ -61,11 +117,6 @@ static int dummycon_switch(struct vc_data *vc) + return 0; + } + +-static int dummycon_blank(struct vc_data *vc, int blank, int mode_switch) +-{ +- return 0; +-} +- + static int dummycon_font_set(struct vc_data *vc, struct console_font *font, + unsigned int flags) + { +diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c +index cd8d52a967aa..5fb156bdcf4e 100644 +--- a/drivers/video/fbdev/core/fbcon.c ++++ b/drivers/video/fbdev/core/fbcon.c +@@ -129,6 +129,12 @@ static inline void fbcon_map_override(void) + } + #endif /* CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY */ + ++#ifdef CONFIG_FRAMEBUFFER_CONSOLE_DEFERRED_TAKEOVER ++static bool deferred_takeover = true; ++#else ++#define deferred_takeover false ++#endif ++ + /* font data */ + static char fontname[40]; + +@@ -499,6 +505,12 @@ static int __init fb_console_setup(char *this_opt) + margin_color = simple_strtoul(options, &options, 0); + continue; + } ++#ifdef CONFIG_FRAMEBUFFER_CONSOLE_DEFERRED_TAKEOVER ++ if (!strcmp(options, "nodefer")) { ++ deferred_takeover = false; ++ continue; ++ } ++#endif + } + return 1; + } +@@ -3100,6 +3112,9 @@ static int fbcon_fb_unregistered(struct fb_info *info) + + WARN_CONSOLE_UNLOCKED(); + ++ if (deferred_takeover) ++ return 0; ++ + idx = info->node; + for (i = first_fb_vc; i <= last_fb_vc; i++) { + if (con2fb_map[i] == idx) +@@ -3140,6 +3155,13 @@ static void fbcon_remap_all(int idx) + + WARN_CONSOLE_UNLOCKED(); + ++ if (deferred_takeover) { ++ for (i = first_fb_vc; i <= last_fb_vc; i++) ++ con2fb_map_boot[i] = idx; ++ fbcon_map_override(); ++ return; ++ } ++ + for (i = first_fb_vc; i <= last_fb_vc; i++) + set_con2fb_map(i, idx, 0); + +@@ -3191,6 +3213,11 @@ static int fbcon_fb_registered(struct fb_info *info) + idx = info->node; + fbcon_select_primary(info); + ++ if (deferred_takeover) { ++ pr_info("fbcon: Deferring console take-over\n"); ++ return 0; ++ } ++ + if (info_idx == -1) { + for (i = first_fb_vc; i <= last_fb_vc; i++) { + if (con2fb_map_boot[i] == idx) { +@@ -3566,8 +3593,46 @@ static int fbcon_init_device(void) + return 0; + } + ++#ifdef CONFIG_FRAMEBUFFER_CONSOLE_DEFERRED_TAKEOVER ++static struct notifier_block fbcon_output_nb; ++ ++static int fbcon_output_notifier(struct notifier_block *nb, ++ unsigned long action, void *data) ++{ ++ int i; ++ ++ WARN_CONSOLE_UNLOCKED(); ++ ++ pr_info("fbcon: Taking over console\n"); ++ ++ dummycon_unregister_output_notifier(&fbcon_output_nb); ++ deferred_takeover = false; ++ logo_shown = FBCON_LOGO_DONTSHOW; ++ ++ for (i = 0; i < FB_MAX; i++) { ++ if (registered_fb[i]) ++ fbcon_fb_registered(registered_fb[i]); ++ } ++ ++ return NOTIFY_OK; ++} ++ ++static void fbcon_register_output_notifier(void) ++{ ++ fbcon_output_nb.notifier_call = fbcon_output_notifier; ++ dummycon_register_output_notifier(&fbcon_output_nb); ++} ++#else ++static inline void fbcon_register_output_notifier(void) {} ++#endif ++ + static void fbcon_start(void) + { ++ if (deferred_takeover) { ++ fbcon_register_output_notifier(); ++ return; ++ } ++ + if (num_registered_fb) { + int i; + +@@ -3594,6 +3659,13 @@ static void fbcon_exit(void) + if (fbcon_has_exited) + return; + ++#ifdef CONFIG_FRAMEBUFFER_CONSOLE_DEFERRED_TAKEOVER ++ if (deferred_takeover) { ++ dummycon_unregister_output_notifier(&fbcon_output_nb); ++ deferred_takeover = false; ++ } ++#endif ++ + kfree((void *)softback_buf); + softback_buf = 0UL; + +diff --git a/include/linux/console.h b/include/linux/console.h +index dfd6b0e97855..f59f3dbca65c 100644 +--- a/include/linux/console.h ++++ b/include/linux/console.h +@@ -21,6 +21,7 @@ struct console_font_op; + struct console_font; + struct module; + struct tty_struct; ++struct notifier_block; + + /* + * this is what the terminal answers to a ESC-Z or csi0c query. +@@ -220,4 +221,8 @@ static inline bool vgacon_text_force(void) { return false; } + + extern void console_init(void); + ++/* For deferred console takeover */ ++void dummycon_register_output_notifier(struct notifier_block *nb); ++void dummycon_unregister_output_notifier(struct notifier_block *nb); ++ + #endif /* _LINUX_CONSOLE_H */ +-- +2.18.0 + |