* [PATCH v2 1/4] fbdev: Wrap user-invoked calls to fb_set_var() in helper
2026-05-22 12:28 [PATCH v2 0/4] fbdev: Internalize fbcon Thomas Zimmermann
@ 2026-05-22 12:28 ` Thomas Zimmermann
2026-05-25 8:52 ` Claude review: " Claude Code Review Bot
2026-05-22 12:28 ` [PATCH v2 2/4] fbdev: Wrap user-invoked calls to fb_blank() " Thomas Zimmermann
` (4 subsequent siblings)
5 siblings, 1 reply; 13+ messages in thread
From: Thomas Zimmermann @ 2026-05-22 12:28 UTC (permalink / raw)
To: deller, simona, airlied, lukas, maddy, mpe, npiggin, chleroy
Cc: dri-devel, linux-fbdev, linuxppc-dev, Thomas Zimmermann
Handle fbcon during display updates in fb_set_var_from_user(). Check
with fbcon if the mode change is possible, update hardware state and
finally update fbcon. Update all callers.
Only the FBIOPUT_VSCREENINFO ioctl currently does all steps. Other
mode-changes callers in sysfs and driver code are missing fbcon-related
steps.
With the new helper, ps3fb and sh_mobile_lcdcfb no longer maintain
fbcon state themselves.
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
---
drivers/video/fbdev/core/fb_chrdev.c | 6 +-----
drivers/video/fbdev/core/fbcon.c | 2 --
drivers/video/fbdev/core/fbmem.c | 13 +++++++++++++
drivers/video/fbdev/core/fbsysfs.c | 4 +---
drivers/video/fbdev/ps3fb.c | 5 +----
drivers/video/fbdev/sh_mobile_lcdcfb.c | 5 +----
include/linux/fb.h | 2 ++
7 files changed, 19 insertions(+), 18 deletions(-)
diff --git a/drivers/video/fbdev/core/fb_chrdev.c b/drivers/video/fbdev/core/fb_chrdev.c
index 4ebd16b7e3b8..54f926fb411b 100644
--- a/drivers/video/fbdev/core/fb_chrdev.c
+++ b/drivers/video/fbdev/core/fb_chrdev.c
@@ -85,11 +85,7 @@ static long do_fb_ioctl(struct fb_info *info, unsigned int cmd,
var.activate &= ~FB_ACTIVATE_KD_TEXT;
console_lock();
lock_fb_info(info);
- ret = fbcon_modechange_possible(info, &var);
- if (!ret)
- ret = fb_set_var(info, &var);
- if (!ret)
- fbcon_update_vcs(info, var.activate & FB_ACTIVATE_ALL);
+ ret = fb_set_var_from_user(info, &var);
unlock_fb_info(info);
console_unlock();
if (!ret && copy_to_user(argp, &var, sizeof(var)))
diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c
index b0e3e765360d..50b84cd32938 100644
--- a/drivers/video/fbdev/core/fbcon.c
+++ b/drivers/video/fbdev/core/fbcon.c
@@ -2699,7 +2699,6 @@ void fbcon_update_vcs(struct fb_info *info, bool all)
else
fbcon_modechanged(info);
}
-EXPORT_SYMBOL(fbcon_update_vcs);
/* let fbcon check if it supports a new screen resolution */
int fbcon_modechange_possible(struct fb_info *info, struct fb_var_screeninfo *var)
@@ -2727,7 +2726,6 @@ int fbcon_modechange_possible(struct fb_info *info, struct fb_var_screeninfo *va
return 0;
}
-EXPORT_SYMBOL_GPL(fbcon_modechange_possible);
int fbcon_mode_deleted(struct fb_info *info,
struct fb_videomode *mode)
diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c
index 30f2b59c47bf..d37a1039e221 100644
--- a/drivers/video/fbdev/core/fbmem.c
+++ b/drivers/video/fbdev/core/fbmem.c
@@ -346,6 +346,19 @@ fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var)
}
EXPORT_SYMBOL(fb_set_var);
+int fb_set_var_from_user(struct fb_info *info, struct fb_var_screeninfo *var)
+{
+ int ret = fbcon_modechange_possible(info, var);
+
+ if (!ret)
+ ret = fb_set_var(info, var);
+ if (!ret)
+ fbcon_update_vcs(info, var->activate & FB_ACTIVATE_ALL);
+
+ return ret;
+}
+EXPORT_SYMBOL(fb_set_var_from_user);
+
static void fb_lcd_notify_blank(struct fb_info *info)
{
int power;
diff --git a/drivers/video/fbdev/core/fbsysfs.c b/drivers/video/fbdev/core/fbsysfs.c
index baa2bae0fb5b..5ece236e6252 100644
--- a/drivers/video/fbdev/core/fbsysfs.c
+++ b/drivers/video/fbdev/core/fbsysfs.c
@@ -19,9 +19,7 @@ static int activate(struct fb_info *fb_info, struct fb_var_screeninfo *var)
var->activate |= FB_ACTIVATE_FORCE;
console_lock();
lock_fb_info(fb_info);
- err = fb_set_var(fb_info, var);
- if (!err)
- fbcon_update_vcs(fb_info, var->activate & FB_ACTIVATE_ALL);
+ err = fb_set_var_from_user(fb_info, var);
unlock_fb_info(fb_info);
console_unlock();
if (err)
diff --git a/drivers/video/fbdev/ps3fb.c b/drivers/video/fbdev/ps3fb.c
index dbcda307f6a6..1376d19b19ae 100644
--- a/drivers/video/fbdev/ps3fb.c
+++ b/drivers/video/fbdev/ps3fb.c
@@ -29,7 +29,6 @@
#include <linux/freezer.h>
#include <linux/uaccess.h>
#include <linux/fb.h>
-#include <linux/fbcon.h>
#include <linux/init.h>
#include <asm/cell-regs.h>
@@ -830,9 +829,7 @@ static int ps3fb_ioctl(struct fb_info *info, unsigned int cmd,
/* Force, in case only special bits changed */
var.activate |= FB_ACTIVATE_FORCE;
par->new_mode_id = val;
- retval = fb_set_var(info, &var);
- if (!retval)
- fbcon_update_vcs(info, var.activate & FB_ACTIVATE_ALL);
+ retval = fb_set_var_from_user(info, &var);
console_unlock();
}
break;
diff --git a/drivers/video/fbdev/sh_mobile_lcdcfb.c b/drivers/video/fbdev/sh_mobile_lcdcfb.c
index 72969fe8e513..e8324b01700f 100644
--- a/drivers/video/fbdev/sh_mobile_lcdcfb.c
+++ b/drivers/video/fbdev/sh_mobile_lcdcfb.c
@@ -15,7 +15,6 @@
#include <linux/ctype.h>
#include <linux/dma-mapping.h>
#include <linux/delay.h>
-#include <linux/fbcon.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/ioctl.h>
@@ -1768,11 +1767,9 @@ static void sh_mobile_fb_reconfig(struct fb_info *info)
var.height = ch->display.height;
var.activate = FB_ACTIVATE_NOW;
- if (fb_set_var(info, &var) < 0)
+ if (fb_set_var_from_user(info, &var) < 0)
/* Couldn't reconfigure, hopefully, can continue as before */
return;
-
- fbcon_update_vcs(info, true);
}
/*
diff --git a/include/linux/fb.h b/include/linux/fb.h
index 5178a33c752c..88680a7cabd5 100644
--- a/include/linux/fb.h
+++ b/include/linux/fb.h
@@ -533,6 +533,8 @@ extern int fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var);
extern int fb_pan_display(struct fb_info *info, struct fb_var_screeninfo *var);
extern int fb_blank(struct fb_info *info, int blank);
+int fb_set_var_from_user(struct fb_info *info, struct fb_var_screeninfo *var);
+
/*
* Helpers for framebuffers in I/O memory
*/
--
2.54.0
^ permalink raw reply related [flat|nested] 13+ messages in thread* Claude review: fbdev: Wrap user-invoked calls to fb_set_var() in helper
2026-05-22 12:28 ` [PATCH v2 1/4] fbdev: Wrap user-invoked calls to fb_set_var() in helper Thomas Zimmermann
@ 2026-05-25 8:52 ` Claude Code Review Bot
0 siblings, 0 replies; 13+ messages in thread
From: Claude Code Review Bot @ 2026-05-25 8:52 UTC (permalink / raw)
To: dri-devel-reviews
Patch Review
Creates `fb_set_var_from_user()` in `fbmem.c` that bundles `fbcon_modechange_possible()` + `fb_set_var()` + `fbcon_update_vcs()` into a single call, then converts all callers.
The chrdev ioctl path (`fb_chrdev.c`) was already doing all three steps — this is a direct refactor with no behavior change.
The sysfs `activate()` path (`fbsysfs.c`) was missing the `fbcon_modechange_possible()` check. The new helper adds it, which is a correctness improvement — mode changes through sysfs will now be properly validated against fbcon constraints.
The `ps3fb` driver was also missing the `fbcon_modechange_possible()` check, which is similarly a correctness improvement.
**Semantic change in `sh_mobile_lcdcfb`:** The original code hardcoded `fbcon_update_vcs(info, true)` (update all VCs). The new helper passes `var->activate & FB_ACTIVATE_ALL`. Since `sh_mobile_fb_reconfig()` sets `var.activate = FB_ACTIVATE_NOW` (which is 0), `FB_ACTIVATE_NOW & FB_ACTIVATE_ALL` evaluates to `false`, meaning only the foreground VC gets updated instead of all VCs. This is a functional change — whether it's intentional or a regression depends on the driver's requirements. It's worth documenting in the commit message if intentional, or fixing if not.
The removal of `EXPORT_SYMBOL` for `fbcon_update_vcs` and `EXPORT_SYMBOL_GPL` for `fbcon_modechange_possible` is correct since patches 1-3 eliminate all out-of-module callers before patch 4 fully internalizes them.
The new `fb_set_var_from_user` is `EXPORT_SYMBOL` which is appropriate since `ps3fb` and `sh_mobile_lcdcfb` are separate drivers that need it.
---
Generated by Claude Code Patch Reviewer
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH v2 2/4] fbdev: Wrap user-invoked calls to fb_blank() in helper
2026-05-22 12:28 [PATCH v2 0/4] fbdev: Internalize fbcon Thomas Zimmermann
2026-05-22 12:28 ` [PATCH v2 1/4] fbdev: Wrap user-invoked calls to fb_set_var() in helper Thomas Zimmermann
@ 2026-05-22 12:28 ` Thomas Zimmermann
2026-05-25 8:52 ` Claude review: " Claude Code Review Bot
2026-05-22 12:28 ` [PATCH v2 3/4] fbdev: Wrap fbcon updates from vga-switcheroo " Thomas Zimmermann
` (3 subsequent siblings)
5 siblings, 1 reply; 13+ messages in thread
From: Thomas Zimmermann @ 2026-05-22 12:28 UTC (permalink / raw)
To: deller, simona, airlied, lukas, maddy, mpe, npiggin, chleroy
Cc: dri-devel, linux-fbdev, linuxppc-dev, Thomas Zimmermann
Handle fbcon during blanking in fb_blank_from_user(). First blank the
hardware, then blank fbcon. Same for unblanking. Update all callers and
resolve the duplicated logic.
With the new helper, fbdev's sysfb code no longer maintains fbcon state
by itself.
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
---
drivers/video/fbdev/core/fb_chrdev.c | 4 +---
drivers/video/fbdev/core/fb_internal.h | 1 +
drivers/video/fbdev/core/fbmem.c | 10 ++++++++++
drivers/video/fbdev/core/fbsysfs.c | 5 +----
4 files changed, 13 insertions(+), 7 deletions(-)
diff --git a/drivers/video/fbdev/core/fb_chrdev.c b/drivers/video/fbdev/core/fb_chrdev.c
index 54f926fb411b..035e67d2c28f 100644
--- a/drivers/video/fbdev/core/fb_chrdev.c
+++ b/drivers/video/fbdev/core/fb_chrdev.c
@@ -138,9 +138,7 @@ static long do_fb_ioctl(struct fb_info *info, unsigned int cmd,
return -EINVAL;
console_lock();
lock_fb_info(info);
- ret = fb_blank(info, arg);
- /* might again call into fb_blank */
- fbcon_fb_blanked(info, arg);
+ ret = fb_blank_from_user(info, arg);
unlock_fb_info(info);
console_unlock();
break;
diff --git a/drivers/video/fbdev/core/fb_internal.h b/drivers/video/fbdev/core/fb_internal.h
index 613832d335fe..62e75bf15b9b 100644
--- a/drivers/video/fbdev/core/fb_internal.h
+++ b/drivers/video/fbdev/core/fb_internal.h
@@ -44,6 +44,7 @@ extern struct fb_info *registered_fb[FB_MAX];
extern int num_registered_fb;
struct fb_info *get_fb_info(unsigned int idx);
void put_fb_info(struct fb_info *fb_info);
+int fb_blank_from_user(struct fb_info *info, int blank);
/* fb_procfs.c */
#if defined(CONFIG_FB_DEVICE)
diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c
index d37a1039e221..1a6758653b64 100644
--- a/drivers/video/fbdev/core/fbmem.c
+++ b/drivers/video/fbdev/core/fbmem.c
@@ -422,6 +422,16 @@ int fb_blank(struct fb_info *info, int blank)
}
EXPORT_SYMBOL(fb_blank);
+int fb_blank_from_user(struct fb_info *info, int blank)
+{
+ int ret = fb_blank(info, blank);
+
+ /* might again call into fb_blank */
+ fbcon_fb_blanked(info, blank);
+
+ return ret;
+}
+
static int fb_check_foreignness(struct fb_info *fi)
{
const bool foreign_endian = fi->flags & FBINFO_FOREIGN_ENDIAN;
diff --git a/drivers/video/fbdev/core/fbsysfs.c b/drivers/video/fbdev/core/fbsysfs.c
index 5ece236e6252..d9743ef35355 100644
--- a/drivers/video/fbdev/core/fbsysfs.c
+++ b/drivers/video/fbdev/core/fbsysfs.c
@@ -7,7 +7,6 @@
#include <linux/console.h>
#include <linux/fb.h>
-#include <linux/fbcon.h>
#include <linux/major.h>
#include "fb_internal.h"
@@ -229,9 +228,7 @@ static ssize_t store_blank(struct device *device,
arg = simple_strtoul(buf, &last, 0);
console_lock();
- err = fb_blank(fb_info, arg);
- /* might again call into fb_blank */
- fbcon_fb_blanked(fb_info, arg);
+ err = fb_blank_from_user(fb_info, arg);
console_unlock();
if (err < 0)
return err;
--
2.54.0
^ permalink raw reply related [flat|nested] 13+ messages in thread* Claude review: fbdev: Wrap user-invoked calls to fb_blank() in helper
2026-05-22 12:28 ` [PATCH v2 2/4] fbdev: Wrap user-invoked calls to fb_blank() " Thomas Zimmermann
@ 2026-05-25 8:52 ` Claude Code Review Bot
0 siblings, 0 replies; 13+ messages in thread
From: Claude Code Review Bot @ 2026-05-25 8:52 UTC (permalink / raw)
To: dri-devel-reviews
Patch Review
Creates `fb_blank_from_user()` in `fbmem.c` that bundles `fb_blank()` + `fbcon_fb_blanked()`.
The helper correctly preserves the existing behavior of calling `fbcon_fb_blanked()` unconditionally (even when `fb_blank()` fails), which matches both the chrdev and sysfs callers.
The declaration is placed in `fb_internal.h` rather than `fb.h` — this is appropriate since `fb_blank_from_user` is only called from within the fbdev core (chrdev and sysfs), unlike `fb_set_var_from_user` which is also called from external drivers.
The existing locking difference between chrdev (uses `lock_fb_info`) and sysfs (does not use `lock_fb_info`) is preserved by this patch. This is a pre-existing inconsistency, not introduced here.
Removal of `#include <linux/fbcon.h>` from `fbsysfs.c` is correct — it no longer directly calls any fbcon functions.
**No issues.**
---
Generated by Claude Code Patch Reviewer
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH v2 3/4] fbdev: Wrap fbcon updates from vga-switcheroo in helper
2026-05-22 12:28 [PATCH v2 0/4] fbdev: Internalize fbcon Thomas Zimmermann
2026-05-22 12:28 ` [PATCH v2 1/4] fbdev: Wrap user-invoked calls to fb_set_var() in helper Thomas Zimmermann
2026-05-22 12:28 ` [PATCH v2 2/4] fbdev: Wrap user-invoked calls to fb_blank() " Thomas Zimmermann
@ 2026-05-22 12:28 ` Thomas Zimmermann
2026-05-25 8:52 ` Claude review: " Claude Code Review Bot
2026-05-22 12:28 ` [PATCH v2 4/4] fbdev: Do not export fbcon from fbdev Thomas Zimmermann
` (2 subsequent siblings)
5 siblings, 1 reply; 13+ messages in thread
From: Thomas Zimmermann @ 2026-05-22 12:28 UTC (permalink / raw)
To: deller, simona, airlied, lukas, maddy, mpe, npiggin, chleroy
Cc: dri-devel, linux-fbdev, linuxppc-dev, Thomas Zimmermann
Handle console remapping in fbcon in fb_switch_output(). Vga-switcheroo
invokes this functionality before switching physical outputs to a new
graphics device. Open-coding fbcon state in vga-switcheroo exposed fbdev
implementation details.
Vga-switcheroo is used for switching physical outputs among graphics
hardware. This functionality is only supported by DRM drivers. A later
update will further move fb_switch_output() into DRM's fbdev emulation;
thus fully decoupling vga-switcheroo from fbdev.
v2:
- use '#if defined' (Helge)
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
---
drivers/gpu/vga/vga_switcheroo.c | 6 +++---
drivers/video/fbdev/core/fbmem.c | 10 ++++++++++
include/linux/fb.h | 1 +
3 files changed, 14 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/vga/vga_switcheroo.c b/drivers/gpu/vga/vga_switcheroo.c
index 8fe1ae3c71bb..22cf52b78b75 100644
--- a/drivers/gpu/vga/vga_switcheroo.c
+++ b/drivers/gpu/vga/vga_switcheroo.c
@@ -31,11 +31,9 @@
#define pr_fmt(fmt) "vga_switcheroo: " fmt
#include <linux/apple-gmux.h>
-#include <linux/console.h>
#include <linux/debugfs.h>
#include <linux/fb.h>
#include <linux/fs.h>
-#include <linux/fbcon.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/pm_domain.h>
@@ -735,8 +733,10 @@ static int vga_switchto_stage2(struct vga_switcheroo_client *new_client)
if (!active->driver_power_control)
set_audio_state(active->id, VGA_SWITCHEROO_OFF);
+#if defined(CONFIG_FB)
if (new_client->fb_info)
- fbcon_remap_all(new_client->fb_info);
+ fb_switch_outputs(new_client->fb_info);
+#endif
mutex_lock(&vgasr_priv.mux_hw_lock);
ret = vgasr_priv.handler->switchto(new_client->id);
diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c
index 1a6758653b64..ecadbc58abff 100644
--- a/drivers/video/fbdev/core/fbmem.c
+++ b/drivers/video/fbdev/core/fbmem.c
@@ -684,6 +684,16 @@ void fb_set_suspend(struct fb_info *info, int state)
}
EXPORT_SYMBOL(fb_set_suspend);
+/**
+ * fb_switch_outputs - framebuffer got the outputs from vga-switcheroo
+ * @info: framebuffer
+ */
+void fb_switch_outputs(struct fb_info *info)
+{
+ fbcon_remap_all(info);
+}
+EXPORT_SYMBOL(fb_switch_outputs);
+
static int __init fbmem_init(void)
{
int ret;
diff --git a/include/linux/fb.h b/include/linux/fb.h
index 88680a7cabd5..e9a26e82322a 100644
--- a/include/linux/fb.h
+++ b/include/linux/fb.h
@@ -608,6 +608,7 @@ void fb_pad_unaligned_buffer(u8 *dst, u32 d_pitch, const u8 *src, u32 idx, u32 h
u32 shift_high, u32 shift_low, u32 mod);
void fb_pad_aligned_buffer(u8 *dst, u32 d_pitch, const u8 *src, u32 s_pitch, u32 height);
extern void fb_set_suspend(struct fb_info *info, int state);
+extern void fb_switch_outputs(struct fb_info *info);
extern int fb_get_color_depth(struct fb_var_screeninfo *var,
struct fb_fix_screeninfo *fix);
extern int fb_get_options(const char *name, char **option);
--
2.54.0
^ permalink raw reply related [flat|nested] 13+ messages in thread* Claude review: fbdev: Wrap fbcon updates from vga-switcheroo in helper
2026-05-22 12:28 ` [PATCH v2 3/4] fbdev: Wrap fbcon updates from vga-switcheroo " Thomas Zimmermann
@ 2026-05-25 8:52 ` Claude Code Review Bot
0 siblings, 0 replies; 13+ messages in thread
From: Claude Code Review Bot @ 2026-05-25 8:52 UTC (permalink / raw)
To: dri-devel-reviews
Patch Review
Creates `fb_switch_outputs()` in `fbmem.c` that wraps `fbcon_remap_all()`.
The `#if defined(CONFIG_FB)` guard in `vga_switcheroo.c` is correct. I verified that the `VGA_SWITCHEROO` Kconfig has `depends on (FRAMEBUFFER_CONSOLE=n || FB=y)`, which guarantees that when `VGA_SWITCHEROO` is built, `CONFIG_FB=y` (not `=m`). So `#if defined(CONFIG_FB)` will always be true when this code is reachable, and the guard serves only as a compile-time safeguard for when `CONFIG_FB` is entirely disabled.
The removal of `#include <linux/console.h>` and `#include <linux/fbcon.h>` from `vga_switcheroo.c` is correct — vga-switcheroo no longer directly uses console or fbcon APIs.
The function is `EXPORT_SYMBOL` which is appropriate since vga_switcheroo is a separate module.
**No issues.**
---
Generated by Claude Code Patch Reviewer
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH v2 4/4] fbdev: Do not export fbcon from fbdev
2026-05-22 12:28 [PATCH v2 0/4] fbdev: Internalize fbcon Thomas Zimmermann
` (2 preceding siblings ...)
2026-05-22 12:28 ` [PATCH v2 3/4] fbdev: Wrap fbcon updates from vga-switcheroo " Thomas Zimmermann
@ 2026-05-22 12:28 ` Thomas Zimmermann
2026-05-25 8:52 ` Claude review: " Claude Code Review Bot
2026-05-22 13:59 ` [PATCH v2 0/4] fbdev: Internalize fbcon Helge Deller
2026-05-25 8:52 ` Claude review: " Claude Code Review Bot
5 siblings, 1 reply; 13+ messages in thread
From: Thomas Zimmermann @ 2026-05-22 12:28 UTC (permalink / raw)
To: deller, simona, airlied, lukas, maddy, mpe, npiggin, chleroy
Cc: dri-devel, linux-fbdev, linuxppc-dev, Thomas Zimmermann
There are no callers of fbcon outside fbdev. Move the declarations
into the internal header.
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
---
MAINTAINERS | 1 -
drivers/video/fbdev/core/fb_chrdev.c | 2 +-
drivers/video/fbdev/core/fbcon.c | 1 -
drivers/video/fbdev/core/fbcon.h | 50 +++++++++++++++++++++++++
drivers/video/fbdev/core/fbmem.c | 2 +-
include/linux/fbcon.h | 55 ----------------------------
6 files changed, 52 insertions(+), 59 deletions(-)
delete mode 100644 include/linux/fbcon.h
diff --git a/MAINTAINERS b/MAINTAINERS
index 6810710e7a57..0ed3ef0b466a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -10147,7 +10147,6 @@ F: drivers/video/fbdev/core/fbcon_rotate.h
F: drivers/video/fbdev/core/fbcon_ud.c
F: drivers/video/fbdev/core/softcursor.c
F: drivers/video/fbdev/core/tileblit.c
-F: include/linux/fbcon.h
F: include/linux/font.h
F: lib/fonts/
diff --git a/drivers/video/fbdev/core/fb_chrdev.c b/drivers/video/fbdev/core/fb_chrdev.c
index 035e67d2c28f..ba1d0bc214c5 100644
--- a/drivers/video/fbdev/core/fb_chrdev.c
+++ b/drivers/video/fbdev/core/fb_chrdev.c
@@ -3,10 +3,10 @@
#include <linux/compat.h>
#include <linux/console.h>
#include <linux/fb.h>
-#include <linux/fbcon.h>
#include <linux/major.h>
#include "fb_internal.h"
+#include "fbcon.h"
/*
* We hold a reference to the fb_info in file->private_data,
diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c
index 50b84cd32938..853b52b40d01 100644
--- a/drivers/video/fbdev/core/fbcon.c
+++ b/drivers/video/fbdev/core/fbcon.c
@@ -70,7 +70,6 @@
#include <linux/printk.h>
#include <linux/slab.h>
#include <linux/fb.h>
-#include <linux/fbcon.h>
#include <linux/vt_kern.h>
#include <linux/selection.h>
#include <linux/font.h>
diff --git a/drivers/video/fbdev/core/fbcon.h b/drivers/video/fbdev/core/fbcon.h
index 321cc7f44baa..407d207b14f1 100644
--- a/drivers/video/fbdev/core/fbcon.h
+++ b/drivers/video/fbdev/core/fbcon.h
@@ -11,6 +11,7 @@
#ifndef _VIDEO_FBCON_H
#define _VIDEO_FBCON_H
+#include <linux/compiler_types.h>
#include <linux/font.h>
#include <linux/types.h>
#include <linux/vt_buffer.h>
@@ -19,6 +20,11 @@
#include <asm/io.h>
+struct fb_blit_caps;
+struct fb_info;
+struct fb_var_screeninfo;
+struct fb_videomode;
+
/*
* This is the interface between the low-level console driver and the
* low-level frame buffer device
@@ -233,4 +239,48 @@ static inline int get_attribute(struct fb_info *info, u16 c)
(void) (&_r == &_v); \
(i == FB_ROTATE_UR || i == FB_ROTATE_UD) ? _r : _v; })
+#ifdef CONFIG_FRAMEBUFFER_CONSOLE
+void __init fb_console_init(void);
+void __exit fb_console_exit(void);
+int fbcon_fb_registered(struct fb_info *info);
+void fbcon_fb_unregistered(struct fb_info *info);
+void fbcon_fb_unbind(struct fb_info *info);
+void fbcon_suspended(struct fb_info *info);
+void fbcon_resumed(struct fb_info *info);
+int fbcon_mode_deleted(struct fb_info *info,
+ struct fb_videomode *mode);
+void fbcon_delete_modelist(struct list_head *head);
+void fbcon_new_modelist(struct fb_info *info);
+void fbcon_get_requirement(struct fb_info *info,
+ struct fb_blit_caps *caps);
+void fbcon_fb_blanked(struct fb_info *info, int blank);
+int fbcon_modechange_possible(struct fb_info *info,
+ struct fb_var_screeninfo *var);
+void fbcon_update_vcs(struct fb_info *info, bool all);
+void fbcon_remap_all(struct fb_info *info);
+int fbcon_set_con2fb_map_ioctl(void __user *argp);
+int fbcon_get_con2fb_map_ioctl(void __user *argp);
+#else
+static inline void fb_console_init(void) {}
+static inline void fb_console_exit(void) {}
+static inline int fbcon_fb_registered(struct fb_info *info) { return 0; }
+static inline void fbcon_fb_unregistered(struct fb_info *info) {}
+static inline void fbcon_fb_unbind(struct fb_info *info) {}
+static inline void fbcon_suspended(struct fb_info *info) {}
+static inline void fbcon_resumed(struct fb_info *info) {}
+static inline int fbcon_mode_deleted(struct fb_info *info,
+ struct fb_videomode *mode) { return 0; }
+static inline void fbcon_delete_modelist(struct list_head *head) {}
+static inline void fbcon_new_modelist(struct fb_info *info) {}
+static inline void fbcon_get_requirement(struct fb_info *info,
+ struct fb_blit_caps *caps) {}
+static inline void fbcon_fb_blanked(struct fb_info *info, int blank) {}
+static inline int fbcon_modechange_possible(struct fb_info *info,
+ struct fb_var_screeninfo *var) { return 0; }
+static inline void fbcon_update_vcs(struct fb_info *info, bool all) {}
+static inline void fbcon_remap_all(struct fb_info *info) {}
+static inline int fbcon_set_con2fb_map_ioctl(void __user *argp) { return 0; }
+static inline int fbcon_get_con2fb_map_ioctl(void __user *argp) { return 0; }
+#endif
+
#endif /* _VIDEO_FBCON_H */
diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c
index ecadbc58abff..e5221653ec2b 100644
--- a/drivers/video/fbdev/core/fbmem.c
+++ b/drivers/video/fbdev/core/fbmem.c
@@ -14,13 +14,13 @@
#include <linux/console.h>
#include <linux/export.h>
#include <linux/fb.h>
-#include <linux/fbcon.h>
#include <linux/lcd.h>
#include <linux/leds.h>
#include <video/nomodeset.h>
#include "fb_internal.h"
+#include "fbcon.h"
/*
* Frame buffer device initialization and setup routines
diff --git a/include/linux/fbcon.h b/include/linux/fbcon.h
deleted file mode 100644
index f206370060e1..000000000000
--- a/include/linux/fbcon.h
+++ /dev/null
@@ -1,55 +0,0 @@
-#ifndef _LINUX_FBCON_H
-#define _LINUX_FBCON_H
-
-#include <linux/compiler_types.h>
-
-struct fb_blit_caps;
-struct fb_info;
-struct fb_var_screeninfo;
-struct fb_videomode;
-
-#ifdef CONFIG_FRAMEBUFFER_CONSOLE
-void __init fb_console_init(void);
-void __exit fb_console_exit(void);
-int fbcon_fb_registered(struct fb_info *info);
-void fbcon_fb_unregistered(struct fb_info *info);
-void fbcon_fb_unbind(struct fb_info *info);
-void fbcon_suspended(struct fb_info *info);
-void fbcon_resumed(struct fb_info *info);
-int fbcon_mode_deleted(struct fb_info *info,
- struct fb_videomode *mode);
-void fbcon_delete_modelist(struct list_head *head);
-void fbcon_new_modelist(struct fb_info *info);
-void fbcon_get_requirement(struct fb_info *info,
- struct fb_blit_caps *caps);
-void fbcon_fb_blanked(struct fb_info *info, int blank);
-int fbcon_modechange_possible(struct fb_info *info,
- struct fb_var_screeninfo *var);
-void fbcon_update_vcs(struct fb_info *info, bool all);
-void fbcon_remap_all(struct fb_info *info);
-int fbcon_set_con2fb_map_ioctl(void __user *argp);
-int fbcon_get_con2fb_map_ioctl(void __user *argp);
-#else
-static inline void fb_console_init(void) {}
-static inline void fb_console_exit(void) {}
-static inline int fbcon_fb_registered(struct fb_info *info) { return 0; }
-static inline void fbcon_fb_unregistered(struct fb_info *info) {}
-static inline void fbcon_fb_unbind(struct fb_info *info) {}
-static inline void fbcon_suspended(struct fb_info *info) {}
-static inline void fbcon_resumed(struct fb_info *info) {}
-static inline int fbcon_mode_deleted(struct fb_info *info,
- struct fb_videomode *mode) { return 0; }
-static inline void fbcon_delete_modelist(struct list_head *head) {}
-static inline void fbcon_new_modelist(struct fb_info *info) {}
-static inline void fbcon_get_requirement(struct fb_info *info,
- struct fb_blit_caps *caps) {}
-static inline void fbcon_fb_blanked(struct fb_info *info, int blank) {}
-static inline int fbcon_modechange_possible(struct fb_info *info,
- struct fb_var_screeninfo *var) { return 0; }
-static inline void fbcon_update_vcs(struct fb_info *info, bool all) {}
-static inline void fbcon_remap_all(struct fb_info *info) {}
-static inline int fbcon_set_con2fb_map_ioctl(void __user *argp) { return 0; }
-static inline int fbcon_get_con2fb_map_ioctl(void __user *argp) { return 0; }
-#endif
-
-#endif /* _LINUX_FBCON_H */
--
2.54.0
^ permalink raw reply related [flat|nested] 13+ messages in thread* Claude review: fbdev: Do not export fbcon from fbdev
2026-05-22 12:28 ` [PATCH v2 4/4] fbdev: Do not export fbcon from fbdev Thomas Zimmermann
@ 2026-05-25 8:52 ` Claude Code Review Bot
0 siblings, 0 replies; 13+ messages in thread
From: Claude Code Review Bot @ 2026-05-25 8:52 UTC (permalink / raw)
To: dri-devel-reviews
Patch Review
Moves all declarations from `include/linux/fbcon.h` into the existing internal `drivers/video/fbdev/core/fbcon.h`, adds necessary forward declarations and `#include <linux/compiler_types.h>`, then deletes the public header.
The approach of appending to the existing internal `fbcon.h` (which already has internal struct definitions and macros) is correct. The forward declarations for `struct fb_blit_caps`, `struct fb_info`, `struct fb_var_screeninfo`, and `struct fb_videomode` are needed since the internal header didn't previously include `<linux/fb.h>`.
`fbcon.c` already includes the local `"fbcon.h"` (line 85 in current tree), so dropping `<linux/fbcon.h>` (line 73) is safe — the declarations remain visible.
`fb_chrdev.c` and `fbmem.c` correctly switch from `<linux/fbcon.h>` to `"fbcon.h"`.
The `MAINTAINERS` update removing the deleted file is correct.
**No issues.**
---
Generated by Claude Code Patch Reviewer
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v2 0/4] fbdev: Internalize fbcon
2026-05-22 12:28 [PATCH v2 0/4] fbdev: Internalize fbcon Thomas Zimmermann
` (3 preceding siblings ...)
2026-05-22 12:28 ` [PATCH v2 4/4] fbdev: Do not export fbcon from fbdev Thomas Zimmermann
@ 2026-05-22 13:59 ` Helge Deller
2026-05-25 8:52 ` Claude review: " Claude Code Review Bot
5 siblings, 0 replies; 13+ messages in thread
From: Helge Deller @ 2026-05-22 13:59 UTC (permalink / raw)
To: Thomas Zimmermann; +Cc: dri-devel, linux-fbdev, linuxppc-dev
On 5/22/26 14:28, Thomas Zimmermann wrote:
> Turn fbcon into an internal client of fbdev. Manage all interactions
> with graphics drivers within fbdev. Add helpers for these tasks and
> convert drivers.
>
> Fbdev's PS3 and SH-Mobile drivers update fbcon as part of user-invoked
> mode changes. Call the new helpers, which also fix inconsistencies
> among the various code paths.
>
> Vga-switcheroo remaps the fbcon terminals when switching physical
> outputs. For now, hide this in another helper. The call will later
> move into DRM's fbdev emulation.
>
> When all refactoring in place, fbdev manages fbcon interactions by
> itself. Remove the public interfaces.
>
> v2:
> - use '#if defined' (Helge)
>
> Thomas Zimmermann (4):
> fbdev: Wrap user-invoked calls to fb_set_var() in helper
> fbdev: Wrap user-invoked calls to fb_blank() in helper
> fbdev: Wrap fbcon updates from vga-switcheroo in helper
> fbdev: Do not export fbcon from fbdev
>
> MAINTAINERS | 1 -
> drivers/gpu/vga/vga_switcheroo.c | 6 +--
> drivers/video/fbdev/core/fb_chrdev.c | 12 ++----
> drivers/video/fbdev/core/fb_internal.h | 1 +
> drivers/video/fbdev/core/fbcon.c | 3 --
> drivers/video/fbdev/core/fbcon.h | 50 +++++++++++++++++++++++
> drivers/video/fbdev/core/fbmem.c | 35 +++++++++++++++-
> drivers/video/fbdev/core/fbsysfs.c | 9 +----
> drivers/video/fbdev/ps3fb.c | 5 +--
> drivers/video/fbdev/sh_mobile_lcdcfb.c | 5 +--
> include/linux/fb.h | 3 ++
> include/linux/fbcon.h | 55 --------------------------
> 12 files changed, 98 insertions(+), 87 deletions(-)
> delete mode 100644 include/linux/fbcon.h
series applied to fbdev git tree.
Thanks!
Helge
^ permalink raw reply [flat|nested] 13+ messages in thread* Claude review: fbdev: Internalize fbcon
2026-05-22 12:28 [PATCH v2 0/4] fbdev: Internalize fbcon Thomas Zimmermann
` (4 preceding siblings ...)
2026-05-22 13:59 ` [PATCH v2 0/4] fbdev: Internalize fbcon Helge Deller
@ 2026-05-25 8:52 ` Claude Code Review Bot
5 siblings, 0 replies; 13+ messages in thread
From: Claude Code Review Bot @ 2026-05-25 8:52 UTC (permalink / raw)
To: dri-devel-reviews
Overall Series Review
Subject: fbdev: Internalize fbcon
Author: Thomas Zimmermann <tzimmermann@suse.de>
Patches: 6
Reviewed: 2026-05-25T18:52:07.550396
---
This is a well-structured 4-patch series from Thomas Zimmermann that internalizes fbcon as a private implementation detail of fbdev. The series creates new helper functions (`fb_set_var_from_user`, `fb_blank_from_user`, `fb_switch_outputs`) to encapsulate fbcon interactions, then moves the fbcon declarations from the public `include/linux/fbcon.h` into a private `drivers/video/fbdev/core/fbcon.h`.
The refactoring is clean and the approach is sound. The series removes exported symbols, consolidates duplicated logic, and fixes inconsistencies where some callers were missing fbcon-related steps. The Kconfig dependency of `VGA_SWITCHEROO` on `(FRAMEBUFFER_CONSOLE=n || FB=y)` justifies the `#if defined(CONFIG_FB)` guard in patch 3.
One semantic change in the `sh_mobile_lcdcfb` driver is worth noting (detailed below), though it may be intentional.
**Overall: Looks good to me with one minor observation.**
---
Generated by Claude Code Patch Reviewer
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH v3 1/4] fbdev: Wrap user-invoked calls to fb_set_var() in helper
2026-05-27 15:14 [PATCH v3 0/4] " Thomas Zimmermann
@ 2026-05-27 15:14 ` Thomas Zimmermann
2026-05-28 2:12 ` Claude review: " Claude Code Review Bot
0 siblings, 1 reply; 13+ messages in thread
From: Thomas Zimmermann @ 2026-05-27 15:14 UTC (permalink / raw)
To: deller, geert, simona, airlied, lukas, maddy, mpe, npiggin,
chleroy
Cc: dri-devel, linux-fbdev, linuxppc-dev, Thomas Zimmermann
Handle fbcon during display updates in fb_set_var_from_user(). Check
with fbcon if the mode change is possible, update hardware state and
finally update fbcon. Update all callers.
Only the FBIOPUT_VSCREENINFO ioctl currently does all steps. Other
mode-changes callers in sysfs and driver code are missing fbcon-related
steps.
With the new helper, ps3fb and sh_mobile_lcdcfb no longer maintain
fbcon state themselves.
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
---
drivers/video/fbdev/core/fb_chrdev.c | 6 +-----
drivers/video/fbdev/core/fbcon.c | 2 --
drivers/video/fbdev/core/fbmem.c | 13 +++++++++++++
drivers/video/fbdev/core/fbsysfs.c | 4 +---
drivers/video/fbdev/ps3fb.c | 5 +----
drivers/video/fbdev/sh_mobile_lcdcfb.c | 5 +----
include/linux/fb.h | 2 ++
7 files changed, 19 insertions(+), 18 deletions(-)
diff --git a/drivers/video/fbdev/core/fb_chrdev.c b/drivers/video/fbdev/core/fb_chrdev.c
index 4ebd16b7e3b8..54f926fb411b 100644
--- a/drivers/video/fbdev/core/fb_chrdev.c
+++ b/drivers/video/fbdev/core/fb_chrdev.c
@@ -85,11 +85,7 @@ static long do_fb_ioctl(struct fb_info *info, unsigned int cmd,
var.activate &= ~FB_ACTIVATE_KD_TEXT;
console_lock();
lock_fb_info(info);
- ret = fbcon_modechange_possible(info, &var);
- if (!ret)
- ret = fb_set_var(info, &var);
- if (!ret)
- fbcon_update_vcs(info, var.activate & FB_ACTIVATE_ALL);
+ ret = fb_set_var_from_user(info, &var);
unlock_fb_info(info);
console_unlock();
if (!ret && copy_to_user(argp, &var, sizeof(var)))
diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c
index b0e3e765360d..50b84cd32938 100644
--- a/drivers/video/fbdev/core/fbcon.c
+++ b/drivers/video/fbdev/core/fbcon.c
@@ -2699,7 +2699,6 @@ void fbcon_update_vcs(struct fb_info *info, bool all)
else
fbcon_modechanged(info);
}
-EXPORT_SYMBOL(fbcon_update_vcs);
/* let fbcon check if it supports a new screen resolution */
int fbcon_modechange_possible(struct fb_info *info, struct fb_var_screeninfo *var)
@@ -2727,7 +2726,6 @@ int fbcon_modechange_possible(struct fb_info *info, struct fb_var_screeninfo *va
return 0;
}
-EXPORT_SYMBOL_GPL(fbcon_modechange_possible);
int fbcon_mode_deleted(struct fb_info *info,
struct fb_videomode *mode)
diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c
index 30f2b59c47bf..d37a1039e221 100644
--- a/drivers/video/fbdev/core/fbmem.c
+++ b/drivers/video/fbdev/core/fbmem.c
@@ -346,6 +346,19 @@ fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var)
}
EXPORT_SYMBOL(fb_set_var);
+int fb_set_var_from_user(struct fb_info *info, struct fb_var_screeninfo *var)
+{
+ int ret = fbcon_modechange_possible(info, var);
+
+ if (!ret)
+ ret = fb_set_var(info, var);
+ if (!ret)
+ fbcon_update_vcs(info, var->activate & FB_ACTIVATE_ALL);
+
+ return ret;
+}
+EXPORT_SYMBOL(fb_set_var_from_user);
+
static void fb_lcd_notify_blank(struct fb_info *info)
{
int power;
diff --git a/drivers/video/fbdev/core/fbsysfs.c b/drivers/video/fbdev/core/fbsysfs.c
index baa2bae0fb5b..5ece236e6252 100644
--- a/drivers/video/fbdev/core/fbsysfs.c
+++ b/drivers/video/fbdev/core/fbsysfs.c
@@ -19,9 +19,7 @@ static int activate(struct fb_info *fb_info, struct fb_var_screeninfo *var)
var->activate |= FB_ACTIVATE_FORCE;
console_lock();
lock_fb_info(fb_info);
- err = fb_set_var(fb_info, var);
- if (!err)
- fbcon_update_vcs(fb_info, var->activate & FB_ACTIVATE_ALL);
+ err = fb_set_var_from_user(fb_info, var);
unlock_fb_info(fb_info);
console_unlock();
if (err)
diff --git a/drivers/video/fbdev/ps3fb.c b/drivers/video/fbdev/ps3fb.c
index dbcda307f6a6..1376d19b19ae 100644
--- a/drivers/video/fbdev/ps3fb.c
+++ b/drivers/video/fbdev/ps3fb.c
@@ -29,7 +29,6 @@
#include <linux/freezer.h>
#include <linux/uaccess.h>
#include <linux/fb.h>
-#include <linux/fbcon.h>
#include <linux/init.h>
#include <asm/cell-regs.h>
@@ -830,9 +829,7 @@ static int ps3fb_ioctl(struct fb_info *info, unsigned int cmd,
/* Force, in case only special bits changed */
var.activate |= FB_ACTIVATE_FORCE;
par->new_mode_id = val;
- retval = fb_set_var(info, &var);
- if (!retval)
- fbcon_update_vcs(info, var.activate & FB_ACTIVATE_ALL);
+ retval = fb_set_var_from_user(info, &var);
console_unlock();
}
break;
diff --git a/drivers/video/fbdev/sh_mobile_lcdcfb.c b/drivers/video/fbdev/sh_mobile_lcdcfb.c
index 72969fe8e513..e8324b01700f 100644
--- a/drivers/video/fbdev/sh_mobile_lcdcfb.c
+++ b/drivers/video/fbdev/sh_mobile_lcdcfb.c
@@ -15,7 +15,6 @@
#include <linux/ctype.h>
#include <linux/dma-mapping.h>
#include <linux/delay.h>
-#include <linux/fbcon.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/ioctl.h>
@@ -1768,11 +1767,9 @@ static void sh_mobile_fb_reconfig(struct fb_info *info)
var.height = ch->display.height;
var.activate = FB_ACTIVATE_NOW;
- if (fb_set_var(info, &var) < 0)
+ if (fb_set_var_from_user(info, &var) < 0)
/* Couldn't reconfigure, hopefully, can continue as before */
return;
-
- fbcon_update_vcs(info, true);
}
/*
diff --git a/include/linux/fb.h b/include/linux/fb.h
index 5178a33c752c..88680a7cabd5 100644
--- a/include/linux/fb.h
+++ b/include/linux/fb.h
@@ -533,6 +533,8 @@ extern int fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var);
extern int fb_pan_display(struct fb_info *info, struct fb_var_screeninfo *var);
extern int fb_blank(struct fb_info *info, int blank);
+int fb_set_var_from_user(struct fb_info *info, struct fb_var_screeninfo *var);
+
/*
* Helpers for framebuffers in I/O memory
*/
--
2.54.0
^ permalink raw reply related [flat|nested] 13+ messages in thread* Claude review: fbdev: Wrap user-invoked calls to fb_set_var() in helper
2026-05-27 15:14 ` [PATCH v3 1/4] fbdev: Wrap user-invoked calls to fb_set_var() in helper Thomas Zimmermann
@ 2026-05-28 2:12 ` Claude Code Review Bot
0 siblings, 0 replies; 13+ messages in thread
From: Claude Code Review Bot @ 2026-05-28 2:12 UTC (permalink / raw)
To: dri-devel-reviews
Patch Review
**Bug: sh_mobile_lcdcfb loses "update all VCs" behavior**
The original `sh_mobile_fb_reconfig()` code was:
```c
if (fb_set_var(info, &var) < 0)
return;
fbcon_update_vcs(info, true); /* <-- always updates ALL VCs */
```
After this patch, it calls `fb_set_var_from_user(info, &var)`, which internally does:
```c
fbcon_update_vcs(info, var->activate & FB_ACTIVATE_ALL);
```
Since `var.activate = FB_ACTIVATE_NOW` (value 0) in `sh_mobile_fb_reconfig`, the expression `0 & 64` evaluates to `0` (false). This changes the behavior from updating **all** VCs to only the **current** VC.
When a display is re-plugged with a different mode, all consoles mapped to that framebuffer should be updated - the original `true` was intentional. The fix should be:
```c
var.activate = FB_ACTIVATE_NOW | FB_ACTIVATE_ALL;
```
in `sh_mobile_fb_reconfig()` before calling `fb_set_var_from_user`.
**ps3fb now gains fbcon_modechange_possible check** - This is a new pre-condition that wasn't present before. The cover letter says this is intentional ("fix inconsistencies"), which is reasonable, but worth noting as a behavioral change: if fbcon rejects the mode, ps3fb's ioctl will now return an error where it previously would have succeeded.
**Export level**: `EXPORT_SYMBOL(fb_set_var_from_user)` is consistent with `EXPORT_SYMBOL(fb_set_var)`. Correct, since ps3fb and sh_mobile_lcdcfb can be built as modules.
**Declaration placement**: `fb_set_var_from_user` is declared in `include/linux/fb.h` (public header), which is correct since it's called from drivers outside fbdev core.
The rest of the patch is mechanical and correct.
---
Generated by Claude Code Patch Reviewer
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 1/4] fbdev: Wrap user-invoked calls to fb_set_var() in helper
2026-05-20 16:00 [PATCH 0/4] fbdev: Internalize fbcon Thomas Zimmermann
@ 2026-05-20 16:00 ` Thomas Zimmermann
2026-05-25 11:30 ` Claude review: " Claude Code Review Bot
0 siblings, 1 reply; 13+ messages in thread
From: Thomas Zimmermann @ 2026-05-20 16:00 UTC (permalink / raw)
To: deller, simona, airlied, lukas, maddy, mpe, npiggin, chleroy
Cc: dri-devel, linux-fbdev, linuxppc-dev, Thomas Zimmermann
Handle fbcon during display updates in fb_set_var_from_user(). Check
with fbcon if the mode change is possible, update hardware state and
finally update fbcon. Update all callers.
Only the FBIOPUT_VSCREENINFO ioctl currently does all steps. Other
mode-changes callers in sysfs and driver code are missing fbcon-related
steps.
With the new helper, ps3fb and sh_mobile_lcdcfb no longer maintain
fbcon state themselves.
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
---
drivers/video/fbdev/core/fb_chrdev.c | 6 +-----
drivers/video/fbdev/core/fbcon.c | 2 --
drivers/video/fbdev/core/fbmem.c | 13 +++++++++++++
drivers/video/fbdev/core/fbsysfs.c | 4 +---
drivers/video/fbdev/ps3fb.c | 5 +----
drivers/video/fbdev/sh_mobile_lcdcfb.c | 5 +----
include/linux/fb.h | 2 ++
7 files changed, 19 insertions(+), 18 deletions(-)
diff --git a/drivers/video/fbdev/core/fb_chrdev.c b/drivers/video/fbdev/core/fb_chrdev.c
index 4ebd16b7e3b8..54f926fb411b 100644
--- a/drivers/video/fbdev/core/fb_chrdev.c
+++ b/drivers/video/fbdev/core/fb_chrdev.c
@@ -85,11 +85,7 @@ static long do_fb_ioctl(struct fb_info *info, unsigned int cmd,
var.activate &= ~FB_ACTIVATE_KD_TEXT;
console_lock();
lock_fb_info(info);
- ret = fbcon_modechange_possible(info, &var);
- if (!ret)
- ret = fb_set_var(info, &var);
- if (!ret)
- fbcon_update_vcs(info, var.activate & FB_ACTIVATE_ALL);
+ ret = fb_set_var_from_user(info, &var);
unlock_fb_info(info);
console_unlock();
if (!ret && copy_to_user(argp, &var, sizeof(var)))
diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c
index b0e3e765360d..50b84cd32938 100644
--- a/drivers/video/fbdev/core/fbcon.c
+++ b/drivers/video/fbdev/core/fbcon.c
@@ -2699,7 +2699,6 @@ void fbcon_update_vcs(struct fb_info *info, bool all)
else
fbcon_modechanged(info);
}
-EXPORT_SYMBOL(fbcon_update_vcs);
/* let fbcon check if it supports a new screen resolution */
int fbcon_modechange_possible(struct fb_info *info, struct fb_var_screeninfo *var)
@@ -2727,7 +2726,6 @@ int fbcon_modechange_possible(struct fb_info *info, struct fb_var_screeninfo *va
return 0;
}
-EXPORT_SYMBOL_GPL(fbcon_modechange_possible);
int fbcon_mode_deleted(struct fb_info *info,
struct fb_videomode *mode)
diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c
index 30f2b59c47bf..d37a1039e221 100644
--- a/drivers/video/fbdev/core/fbmem.c
+++ b/drivers/video/fbdev/core/fbmem.c
@@ -346,6 +346,19 @@ fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var)
}
EXPORT_SYMBOL(fb_set_var);
+int fb_set_var_from_user(struct fb_info *info, struct fb_var_screeninfo *var)
+{
+ int ret = fbcon_modechange_possible(info, var);
+
+ if (!ret)
+ ret = fb_set_var(info, var);
+ if (!ret)
+ fbcon_update_vcs(info, var->activate & FB_ACTIVATE_ALL);
+
+ return ret;
+}
+EXPORT_SYMBOL(fb_set_var_from_user);
+
static void fb_lcd_notify_blank(struct fb_info *info)
{
int power;
diff --git a/drivers/video/fbdev/core/fbsysfs.c b/drivers/video/fbdev/core/fbsysfs.c
index baa2bae0fb5b..5ece236e6252 100644
--- a/drivers/video/fbdev/core/fbsysfs.c
+++ b/drivers/video/fbdev/core/fbsysfs.c
@@ -19,9 +19,7 @@ static int activate(struct fb_info *fb_info, struct fb_var_screeninfo *var)
var->activate |= FB_ACTIVATE_FORCE;
console_lock();
lock_fb_info(fb_info);
- err = fb_set_var(fb_info, var);
- if (!err)
- fbcon_update_vcs(fb_info, var->activate & FB_ACTIVATE_ALL);
+ err = fb_set_var_from_user(fb_info, var);
unlock_fb_info(fb_info);
console_unlock();
if (err)
diff --git a/drivers/video/fbdev/ps3fb.c b/drivers/video/fbdev/ps3fb.c
index dbcda307f6a6..1376d19b19ae 100644
--- a/drivers/video/fbdev/ps3fb.c
+++ b/drivers/video/fbdev/ps3fb.c
@@ -29,7 +29,6 @@
#include <linux/freezer.h>
#include <linux/uaccess.h>
#include <linux/fb.h>
-#include <linux/fbcon.h>
#include <linux/init.h>
#include <asm/cell-regs.h>
@@ -830,9 +829,7 @@ static int ps3fb_ioctl(struct fb_info *info, unsigned int cmd,
/* Force, in case only special bits changed */
var.activate |= FB_ACTIVATE_FORCE;
par->new_mode_id = val;
- retval = fb_set_var(info, &var);
- if (!retval)
- fbcon_update_vcs(info, var.activate & FB_ACTIVATE_ALL);
+ retval = fb_set_var_from_user(info, &var);
console_unlock();
}
break;
diff --git a/drivers/video/fbdev/sh_mobile_lcdcfb.c b/drivers/video/fbdev/sh_mobile_lcdcfb.c
index 72969fe8e513..e8324b01700f 100644
--- a/drivers/video/fbdev/sh_mobile_lcdcfb.c
+++ b/drivers/video/fbdev/sh_mobile_lcdcfb.c
@@ -15,7 +15,6 @@
#include <linux/ctype.h>
#include <linux/dma-mapping.h>
#include <linux/delay.h>
-#include <linux/fbcon.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/ioctl.h>
@@ -1768,11 +1767,9 @@ static void sh_mobile_fb_reconfig(struct fb_info *info)
var.height = ch->display.height;
var.activate = FB_ACTIVATE_NOW;
- if (fb_set_var(info, &var) < 0)
+ if (fb_set_var_from_user(info, &var) < 0)
/* Couldn't reconfigure, hopefully, can continue as before */
return;
-
- fbcon_update_vcs(info, true);
}
/*
diff --git a/include/linux/fb.h b/include/linux/fb.h
index 5178a33c752c..88680a7cabd5 100644
--- a/include/linux/fb.h
+++ b/include/linux/fb.h
@@ -533,6 +533,8 @@ extern int fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var);
extern int fb_pan_display(struct fb_info *info, struct fb_var_screeninfo *var);
extern int fb_blank(struct fb_info *info, int blank);
+int fb_set_var_from_user(struct fb_info *info, struct fb_var_screeninfo *var);
+
/*
* Helpers for framebuffers in I/O memory
*/
--
2.54.0
^ permalink raw reply related [flat|nested] 13+ messages in thread* Claude review: fbdev: Wrap user-invoked calls to fb_set_var() in helper
2026-05-20 16:00 ` [PATCH 1/4] fbdev: Wrap user-invoked calls to fb_set_var() in helper Thomas Zimmermann
@ 2026-05-25 11:30 ` Claude Code Review Bot
0 siblings, 0 replies; 13+ messages in thread
From: Claude Code Review Bot @ 2026-05-25 11:30 UTC (permalink / raw)
To: dri-devel-reviews
Patch Review
**Correctness**: The new `fb_set_var_from_user()` correctly consolidates the three-step pattern: check with `fbcon_modechange_possible()`, call `fb_set_var()`, then `fbcon_update_vcs()`. This is a clean factoring.
**Behavioral fix for sysfs path**: The `activate()` function in `fbsysfs.c` previously skipped `fbcon_modechange_possible()`. Now it calls it via the helper. This is a fix for an existing inconsistency, as the commit message notes — good.
**Behavioral change in sh_mobile_lcdcfb**: The original code at `sh_mobile_lcdcfb.c:1775`:
```c
var.activate = FB_ACTIVATE_NOW;
...
fbcon_update_vcs(info, true);
```
becomes (via `fb_set_var_from_user`):
```c
fbcon_update_vcs(info, var->activate & FB_ACTIVATE_ALL);
```
Since `FB_ACTIVATE_NOW` is 0 and `FB_ACTIVATE_ALL` is 64, the `all` parameter changes from `true` to `false`. This means only the current VC gets updated rather than all VCs. This may be the intended fix (the cover letter says "fix inconsistencies among the various code paths"), but it's a user-visible behavioral change that should be explicitly mentioned in the commit message.
**EXPORT_SYMBOL**: `fb_set_var_from_user` is exported with `EXPORT_SYMBOL` (not `_GPL`), matching `fb_set_var`. Fine since it's used by `ps3fb` and `sh_mobile_lcdcfb` which can be modules.
**Minor**: The removed `EXPORT_SYMBOL(fbcon_update_vcs)` and `EXPORT_SYMBOL_GPL(fbcon_modechange_possible)` in fbcon.c are now unnecessary since only fbmem.c calls them — this is correct.
---
Generated by Claude Code Patch Reviewer
^ permalink raw reply [flat|nested] 13+ messages in thread