* [PATCH v2 0/7] vt: Simplify console-blanking interface
@ 2026-10-16 9:11 Thomas Zimmermann
2026-10-16 9:11 ` [PATCH v2 1/7] vt: Add con_unblank callback to struct consw Thomas Zimmermann
` (6 more replies)
0 siblings, 7 replies; 15+ messages in thread
From: Thomas Zimmermann @ 2026-10-16 9:11 UTC (permalink / raw)
To: gregkh, jirislaby, deller, James.Bottomley, simona
Cc: linux-kernel, linux-serial, linux-fbdev, linux-parisc,
sashiko-reviews, Thomas Zimmermann
Update con_blank from struct consw to use enum vesa_blank_mode according
to its intented semantics. Handle unblanking in the separate new callback
con_unblank. Update all consoles.
Some background: the vt subsystem calls con_blank with what at first
appears to be non-sensical value. This is because the blank value and the
type of the blank parameter do not match: con_blank mixes up console blank
state and monitor DPMS levels for power saving in the same argument.
The implementation of con_blank in various consoles suffers from a similar
problem: their interpretation of the given blank value often disagrees with
what the value's type suggests.
Patch 1 adds a new helper con_unblank, which handles all unblanking. This
allows for changing con_blank to only handle blanking. There's support
for both semantics while consoles are being converted.
Patches 2 to 6 implement con_unblank for the individual consoles. With
this, con_blank changes to its new semantics. Each console gets a single
callback for blanking and a single callback for unblanking. Switching a
console between text and graphics mode is currently tied to the blanking
helpers. The mode_switch parameter controls this. As suggested in the
earlier reviews, rather detect a mode switch from the existing state.
The mode_switch parameter is deprecated. A later series might rework the
mode switching entirely.
With all consoles updated, patch 7 removes the old semantics and the
mode_switch parameter.
Tested with vgacon on a SiS 6202 VGA and with fbcon on a Matrox G200
VGA device. The latter also ran fbcon via DRM fbdev emulation. It's easy
to test this with setterm, like this:
setterm --blank force # blank
setterm --blank poke # unblank
setterm --powersave powerdown # set VESA DPMS level 3
setterm --blank force # blank and turn off monitor
setterm --blank poke # unblank
Blanking and unblanking still works in all tested cases.
Newport and sticon are built-only, due to a lack of test equipment.
v2:
- rewrite series with con_unblank (GregKH)
- drop mode_switch from console implementations
Thomas Zimmermann (7):
vt: Add con_unblank callback to struct consw
dummycon: Implement struct consw.con_unblank
fbcon: Implement struct consw.con_unblank
newport_con: Implement struct consw.con_unblank
sticon: Implement struct consw.con_unblank
vgacon: Implement struct consw.con_unblank
vt: Remove old-style con_blank
drivers/tty/vt/vt.c | 9 ++---
drivers/video/console/dummycon.c | 18 +++++++--
drivers/video/console/newport_con.c | 27 ++++++-------
drivers/video/console/sticon.c | 27 ++++++++-----
drivers/video/console/vgacon.c | 60 +++++++++++++++++------------
drivers/video/fbdev/core/fbcon.c | 60 ++++++++++++++++++++---------
include/linux/console.h | 12 +++---
7 files changed, 132 insertions(+), 81 deletions(-)
base-commit: b0bd9fb9e92aae2a653efa1d0407daa2aabe99d0
--
2.55.0
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH v2 1/7] vt: Add con_unblank callback to struct consw
2026-10-16 9:11 [PATCH v2 0/7] vt: Simplify console-blanking interface Thomas Zimmermann
@ 2026-10-16 9:11 ` Thomas Zimmermann
2026-10-16 9:44 ` sashiko-bot
2026-10-16 9:11 ` [PATCH v2 2/7] dummycon: Implement struct consw.con_unblank Thomas Zimmermann
` (5 subsequent siblings)
6 siblings, 1 reply; 15+ messages in thread
From: Thomas Zimmermann @ 2026-10-16 9:11 UTC (permalink / raw)
To: gregkh, jirislaby, deller, James.Bottomley, simona
Cc: linux-kernel, linux-serial, linux-fbdev, linux-parisc,
sashiko-reviews, Thomas Zimmermann
Add struct consw.con_unblank as inverse operation to con_black.
If implemented invoke con_blank to turn the console from blanked to
unblanked. Also update the semantics of con_blank in this case: The
blank parameter of con_blank receives a VESA blank mode from enum
vesa_blank_mode instead of the hybrid unblank/blank values it has
used so far.
With con_unblank not implemented, invoke con_blank for blanking and
unblanking as before.
The old semantics of con_blank will be removed when all consoles
implement con_unblank.
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
---
drivers/tty/vt/vt.c | 30 +++++++++++++++++++++++-------
include/linux/console.h | 9 ++++++---
2 files changed, 29 insertions(+), 10 deletions(-)
diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
index 57edf37495a8..04e28166b78d 100644
--- a/drivers/tty/vt/vt.c
+++ b/drivers/tty/vt/vt.c
@@ -4671,7 +4671,10 @@ void do_blank_screen(int entering_gfx)
if (console_blanked) {
if (blank_state == blank_vesa_wait) {
blank_state = blank_off;
- vc->vc_sw->con_blank(vc, vesa_blank_mode + 1, 0);
+ if (vc->vc_sw->con_unblank)
+ vc->vc_sw->con_blank(vc, vesa_blank_mode, 0);
+ else
+ vc->vc_sw->con_blank(vc, vesa_blank_mode + 1, 0);
}
return;
}
@@ -4680,7 +4683,10 @@ void do_blank_screen(int entering_gfx)
if (entering_gfx) {
hide_cursor(vc);
save_screen(vc);
- vc->vc_sw->con_blank(vc, VESA_VSYNC_SUSPEND, 1);
+ if (vc->vc_sw->con_unblank)
+ vc->vc_sw->con_blank(vc, VESA_NO_BLANKING, 1);
+ else
+ vc->vc_sw->con_blank(vc, VESA_VSYNC_SUSPEND, 1);
console_blanked = fg_console + 1;
blank_state = blank_off;
set_origin(vc);
@@ -4701,8 +4707,12 @@ void do_blank_screen(int entering_gfx)
save_screen(vc);
/* In case we need to reset origin, blanking hook returns 1 */
- i = vc->vc_sw->con_blank(vc, vesa_off_interval ? VESA_VSYNC_SUSPEND :
- (vesa_blank_mode + 1), 0);
+ if (vc->vc_sw->con_unblank)
+ i = vc->vc_sw->con_blank(vc, vesa_off_interval ? VESA_NO_BLANKING :
+ vesa_blank_mode, 0);
+ else
+ i = vc->vc_sw->con_blank(vc, vesa_off_interval ? VESA_VSYNC_SUSPEND :
+ (vesa_blank_mode + 1), 0);
console_blanked = fg_console + 1;
if (i)
set_origin(vc);
@@ -4753,9 +4763,15 @@ void do_unblank_screen(int leaving_gfx)
}
console_blanked = 0;
- if (vc->vc_sw->con_blank(vc, VESA_NO_BLANKING, leaving_gfx))
- /* Low-level driver cannot restore -> do it ourselves */
- update_screen(vc);
+ if (vc->vc_sw->con_unblank) {
+ if (vc->vc_sw->con_unblank(vc))
+ /* Low-level driver cannot restore -> do it ourselves */
+ update_screen(vc);
+ } else {
+ if (vc->vc_sw->con_blank(vc, VESA_NO_BLANKING, leaving_gfx))
+ /* Low-level driver cannot restore -> do it ourselves */
+ update_screen(vc);
+ }
if (console_blank_hook)
console_blank_hook(0);
set_palette(vc);
diff --git a/include/linux/console.h b/include/linux/console.h
index 502d1abe3f50..aadcb6053cb0 100644
--- a/include/linux/console.h
+++ b/include/linux/console.h
@@ -55,9 +55,11 @@ enum vc_intensity;
* Invoked by csi_M and printing to the console.
* @con_switch: notifier about the console switch; it is supposed to return
* true if a redraw is needed.
- * @con_blank: blank/unblank the console. The target mode is passed in @blank.
- * @mode_switch is set if changing from/to text/graphics. The hook
- * is supposed to return true if a redraw is needed.
+ * @con_blank: blank the console. The preferred VESA blank mode is passed in
+ * @blank. @mode_switch is set if changing from/to text/graphics.
+ * The hook is supposed to return true if a redraw is needed.
+ * @con_unblank: unblank the console. The hook is supposed to return true if
+ * a redraw is needed.
* @con_font_set: set console @vc font to @font with height @vpitch. @flags can
* be %KD_FONT_FLAG_DONT_RECALC. (optional)
* @con_font_get: fetch the current font on @vc of height @vpitch into @font.
@@ -99,6 +101,7 @@ struct consw {
bool (*con_switch)(struct vc_data *vc);
bool (*con_blank)(struct vc_data *vc, enum vesa_blank_mode blank,
bool mode_switch);
+ bool (*con_unblank)(struct vc_data *vc);
int (*con_font_set)(struct vc_data *vc,
const struct console_font *font,
unsigned int vpitch, unsigned int flags);
--
2.55.0
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH v2 2/7] dummycon: Implement struct consw.con_unblank
2026-10-16 9:11 [PATCH v2 0/7] vt: Simplify console-blanking interface Thomas Zimmermann
2026-10-16 9:11 ` [PATCH v2 1/7] vt: Add con_unblank callback to struct consw Thomas Zimmermann
@ 2026-10-16 9:11 ` Thomas Zimmermann
2026-10-16 9:46 ` sashiko-bot
2026-10-16 9:11 ` [PATCH v2 3/7] fbcon: " Thomas Zimmermann
` (4 subsequent siblings)
6 siblings, 1 reply; 15+ messages in thread
From: Thomas Zimmermann @ 2026-10-16 9:11 UTC (permalink / raw)
To: gregkh, jirislaby, deller, James.Bottomley, simona
Cc: linux-kernel, linux-serial, linux-fbdev, linux-parisc,
sashiko-reviews, Thomas Zimmermann
Implement con_unblank from struct consw as a duplicate of con_blank.
As dummycon does not do anything, the implementation only returns
true or false to trigger a redraw (or not).
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
---
drivers/video/console/dummycon.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/drivers/video/console/dummycon.c b/drivers/video/console/dummycon.c
index 7d02470f19b9..ea34a7e84472 100644
--- a/drivers/video/console/dummycon.c
+++ b/drivers/video/console/dummycon.c
@@ -86,6 +86,11 @@ static bool dummycon_blank(struct vc_data *vc, enum vesa_blank_mode blank,
return true;
}
+static bool dummycon_unblank(struct vc_data *vc)
+{
+ return true;
+}
+
static bool dummycon_switch(struct vc_data *vc)
{
/*
@@ -104,6 +109,12 @@ static bool dummycon_blank(struct vc_data *vc, enum vesa_blank_mode blank,
{
return false;
}
+
+static bool dummycon_unblank(struct vc_data *vc)
+{
+ return false;
+}
+
static bool dummycon_switch(struct vc_data *vc)
{
return false;
@@ -155,5 +166,6 @@ const struct consw dummy_con = {
.con_scroll = dummycon_scroll,
.con_switch = dummycon_switch,
.con_blank = dummycon_blank,
+ .con_unblank = dummycon_unblank,
};
EXPORT_SYMBOL_GPL(dummy_con);
--
2.55.0
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH v2 3/7] fbcon: Implement struct consw.con_unblank
2026-10-16 9:11 [PATCH v2 0/7] vt: Simplify console-blanking interface Thomas Zimmermann
2026-10-16 9:11 ` [PATCH v2 1/7] vt: Add con_unblank callback to struct consw Thomas Zimmermann
2026-10-16 9:11 ` [PATCH v2 2/7] dummycon: Implement struct consw.con_unblank Thomas Zimmermann
@ 2026-10-16 9:11 ` Thomas Zimmermann
2026-10-16 10:01 ` sashiko-bot
2026-10-16 9:11 ` [PATCH v2 4/7] newport_con: " Thomas Zimmermann
` (3 subsequent siblings)
6 siblings, 1 reply; 15+ messages in thread
From: Thomas Zimmermann @ 2026-10-16 9:11 UTC (permalink / raw)
To: gregkh, jirislaby, deller, James.Bottomley, simona
Cc: linux-kernel, linux-serial, linux-fbdev, linux-parisc,
sashiko-reviews, Thomas Zimmermann
Implement con_unblank from struct consw with the !blank branches from
fbcon_blank(). The new function is called fbcon_unblank(). Remove the
duplicated code from fbcon_blank().
Fbcon tracks fbdev blank state in par->blank_state using fbdev's FB_BLANK
constants. In fbcon_unblank() the stored value is always FB_BLANK_UNBLANK.
In fbcon_blank(), the new blank state is 1 + plus the VESA blank mode
given in the parameter blank.
fbcon_blank() now disables the cursor worker unconditionally.
Unblanking while switching the console from graphics to text mode
requires setting the display with fb_set_var(). fbcon_unblank() does not
receive the mode_switch flag from its caller, so track the flag with the
par->graphics and vc->vc_num fields. A later update might add a mode-
switching callback to simplify this logic.
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
---
drivers/video/fbdev/core/fbcon.c | 56 ++++++++++++++++++++++----------
1 file changed, 39 insertions(+), 17 deletions(-)
diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c
index 615fa596b7cc..6d564111ebd0 100644
--- a/drivers/video/fbdev/core/fbcon.c
+++ b/drivers/video/fbdev/core/fbcon.c
@@ -2293,32 +2293,53 @@ static bool fbcon_blank(struct vc_data *vc, enum vesa_blank_mode blank,
struct fb_info *info = fbcon_info_from_console(vc->vc_num);
struct fbcon_par *par = info->fbcon_par;
- if (mode_switch) {
- struct fb_var_screeninfo var = info->var;
+ if (mode_switch)
+ par->graphics = true;
- par->graphics = 1;
+ if (fbcon_is_active(vc, info)) {
+ int blank_state = 1 + blank; /* convert VESA to FB_BLANK constant */
- if (!blank) {
- var.activate = FB_ACTIVATE_NOW | FB_ACTIVATE_FORCE |
- FB_ACTIVATE_KD_TEXT;
- fb_set_var(info, &var);
- par->graphics = 0;
- par->var = info->var;
+ if (par->blank_state != blank_state) {
+ par->blank_state = blank_state;
+ fbcon_cursor(vc, false);
+ par->cursor_flash = false;
+
+ if (fb_blank(info, blank_state))
+ fbcon_generic_blank(vc, info, true);
}
}
+ fbcon_del_cursor_work(info);
+
+ return false;
+}
+
+static bool fbcon_unblank(struct vc_data *vc)
+{
+ struct fb_info *info = fbcon_info_from_console(vc->vc_num);
+ struct fbcon_par *par = info->fbcon_par;
+ bool mode_switch = par->graphics && vc->vc_mode == KD_TEXT;
+
+ if (mode_switch) {
+ struct fb_var_screeninfo var = info->var;
+
+ var.activate = FB_ACTIVATE_NOW | FB_ACTIVATE_FORCE | FB_ACTIVATE_KD_TEXT;
+ fb_set_var(info, &var);
+ par->graphics = false;
+ par->var = info->var;
+ }
+
if (fbcon_is_active(vc, info)) {
- if (par->blank_state != blank) {
- par->blank_state = blank;
- fbcon_cursor(vc, !blank);
- par->cursor_flash = (!blank);
+ if (par->blank_state != FB_BLANK_UNBLANK) {
+ par->blank_state = FB_BLANK_UNBLANK;
+ fbcon_cursor(vc, true);
+ par->cursor_flash = true;
- if (fb_blank(info, blank))
- fbcon_generic_blank(vc, info, blank);
+ if (fb_blank(info, FB_BLANK_UNBLANK))
+ fbcon_generic_blank(vc, info, false);
}
- if (!blank)
- update_screen(vc);
+ update_screen(vc);
}
if (mode_switch || !fbcon_is_active(vc, info) || par->blank_state != FB_BLANK_UNBLANK)
@@ -3168,6 +3189,7 @@ static const struct consw fb_con = {
.con_scroll = fbcon_scroll,
.con_switch = fbcon_switch,
.con_blank = fbcon_blank,
+ .con_unblank = fbcon_unblank,
.con_font_set = fbcon_set_font,
.con_font_get = fbcon_get_font,
.con_font_default = fbcon_set_def_font,
--
2.55.0
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH v2 4/7] newport_con: Implement struct consw.con_unblank
2026-10-16 9:11 [PATCH v2 0/7] vt: Simplify console-blanking interface Thomas Zimmermann
` (2 preceding siblings ...)
2026-10-16 9:11 ` [PATCH v2 3/7] fbcon: " Thomas Zimmermann
@ 2026-10-16 9:11 ` Thomas Zimmermann
2026-10-16 10:07 ` sashiko-bot
2026-10-16 9:11 ` [PATCH v2 5/7] sticon: " Thomas Zimmermann
` (2 subsequent siblings)
6 siblings, 1 reply; 15+ messages in thread
From: Thomas Zimmermann @ 2026-10-16 9:11 UTC (permalink / raw)
To: gregkh, jirislaby, deller, James.Bottomley, simona
Cc: linux-kernel, linux-serial, linux-fbdev, linux-parisc,
sashiko-reviews, Thomas Zimmermann
Implement con_unblank from struct consw with the VESA_NO_BLANKING
branch from newport_blank(). Remove that code from the blank helper.
Both helpers, newport_blank() and newport_unbank(), clear or set
a single flag in a hardware register. No further VESA DPMS blanking
is supported.
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
---
drivers/video/console/newport_con.c | 24 +++++++++++++-----------
1 file changed, 13 insertions(+), 11 deletions(-)
diff --git a/drivers/video/console/newport_con.c b/drivers/video/console/newport_con.c
index ecbbe2e4e2a6..c617a9a27e4c 100644
--- a/drivers/video/console/newport_con.c
+++ b/drivers/video/console/newport_con.c
@@ -481,17 +481,18 @@ static bool newport_blank(struct vc_data *c, enum vesa_blank_mode blank,
{
unsigned short treg;
- if (blank == VESA_NO_BLANKING) {
- /* unblank console */
- treg = newport_vc2_get(npregs, VC2_IREG_CONTROL);
- newport_vc2_set(npregs, VC2_IREG_CONTROL,
- (treg | VC2_CTRL_EDISP));
- } else {
- /* blank console */
- treg = newport_vc2_get(npregs, VC2_IREG_CONTROL);
- newport_vc2_set(npregs, VC2_IREG_CONTROL,
- (treg & ~(VC2_CTRL_EDISP)));
- }
+ treg = newport_vc2_get(npregs, VC2_IREG_CONTROL);
+ newport_vc2_set(npregs, VC2_IREG_CONTROL, (treg & ~(VC2_CTRL_EDISP)));
+
+ return true;
+}
+
+static bool newport_unblank(struct vc_data *c)
+{
+ unsigned short treg;
+
+ treg = newport_vc2_get(npregs, VC2_IREG_CONTROL);
+ newport_vc2_set(npregs, VC2_IREG_CONTROL, (treg | VC2_CTRL_EDISP));
return true;
}
@@ -666,6 +667,7 @@ const struct consw newport_con = {
.con_scroll = newport_scroll,
.con_switch = newport_switch,
.con_blank = newport_blank,
+ .con_unblank = newport_unblank,
.con_font_set = newport_font_set,
.con_font_default = newport_font_default,
.con_save_screen = newport_save_screen
--
2.55.0
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH v2 5/7] sticon: Implement struct consw.con_unblank
2026-10-16 9:11 [PATCH v2 0/7] vt: Simplify console-blanking interface Thomas Zimmermann
` (3 preceding siblings ...)
2026-10-16 9:11 ` [PATCH v2 4/7] newport_con: " Thomas Zimmermann
@ 2026-10-16 9:11 ` Thomas Zimmermann
2026-10-16 10:13 ` sashiko-bot
2026-10-16 9:11 ` [PATCH v2 6/7] vgacon: " Thomas Zimmermann
2026-10-16 9:11 ` [PATCH v2 7/7] vt: Remove old-style con_blank Thomas Zimmermann
6 siblings, 1 reply; 15+ messages in thread
From: Thomas Zimmermann @ 2026-10-16 9:11 UTC (permalink / raw)
To: gregkh, jirislaby, deller, James.Bottomley, simona
Cc: linux-kernel, linux-serial, linux-fbdev, linux-parisc,
sashiko-reviews, Thomas Zimmermann
Implement con_unblank from struct consw. The new function is called
sticon_unblank(). Remove the related code from sticon_blank().
Sticon uses the global state vga_is_gfx in several places to test if
the console runs in text or graphics mode. Track the mode switches in
sticon_blank() and sticon_unblank(). As sticon_unblank() does not have
a mode_switch parameter, derive the value from vga_is_gfx and vc_mode.
There is no display unblanking in sticon: only return true to redraw
the console.
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
---
drivers/video/console/sticon.c | 22 ++++++++++++++--------
1 file changed, 14 insertions(+), 8 deletions(-)
diff --git a/drivers/video/console/sticon.c b/drivers/video/console/sticon.c
index 6f58e6a9e76a..0d882ea6b37f 100644
--- a/drivers/video/console/sticon.c
+++ b/drivers/video/console/sticon.c
@@ -302,17 +302,22 @@ static bool sticon_switch(struct vc_data *conp)
static bool sticon_blank(struct vc_data *c, enum vesa_blank_mode blank,
bool mode_switch)
{
- if (blank == VESA_NO_BLANKING) {
+ sti_clear(sticon_sti, 0, 0, c->vc_rows, c->vc_cols, BLANK, font_data[c->vc_num]);
+
if (mode_switch)
- vga_is_gfx = 0;
+ vga_is_gfx = 1;
+
return true;
- }
- sti_clear(sticon_sti, 0, 0, c->vc_rows, c->vc_cols, BLANK,
- font_data[c->vc_num]);
- if (mode_switch)
- vga_is_gfx = 1;
+}
- return true;
+static bool sticon_unblank(struct vc_data *c)
+{
+ bool mode_switch = vga_is_gfx && c->vc_mode == KD_TEXT;
+
+ if (mode_switch)
+ vga_is_gfx = 0;
+
+ return true;
}
static u8 sticon_build_attr(struct vc_data *conp, u8 color,
@@ -356,6 +361,7 @@ static const struct consw sti_con = {
.con_scroll = sticon_scroll,
.con_switch = sticon_switch,
.con_blank = sticon_blank,
+ .con_unblank = sticon_unblank,
.con_font_set = sticon_font_set,
.con_font_default = sticon_font_default,
.con_build_attr = sticon_build_attr,
--
2.55.0
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH v2 6/7] vgacon: Implement struct consw.con_unblank
2026-10-16 9:11 [PATCH v2 0/7] vt: Simplify console-blanking interface Thomas Zimmermann
` (4 preceding siblings ...)
2026-10-16 9:11 ` [PATCH v2 5/7] sticon: " Thomas Zimmermann
@ 2026-10-16 9:11 ` Thomas Zimmermann
2026-10-16 10:26 ` sashiko-bot
2026-10-16 9:11 ` [PATCH v2 7/7] vt: Remove old-style con_blank Thomas Zimmermann
6 siblings, 1 reply; 15+ messages in thread
From: Thomas Zimmermann @ 2026-10-16 9:11 UTC (permalink / raw)
To: gregkh, jirislaby, deller, James.Bottomley, simona
Cc: linux-kernel, linux-serial, linux-fbdev, linux-parisc,
sashiko-reviews, Thomas Zimmermann
Implement con_unblank from struct consw with the VESA_NO_BLANKING
case from vgacon_blank(). The new function is called vgacon_unblank().
Remove the duplicated code from vgacon_blank().
Vgacon uses the global state vga_is_gfx in several places to test if
the console runs on text or graphics mode. Track the mode switches in
vgacon_blank() and vga_unblank(). As vgacon_unblank() does not have
a mode_switch parameter, derive the value from vga_is_gfx and vc_mode.
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
---
drivers/video/console/vgacon.c | 53 ++++++++++++++++++++--------------
1 file changed, 31 insertions(+), 22 deletions(-)
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index 536e7fe4d142..7f52164c30af 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -800,39 +800,47 @@ static void vga_pal_blank(struct vgastate *state)
static bool vgacon_blank(struct vc_data *c, enum vesa_blank_mode blank,
bool mode_switch)
{
+ if (mode_switch)
+ vga_is_gfx = true;
+
switch (blank) {
- case VESA_NO_BLANKING: /* Unblank */
- if (vga_vesa_blanked) {
- vga_vesa_unblank(&vgastate);
- vga_vesa_blanked = VESA_NO_BLANKING;
- }
- if (vga_palette_blanked) {
- vga_set_palette(c, color_table);
- vga_palette_blanked = false;
- return 0;
- }
- vga_is_gfx = false;
- /* Tell console.c that it has to restore the screen itself */
- return 1;
- case VESA_VSYNC_SUSPEND: /* Normal blanking */
+ case VESA_NO_BLANKING: /* Normal blanking */
if (!mode_switch && vga_video_type == VIDEO_TYPE_VGAC) {
vga_pal_blank(&vgastate);
vga_palette_blanked = true;
- return 0;
+ return false;
}
vgacon_set_origin(c);
- scr_memsetw((void *) vga_vram_base, BLANK,
- c->vc_screenbuf_size);
- if (mode_switch)
- vga_is_gfx = true;
- return 1;
+ scr_memsetw((void *)vga_vram_base, BLANK, c->vc_screenbuf_size);
+ return true;
default: /* VESA blanking */
if (vga_video_type == VIDEO_TYPE_VGAC) {
- vga_vesa_blank(&vgastate, blank - 1);
+ vga_vesa_blank(&vgastate, blank);
vga_vesa_blanked = blank;
}
- return 0;
+ return false;
+ }
+}
+
+static bool vgacon_unblank(struct vc_data *c)
+{
+ bool mode_switch = vga_is_gfx && c->vc_mode == KD_TEXT;
+
+ if (mode_switch)
+ vga_is_gfx = false;
+
+ if (vga_vesa_blanked) {
+ vga_vesa_unblank(&vgastate);
+ vga_vesa_blanked = VESA_NO_BLANKING;
}
+
+ if (vga_palette_blanked) {
+ vga_set_palette(c, color_table);
+ vga_palette_blanked = false;
+ return false;
+ }
+
+ return true;
}
/*
@@ -1201,6 +1209,7 @@ const struct consw vga_con = {
.con_scroll = vgacon_scroll,
.con_switch = vgacon_switch,
.con_blank = vgacon_blank,
+ .con_unblank = vgacon_unblank,
.con_font_set = vgacon_font_set,
.con_font_get = vgacon_font_get,
.con_resize = vgacon_resize,
--
2.55.0
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH v2 7/7] vt: Remove old-style con_blank
2026-10-16 9:11 [PATCH v2 0/7] vt: Simplify console-blanking interface Thomas Zimmermann
` (5 preceding siblings ...)
2026-10-16 9:11 ` [PATCH v2 6/7] vgacon: " Thomas Zimmermann
@ 2026-10-16 9:11 ` Thomas Zimmermann
2026-10-16 10:38 ` sashiko-bot
6 siblings, 1 reply; 15+ messages in thread
From: Thomas Zimmermann @ 2026-10-16 9:11 UTC (permalink / raw)
To: gregkh, jirislaby, deller, James.Bottomley, simona
Cc: linux-kernel, linux-serial, linux-fbdev, linux-parisc,
sashiko-reviews, Thomas Zimmermann
All consoles implement the new con_blank plus con_unblank. Remove
the old semantics from con_blank. Always pass a VESA blank mode to
the blank parameter. Remove the mode_switch parameter. For unblanking
call con_unblank unconditionally.
Most consoles handle switches from text to graphics mode in their
con_blank callback. With the mode_switch parameter removed, detect
mode switches from console state plus vc_mode. A later change might
add a callback for switching modes to struct consw.
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
---
drivers/tty/vt/vt.c | 29 ++++++-----------------------
drivers/video/console/dummycon.c | 6 ++----
drivers/video/console/newport_con.c | 3 +--
drivers/video/console/sticon.c | 5 +++--
drivers/video/console/vgacon.c | 7 ++++---
drivers/video/fbdev/core/fbcon.c | 4 ++--
include/linux/console.h | 7 +++----
7 files changed, 21 insertions(+), 40 deletions(-)
diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
index 04e28166b78d..13914b582cef 100644
--- a/drivers/tty/vt/vt.c
+++ b/drivers/tty/vt/vt.c
@@ -4671,10 +4671,7 @@ void do_blank_screen(int entering_gfx)
if (console_blanked) {
if (blank_state == blank_vesa_wait) {
blank_state = blank_off;
- if (vc->vc_sw->con_unblank)
- vc->vc_sw->con_blank(vc, vesa_blank_mode, 0);
- else
- vc->vc_sw->con_blank(vc, vesa_blank_mode + 1, 0);
+ vc->vc_sw->con_blank(vc, vesa_blank_mode);
}
return;
}
@@ -4683,10 +4680,7 @@ void do_blank_screen(int entering_gfx)
if (entering_gfx) {
hide_cursor(vc);
save_screen(vc);
- if (vc->vc_sw->con_unblank)
- vc->vc_sw->con_blank(vc, VESA_NO_BLANKING, 1);
- else
- vc->vc_sw->con_blank(vc, VESA_VSYNC_SUSPEND, 1);
+ vc->vc_sw->con_blank(vc, VESA_NO_BLANKING);
console_blanked = fg_console + 1;
blank_state = blank_off;
set_origin(vc);
@@ -4707,12 +4701,7 @@ void do_blank_screen(int entering_gfx)
save_screen(vc);
/* In case we need to reset origin, blanking hook returns 1 */
- if (vc->vc_sw->con_unblank)
- i = vc->vc_sw->con_blank(vc, vesa_off_interval ? VESA_NO_BLANKING :
- vesa_blank_mode, 0);
- else
- i = vc->vc_sw->con_blank(vc, vesa_off_interval ? VESA_VSYNC_SUSPEND :
- (vesa_blank_mode + 1), 0);
+ i = vc->vc_sw->con_blank(vc, vesa_off_interval ? VESA_NO_BLANKING : vesa_blank_mode);
console_blanked = fg_console + 1;
if (i)
set_origin(vc);
@@ -4763,15 +4752,9 @@ void do_unblank_screen(int leaving_gfx)
}
console_blanked = 0;
- if (vc->vc_sw->con_unblank) {
- if (vc->vc_sw->con_unblank(vc))
- /* Low-level driver cannot restore -> do it ourselves */
- update_screen(vc);
- } else {
- if (vc->vc_sw->con_blank(vc, VESA_NO_BLANKING, leaving_gfx))
- /* Low-level driver cannot restore -> do it ourselves */
- update_screen(vc);
- }
+ if (vc->vc_sw->con_unblank(vc))
+ /* Low-level driver cannot restore -> do it ourselves */
+ update_screen(vc);
if (console_blank_hook)
console_blank_hook(0);
set_palette(vc);
diff --git a/drivers/video/console/dummycon.c b/drivers/video/console/dummycon.c
index ea34a7e84472..a206a3de9f4d 100644
--- a/drivers/video/console/dummycon.c
+++ b/drivers/video/console/dummycon.c
@@ -79,8 +79,7 @@ static void dummycon_putcs(struct vc_data *vc, const u16 *s, unsigned int count,
raw_notifier_call_chain(&dummycon_output_nh, 0, NULL);
}
-static bool dummycon_blank(struct vc_data *vc, enum vesa_blank_mode blank,
- bool mode_switch)
+static bool dummycon_blank(struct vc_data *vc, enum vesa_blank_mode blank)
{
/* Redraw, so that we get putc(s) for output done while blanked */
return true;
@@ -104,8 +103,7 @@ static void dummycon_putc(struct vc_data *vc, u16 c, unsigned int y,
unsigned int x) { }
static void dummycon_putcs(struct vc_data *vc, const u16 *s, unsigned int count,
unsigned int ypos, unsigned int xpos) { }
-static bool dummycon_blank(struct vc_data *vc, enum vesa_blank_mode blank,
- bool mode_switch)
+static bool dummycon_blank(struct vc_data *vc, enum vesa_blank_mode blank)
{
return false;
}
diff --git a/drivers/video/console/newport_con.c b/drivers/video/console/newport_con.c
index c617a9a27e4c..5b2d927fccbc 100644
--- a/drivers/video/console/newport_con.c
+++ b/drivers/video/console/newport_con.c
@@ -476,8 +476,7 @@ static bool newport_switch(struct vc_data *vc)
return true;
}
-static bool newport_blank(struct vc_data *c, enum vesa_blank_mode blank,
- bool mode_switch)
+static bool newport_blank(struct vc_data *c, enum vesa_blank_mode blank)
{
unsigned short treg;
diff --git a/drivers/video/console/sticon.c b/drivers/video/console/sticon.c
index 0d882ea6b37f..fb0a8aa4c2bc 100644
--- a/drivers/video/console/sticon.c
+++ b/drivers/video/console/sticon.c
@@ -299,9 +299,10 @@ static bool sticon_switch(struct vc_data *conp)
return true; /* needs refreshing */
}
-static bool sticon_blank(struct vc_data *c, enum vesa_blank_mode blank,
- bool mode_switch)
+static bool sticon_blank(struct vc_data *c, enum vesa_blank_mode blank)
{
+ bool mode_switch = !vga_is_gfx && c->vc_mode == KD_GRAPHICS;
+
sti_clear(sticon_sti, 0, 0, c->vc_rows, c->vc_cols, BLANK, font_data[c->vc_num]);
if (mode_switch)
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index 7f52164c30af..6463fb7676c5 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -797,15 +797,16 @@ static void vga_pal_blank(struct vgastate *state)
}
}
-static bool vgacon_blank(struct vc_data *c, enum vesa_blank_mode blank,
- bool mode_switch)
+static bool vgacon_blank(struct vc_data *c, enum vesa_blank_mode blank)
{
+ bool mode_switch = !vga_is_gfx && c->vc_mode == KD_GRAPHICS;
+
if (mode_switch)
vga_is_gfx = true;
switch (blank) {
case VESA_NO_BLANKING: /* Normal blanking */
- if (!mode_switch && vga_video_type == VIDEO_TYPE_VGAC) {
+ if (c->vc_mode == KD_TEXT && vga_video_type == VIDEO_TYPE_VGAC) {
vga_pal_blank(&vgastate);
vga_palette_blanked = true;
return false;
diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c
index 6d564111ebd0..c9a8fb49c06b 100644
--- a/drivers/video/fbdev/core/fbcon.c
+++ b/drivers/video/fbdev/core/fbcon.c
@@ -2287,11 +2287,11 @@ static void fbcon_generic_blank(struct vc_data *vc, struct fb_info *info,
}
}
-static bool fbcon_blank(struct vc_data *vc, enum vesa_blank_mode blank,
- bool mode_switch)
+static bool fbcon_blank(struct vc_data *vc, enum vesa_blank_mode blank)
{
struct fb_info *info = fbcon_info_from_console(vc->vc_num);
struct fbcon_par *par = info->fbcon_par;
+ bool mode_switch = !par->graphics && vc->vc_mode == KD_GRAPHICS;
if (mode_switch)
par->graphics = true;
diff --git a/include/linux/console.h b/include/linux/console.h
index aadcb6053cb0..b59b6ac0c01e 100644
--- a/include/linux/console.h
+++ b/include/linux/console.h
@@ -56,8 +56,8 @@ enum vc_intensity;
* @con_switch: notifier about the console switch; it is supposed to return
* true if a redraw is needed.
* @con_blank: blank the console. The preferred VESA blank mode is passed in
- * @blank. @mode_switch is set if changing from/to text/graphics.
- * The hook is supposed to return true if a redraw is needed.
+ * @blank. The hook is supposed to return true if a redraw is
+ * needed.
* @con_unblank: unblank the console. The hook is supposed to return true if
* a redraw is needed.
* @con_font_set: set console @vc font to @font with height @vpitch. @flags can
@@ -99,8 +99,7 @@ struct consw {
unsigned int bottom, enum con_scroll dir,
unsigned int lines);
bool (*con_switch)(struct vc_data *vc);
- bool (*con_blank)(struct vc_data *vc, enum vesa_blank_mode blank,
- bool mode_switch);
+ bool (*con_blank)(struct vc_data *vc, enum vesa_blank_mode blank);
bool (*con_unblank)(struct vc_data *vc);
int (*con_font_set)(struct vc_data *vc,
const struct console_font *font,
--
2.55.0
^ permalink raw reply related [flat|nested] 15+ messages in thread
* Re: [PATCH v2 1/7] vt: Add con_unblank callback to struct consw
2026-10-16 9:11 ` [PATCH v2 1/7] vt: Add con_unblank callback to struct consw Thomas Zimmermann
@ 2026-10-16 9:44 ` sashiko-bot
0 siblings, 0 replies; 15+ messages in thread
From: sashiko-bot @ 2026-10-16 9:44 UTC (permalink / raw)
To: Thomas Zimmermann; +Cc: linux-serial
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] vt: Meaningful commit message mismatch regarding con_blank vs con_unblank
--
commit b9997468d0018b5c7f81e52b909c357d93d38641
Author: Thomas Zimmermann <tzimmermann@suse.de>
vt: Add con_unblank callback to struct consw
This commit introduces a new con_unblank callback to struct consw as
the inverse operation of con_blank. It updates console blanking and
unblanking logic to utilize this new callback when implemented, while
falling back to the old semantics otherwise.
> Add struct consw.con_unblank as inverse operation to con_black.
[Severity: Medium]
This isn't a bug, but there's a minor typo here: "con_black" instead of
"con_blank".
> If implemented invoke con_blank to turn the console from blanked to
> unblanked.
[Severity: Medium]
Does this description accurately reflect the code changes? The text states
that con_blank is invoked to turn the console from blanked to unblanked if
the new callback is implemented, but the code actually invokes con_unblank
directly.
Looking at do_unblank_screen() in the diff:
> diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
> --- a/drivers/tty/vt/vt.c
> +++ b/drivers/tty/vt/vt.c
[ ... ]
> @@ -4756,9 +4766,15 @@ void do_unblank_screen(int leaving_gfx)
> }
>
> console_blanked = 0;
> - if (vc->vc_sw->con_blank(vc, VESA_NO_BLANKING, leaving_gfx))
> - /* Low-level driver cannot restore -> do it ourselves */
> - update_screen(vc);
> + if (vc->vc_sw->con_unblank) {
> + if (vc->vc_sw->con_unblank(vc))
> + /* Low-level driver cannot restore -> do it ourselves */
> + update_screen(vc);
The new logic successfully calls con_unblank(vc) instead of con_blank() for
this operation. Could the commit message be updated to clarify that
con_unblank() is invoked directly when transitioning from blanked to
unblanked?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261016093357.33294-1-tzimmermann@suse.de?part=1
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v2 2/7] dummycon: Implement struct consw.con_unblank
2026-10-16 9:11 ` [PATCH v2 2/7] dummycon: Implement struct consw.con_unblank Thomas Zimmermann
@ 2026-10-16 9:46 ` sashiko-bot
0 siblings, 0 replies; 15+ messages in thread
From: sashiko-bot @ 2026-10-16 9:46 UTC (permalink / raw)
To: Thomas Zimmermann; +Cc: linux-serial
> Implement con_unblank from struct consw as a duplicate of con_blank.
> As dummycon does not do anything, the implementation only returns
> true or false to trigger a redraw (or not).
>
> Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Sashiko has reviewed this patch and found no issues. It looks great!
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261016093357.33294-1-tzimmermann@suse.de?part=2
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v2 3/7] fbcon: Implement struct consw.con_unblank
2026-10-16 9:11 ` [PATCH v2 3/7] fbcon: " Thomas Zimmermann
@ 2026-10-16 10:01 ` sashiko-bot
0 siblings, 0 replies; 15+ messages in thread
From: sashiko-bot @ 2026-10-16 10:01 UTC (permalink / raw)
To: Thomas Zimmermann; +Cc: linux-serial
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] fbcon: missing mode restore on VT switch due to par->graphics desync
--
commit c18deeb283bd933a2a74f5f89b8adc5baff05746
Author: Thomas Zimmermann <tzimmermann@suse.de>
fbcon: Implement struct consw.con_unblank
Implement con_unblank from struct consw with the !blank branches from
fbcon_blank(). The new function is called fbcon_unblank(). Remove the
duplicated code from fbcon_blank().
> diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c
> index caad4e06944ea..6b6f162c90dd3 100644
> --- a/drivers/video/fbdev/core/fbcon.c
> +++ b/drivers/video/fbdev/core/fbcon.c
> @@ -2293,32 +2293,53 @@ static bool fbcon_blank(struct vc_data *vc, enum vesa_blank_mode blank,
[ ... ]
> +static bool fbcon_unblank(struct vc_data *vc)
> +{
> + struct fb_info *info = fbcon_info_from_console(vc->vc_num);
> + struct fbcon_par *par = info->fbcon_par;
> + bool mode_switch = par->graphics && vc->vc_mode == KD_TEXT;
[Severity: High]
Can par->graphics become out of sync and prevent a required mode restore?
If vt_kdsetmode(KD_GRAPHICS) is called on a background console, it returns
early without calling do_blank_screen(), leaving par->graphics as false.
When switching to this VT, if the previous foreground VT was also in
KD_GRAPHICS mode, complete_change_console() in drivers/tty/vt/vt_ioctl.c skips
do_blank_screen() because old_vc_mode matches vc->vc_mode:
if (old_vc_mode != vc->vc_mode) {
if (vc->vc_mode == KD_TEXT)
do_unblank_screen(1);
else
do_blank_screen(1);
}
Because do_blank_screen() is skipped, par->graphics remains false for the new
framebuffer. When the application later exits and calls ioctl(KDSETMODE,
KD_TEXT), fbcon_unblank() is triggered.
Since par->graphics is false, mode_switch evaluates to false, skipping
fb_set_var() with FB_ACTIVATE_KD_TEXT. Without FB_ACTIVATE_KD_TEXT, DRM
helpers (like drm_fb_helper_set_par()) won't force a mode restore before the
DRM master drops its locks, which could leave the display frozen or corrupted.
> +
> + if (mode_switch) {
> + struct fb_var_screeninfo var = info->var;
> +
> + var.activate = FB_ACTIVATE_NOW | FB_ACTIVATE_FORCE | FB_ACTIVATE_KD_TEXT;
> + fb_set_var(info, &var);
> + par->graphics = false;
> + par->var = info->var;
> + }
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261016093357.33294-1-tzimmermann@suse.de?part=3
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v2 4/7] newport_con: Implement struct consw.con_unblank
2026-10-16 9:11 ` [PATCH v2 4/7] newport_con: " Thomas Zimmermann
@ 2026-10-16 10:07 ` sashiko-bot
0 siblings, 0 replies; 15+ messages in thread
From: sashiko-bot @ 2026-10-16 10:07 UTC (permalink / raw)
To: Thomas Zimmermann; +Cc: linux-serial
> Implement con_unblank from struct consw with the VESA_NO_BLANKING
> branch from newport_blank(). Remove that code from the blank helper.
>
> Both helpers, newport_blank() and newport_unbank(), clear or set
> a single flag in a hardware register. No further VESA DPMS blanking
> is supported.
>
> Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Sashiko has reviewed this patch and found no issues. It looks great!
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261016093357.33294-1-tzimmermann@suse.de?part=4
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v2 5/7] sticon: Implement struct consw.con_unblank
2026-10-16 9:11 ` [PATCH v2 5/7] sticon: " Thomas Zimmermann
@ 2026-10-16 10:13 ` sashiko-bot
0 siblings, 0 replies; 15+ messages in thread
From: sashiko-bot @ 2026-10-16 10:13 UTC (permalink / raw)
To: Thomas Zimmermann; +Cc: linux-serial
> Implement con_unblank from struct consw. The new function is called
> sticon_unblank(). Remove the related code from sticon_blank().
>
> Sticon uses the global state vga_is_gfx in several places to test if
> the console runs in text or graphics mode. Track the mode switches in
> sticon_blank() and sticon_unblank(). As sticon_unblank() does not have
> a mode_switch parameter, derive the value from vga_is_gfx and vc_mode.
>
> There is no display unblanking in sticon: only return true to redraw
> the console.
>
> Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Sashiko has reviewed this patch and found no issues. It looks great!
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261016093357.33294-1-tzimmermann@suse.de?part=5
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v2 6/7] vgacon: Implement struct consw.con_unblank
2026-10-16 9:11 ` [PATCH v2 6/7] vgacon: " Thomas Zimmermann
@ 2026-10-16 10:26 ` sashiko-bot
0 siblings, 0 replies; 15+ messages in thread
From: sashiko-bot @ 2026-10-16 10:26 UTC (permalink / raw)
To: Thomas Zimmermann; +Cc: linux-serial
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] console: IRQ state leak in vgacon_unblank() during panic
- [Medium] vgacon: failure to blank screen during graphics mode switch
--
commit 1fe83e2b75ae124b5285efec89c3a22f914e107d
Author: Thomas Zimmermann <tzimmermann@suse.de>
vgacon: Implement struct consw.con_unblank
This commit implements the con_unblank callback from struct consw by
extracting the VESA_NO_BLANKING logic from vgacon_blank() into a new
function named vgacon_unblank(). It also updates how the global
vga_is_gfx mode tracking is handled during console transitions.
> diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
> index 37bd18730fe0d..761c8da10449b 100644
> --- a/drivers/video/console/vgacon.c
> +++ b/drivers/video/console/vgacon.c
> @@ -800,39 +800,47 @@ static void vga_pal_blank(struct vgastate *state)
> static bool vgacon_blank(struct vc_data *c, enum vesa_blank_mode blank,
> bool mode_switch)
> {
> + if (mode_switch)
> + vga_is_gfx = true;
[Severity: Medium]
Does setting vga_is_gfx to true before calling vgacon_set_origin() prevent
the screen from blanking correctly?
If mode_switch is true, vga_is_gfx is set to true immediately. Later in this
same path under VESA_NO_BLANKING, vgacon_set_origin() is called:
static bool vgacon_set_origin(struct vc_data *c)
{
if (vga_is_gfx || /* We don't play origin tricks in graphic modes */
(console_blanked && !vga_palette_blanked)) /* Nor we write to blanked screens */
return false;
...
}
Because vga_is_gfx is already set to true, vgacon_set_origin() will
short-circuit and return false without reprogramming the hardware mem_top.
Will this result in a visible flash of uncleared text before the graphics
driver takes over?
> +
> switch (blank) {
[ ... ]
> +static bool vgacon_unblank(struct vc_data *c)
> +{
> + bool mode_switch = vga_is_gfx && c->vc_mode == KD_TEXT;
> +
> + if (mode_switch)
> + vga_is_gfx = false;
> +
> + if (vga_vesa_blanked) {
> + vga_vesa_unblank(&vgastate);
[Severity: High]
Can this call safely execute in a panic context where interrupts must
remain disabled?
When panic() executes, it explicitly disables local interrupts via
local_irq_disable() before calling console_unblank().
The console unblanking subsystem will invoke this new .con_unblank callback,
which calls vga_vesa_unblank(). However, vga_vesa_unblank() uses
raw_spin_unlock_irq():
static void vga_vesa_unblank(struct vgastate *state)
{
/* restore original values of VGA controller registers */
raw_spin_lock_irq(&vga_lock);
...
raw_spin_unlock_irq(&vga_lock);
}
This unconditionally re-enables hardware interrupts, which destroys the safe
context set up by panic(). If a hardware interrupt fires during the remainder
of the panic sequence, could it lead to secondary oopses or deadlocks that
hide the panic logs from the user?
Should the vga_lock acquisition use irqsave/irqrestore variants instead
to preserve the caller's IRQ state?
> + vga_vesa_blanked = VESA_NO_BLANKING;
> }
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261016093357.33294-1-tzimmermann@suse.de?part=6
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v2 7/7] vt: Remove old-style con_blank
2026-10-16 9:11 ` [PATCH v2 7/7] vt: Remove old-style con_blank Thomas Zimmermann
@ 2026-10-16 10:38 ` sashiko-bot
0 siblings, 0 replies; 15+ messages in thread
From: sashiko-bot @ 2026-10-16 10:38 UTC (permalink / raw)
To: Thomas Zimmermann; +Cc: linux-serial
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] vt: loss of text mode on unblanking if VT was blanked prior to KD_GRAPHICS
- [Medium] vt: display corruption due to premature vga_is_gfx assignment
--
commit 397a971ae2e535d87f46ac40e90cdd6df9d84c84
Author: Thomas Zimmermann <tzimmermann@suse.de>
Subject: vt: Remove old-style con_blank
This commit removes the mode_switch parameter from con_blank and con_unblank
callbacks. Consoles are now updated to detect mode switches internally from
the console state and vc_mode.
> --- a/drivers/tty/vt/vt.c
> +++ b/drivers/tty/vt/vt.c
> @@ -4674,10 +4674,7 @@ void do_blank_screen(int entering_gfx)
> if (console_blanked) {
> if (blank_state == blank_vesa_wait) {
> blank_state = blank_off;
> - if (vc->vc_sw->con_unblank)
> - vc->vc_sw->con_blank(vc, vesa_blank_mode, 0);
> - else
> - vc->vc_sw->con_blank(vc, vesa_blank_mode + 1, 0);
> + vc->vc_sw->con_blank(vc, vesa_blank_mode);
> }
> return;
> }
[Severity: High]
If the console is already blanked and not in the vesa_wait state,
do_blank_screen() returns early and skips the con_blank callback entirely.
Because this patch removes the leaving_gfx parameter from the unblank
callback, fbcon_unblank() must now deduce the mode switch internally by
checking if par->graphics is true.
Since par->graphics is only set to true inside fbcon_blank(), skipping
fbcon_blank() leaves it as false:
do_blank_screen()
if (console_blanked) {
return; /* fbcon_blank is skipped, par->graphics remains false */
}
When fbcon_unblank() is later called to switch back to KD_TEXT:
fbcon_unblank()
bool mode_switch = par->graphics && vc->vc_mode == KD_TEXT;
if (mode_switch) {
/* restore text mode */
}
Does this cause the hardware text mode restoration to be bypassed when
mode_switch evaluates to false, leaving the VT frozen?
> --- a/drivers/video/console/vgacon.c
> +++ b/drivers/video/console/vgacon.c
> @@ -797,15 +797,16 @@ static void vga_pal_blank(struct vgastate *state)
> }
> }
>
> -static bool vgacon_blank(struct vc_data *c, enum vesa_blank_mode blank,
> - bool mode_switch)
> +static bool vgacon_blank(struct vc_data *c, enum vesa_blank_mode blank)
> {
> + bool mode_switch = !vga_is_gfx && c->vc_mode == KD_GRAPHICS;
> +
> + if (mode_switch)
> + vga_is_gfx = true;
> +
[Severity: Medium]
Does setting vga_is_gfx = true here cause vgacon_set_origin() to abort
early?
vgacon_set_origin() is called later in this function during normal blanking:
vgacon_blank()
if (mode_switch)
vga_is_gfx = true;
switch (blank) {
case VESA_NO_BLANKING:
vgacon_set_origin(c);
However, vgacon_set_origin() includes an early return if vga_is_gfx is true:
vgacon_set_origin()
if (vga_is_gfx || ... )
return;
If vgacon_set_origin() is skipped, the hardware CRTC offset won't be
reset to vga_vram_base. Even though scr_memsetw() clears the memory
at vga_vram_base, will the unreset CRTC offset cause the display hardware
to continue showing old memory, resulting in display corruption?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261016093357.33294-1-tzimmermann@suse.de?part=7
^ permalink raw reply [flat|nested] 15+ messages in thread
end of thread, other threads:[~2026-10-16 10:38 UTC | newest]
Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-16 9:11 [PATCH v2 0/7] vt: Simplify console-blanking interface Thomas Zimmermann
2026-10-16 9:11 ` [PATCH v2 1/7] vt: Add con_unblank callback to struct consw Thomas Zimmermann
2026-10-16 9:44 ` sashiko-bot
2026-10-16 9:11 ` [PATCH v2 2/7] dummycon: Implement struct consw.con_unblank Thomas Zimmermann
2026-10-16 9:46 ` sashiko-bot
2026-10-16 9:11 ` [PATCH v2 3/7] fbcon: " Thomas Zimmermann
2026-10-16 10:01 ` sashiko-bot
2026-10-16 9:11 ` [PATCH v2 4/7] newport_con: " Thomas Zimmermann
2026-10-16 10:07 ` sashiko-bot
2026-10-16 9:11 ` [PATCH v2 5/7] sticon: " Thomas Zimmermann
2026-10-16 10:13 ` sashiko-bot
2026-10-16 9:11 ` [PATCH v2 6/7] vgacon: " Thomas Zimmermann
2026-10-16 10:26 ` sashiko-bot
2026-10-16 9:11 ` [PATCH v2 7/7] vt: Remove old-style con_blank Thomas Zimmermann
2026-10-16 10:38 ` sashiko-bot
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox