* [PATCH 0/2] vt: Simplify console-blanking interface
@ 2026-10-12 9:27 Thomas Zimmermann
2026-10-12 9:27 ` [PATCH 1/2] vt: Use boolean as parameter to do_blank_screen() and do_unblank_screen() Thomas Zimmermann
2026-10-12 9:27 ` [PATCH 2/2] vt: Distinguish between blanking and VESA blank mode in con_blank Thomas Zimmermann
0 siblings, 2 replies; 9+ messages in thread
From: Thomas Zimmermann @ 2026-10-12 9:27 UTC (permalink / raw)
To: gregkh, jirislaby, deller, James.Bottomley, simona
Cc: linux-kernel, linux-serial, linux-fbdev, linux-parisc,
sashiko-reviews, Thomas Zimmermann
The vt subsystem calls con_blank with what appears to be non-sensical
value. This is because the values and the type of the blank argument
do not match: it mixes up console blank state and monitor DPMS levels
for powersaving. The implmentations of con_blank in various consoles
suffer from the same problem. Update con_blank to a clearer interface.
Also update the consoles.
Patch 1 does a bit of preparation. It converts a boolean parameter
from int to bool, so that its meaning is clearer.
Patch 2 updates con_blank. The callback's blank parameter now controls
blanking in general. The new blank_mode parameter controls the monitor
status and related powersaving.
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. Its easy
to test this with setterm, like this
setterm --blank force # blank
setterm --blank poke # unblank
setterm --blank force --powersave powerdown # blank and turn off monitor
Blanking and unblanking still works in all tested cases.
Thomas Zimmermann (2):
vt: Use boolean as parameter to do_blank_screen() and
do_unblank_screen()
vt: Distinguish between blanking and VESA blank mode in con_blank
drivers/tty/vt/vt.c | 25 ++++++++--------
drivers/tty/vt/vt_ioctl.c | 12 ++++----
drivers/video/console/dummycon.c | 4 +--
drivers/video/console/newport_con.c | 4 +--
drivers/video/console/sticon.c | 4 +--
drivers/video/console/vgacon.c | 44 +++++++++++++++--------------
drivers/video/fbdev/core/fbcon.c | 23 +++++++--------
include/linux/console.h | 9 ++++--
include/linux/vt_kern.h | 5 ++--
9 files changed, 69 insertions(+), 61 deletions(-)
base-commit: b0bd9fb9e92aae2a653efa1d0407daa2aabe99d0
--
2.55.0
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 1/2] vt: Use boolean as parameter to do_blank_screen() and do_unblank_screen()
2026-10-12 9:27 [PATCH 0/2] vt: Simplify console-blanking interface Thomas Zimmermann
@ 2026-10-12 9:27 ` Thomas Zimmermann
2026-10-12 11:30 ` Greg KH
2026-10-12 9:27 ` [PATCH 2/2] vt: Distinguish between blanking and VESA blank mode in con_blank Thomas Zimmermann
1 sibling, 1 reply; 9+ messages in thread
From: Thomas Zimmermann @ 2026-10-12 9:27 UTC (permalink / raw)
To: gregkh, jirislaby, deller, James.Bottomley, simona
Cc: linux-kernel, linux-serial, linux-fbdev, linux-parisc,
sashiko-reviews, Thomas Zimmermann
The parameters to do_blank_screen() and do_unblank_screen() signal
whether the call is part of a switch between text and graphics mode.
Convert to boolean. No functional changes.
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
---
drivers/tty/vt/vt.c | 20 ++++++++++----------
drivers/tty/vt/vt_ioctl.c | 12 ++++++------
drivers/video/fbdev/core/fbcon.c | 4 ++--
include/linux/vt_kern.h | 5 +++--
4 files changed, 21 insertions(+), 20 deletions(-)
diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
index 57edf37495a8..9e7b4419b422 100644
--- a/drivers/tty/vt/vt.c
+++ b/drivers/tty/vt/vt.c
@@ -3374,7 +3374,7 @@ static void console_callback(struct work_struct *ignored)
scrollback_delta = 0;
}
if (blank_timer_expired) {
- do_blank_screen(0);
+ do_blank_screen(false);
blank_timer_expired = 0;
}
notify_update(vc_cons[fg_console].d);
@@ -3636,7 +3636,7 @@ int tioclinux(struct tty_struct *tty, unsigned long arg)
case TIOCL_BLANKSCREEN: /* until explicitly unblanked, not only poked */
scoped_guard(console_lock) {
ignore_poke = 1;
- do_blank_screen(0);
+ do_blank_screen(false);
}
break;
case TIOCL_BLANKEDSCREEN:
@@ -4659,7 +4659,7 @@ static int set_vesa_blanking(u8 __user *mode_user)
return 0;
}
-void do_blank_screen(int entering_gfx)
+void do_blank_screen(bool entering_gfx)
{
struct vc_data *vc = vc_cons[fg_console].d;
int i;
@@ -4671,7 +4671,7 @@ 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);
+ vc->vc_sw->con_blank(vc, vesa_blank_mode + 1, false);
}
return;
}
@@ -4680,7 +4680,7 @@ 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);
+ vc->vc_sw->con_blank(vc, VESA_VSYNC_SUSPEND, true);
console_blanked = fg_console + 1;
blank_state = blank_off;
set_origin(vc);
@@ -4702,7 +4702,7 @@ 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);
+ (vesa_blank_mode + 1), false);
console_blanked = fg_console + 1;
if (i)
set_origin(vc);
@@ -4721,7 +4721,7 @@ EXPORT_SYMBOL(do_blank_screen);
/*
* Called by timer as well as from vt_console_driver
*/
-void do_unblank_screen(int leaving_gfx)
+void do_unblank_screen(bool leaving_gfx)
{
struct vc_data *vc;
@@ -4767,13 +4767,13 @@ EXPORT_SYMBOL(do_unblank_screen);
/*
* This is called by the outside world to cause a forced unblank, mostly for
- * oopses. Currently, I just call do_unblank_screen(0), but we could eventually
- * call it with 1 as an argument and so force a mode restore... that may kill
+ * oopses. Currently, I just call do_unblank_screen(false), but we could eventually
+ * call it with true as an argument and so force a mode restore... that may kill
* X or at least garbage the screen but would also make the Oops visible...
*/
static void unblank_screen(void)
{
- do_unblank_screen(0);
+ do_unblank_screen(false);
}
/*
diff --git a/drivers/tty/vt/vt_ioctl.c b/drivers/tty/vt/vt_ioctl.c
index ecefe4a666f2..1241b39d6e68 100644
--- a/drivers/tty/vt/vt_ioctl.c
+++ b/drivers/tty/vt/vt_ioctl.c
@@ -273,9 +273,9 @@ static int vt_kdsetmode(struct vc_data *vc, unsigned long mode)
/* explicitly blank/unblank the screen if switching modes */
if (mode == KD_TEXT)
- do_unblank_screen(1);
+ do_unblank_screen(true);
else
- do_blank_screen(1);
+ do_blank_screen(true);
return 0;
}
@@ -1152,9 +1152,9 @@ static void complete_change_console(struct vc_data *vc)
*/
if (old_vc_mode != vc->vc_mode) {
if (vc->vc_mode == KD_TEXT)
- do_unblank_screen(1);
+ do_unblank_screen(true);
else
- do_blank_screen(1);
+ do_blank_screen(true);
}
/*
@@ -1182,9 +1182,9 @@ static void complete_change_console(struct vc_data *vc)
if (old_vc_mode != vc->vc_mode) {
if (vc->vc_mode == KD_TEXT)
- do_unblank_screen(1);
+ do_unblank_screen(true);
else
- do_blank_screen(1);
+ do_blank_screen(true);
}
}
}
diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c
index 615fa596b7cc..274f6bf6e165 100644
--- a/drivers/video/fbdev/core/fbcon.c
+++ b/drivers/video/fbdev/core/fbcon.c
@@ -3051,9 +3051,9 @@ void fbcon_fb_blanked(struct fb_info *info, int blank)
if (con_is_visible(vc)) {
if (blank)
- do_blank_screen(0);
+ do_blank_screen(false);
else
- do_unblank_screen(0);
+ do_unblank_screen(false);
}
par->blank_state = blank;
}
diff --git a/include/linux/vt_kern.h b/include/linux/vt_kern.h
index d008c3d0a9bb..b4e3a2543777 100644
--- a/include/linux/vt_kern.h
+++ b/include/linux/vt_kern.h
@@ -10,6 +10,7 @@
#include <linux/vt.h>
#include <linux/kd.h>
#include <linux/tty.h>
+#include <linux/types.h>
#include <linux/mutex.h>
#include <linux/console_struct.h>
#include <linux/mm.h>
@@ -29,8 +30,8 @@ int __vc_resize(struct vc_data *vc, unsigned int cols, unsigned int lines,
bool from_user);
struct vc_data *vc_deallocate(unsigned int console);
void reset_palette(struct vc_data *vc);
-void do_blank_screen(int entering_gfx);
-void do_unblank_screen(int leaving_gfx);
+void do_blank_screen(bool entering_gfx);
+void do_unblank_screen(bool leaving_gfx);
void poke_blanked_console(void);
int con_font_op(struct vc_data *vc, struct console_font_op *op);
int con_set_cmap(unsigned char __user *cmap);
--
2.55.0
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 2/2] vt: Distinguish between blanking and VESA blank mode in con_blank
2026-10-12 9:27 [PATCH 0/2] vt: Simplify console-blanking interface Thomas Zimmermann
2026-10-12 9:27 ` [PATCH 1/2] vt: Use boolean as parameter to do_blank_screen() and do_unblank_screen() Thomas Zimmermann
@ 2026-10-12 9:27 ` Thomas Zimmermann
2026-10-12 11:29 ` Greg KH
1 sibling, 1 reply; 9+ messages in thread
From: Thomas Zimmermann @ 2026-10-12 9:27 UTC (permalink / raw)
To: gregkh, jirislaby, deller, James.Bottomley, simona
Cc: linux-kernel, linux-serial, linux-fbdev, linux-parisc,
sashiko-reviews, Thomas Zimmermann
The con_blank callback in struct consw encodes blanking and display
blank mode in a single parameter named blank. Its semantics equal
the FB_BLANK constants from the fbdev subsystems. Yet it is of type
enum vesa_blank_mode, which describes VESA DPMS levels of the attached
monitor. Although related, this is something else.
For this reason, calls to con_blank fill the blank parameter with
values that appear non-sensical at first. For example, to blank the
console, but keep the monitor on, vt passes VESA_VSYNC_SUSPEND (eq '1').
This is because consoles interpret '1' as pixels-off-but-monitor-on.
The constant VESA_VSYNC_SUSPEND actually means monitor-vsync-off. And
the argument used for monitor-vsync-off is VESA_VSYNC_SUSPEND+1.
To fix this by splitting blank into two parameters, blank and blank_mode.
The new blank is a boolean to control the display blanking. If cleared,
the console creates display output, if set the console does not. The
new parameter blank_mode specifies the VESA blank mode for the monitor
and equals VESA DPMS levels. If blank is set, blank_mode gives a hint
to the console, on how to set up the signal to the monitor.
The actual interpretation is up to the console. Newportcon and sticon
only handle blank or not-blank. Fbcon and vgacon implement blank plus
the VESA DPMS handling. The implementation of both consoles is again
somewhat confusing because types and values do not match. Clean up
both with the new blank/blank_mode logic.
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
---
drivers/tty/vt/vt.c | 11 ++++----
drivers/video/console/dummycon.c | 4 +--
drivers/video/console/newport_con.c | 4 +--
drivers/video/console/sticon.c | 4 +--
drivers/video/console/vgacon.c | 44 +++++++++++++++--------------
drivers/video/fbdev/core/fbcon.c | 19 +++++++------
include/linux/console.h | 9 ++++--
7 files changed, 51 insertions(+), 44 deletions(-)
diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
index 9e7b4419b422..f762c965351d 100644
--- a/drivers/tty/vt/vt.c
+++ b/drivers/tty/vt/vt.c
@@ -4671,7 +4671,7 @@ void do_blank_screen(bool 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, false);
+ vc->vc_sw->con_blank(vc, true, vesa_blank_mode, false);
}
return;
}
@@ -4680,7 +4680,7 @@ void do_blank_screen(bool entering_gfx)
if (entering_gfx) {
hide_cursor(vc);
save_screen(vc);
- vc->vc_sw->con_blank(vc, VESA_VSYNC_SUSPEND, true);
+ vc->vc_sw->con_blank(vc, true, VESA_NO_BLANKING, true);
console_blanked = fg_console + 1;
blank_state = blank_off;
set_origin(vc);
@@ -4701,8 +4701,9 @@ void do_blank_screen(bool 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), false);
+ i = vc->vc_sw->con_blank(vc, true,
+ vesa_off_interval ? VESA_NO_BLANKING : vesa_blank_mode,
+ false);
console_blanked = fg_console + 1;
if (i)
set_origin(vc);
@@ -4753,7 +4754,7 @@ void do_unblank_screen(bool leaving_gfx)
}
console_blanked = 0;
- if (vc->vc_sw->con_blank(vc, VESA_NO_BLANKING, leaving_gfx))
+ if (vc->vc_sw->con_blank(vc, false, VESA_NO_BLANKING, leaving_gfx))
/* Low-level driver cannot restore -> do it ourselves */
update_screen(vc);
if (console_blank_hook)
diff --git a/drivers/video/console/dummycon.c b/drivers/video/console/dummycon.c
index 7d02470f19b9..50aaccffcccf 100644
--- a/drivers/video/console/dummycon.c
+++ b/drivers/video/console/dummycon.c
@@ -79,7 +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,
+static bool dummycon_blank(struct vc_data *vc, bool blank, enum vesa_blank_mode blank_mode,
bool mode_switch)
{
/* Redraw, so that we get putc(s) for output done while blanked */
@@ -99,7 +99,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,
+static bool dummycon_blank(struct vc_data *vc, bool blank, enum vesa_blank_mode blank_mode,
bool mode_switch)
{
return false;
diff --git a/drivers/video/console/newport_con.c b/drivers/video/console/newport_con.c
index ecbbe2e4e2a6..90e6d70f94bb 100644
--- a/drivers/video/console/newport_con.c
+++ b/drivers/video/console/newport_con.c
@@ -476,12 +476,12 @@ static bool newport_switch(struct vc_data *vc)
return true;
}
-static bool newport_blank(struct vc_data *c, enum vesa_blank_mode blank,
+static bool newport_blank(struct vc_data *c, bool blank, enum vesa_blank_mode blank_mode,
bool mode_switch)
{
unsigned short treg;
- if (blank == VESA_NO_BLANKING) {
+ if (!blank) {
/* unblank console */
treg = newport_vc2_get(npregs, VC2_IREG_CONTROL);
newport_vc2_set(npregs, VC2_IREG_CONTROL,
diff --git a/drivers/video/console/sticon.c b/drivers/video/console/sticon.c
index 6f58e6a9e76a..00e5f86dd35a 100644
--- a/drivers/video/console/sticon.c
+++ b/drivers/video/console/sticon.c
@@ -299,10 +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,
+static bool sticon_blank(struct vc_data *c, bool blank, enum vesa_blank_mode blank_mode,
bool mode_switch)
{
- if (blank == VESA_NO_BLANKING) {
+ if (!blank) {
if (mode_switch)
vga_is_gfx = 0;
return true;
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index 536e7fe4d142..a3a45b6956df 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -797,11 +797,31 @@ static void vga_pal_blank(struct vgastate *state)
}
}
-static bool vgacon_blank(struct vc_data *c, enum vesa_blank_mode blank,
+static bool vgacon_blank(struct vc_data *c, bool blank, enum vesa_blank_mode blank_mode,
bool mode_switch)
{
- switch (blank) {
- case VESA_NO_BLANKING: /* Unblank */
+ if (blank) {
+ switch (blank_mode) {
+ 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;
+ }
+ vgacon_set_origin(c);
+ scr_memsetw((void *)vga_vram_base, BLANK,
+ c->vc_screenbuf_size);
+ if (mode_switch)
+ vga_is_gfx = true;
+ return 1;
+ default: /* VESA blanking */
+ if (vga_video_type == VIDEO_TYPE_VGAC) {
+ vga_vesa_blank(&vgastate, blank_mode);
+ vga_vesa_blanked = blank_mode;
+ }
+ return 0;
+ }
+ } else { /* Unblank */
if (vga_vesa_blanked) {
vga_vesa_unblank(&vgastate);
vga_vesa_blanked = VESA_NO_BLANKING;
@@ -814,24 +834,6 @@ static bool vgacon_blank(struct vc_data *c, enum vesa_blank_mode blank,
vga_is_gfx = false;
/* Tell console.c that it has to restore the screen itself */
return 1;
- case VESA_VSYNC_SUSPEND: /* Normal blanking */
- if (!mode_switch && vga_video_type == VIDEO_TYPE_VGAC) {
- vga_pal_blank(&vgastate);
- vga_palette_blanked = true;
- return 0;
- }
- vgacon_set_origin(c);
- scr_memsetw((void *) vga_vram_base, BLANK,
- c->vc_screenbuf_size);
- if (mode_switch)
- vga_is_gfx = true;
- return 1;
- default: /* VESA blanking */
- if (vga_video_type == VIDEO_TYPE_VGAC) {
- vga_vesa_blank(&vgastate, blank - 1);
- vga_vesa_blanked = blank;
- }
- return 0;
}
}
diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c
index 274f6bf6e165..7f75b4f5da74 100644
--- a/drivers/video/fbdev/core/fbcon.c
+++ b/drivers/video/fbdev/core/fbcon.c
@@ -2287,18 +2287,19 @@ 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,
+static bool fbcon_blank(struct vc_data *vc, bool blank, enum vesa_blank_mode blank_mode,
bool mode_switch)
{
struct fb_info *info = fbcon_info_from_console(vc->vc_num);
struct fbcon_par *par = info->fbcon_par;
+ int blank_state = !blank ? FB_BLANK_UNBLANK : blank_mode + 1;
if (mode_switch) {
struct fb_var_screeninfo var = info->var;
par->graphics = 1;
- if (!blank) {
+ if (!blank_state) {
var.activate = FB_ACTIVATE_NOW | FB_ACTIVATE_FORCE |
FB_ACTIVATE_KD_TEXT;
fb_set_var(info, &var);
@@ -2308,16 +2309,16 @@ static bool fbcon_blank(struct vc_data *vc, enum vesa_blank_mode blank,
}
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 != blank_state) {
+ par->blank_state = blank_state;
+ fbcon_cursor(vc, !blank_state);
+ par->cursor_flash = (!blank_state);
- if (fb_blank(info, blank))
- fbcon_generic_blank(vc, info, blank);
+ if (fb_blank(info, blank_state))
+ fbcon_generic_blank(vc, info, blank_state);
}
- if (!blank)
+ if (!blank_state)
update_screen(vc);
}
diff --git a/include/linux/console.h b/include/linux/console.h
index 502d1abe3f50..19f80556e9b2 100644
--- a/include/linux/console.h
+++ b/include/linux/console.h
@@ -56,8 +56,10 @@ enum vc_intensity;
* @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.
+ * @blank_mode contains the requested level of power saving
+ * if @blank is true. @mode_switch is set if changing from/to
+ * text/graphics. 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.
@@ -97,7 +99,8 @@ 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 (*con_blank)(struct vc_data *vc, bool blank,
+ enum vesa_blank_mode blank_mode,
bool mode_switch);
int (*con_font_set)(struct vc_data *vc,
const struct console_font *font,
--
2.55.0
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 2/2] vt: Distinguish between blanking and VESA blank mode in con_blank
2026-10-12 9:27 ` [PATCH 2/2] vt: Distinguish between blanking and VESA blank mode in con_blank Thomas Zimmermann
@ 2026-10-12 11:29 ` Greg KH
2026-10-12 12:08 ` Thomas Zimmermann
0 siblings, 1 reply; 9+ messages in thread
From: Greg KH @ 2026-10-12 11:29 UTC (permalink / raw)
To: Thomas Zimmermann
Cc: jirislaby, deller, James.Bottomley, simona, linux-kernel,
linux-serial, linux-fbdev, linux-parisc, sashiko-reviews
On Mon, Oct 12, 2026 at 11:27:39AM +0200, Thomas Zimmermann wrote:
> The con_blank callback in struct consw encodes blanking and display
> blank mode in a single parameter named blank. Its semantics equal
> the FB_BLANK constants from the fbdev subsystems. Yet it is of type
> enum vesa_blank_mode, which describes VESA DPMS levels of the attached
> monitor. Although related, this is something else.
>
> For this reason, calls to con_blank fill the blank parameter with
> values that appear non-sensical at first. For example, to blank the
> console, but keep the monitor on, vt passes VESA_VSYNC_SUSPEND (eq '1').
> This is because consoles interpret '1' as pixels-off-but-monitor-on.
> The constant VESA_VSYNC_SUSPEND actually means monitor-vsync-off. And
> the argument used for monitor-vsync-off is VESA_VSYNC_SUSPEND+1.
>
> To fix this by splitting blank into two parameters, blank and blank_mode.
> The new blank is a boolean to control the display blanking. If cleared,
> the console creates display output, if set the console does not. The
> new parameter blank_mode specifies the VESA blank mode for the monitor
> and equals VESA DPMS levels. If blank is set, blank_mode gives a hint
> to the console, on how to set up the signal to the monitor.
>
> The actual interpretation is up to the console. Newportcon and sticon
> only handle blank or not-blank. Fbcon and vgacon implement blank plus
> the VESA DPMS handling. The implementation of both consoles is again
> somewhat confusing because types and values do not match. Clean up
> both with the new blank/blank_mode logic.
>
> Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
> ---
> drivers/tty/vt/vt.c | 11 ++++----
> drivers/video/console/dummycon.c | 4 +--
> drivers/video/console/newport_con.c | 4 +--
> drivers/video/console/sticon.c | 4 +--
> drivers/video/console/vgacon.c | 44 +++++++++++++++--------------
> drivers/video/fbdev/core/fbcon.c | 19 +++++++------
> include/linux/console.h | 9 ++++--
> 7 files changed, 51 insertions(+), 44 deletions(-)
>
> diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
> index 9e7b4419b422..f762c965351d 100644
> --- a/drivers/tty/vt/vt.c
> +++ b/drivers/tty/vt/vt.c
> @@ -4671,7 +4671,7 @@ void do_blank_screen(bool 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, false);
> + vc->vc_sw->con_blank(vc, true, vesa_blank_mode, false);
I hate adding random bool to function parameters as now you need to go
look them up to try to determine exactly what happened.
Why not just 2 different callbacks:
> -static bool vgacon_blank(struct vc_data *c, enum vesa_blank_mode blank,
> +static bool vgacon_blank(struct vc_data *c, bool blank, enum vesa_blank_mode blank_mode,
> bool mode_switch)
> {
> - switch (blank) {
> - case VESA_NO_BLANKING: /* Unblank */
> + if (blank) {
> + switch (blank_mode) {
> + 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;
> + }
> + vgacon_set_origin(c);
> + scr_memsetw((void *)vga_vram_base, BLANK,
> + c->vc_screenbuf_size);
> + if (mode_switch)
> + vga_is_gfx = true;
> + return 1;
> + default: /* VESA blanking */
> + if (vga_video_type == VIDEO_TYPE_VGAC) {
> + vga_vesa_blank(&vgastate, blank_mode);
> + vga_vesa_blanked = blank_mode;
> + }
> + return 0;
> + }
> + } else { /* Unblank */
> if (vga_vesa_blanked) {
> vga_vesa_unblank(&vgastate);
> vga_vesa_blanked = VESA_NO_BLANKING;
> @@ -814,24 +834,6 @@ static bool vgacon_blank(struct vc_data *c, enum vesa_blank_mode blank,
> vga_is_gfx = false;
> /* Tell console.c that it has to restore the screen itself */
> return 1;
> - case VESA_VSYNC_SUSPEND: /* Normal blanking */
> - if (!mode_switch && vga_video_type == VIDEO_TYPE_VGAC) {
> - vga_pal_blank(&vgastate);
> - vga_palette_blanked = true;
> - return 0;
> - }
> - vgacon_set_origin(c);
> - scr_memsetw((void *) vga_vram_base, BLANK,
> - c->vc_screenbuf_size);
> - if (mode_switch)
> - vga_is_gfx = true;
> - return 1;
> - default: /* VESA blanking */
> - if (vga_video_type == VIDEO_TYPE_VGAC) {
> - vga_vesa_blank(&vgastate, blank - 1);
> - vga_vesa_blanked = blank;
> - }
> - return 0;
> }
This can be vgacon_blank() and vgacon_unblank(), right? That way we
have a hint as to what is happening and don't have to try to remember
that a bool as parameter 2 is blank/unblank.
thanks,
greg k-h
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 1/2] vt: Use boolean as parameter to do_blank_screen() and do_unblank_screen()
2026-10-12 9:27 ` [PATCH 1/2] vt: Use boolean as parameter to do_blank_screen() and do_unblank_screen() Thomas Zimmermann
@ 2026-10-12 11:30 ` Greg KH
2026-10-12 12:28 ` Thomas Zimmermann
0 siblings, 1 reply; 9+ messages in thread
From: Greg KH @ 2026-10-12 11:30 UTC (permalink / raw)
To: Thomas Zimmermann
Cc: jirislaby, deller, James.Bottomley, simona, linux-kernel,
linux-serial, linux-fbdev, linux-parisc, sashiko-reviews
On Mon, Oct 12, 2026 at 11:27:38AM +0200, Thomas Zimmermann wrote:
> The parameters to do_blank_screen() and do_unblank_screen() signal
> whether the call is part of a switch between text and graphics mode.
> Convert to boolean. No functional changes.
>
> Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
> ---
> drivers/tty/vt/vt.c | 20 ++++++++++----------
> drivers/tty/vt/vt_ioctl.c | 12 ++++++------
> drivers/video/fbdev/core/fbcon.c | 4 ++--
> include/linux/vt_kern.h | 5 +++--
> 4 files changed, 21 insertions(+), 20 deletions(-)
>
> diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
> index 57edf37495a8..9e7b4419b422 100644
> --- a/drivers/tty/vt/vt.c
> +++ b/drivers/tty/vt/vt.c
> @@ -3374,7 +3374,7 @@ static void console_callback(struct work_struct *ignored)
> scrollback_delta = 0;
> }
> if (blank_timer_expired) {
> - do_blank_screen(0);
> + do_blank_screen(false);
Same type of comment here, this bool doesn't really tell what is
happening at all (not your fault, 0/1 doesn't either.)
I'm all for this patch but shouldn't this be fixed up to be 2 different
named functions entirely?
thanks,
greg k-h
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 2/2] vt: Distinguish between blanking and VESA blank mode in con_blank
2026-10-12 11:29 ` Greg KH
@ 2026-10-12 12:08 ` Thomas Zimmermann
0 siblings, 0 replies; 9+ messages in thread
From: Thomas Zimmermann @ 2026-10-12 12:08 UTC (permalink / raw)
To: Greg KH
Cc: jirislaby, deller, James.Bottomley, simona, linux-kernel,
linux-serial, linux-fbdev, linux-parisc, sashiko-reviews
Hi
Am 12.10.26 um 13:29 schrieb Greg KH:
> On Mon, Oct 12, 2026 at 11:27:39AM +0200, Thomas Zimmermann wrote:
>> The con_blank callback in struct consw encodes blanking and display
>> blank mode in a single parameter named blank. Its semantics equal
>> the FB_BLANK constants from the fbdev subsystems. Yet it is of type
>> enum vesa_blank_mode, which describes VESA DPMS levels of the attached
>> monitor. Although related, this is something else.
>>
>> For this reason, calls to con_blank fill the blank parameter with
>> values that appear non-sensical at first. For example, to blank the
>> console, but keep the monitor on, vt passes VESA_VSYNC_SUSPEND (eq '1').
>> This is because consoles interpret '1' as pixels-off-but-monitor-on.
>> The constant VESA_VSYNC_SUSPEND actually means monitor-vsync-off. And
>> the argument used for monitor-vsync-off is VESA_VSYNC_SUSPEND+1.
>>
>> To fix this by splitting blank into two parameters, blank and blank_mode.
>> The new blank is a boolean to control the display blanking. If cleared,
>> the console creates display output, if set the console does not. The
>> new parameter blank_mode specifies the VESA blank mode for the monitor
>> and equals VESA DPMS levels. If blank is set, blank_mode gives a hint
>> to the console, on how to set up the signal to the monitor.
>>
>> The actual interpretation is up to the console. Newportcon and sticon
>> only handle blank or not-blank. Fbcon and vgacon implement blank plus
>> the VESA DPMS handling. The implementation of both consoles is again
>> somewhat confusing because types and values do not match. Clean up
>> both with the new blank/blank_mode logic.
>>
>> Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
>> ---
>> drivers/tty/vt/vt.c | 11 ++++----
>> drivers/video/console/dummycon.c | 4 +--
>> drivers/video/console/newport_con.c | 4 +--
>> drivers/video/console/sticon.c | 4 +--
>> drivers/video/console/vgacon.c | 44 +++++++++++++++--------------
>> drivers/video/fbdev/core/fbcon.c | 19 +++++++------
>> include/linux/console.h | 9 ++++--
>> 7 files changed, 51 insertions(+), 44 deletions(-)
>>
>> diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
>> index 9e7b4419b422..f762c965351d 100644
>> --- a/drivers/tty/vt/vt.c
>> +++ b/drivers/tty/vt/vt.c
>> @@ -4671,7 +4671,7 @@ void do_blank_screen(bool 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, false);
>> + vc->vc_sw->con_blank(vc, true, vesa_blank_mode, false);
> I hate adding random bool to function parameters as now you need to go
> look them up to try to determine exactly what happened.
>
> Why not just 2 different callbacks:
Sounds like a cleaner design.
>
>> -static bool vgacon_blank(struct vc_data *c, enum vesa_blank_mode blank,
>> +static bool vgacon_blank(struct vc_data *c, bool blank, enum vesa_blank_mode blank_mode,
>> bool mode_switch)
>> {
>> - switch (blank) {
>> - case VESA_NO_BLANKING: /* Unblank */
>> + if (blank) {
>> + switch (blank_mode) {
>> + 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;
>> + }
>> + vgacon_set_origin(c);
>> + scr_memsetw((void *)vga_vram_base, BLANK,
>> + c->vc_screenbuf_size);
>> + if (mode_switch)
>> + vga_is_gfx = true;
>> + return 1;
>> + default: /* VESA blanking */
>> + if (vga_video_type == VIDEO_TYPE_VGAC) {
>> + vga_vesa_blank(&vgastate, blank_mode);
>> + vga_vesa_blanked = blank_mode;
>> + }
>> + return 0;
>> + }
>> + } else { /* Unblank */
>> if (vga_vesa_blanked) {
>> vga_vesa_unblank(&vgastate);
>> vga_vesa_blanked = VESA_NO_BLANKING;
>> @@ -814,24 +834,6 @@ static bool vgacon_blank(struct vc_data *c, enum vesa_blank_mode blank,
>> vga_is_gfx = false;
>> /* Tell console.c that it has to restore the screen itself */
>> return 1;
>> - case VESA_VSYNC_SUSPEND: /* Normal blanking */
>> - if (!mode_switch && vga_video_type == VIDEO_TYPE_VGAC) {
>> - vga_pal_blank(&vgastate);
>> - vga_palette_blanked = true;
>> - return 0;
>> - }
>> - vgacon_set_origin(c);
>> - scr_memsetw((void *) vga_vram_base, BLANK,
>> - c->vc_screenbuf_size);
>> - if (mode_switch)
>> - vga_is_gfx = true;
>> - return 1;
>> - default: /* VESA blanking */
>> - if (vga_video_type == VIDEO_TYPE_VGAC) {
>> - vga_vesa_blank(&vgastate, blank - 1);
>> - vga_vesa_blanked = blank;
>> - }
>> - return 0;
>> }
> This can be vgacon_blank() and vgacon_unblank(), right? That way we
> have a hint as to what is happening and don't have to try to remember
> that a bool as parameter 2 is blank/unblank.
Yeah, we can do that. We'd also not need the VESA mode in the unblank
case. It's always VESA_NO_BLANKING there.
Best regards
Thomas
>
> thanks,
>
> greg k-h
>
--
--
Thomas Zimmermann
Graphics Driver Developer
SUSE Software Solutions Germany GmbH
Frankenstr. 146, 90461 Nürnberg, Germany, www.suse.com
GF: Stefan Gaiser, Jochen Jaser, Abhinav Puri, (HRB 36809, AG Nürnberg)
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 1/2] vt: Use boolean as parameter to do_blank_screen() and do_unblank_screen()
2026-10-12 11:30 ` Greg KH
@ 2026-10-12 12:28 ` Thomas Zimmermann
2026-10-12 12:41 ` Thomas Zimmermann
0 siblings, 1 reply; 9+ messages in thread
From: Thomas Zimmermann @ 2026-10-12 12:28 UTC (permalink / raw)
To: Greg KH
Cc: jirislaby, deller, James.Bottomley, simona, linux-kernel,
linux-serial, linux-fbdev, linux-parisc, sashiko-reviews
Hi
Am 12.10.26 um 13:30 schrieb Greg KH:
> On Mon, Oct 12, 2026 at 11:27:38AM +0200, Thomas Zimmermann wrote:
>> The parameters to do_blank_screen() and do_unblank_screen() signal
>> whether the call is part of a switch between text and graphics mode.
>> Convert to boolean. No functional changes.
>>
>> Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
>> ---
>> drivers/tty/vt/vt.c | 20 ++++++++++----------
>> drivers/tty/vt/vt_ioctl.c | 12 ++++++------
>> drivers/video/fbdev/core/fbcon.c | 4 ++--
>> include/linux/vt_kern.h | 5 +++--
>> 4 files changed, 21 insertions(+), 20 deletions(-)
>>
>> diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
>> index 57edf37495a8..9e7b4419b422 100644
>> --- a/drivers/tty/vt/vt.c
>> +++ b/drivers/tty/vt/vt.c
>> @@ -3374,7 +3374,7 @@ static void console_callback(struct work_struct *ignored)
>> scrollback_delta = 0;
>> }
>> if (blank_timer_expired) {
>> - do_blank_screen(0);
>> + do_blank_screen(false);
> Same type of comment here, this bool doesn't really tell what is
> happening at all (not your fault, 0/1 doesn't either.)
>
> I'm all for this patch but shouldn't this be fixed up to be 2 different
> named functions entirely?
Can you elaborate? Do you mean there should be a separate helper and
callback for switching between KD_TEXT and KD_GRAPHICS?
Looking through the *_blank_screen() helpers and the console
implementations, I think we'd mostly duplicate code. Mode-switching and
blanking are tightly coupled. Semantics get a bit cleaner with the
change you proposed to patch 1, I think.
Or, we'd have to untangle all of it. The result would likely look
something like this:
vt_set_mode(kd_mode)
{
if (kd_mode == GRAPHICS)
do_blank_screen() /* blank before going to graphics */
consw->con_setmode(kd_mode)
if (kd_mode != GRAPHICS)
do_unblank_screen() /* unblank after coming back from graphics */
}
Best regards
Thomas
>
> thanks,
>
> greg k-h
--
--
Thomas Zimmermann
Graphics Driver Developer
SUSE Software Solutions Germany GmbH
Frankenstr. 146, 90461 Nürnberg, Germany, www.suse.com
GF: Stefan Gaiser, Jochen Jaser, Abhinav Puri, (HRB 36809, AG Nürnberg)
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 1/2] vt: Use boolean as parameter to do_blank_screen() and do_unblank_screen()
2026-10-12 12:28 ` Thomas Zimmermann
@ 2026-10-12 12:41 ` Thomas Zimmermann
2026-10-12 16:13 ` Greg KH
0 siblings, 1 reply; 9+ messages in thread
From: Thomas Zimmermann @ 2026-10-12 12:41 UTC (permalink / raw)
To: Greg KH
Cc: jirislaby, deller, James.Bottomley, simona, linux-kernel,
linux-serial, linux-fbdev, linux-parisc, sashiko-reviews
Am 12.10.26 um 14:28 schrieb Thomas Zimmermann:
> Hi
>
> Am 12.10.26 um 13:30 schrieb Greg KH:
>> On Mon, Oct 12, 2026 at 11:27:38AM +0200, Thomas Zimmermann wrote:
>>> The parameters to do_blank_screen() and do_unblank_screen() signal
>>> whether the call is part of a switch between text and graphics mode.
>>> Convert to boolean. No functional changes.
>>>
>>> Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
>>> ---
>>> drivers/tty/vt/vt.c | 20 ++++++++++----------
>>> drivers/tty/vt/vt_ioctl.c | 12 ++++++------
>>> drivers/video/fbdev/core/fbcon.c | 4 ++--
>>> include/linux/vt_kern.h | 5 +++--
>>> 4 files changed, 21 insertions(+), 20 deletions(-)
>>>
>>> diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
>>> index 57edf37495a8..9e7b4419b422 100644
>>> --- a/drivers/tty/vt/vt.c
>>> +++ b/drivers/tty/vt/vt.c
>>> @@ -3374,7 +3374,7 @@ static void console_callback(struct
>>> work_struct *ignored)
>>> scrollback_delta = 0;
>>> }
>>> if (blank_timer_expired) {
>>> - do_blank_screen(0);
>>> + do_blank_screen(false);
>> Same type of comment here, this bool doesn't really tell what is
>> happening at all (not your fault, 0/1 doesn't either.)
>>
>> I'm all for this patch but shouldn't this be fixed up to be 2 different
>> named functions entirely?
>
> Can you elaborate? Do you mean there should be a separate helper and
> callback for switching between KD_TEXT and KD_GRAPHICS?
>
> Looking through the *_blank_screen() helpers and the console
> implementations, I think we'd mostly duplicate code. Mode-switching
> and blanking are tightly coupled. Semantics get a bit cleaner with
> the change you proposed to patch 1, I think.
And looking even further, it's not entirely clear why consw.con_blank
even receives the mode_switch parameter. The consoles track it with
some internal state, but all of the mode information is available in
struct vc_data.vc_mode as well. I think mode_switch and similar
booleans could be replaced with using vc_mode directly.
--
--
Thomas Zimmermann
Graphics Driver Developer
SUSE Software Solutions Germany GmbH
Frankenstr. 146, 90461 Nürnberg, Germany, www.suse.com
GF: Stefan Gaiser, Jochen Jaser, Abhinav Puri, (HRB 36809, AG Nürnberg)
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 1/2] vt: Use boolean as parameter to do_blank_screen() and do_unblank_screen()
2026-10-12 12:41 ` Thomas Zimmermann
@ 2026-10-12 16:13 ` Greg KH
0 siblings, 0 replies; 9+ messages in thread
From: Greg KH @ 2026-10-12 16:13 UTC (permalink / raw)
To: Thomas Zimmermann
Cc: jirislaby, deller, James.Bottomley, simona, linux-kernel,
linux-serial, linux-fbdev, linux-parisc, sashiko-reviews
On Mon, Oct 12, 2026 at 02:41:34PM +0200, Thomas Zimmermann wrote:
>
>
> Am 12.10.26 um 14:28 schrieb Thomas Zimmermann:
> > Hi
> >
> > Am 12.10.26 um 13:30 schrieb Greg KH:
> > > On Mon, Oct 12, 2026 at 11:27:38AM +0200, Thomas Zimmermann wrote:
> > > > The parameters to do_blank_screen() and do_unblank_screen() signal
> > > > whether the call is part of a switch between text and graphics mode.
> > > > Convert to boolean. No functional changes.
> > > >
> > > > Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
> > > > ---
> > > > drivers/tty/vt/vt.c | 20 ++++++++++----------
> > > > drivers/tty/vt/vt_ioctl.c | 12 ++++++------
> > > > drivers/video/fbdev/core/fbcon.c | 4 ++--
> > > > include/linux/vt_kern.h | 5 +++--
> > > > 4 files changed, 21 insertions(+), 20 deletions(-)
> > > >
> > > > diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
> > > > index 57edf37495a8..9e7b4419b422 100644
> > > > --- a/drivers/tty/vt/vt.c
> > > > +++ b/drivers/tty/vt/vt.c
> > > > @@ -3374,7 +3374,7 @@ static void console_callback(struct
> > > > work_struct *ignored)
> > > > scrollback_delta = 0;
> > > > }
> > > > if (blank_timer_expired) {
> > > > - do_blank_screen(0);
> > > > + do_blank_screen(false);
> > > Same type of comment here, this bool doesn't really tell what is
> > > happening at all (not your fault, 0/1 doesn't either.)
> > >
> > > I'm all for this patch but shouldn't this be fixed up to be 2 different
> > > named functions entirely?
> >
> > Can you elaborate? Do you mean there should be a separate helper and
> > callback for switching between KD_TEXT and KD_GRAPHICS?
> >
> > Looking through the *_blank_screen() helpers and the console
> > implementations, I think we'd mostly duplicate code. Mode-switching and
> > blanking are tightly coupled. Semantics get a bit cleaner with the
> > change you proposed to patch 1, I think.
>
> And looking even further, it's not entirely clear why consw.con_blank even
> receives the mode_switch parameter. The consoles track it with some
> internal state, but all of the mode information is available in struct
> vc_data.vc_mode as well. I think mode_switch and similar booleans could be
> replaced with using vc_mode directly.
Yeah, that would be best overall, as the structure has the "state"
needed, no need to keep it separate in random variables. This is some
old code before we all learned not to have global variables :)
thanks,
greg k-h
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2026-10-12 16:13 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-12 9:27 [PATCH 0/2] vt: Simplify console-blanking interface Thomas Zimmermann
2026-10-12 9:27 ` [PATCH 1/2] vt: Use boolean as parameter to do_blank_screen() and do_unblank_screen() Thomas Zimmermann
2026-10-12 11:30 ` Greg KH
2026-10-12 12:28 ` Thomas Zimmermann
2026-10-12 12:41 ` Thomas Zimmermann
2026-10-12 16:13 ` Greg KH
2026-10-12 9:27 ` [PATCH 2/2] vt: Distinguish between blanking and VESA blank mode in con_blank Thomas Zimmermann
2026-10-12 11:29 ` Greg KH
2026-10-12 12:08 ` Thomas Zimmermann
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®