|
@@ -129,6 +129,12 @@ static inline void fbcon_map_override(void)
|
|
}
|
|
}
|
|
#endif /* CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY */
|
|
#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 */
|
|
/* font data */
|
|
static char fontname[40];
|
|
static char fontname[40];
|
|
|
|
|
|
@@ -499,6 +505,12 @@ static int __init fb_console_setup(char *this_opt)
|
|
margin_color = simple_strtoul(options, &options, 0);
|
|
margin_color = simple_strtoul(options, &options, 0);
|
|
continue;
|
|
continue;
|
|
}
|
|
}
|
|
|
|
+#ifdef CONFIG_FRAMEBUFFER_CONSOLE_DEFERRED_TAKEOVER
|
|
|
|
+ if (!strcmp(options, "nodefer")) {
|
|
|
|
+ deferred_takeover = false;
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+#endif
|
|
}
|
|
}
|
|
return 1;
|
|
return 1;
|
|
}
|
|
}
|
|
@@ -3100,6 +3112,9 @@ static int fbcon_fb_unregistered(struct fb_info *info)
|
|
|
|
|
|
WARN_CONSOLE_UNLOCKED();
|
|
WARN_CONSOLE_UNLOCKED();
|
|
|
|
|
|
|
|
+ if (deferred_takeover)
|
|
|
|
+ return 0;
|
|
|
|
+
|
|
idx = info->node;
|
|
idx = info->node;
|
|
for (i = first_fb_vc; i <= last_fb_vc; i++) {
|
|
for (i = first_fb_vc; i <= last_fb_vc; i++) {
|
|
if (con2fb_map[i] == idx)
|
|
if (con2fb_map[i] == idx)
|
|
@@ -3140,6 +3155,13 @@ static void fbcon_remap_all(int idx)
|
|
|
|
|
|
WARN_CONSOLE_UNLOCKED();
|
|
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++)
|
|
for (i = first_fb_vc; i <= last_fb_vc; i++)
|
|
set_con2fb_map(i, idx, 0);
|
|
set_con2fb_map(i, idx, 0);
|
|
|
|
|
|
@@ -3191,6 +3213,11 @@ static int fbcon_fb_registered(struct fb_info *info)
|
|
idx = info->node;
|
|
idx = info->node;
|
|
fbcon_select_primary(info);
|
|
fbcon_select_primary(info);
|
|
|
|
|
|
|
|
+ if (deferred_takeover) {
|
|
|
|
+ pr_info("fbcon: Deferring console take-over\n");
|
|
|
|
+ return 0;
|
|
|
|
+ }
|
|
|
|
+
|
|
if (info_idx == -1) {
|
|
if (info_idx == -1) {
|
|
for (i = first_fb_vc; i <= last_fb_vc; i++) {
|
|
for (i = first_fb_vc; i <= last_fb_vc; i++) {
|
|
if (con2fb_map_boot[i] == idx) {
|
|
if (con2fb_map_boot[i] == idx) {
|
|
@@ -3566,8 +3593,46 @@ static int fbcon_init_device(void)
|
|
return 0;
|
|
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)
|
|
static void fbcon_start(void)
|
|
{
|
|
{
|
|
|
|
+ if (deferred_takeover) {
|
|
|
|
+ fbcon_register_output_notifier();
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
if (num_registered_fb) {
|
|
if (num_registered_fb) {
|
|
int i;
|
|
int i;
|
|
|
|
|
|
@@ -3594,6 +3659,13 @@ static void fbcon_exit(void)
|
|
if (fbcon_has_exited)
|
|
if (fbcon_has_exited)
|
|
return;
|
|
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);
|
|
kfree((void *)softback_buf);
|
|
softback_buf = 0UL;
|
|
softback_buf = 0UL;
|
|
|
|
|