* [PATCH] fbdev: Use device_create_with_groups() to fix sysfs groups registration race
From: Hans de Goede @ 2025-12-21 16:57 UTC (permalink / raw)
To: Simona Vetter, Helge Deller
Cc: Hans de Goede, Thomas Zimmermann, dri-devel, linux-fbdev, stable,
Shixiong Ou
The fbdev sysfs attributes are registered after sending the uevent for
the device creation, leaving a race window where e.g. udev rules may
not be able to access the sysfs attributes because the registration is
not done yet.
Fix this by switching to device_create_with_groups(). This also results in
a nice cleanup. After switching to device_create_with_groups() all that
is left of fb_init_device() is setting the drvdata and that can be passed
to device_create[_with_groups]() too. After which fb_init_device() can
be completely removed.
Dropping fb_init_device() + fb_cleanup_device() in turn allows removing
fb_info.class_flag as they were the only user of this field.
Fixes: 5fc830d6aca1 ("fbdev: Register sysfs groups through device_add_group")
Cc: stable@vger.kernel.org
Cc: Shixiong Ou <oushixiong@kylinos.cn>
Signed-off-by: Hans de Goede <johannes.goede@oss.qualcomm.com>
---
Note the fixes tag is technically wrong. This race has existed forever.
The commit I picked for the fixes tag is a dependency of this change not
the commit introducing the race. I don't believe that backporting this
back any further is useful which is why I went with this commit.
---
drivers/video/fbdev/core/fbsysfs.c | 36 +++---------------------------
include/linux/fb.h | 1 -
2 files changed, 3 insertions(+), 34 deletions(-)
diff --git a/drivers/video/fbdev/core/fbsysfs.c b/drivers/video/fbdev/core/fbsysfs.c
index b8344c40073b..baa2bae0fb5b 100644
--- a/drivers/video/fbdev/core/fbsysfs.c
+++ b/drivers/video/fbdev/core/fbsysfs.c
@@ -12,8 +12,6 @@
#include "fb_internal.h"
-#define FB_SYSFS_FLAG_ATTR 1
-
static int activate(struct fb_info *fb_info, struct fb_var_screeninfo *var)
{
int err;
@@ -451,33 +449,7 @@ static struct attribute *fb_device_attrs[] = {
NULL,
};
-static const struct attribute_group fb_device_attr_group = {
- .attrs = fb_device_attrs,
-};
-
-static int fb_init_device(struct fb_info *fb_info)
-{
- int ret;
-
- dev_set_drvdata(fb_info->dev, fb_info);
-
- fb_info->class_flag |= FB_SYSFS_FLAG_ATTR;
-
- ret = device_add_group(fb_info->dev, &fb_device_attr_group);
- if (ret)
- fb_info->class_flag &= ~FB_SYSFS_FLAG_ATTR;
-
- return 0;
-}
-
-static void fb_cleanup_device(struct fb_info *fb_info)
-{
- if (fb_info->class_flag & FB_SYSFS_FLAG_ATTR) {
- device_remove_group(fb_info->dev, &fb_device_attr_group);
-
- fb_info->class_flag &= ~FB_SYSFS_FLAG_ATTR;
- }
-}
+ATTRIBUTE_GROUPS(fb_device);
int fb_device_create(struct fb_info *fb_info)
{
@@ -485,14 +457,13 @@ int fb_device_create(struct fb_info *fb_info)
dev_t devt = MKDEV(FB_MAJOR, node);
int ret;
- fb_info->dev = device_create(fb_class, fb_info->device, devt, NULL, "fb%d", node);
+ fb_info->dev = device_create_with_groups(fb_class, fb_info->device, devt, fb_info,
+ fb_device_groups, "fb%d", node);
if (IS_ERR(fb_info->dev)) {
/* Not fatal */
ret = PTR_ERR(fb_info->dev);
pr_warn("Unable to create device for framebuffer %d; error %d\n", node, ret);
fb_info->dev = NULL;
- } else {
- fb_init_device(fb_info);
}
return 0;
@@ -505,7 +476,6 @@ void fb_device_destroy(struct fb_info *fb_info)
if (!fb_info->dev)
return;
- fb_cleanup_device(fb_info);
device_destroy(fb_class, devt);
fb_info->dev = NULL;
}
diff --git a/include/linux/fb.h b/include/linux/fb.h
index 05cc251035da..c3302d513546 100644
--- a/include/linux/fb.h
+++ b/include/linux/fb.h
@@ -497,7 +497,6 @@ struct fb_info {
#if defined(CONFIG_FB_DEVICE)
struct device *dev; /* This is this fb device */
#endif
- int class_flag; /* private sysfs flags */
#ifdef CONFIG_FB_TILEBLITTING
struct fb_tile_ops *tileops; /* Tile Blitting */
#endif
--
2.52.0
^ permalink raw reply related
* [PATCH] staging/sm750fb: remove outdated TODO lines
From: William Hansen-Baird @ 2025-12-22 21:28 UTC (permalink / raw)
To: Sudip Mukherjee, Teddy Wang, Greg Kroah-Hartman
Cc: linux-fbdev, linux-staging, linux-kernel, William Hansen-Baird
The TODO lines about "checkpatch cleanup" and "kernel coding style"
are no longer needed as all files conform to the kernel coding style,
as verified with checkpatch.pl
Note: checkpatch reports a false positive WARNING for sm750.c line 36
about missing const in static const char *g_fbmode[].
checkpatch suggests static const char * const g_fbmode[].
This was intentional, as the array is modified throughout the code,
while the inner strings remain unchanged.
Signed-off-by: William Hansen-Baird <william.hansen.baird@icloud.com>
---
drivers/staging/sm750fb/TODO | 2 --
1 file changed, 2 deletions(-)
diff --git a/drivers/staging/sm750fb/TODO b/drivers/staging/sm750fb/TODO
index 7ce632d040b3..037984801654 100644
--- a/drivers/staging/sm750fb/TODO
+++ b/drivers/staging/sm750fb/TODO
@@ -1,6 +1,4 @@
TODO:
-- lots of checkpatch cleanup
-- use kernel coding style
- refine the code and remove unused code
- Implement hardware acceleration for imageblit if image->depth > 1
- must be ported to the atomic kms framework in the drm subsystem (which will
--
2.52.0
^ permalink raw reply related
* [PATCH 5.10] fbcon: Add check for return value
From: Ваторопин Андрей @ 2025-12-23 6:31 UTC (permalink / raw)
To: Bartlomiej Zolnierkiewicz
Cc: Ваторопин Андрей,
Thomas Zimmermann, Greg Kroah-Hartman, Samasth Norway Ananda,
Zsolt Kajtar, Lucas De Marchi, Antonino A. Daplas, Andrew Morton,
dri-devel@lists.freedesktop.org, linux-fbdev@vger.kernel.org,
linux-kernel@vger.kernel.org, lvc-project@linuxtesting.org,
stable@vger.kernel.org
From: Andrey Vatoropin <a.vatoropin@crpt.ru>
If fbcon_open() fails when called from con2fb_acquire_newinfo() then
info->fbcon_par pointer remains NULL which is later dereferenced.
Add check for return value of the function con2fb_acquire_newinfo() to
avoid it.
Found by Linux Verification Center (linuxtesting.org) with SVACE.
Fixes: d1baa4ffa677 ("fbcon: set_con2fb_map fixes")
Cc: stable@vger.kernel.org
Signed-off-by: Andrey Vatoropin <a.vatoropin@crpt.ru>
---
drivers/video/fbdev/core/fbcon.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c
index 3dd03e02bf97..d9b2b54f00db 100644
--- a/drivers/video/fbdev/core/fbcon.c
+++ b/drivers/video/fbdev/core/fbcon.c
@@ -1057,7 +1057,8 @@ static void fbcon_init(struct vc_data *vc, int init)
return;
if (!info->fbcon_par)
- con2fb_acquire_newinfo(vc, info, vc->vc_num, -1);
+ if (con2fb_acquire_newinfo(vc, info, vc->vc_num, -1))
+ return;
/* If we are not the first console on this
fb, copy the font from that console */
--
2.43.0
^ permalink raw reply related
* [PATCH] staging: sm750fb: improve clarity in TODO file
From: Tejas Chaudhari @ 2025-12-23 18:59 UTC (permalink / raw)
To: Sudip Mukherjee, Teddy Wang
Cc: Greg Kroah-Hartman, linux-staging, linux-fbdev, Tejas Chaudhari
Improve wording and consistency in the sm750fb TODO file
by clarifying references to checkpatch.pl and improving
sentence readability.
No functional changes.
Signed-off-by: Tejas Chaudhari <tejaschaudhari038@gmail.com>
---
drivers/staging/sm750fb/TODO | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/staging/sm750fb/TODO b/drivers/staging/sm750fb/TODO
index 7ce632d04..56ffd9b36 100644
--- a/drivers/staging/sm750fb/TODO
+++ b/drivers/staging/sm750fb/TODO
@@ -1,8 +1,8 @@
TODO:
-- lots of checkpatch cleanup
+- lots of checkpatch.pl cleanup
- use kernel coding style
- refine the code and remove unused code
-- Implement hardware acceleration for imageblit if image->depth > 1
+- Implement hardware acceleration for imageblit when image->depth > 1
- must be ported to the atomic kms framework in the drm subsystem (which will
give you a basic fbdev driver for free)
--
2.39.5 (Apple Git-154)
^ permalink raw reply related
* [PATCH] staging: sm750fb: make g_fbmode array fully const
From: Tejas Chaudhari @ 2025-12-23 19:11 UTC (permalink / raw)
To: linux-staging
Cc: linux-fbdev, sudipm.mukherjee, teddy.wang, gregkh,
Tejas Chaudhari
Fix a checkpatch warning by marking the g_fbmode array itself
as const, since its contents are not modified.
No functional changes.
Signed-off-by: Tejas Chaudhari <tejaschaudhari038@gmail.com>
---
drivers/staging/sm750fb/sm750.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/staging/sm750fb/sm750.c b/drivers/staging/sm750fb/sm750.c
index fecd7457e..15b5de33b 100644
--- a/drivers/staging/sm750fb/sm750.c
+++ b/drivers/staging/sm750fb/sm750.c
@@ -33,7 +33,7 @@
static int g_hwcursor = 1;
static int g_noaccel;
static int g_nomtrr;
-static const char *g_fbmode[] = {NULL, NULL};
+static const char * const g_fbmode[] = {NULL, NULL};
static const char *g_def_fbmode = "1024x768-32@60";
static char *g_settings;
static int g_dualview;
--
2.39.5 (Apple Git-154)
^ permalink raw reply related
* [PATCH] staging: sm750fb: rename fixId to fix_id
From: Tejas Chaudhari @ 2025-12-23 19:24 UTC (permalink / raw)
To: linux-staging
Cc: linux-fbdev, sudipm.mukherjee, teddy.wang, gregkh,
Tejas Chaudhari
Rename the local fixId array to fix_id to follow
kernel naming conventions and fix a checkpatch
CamelCase warning.
No functional changes.
Signed-off-by: Tejas Chaudhari <tejaschaudhari038@gmail.com>
---
drivers/staging/sm750fb/sm750.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/staging/sm750fb/sm750.c b/drivers/staging/sm750fb/sm750.c
index 15b5de33b..7afb58561 100644
--- a/drivers/staging/sm750fb/sm750.c
+++ b/drivers/staging/sm750fb/sm750.c
@@ -740,7 +740,7 @@ static int lynxfb_set_fbinfo(struct fb_info *info, int index)
"kernel HELPERS prepared vesa_modes",
};
- static const char *fixId[2] = {
+ static const char *fix_id[2] = {
"sm750_fb1", "sm750_fb2",
};
@@ -862,7 +862,7 @@ static int lynxfb_set_fbinfo(struct fb_info *info, int index)
fix->ywrapstep = crtc->ywrapstep;
fix->accel = FB_ACCEL_SMI;
- strscpy(fix->id, fixId[index], sizeof(fix->id));
+ strscpy(fix->id, fix_id[index], sizeof(fix->id));
fix->smem_start = crtc->o_screen + sm750_dev->vidmem_start;
pr_info("fix->smem_start = %lx\n", fix->smem_start);
--
2.39.5 (Apple Git-154)
^ permalink raw reply related
* [PATCH] staging: sm750fb: rename fixId to fix_id
From: Tejas Chaudhari @ 2025-12-23 19:27 UTC (permalink / raw)
To: linux-staging
Cc: linux-fbdev, sudipm.mukherjee, teddy.wang, gregkh,
Tejas Chaudhari
Rename the local fixId array to fix_id to follow
kernel naming conventions and fix a checkpatch
CamelCase warning.
No functional changes.
Signed-off-by: Tejas Chaudhari <tejaschaudhari038@gmail.com>
---
drivers/staging/sm750fb/sm750.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/staging/sm750fb/sm750.c b/drivers/staging/sm750fb/sm750.c
index 15b5de33b..7afb58561 100644
--- a/drivers/staging/sm750fb/sm750.c
+++ b/drivers/staging/sm750fb/sm750.c
@@ -740,7 +740,7 @@ static int lynxfb_set_fbinfo(struct fb_info *info, int index)
"kernel HELPERS prepared vesa_modes",
};
- static const char *fixId[2] = {
+ static const char *fix_id[2] = {
"sm750_fb1", "sm750_fb2",
};
@@ -862,7 +862,7 @@ static int lynxfb_set_fbinfo(struct fb_info *info, int index)
fix->ywrapstep = crtc->ywrapstep;
fix->accel = FB_ACCEL_SMI;
- strscpy(fix->id, fixId[index], sizeof(fix->id));
+ strscpy(fix->id, fix_id[index], sizeof(fix->id));
fix->smem_start = crtc->o_screen + sm750_dev->vidmem_start;
pr_info("fix->smem_start = %lx\n", fix->smem_start);
--
2.39.5 (Apple Git-154)
^ permalink raw reply related
* Re: [PATCH] staging: sm750fb: make g_fbmode array fully const
From: kernel test robot @ 2025-12-24 11:35 UTC (permalink / raw)
To: Tejas Chaudhari, linux-staging
Cc: oe-kbuild-all, linux-fbdev, sudipm.mukherjee, teddy.wang, gregkh,
Tejas Chaudhari
In-Reply-To: <20251223191141.14206-1-tejaschaudhari038@gmail.com>
Hi Tejas,
kernel test robot noticed the following build errors:
[auto build test ERROR on staging/staging-testing]
url: https://github.com/intel-lab-lkp/linux/commits/Tejas-Chaudhari/staging-sm750fb-make-g_fbmode-array-fully-const/20251224-031344
base: staging/staging-testing
patch link: https://lore.kernel.org/r/20251223191141.14206-1-tejaschaudhari038%40gmail.com
patch subject: [PATCH] staging: sm750fb: make g_fbmode array fully const
config: x86_64-randconfig-004-20251224 (https://download.01.org/0day-ci/archive/20251224/202512241948.KJeOfUVv-lkp@intel.com/config)
compiler: gcc-14 (Debian 14.2.0-19) 14.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20251224/202512241948.KJeOfUVv-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202512241948.KJeOfUVv-lkp@intel.com/
All errors (new ones prefixed by >>):
drivers/staging/sm750fb/sm750.c: In function 'lynxfb_set_fbinfo':
>> drivers/staging/sm750fb/sm750.c:795:33: error: assignment of read-only location 'g_fbmode[index]'
795 | g_fbmode[index] = g_def_fbmode;
| ^
drivers/staging/sm750fb/sm750.c:797:41: error: assignment of read-only location 'g_fbmode[index]'
797 | g_fbmode[index] = g_fbmode[0];
| ^
drivers/staging/sm750fb/sm750.c: In function 'sm750fb_setup':
>> drivers/staging/sm750fb/sm750.c:958:45: error: assignment of read-only location 'g_fbmode[0]'
958 | g_fbmode[0] = opt;
| ^
drivers/staging/sm750fb/sm750.c:962:45: error: assignment of read-only location 'g_fbmode[1]'
962 | g_fbmode[1] = opt;
| ^
vim +795 drivers/staging/sm750fb/sm750.c
81dee67e215b23 Sudip Mukherjee 2015-03-03 722
81dee67e215b23 Sudip Mukherjee 2015-03-03 723 static int lynxfb_set_fbinfo(struct fb_info *info, int index)
81dee67e215b23 Sudip Mukherjee 2015-03-03 724 {
81dee67e215b23 Sudip Mukherjee 2015-03-03 725 int i;
81dee67e215b23 Sudip Mukherjee 2015-03-03 726 struct lynxfb_par *par;
e359b6a863e19f Mike Rapoport 2015-10-26 727 struct sm750_dev *sm750_dev;
81dee67e215b23 Sudip Mukherjee 2015-03-03 728 struct lynxfb_crtc *crtc;
81dee67e215b23 Sudip Mukherjee 2015-03-03 729 struct lynxfb_output *output;
81dee67e215b23 Sudip Mukherjee 2015-03-03 730 struct fb_var_screeninfo *var;
81dee67e215b23 Sudip Mukherjee 2015-03-03 731 struct fb_fix_screeninfo *fix;
81dee67e215b23 Sudip Mukherjee 2015-03-03 732
81dee67e215b23 Sudip Mukherjee 2015-03-03 733 const struct fb_videomode *pdb[] = {
81dee67e215b23 Sudip Mukherjee 2015-03-03 734 lynx750_ext, NULL, vesa_modes,
81dee67e215b23 Sudip Mukherjee 2015-03-03 735 };
81dee67e215b23 Sudip Mukherjee 2015-03-03 736 int cdb[] = {ARRAY_SIZE(lynx750_ext), 0, VESA_MODEDB_SIZE};
d5d66cfea2ca28 Kelsey Skunberg 2019-04-27 737 static const char * const mdb_desc[] = {
81dee67e215b23 Sudip Mukherjee 2015-03-03 738 "driver prepared modes",
81dee67e215b23 Sudip Mukherjee 2015-03-03 739 "kernel prepared default modedb",
81dee67e215b23 Sudip Mukherjee 2015-03-03 740 "kernel HELPERS prepared vesa_modes",
81dee67e215b23 Sudip Mukherjee 2015-03-03 741 };
81dee67e215b23 Sudip Mukherjee 2015-03-03 742
8c475735085a7d Tim Wassink 2025-12-21 743 static const char *fix_id[2] = {
81dee67e215b23 Sudip Mukherjee 2015-03-03 744 "sm750_fb1", "sm750_fb2",
81dee67e215b23 Sudip Mukherjee 2015-03-03 745 };
81dee67e215b23 Sudip Mukherjee 2015-03-03 746
81dee67e215b23 Sudip Mukherjee 2015-03-03 747 int ret, line_length;
81dee67e215b23 Sudip Mukherjee 2015-03-03 748
81dee67e215b23 Sudip Mukherjee 2015-03-03 749 ret = 0;
81dee67e215b23 Sudip Mukherjee 2015-03-03 750 par = (struct lynxfb_par *)info->par;
e359b6a863e19f Mike Rapoport 2015-10-26 751 sm750_dev = par->dev;
81dee67e215b23 Sudip Mukherjee 2015-03-03 752 crtc = &par->crtc;
81dee67e215b23 Sudip Mukherjee 2015-03-03 753 output = &par->output;
81dee67e215b23 Sudip Mukherjee 2015-03-03 754 var = &info->var;
81dee67e215b23 Sudip Mukherjee 2015-03-03 755 fix = &info->fix;
81dee67e215b23 Sudip Mukherjee 2015-03-03 756
81dee67e215b23 Sudip Mukherjee 2015-03-03 757 /* set index */
81dee67e215b23 Sudip Mukherjee 2015-03-03 758 par->index = index;
81dee67e215b23 Sudip Mukherjee 2015-03-03 759 output->channel = &crtc->channel;
81dee67e215b23 Sudip Mukherjee 2015-03-03 760 sm750fb_set_drv(par);
81dee67e215b23 Sudip Mukherjee 2015-03-03 761
d11ac7cbcc266c Sudip Mukherjee 2015-08-07 762 /*
d11ac7cbcc266c Sudip Mukherjee 2015-08-07 763 * set current cursor variable and proc pointer,
d11ac7cbcc266c Sudip Mukherjee 2015-08-07 764 * must be set after crtc member initialized
d11ac7cbcc266c Sudip Mukherjee 2015-08-07 765 */
fdc234d85210d9 Benjamin Philip 2021-07-28 766 crtc->cursor.offset = crtc->o_screen + crtc->vidmem_size - 1024;
e359b6a863e19f Mike Rapoport 2015-10-26 767 crtc->cursor.mmio = sm750_dev->pvReg +
e359b6a863e19f Mike Rapoport 2015-10-26 768 0x800f0 + (int)crtc->channel * 0x140;
81dee67e215b23 Sudip Mukherjee 2015-03-03 769
81dee67e215b23 Sudip Mukherjee 2015-03-03 770 pr_info("crtc->cursor.mmio = %p\n", crtc->cursor.mmio);
cd33da26036ea5 Christopher Carbone 2022-08-23 771 crtc->cursor.max_h = 64;
cd33da26036ea5 Christopher Carbone 2022-08-23 772 crtc->cursor.max_w = 64;
39f9137268ee3d Benjamin Philip 2021-07-26 773 crtc->cursor.size = crtc->cursor.max_h * crtc->cursor.max_w * 2 / 8;
e359b6a863e19f Mike Rapoport 2015-10-26 774 crtc->cursor.vstart = sm750_dev->pvMem + crtc->cursor.offset;
81dee67e215b23 Sudip Mukherjee 2015-03-03 775
3de08a2d14ff8c Lorenzo Stoakes 2015-03-20 776 memset_io(crtc->cursor.vstart, 0, crtc->cursor.size);
f7c8a046577e09 Thomas Zimmermann 2023-11-27 777 if (!g_hwcursor)
52d0744d751d8f Arnd Bergmann 2016-11-09 778 sm750_hw_cursor_disable(&crtc->cursor);
81dee67e215b23 Sudip Mukherjee 2015-03-03 779
81dee67e215b23 Sudip Mukherjee 2015-03-03 780 /* set info->fbops, must be set before fb_find_mode */
e359b6a863e19f Mike Rapoport 2015-10-26 781 if (!sm750_dev->accel_off) {
81dee67e215b23 Sudip Mukherjee 2015-03-03 782 /* use 2d acceleration */
f7c8a046577e09 Thomas Zimmermann 2023-11-27 783 if (!g_hwcursor)
f7c8a046577e09 Thomas Zimmermann 2023-11-27 784 info->fbops = &lynxfb_ops_accel;
f7c8a046577e09 Thomas Zimmermann 2023-11-27 785 else
f7c8a046577e09 Thomas Zimmermann 2023-11-27 786 info->fbops = &lynxfb_ops_accel_with_cursor;
f7c8a046577e09 Thomas Zimmermann 2023-11-27 787 } else {
f7c8a046577e09 Thomas Zimmermann 2023-11-27 788 if (!g_hwcursor)
81dee67e215b23 Sudip Mukherjee 2015-03-03 789 info->fbops = &lynxfb_ops;
f7c8a046577e09 Thomas Zimmermann 2023-11-27 790 else
f7c8a046577e09 Thomas Zimmermann 2023-11-27 791 info->fbops = &lynxfb_ops_with_cursor;
f7c8a046577e09 Thomas Zimmermann 2023-11-27 792 }
81dee67e215b23 Sudip Mukherjee 2015-03-03 793
81dee67e215b23 Sudip Mukherjee 2015-03-03 794 if (!g_fbmode[index]) {
81dee67e215b23 Sudip Mukherjee 2015-03-03 @795 g_fbmode[index] = g_def_fbmode;
81dee67e215b23 Sudip Mukherjee 2015-03-03 796 if (index)
81dee67e215b23 Sudip Mukherjee 2015-03-03 797 g_fbmode[index] = g_fbmode[0];
81dee67e215b23 Sudip Mukherjee 2015-03-03 798 }
81dee67e215b23 Sudip Mukherjee 2015-03-03 799
81dee67e215b23 Sudip Mukherjee 2015-03-03 800 for (i = 0; i < 3; i++) {
81dee67e215b23 Sudip Mukherjee 2015-03-03 801 ret = fb_find_mode(var, info, g_fbmode[index],
81dee67e215b23 Sudip Mukherjee 2015-03-03 802 pdb[i], cdb[i], NULL, 8);
81dee67e215b23 Sudip Mukherjee 2015-03-03 803
81dee67e215b23 Sudip Mukherjee 2015-03-03 804 if (ret == 1) {
81dee67e215b23 Sudip Mukherjee 2015-03-03 805 pr_info("success! use specified mode:%s in %s\n",
81dee67e215b23 Sudip Mukherjee 2015-03-03 806 g_fbmode[index],
81dee67e215b23 Sudip Mukherjee 2015-03-03 807 mdb_desc[i]);
81dee67e215b23 Sudip Mukherjee 2015-03-03 808 break;
81dee67e215b23 Sudip Mukherjee 2015-03-03 809 } else if (ret == 2) {
81dee67e215b23 Sudip Mukherjee 2015-03-03 810 pr_warn("use specified mode:%s in %s,with an ignored refresh rate\n",
81dee67e215b23 Sudip Mukherjee 2015-03-03 811 g_fbmode[index],
81dee67e215b23 Sudip Mukherjee 2015-03-03 812 mdb_desc[i]);
81dee67e215b23 Sudip Mukherjee 2015-03-03 813 break;
81dee67e215b23 Sudip Mukherjee 2015-03-03 814 } else if (ret == 3) {
81dee67e215b23 Sudip Mukherjee 2015-03-03 815 pr_warn("wanna use default mode\n");
4bd9503d0becdb Michel von Czettritz 2015-03-26 816 /*break;*/
81dee67e215b23 Sudip Mukherjee 2015-03-03 817 } else if (ret == 4) {
81dee67e215b23 Sudip Mukherjee 2015-03-03 818 pr_warn("fall back to any valid mode\n");
81dee67e215b23 Sudip Mukherjee 2015-03-03 819 } else {
3318bb5e945f70 Michel von Czettritz 2015-03-26 820 pr_warn("ret = %d,fb_find_mode failed,with %s\n",
3318bb5e945f70 Michel von Czettritz 2015-03-26 821 ret,
3318bb5e945f70 Michel von Czettritz 2015-03-26 822 mdb_desc[i]);
81dee67e215b23 Sudip Mukherjee 2015-03-03 823 }
81dee67e215b23 Sudip Mukherjee 2015-03-03 824 }
81dee67e215b23 Sudip Mukherjee 2015-03-03 825
81dee67e215b23 Sudip Mukherjee 2015-03-03 826 /* some member of info->var had been set by fb_find_mode */
81dee67e215b23 Sudip Mukherjee 2015-03-03 827
271dbae3c6a1da Prasant Jalan 2017-04-01 828 pr_info("Member of info->var is :\n"
271dbae3c6a1da Prasant Jalan 2017-04-01 829 "xres=%d\n"
271dbae3c6a1da Prasant Jalan 2017-04-01 830 "yres=%d\n"
271dbae3c6a1da Prasant Jalan 2017-04-01 831 "xres_virtual=%d\n"
271dbae3c6a1da Prasant Jalan 2017-04-01 832 "yres_virtual=%d\n"
271dbae3c6a1da Prasant Jalan 2017-04-01 833 "xoffset=%d\n"
271dbae3c6a1da Prasant Jalan 2017-04-01 834 "yoffset=%d\n"
271dbae3c6a1da Prasant Jalan 2017-04-01 835 "bits_per_pixel=%d\n"
271dbae3c6a1da Prasant Jalan 2017-04-01 836 " ...\n",
3318bb5e945f70 Michel von Czettritz 2015-03-26 837 var->xres,
3318bb5e945f70 Michel von Czettritz 2015-03-26 838 var->yres,
3318bb5e945f70 Michel von Czettritz 2015-03-26 839 var->xres_virtual,
3318bb5e945f70 Michel von Czettritz 2015-03-26 840 var->yres_virtual,
3318bb5e945f70 Michel von Czettritz 2015-03-26 841 var->xoffset,
3318bb5e945f70 Michel von Czettritz 2015-03-26 842 var->yoffset,
3318bb5e945f70 Michel von Czettritz 2015-03-26 843 var->bits_per_pixel);
81dee67e215b23 Sudip Mukherjee 2015-03-03 844
81dee67e215b23 Sudip Mukherjee 2015-03-03 845 /* set par */
81dee67e215b23 Sudip Mukherjee 2015-03-03 846 par->info = info;
81dee67e215b23 Sudip Mukherjee 2015-03-03 847
81dee67e215b23 Sudip Mukherjee 2015-03-03 848 /* set info */
e3a3f9f5123683 Mike Rapoport 2015-10-26 849 line_length = ALIGN((var->xres_virtual * var->bits_per_pixel / 8),
e3a3f9f5123683 Mike Rapoport 2015-10-26 850 crtc->line_pad);
81dee67e215b23 Sudip Mukherjee 2015-03-03 851
81dee67e215b23 Sudip Mukherjee 2015-03-03 852 info->pseudo_palette = &par->pseudo_palette[0];
cc59bde1c920ab Benjamin Philip 2021-07-28 853 info->screen_base = crtc->v_screen;
81dee67e215b23 Sudip Mukherjee 2015-03-03 854 pr_debug("screen_base vaddr = %p\n", info->screen_base);
81dee67e215b23 Sudip Mukherjee 2015-03-03 855 info->screen_size = line_length * var->yres_virtual;
81dee67e215b23 Sudip Mukherjee 2015-03-03 856
81dee67e215b23 Sudip Mukherjee 2015-03-03 857 /* set info->fix */
81dee67e215b23 Sudip Mukherjee 2015-03-03 858 fix->type = FB_TYPE_PACKED_PIXELS;
81dee67e215b23 Sudip Mukherjee 2015-03-03 859 fix->type_aux = 0;
81dee67e215b23 Sudip Mukherjee 2015-03-03 860 fix->xpanstep = crtc->xpanstep;
81dee67e215b23 Sudip Mukherjee 2015-03-03 861 fix->ypanstep = crtc->ypanstep;
81dee67e215b23 Sudip Mukherjee 2015-03-03 862 fix->ywrapstep = crtc->ywrapstep;
81dee67e215b23 Sudip Mukherjee 2015-03-03 863 fix->accel = FB_ACCEL_SMI;
81dee67e215b23 Sudip Mukherjee 2015-03-03 864
8c475735085a7d Tim Wassink 2025-12-21 865 strscpy(fix->id, fix_id[index], sizeof(fix->id));
81dee67e215b23 Sudip Mukherjee 2015-03-03 866
fdc234d85210d9 Benjamin Philip 2021-07-28 867 fix->smem_start = crtc->o_screen + sm750_dev->vidmem_start;
81dee67e215b23 Sudip Mukherjee 2015-03-03 868 pr_info("fix->smem_start = %lx\n", fix->smem_start);
d11ac7cbcc266c Sudip Mukherjee 2015-08-07 869 /*
d11ac7cbcc266c Sudip Mukherjee 2015-08-07 870 * according to mmap experiment from user space application,
81dee67e215b23 Sudip Mukherjee 2015-03-03 871 * fix->mmio_len should not larger than virtual size
81dee67e215b23 Sudip Mukherjee 2015-03-03 872 * (xres_virtual x yres_virtual x ByPP)
81dee67e215b23 Sudip Mukherjee 2015-03-03 873 * Below line maybe buggy when user mmap fb dev node and write
81dee67e215b23 Sudip Mukherjee 2015-03-03 874 * data into the bound over virtual size
d11ac7cbcc266c Sudip Mukherjee 2015-08-07 875 */
81dee67e215b23 Sudip Mukherjee 2015-03-03 876 fix->smem_len = crtc->vidmem_size;
81dee67e215b23 Sudip Mukherjee 2015-03-03 877 pr_info("fix->smem_len = %x\n", fix->smem_len);
81dee67e215b23 Sudip Mukherjee 2015-03-03 878 info->screen_size = fix->smem_len;
81dee67e215b23 Sudip Mukherjee 2015-03-03 879 fix->line_length = line_length;
e359b6a863e19f Mike Rapoport 2015-10-26 880 fix->mmio_start = sm750_dev->vidreg_start;
81dee67e215b23 Sudip Mukherjee 2015-03-03 881 pr_info("fix->mmio_start = %lx\n", fix->mmio_start);
e359b6a863e19f Mike Rapoport 2015-10-26 882 fix->mmio_len = sm750_dev->vidreg_size;
81dee67e215b23 Sudip Mukherjee 2015-03-03 883 pr_info("fix->mmio_len = %x\n", fix->mmio_len);
b610e1193a917f Matej Dujava 2020-04-30 884
b610e1193a917f Matej Dujava 2020-04-30 885 lynxfb_set_visual_mode(info);
81dee67e215b23 Sudip Mukherjee 2015-03-03 886
81dee67e215b23 Sudip Mukherjee 2015-03-03 887 /* set var */
81dee67e215b23 Sudip Mukherjee 2015-03-03 888 var->activate = FB_ACTIVATE_NOW;
81dee67e215b23 Sudip Mukherjee 2015-03-03 889 var->accel_flags = 0;
81dee67e215b23 Sudip Mukherjee 2015-03-03 890 var->vmode = FB_VMODE_NONINTERLACED;
81dee67e215b23 Sudip Mukherjee 2015-03-03 891
81dee67e215b23 Sudip Mukherjee 2015-03-03 892 pr_debug("#1 show info->cmap :\nstart=%d,len=%d,red=%p,green=%p,blue=%p,transp=%p\n",
81dee67e215b23 Sudip Mukherjee 2015-03-03 893 info->cmap.start, info->cmap.len,
81dee67e215b23 Sudip Mukherjee 2015-03-03 894 info->cmap.red, info->cmap.green, info->cmap.blue,
81dee67e215b23 Sudip Mukherjee 2015-03-03 895 info->cmap.transp);
81dee67e215b23 Sudip Mukherjee 2015-03-03 896
61c507cf652da1 Michel von Czettritz 2015-03-26 897 ret = fb_alloc_cmap(&info->cmap, 256, 0);
61c507cf652da1 Michel von Czettritz 2015-03-26 898 if (ret < 0) {
008272072d61a8 Masanari Iida 2015-05-28 899 pr_err("Could not allocate memory for cmap.\n");
81dee67e215b23 Sudip Mukherjee 2015-03-03 900 goto exit;
81dee67e215b23 Sudip Mukherjee 2015-03-03 901 }
81dee67e215b23 Sudip Mukherjee 2015-03-03 902
81dee67e215b23 Sudip Mukherjee 2015-03-03 903 pr_debug("#2 show info->cmap :\nstart=%d,len=%d,red=%p,green=%p,blue=%p,transp=%p\n",
81dee67e215b23 Sudip Mukherjee 2015-03-03 904 info->cmap.start, info->cmap.len,
81dee67e215b23 Sudip Mukherjee 2015-03-03 905 info->cmap.red, info->cmap.green, info->cmap.blue,
81dee67e215b23 Sudip Mukherjee 2015-03-03 906 info->cmap.transp);
81dee67e215b23 Sudip Mukherjee 2015-03-03 907
81dee67e215b23 Sudip Mukherjee 2015-03-03 908 exit:
81dee67e215b23 Sudip Mukherjee 2015-03-03 909 lynxfb_ops_check_var(var, info);
81dee67e215b23 Sudip Mukherjee 2015-03-03 910 return ret;
81dee67e215b23 Sudip Mukherjee 2015-03-03 911 }
81dee67e215b23 Sudip Mukherjee 2015-03-03 912
81dee67e215b23 Sudip Mukherjee 2015-03-03 913 /* chip specific g_option configuration routine */
700591a9adc8b1 Mike Rapoport 2015-10-26 914 static void sm750fb_setup(struct sm750_dev *sm750_dev, char *src)
81dee67e215b23 Sudip Mukherjee 2015-03-03 915 {
81dee67e215b23 Sudip Mukherjee 2015-03-03 916 char *opt;
81dee67e215b23 Sudip Mukherjee 2015-03-03 917 int swap;
81dee67e215b23 Sudip Mukherjee 2015-03-03 918
81dee67e215b23 Sudip Mukherjee 2015-03-03 919 swap = 0;
81dee67e215b23 Sudip Mukherjee 2015-03-03 920
1757d106a9ce8c Mike Rapoport 2015-10-26 921 sm750_dev->initParm.chip_clk = 0;
1757d106a9ce8c Mike Rapoport 2015-10-26 922 sm750_dev->initParm.mem_clk = 0;
1757d106a9ce8c Mike Rapoport 2015-10-26 923 sm750_dev->initParm.master_clk = 0;
1757d106a9ce8c Mike Rapoport 2015-10-26 924 sm750_dev->initParm.powerMode = 0;
1757d106a9ce8c Mike Rapoport 2015-10-26 925 sm750_dev->initParm.setAllEngOff = 0;
1757d106a9ce8c Mike Rapoport 2015-10-26 926 sm750_dev->initParm.resetMemory = 1;
81dee67e215b23 Sudip Mukherjee 2015-03-03 927
81dee67e215b23 Sudip Mukherjee 2015-03-03 928 /* defaultly turn g_hwcursor on for both view */
81dee67e215b23 Sudip Mukherjee 2015-03-03 929 g_hwcursor = 3;
81dee67e215b23 Sudip Mukherjee 2015-03-03 930
81dee67e215b23 Sudip Mukherjee 2015-03-03 931 if (!src || !*src) {
c56de0967a658c Elise Lennion 2016-10-31 932 dev_warn(&sm750_dev->pdev->dev, "no specific g_option.\n");
81dee67e215b23 Sudip Mukherjee 2015-03-03 933 goto NO_PARAM;
81dee67e215b23 Sudip Mukherjee 2015-03-03 934 }
81dee67e215b23 Sudip Mukherjee 2015-03-03 935
0fa96e39279988 Sudip Mukherjee 2015-03-10 936 while ((opt = strsep(&src, ":")) != NULL && *opt != 0) {
c56de0967a658c Elise Lennion 2016-10-31 937 dev_info(&sm750_dev->pdev->dev, "opt=%s\n", opt);
c56de0967a658c Elise Lennion 2016-10-31 938 dev_info(&sm750_dev->pdev->dev, "src=%s\n", src);
81dee67e215b23 Sudip Mukherjee 2015-03-03 939
144634a6b42146 Katie Dunne 2017-02-19 940 if (!strncmp(opt, "swap", strlen("swap"))) {
81dee67e215b23 Sudip Mukherjee 2015-03-03 941 swap = 1;
144634a6b42146 Katie Dunne 2017-02-19 942 } else if (!strncmp(opt, "nocrt", strlen("nocrt"))) {
1757d106a9ce8c Mike Rapoport 2015-10-26 943 sm750_dev->nocrt = 1;
144634a6b42146 Katie Dunne 2017-02-19 944 } else if (!strncmp(opt, "36bit", strlen("36bit"))) {
1757d106a9ce8c Mike Rapoport 2015-10-26 945 sm750_dev->pnltype = sm750_doubleTFT;
144634a6b42146 Katie Dunne 2017-02-19 946 } else if (!strncmp(opt, "18bit", strlen("18bit"))) {
1757d106a9ce8c Mike Rapoport 2015-10-26 947 sm750_dev->pnltype = sm750_dualTFT;
144634a6b42146 Katie Dunne 2017-02-19 948 } else if (!strncmp(opt, "24bit", strlen("24bit"))) {
1757d106a9ce8c Mike Rapoport 2015-10-26 949 sm750_dev->pnltype = sm750_24TFT;
144634a6b42146 Katie Dunne 2017-02-19 950 } else if (!strncmp(opt, "nohwc0", strlen("nohwc0"))) {
81dee67e215b23 Sudip Mukherjee 2015-03-03 951 g_hwcursor &= ~0x1;
144634a6b42146 Katie Dunne 2017-02-19 952 } else if (!strncmp(opt, "nohwc1", strlen("nohwc1"))) {
81dee67e215b23 Sudip Mukherjee 2015-03-03 953 g_hwcursor &= ~0x2;
144634a6b42146 Katie Dunne 2017-02-19 954 } else if (!strncmp(opt, "nohwc", strlen("nohwc"))) {
81dee67e215b23 Sudip Mukherjee 2015-03-03 955 g_hwcursor = 0;
144634a6b42146 Katie Dunne 2017-02-19 956 } else {
81dee67e215b23 Sudip Mukherjee 2015-03-03 957 if (!g_fbmode[0]) {
81dee67e215b23 Sudip Mukherjee 2015-03-03 @958 g_fbmode[0] = opt;
cee9ba1c30d051 Abdul Rauf 2017-01-08 959 dev_info(&sm750_dev->pdev->dev,
cee9ba1c30d051 Abdul Rauf 2017-01-08 960 "find fbmode0 : %s\n", g_fbmode[0]);
81dee67e215b23 Sudip Mukherjee 2015-03-03 961 } else if (!g_fbmode[1]) {
81dee67e215b23 Sudip Mukherjee 2015-03-03 962 g_fbmode[1] = opt;
cee9ba1c30d051 Abdul Rauf 2017-01-08 963 dev_info(&sm750_dev->pdev->dev,
cee9ba1c30d051 Abdul Rauf 2017-01-08 964 "find fbmode1 : %s\n", g_fbmode[1]);
81dee67e215b23 Sudip Mukherjee 2015-03-03 965 } else {
c56de0967a658c Elise Lennion 2016-10-31 966 dev_warn(&sm750_dev->pdev->dev, "How many view you wann set?\n");
81dee67e215b23 Sudip Mukherjee 2015-03-03 967 }
81dee67e215b23 Sudip Mukherjee 2015-03-03 968 }
81dee67e215b23 Sudip Mukherjee 2015-03-03 969 }
81dee67e215b23 Sudip Mukherjee 2015-03-03 970
81dee67e215b23 Sudip Mukherjee 2015-03-03 971 NO_PARAM:
e359b6a863e19f Mike Rapoport 2015-10-26 972 if (sm750_dev->revid != SM750LE_REVISION_ID) {
a3f92cc94c6126 Mike Rapoport 2016-01-17 973 if (sm750_dev->fb_count > 1) {
81dee67e215b23 Sudip Mukherjee 2015-03-03 974 if (swap)
1757d106a9ce8c Mike Rapoport 2015-10-26 975 sm750_dev->dataflow = sm750_dual_swap;
81dee67e215b23 Sudip Mukherjee 2015-03-03 976 else
1757d106a9ce8c Mike Rapoport 2015-10-26 977 sm750_dev->dataflow = sm750_dual_normal;
81dee67e215b23 Sudip Mukherjee 2015-03-03 978 } else {
81dee67e215b23 Sudip Mukherjee 2015-03-03 979 if (swap)
1757d106a9ce8c Mike Rapoport 2015-10-26 980 sm750_dev->dataflow = sm750_simul_sec;
81dee67e215b23 Sudip Mukherjee 2015-03-03 981 else
1757d106a9ce8c Mike Rapoport 2015-10-26 982 sm750_dev->dataflow = sm750_simul_pri;
81dee67e215b23 Sudip Mukherjee 2015-03-03 983 }
81dee67e215b23 Sudip Mukherjee 2015-03-03 984 } else {
81dee67e215b23 Sudip Mukherjee 2015-03-03 985 /* SM750LE only have one crt channel */
1757d106a9ce8c Mike Rapoport 2015-10-26 986 sm750_dev->dataflow = sm750_simul_sec;
81dee67e215b23 Sudip Mukherjee 2015-03-03 987 /* sm750le do not have complex attributes */
1757d106a9ce8c Mike Rapoport 2015-10-26 988 sm750_dev->nocrt = 0;
81dee67e215b23 Sudip Mukherjee 2015-03-03 989 }
81dee67e215b23 Sudip Mukherjee 2015-03-03 990 }
81dee67e215b23 Sudip Mukherjee 2015-03-03 991
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply
* Re: [PATCH] staging: sm750fb: make g_fbmode array fully const
From: kernel test robot @ 2025-12-24 12:20 UTC (permalink / raw)
To: Tejas Chaudhari, linux-staging
Cc: llvm, oe-kbuild-all, linux-fbdev, sudipm.mukherjee, teddy.wang,
gregkh, Tejas Chaudhari
In-Reply-To: <20251223191141.14206-1-tejaschaudhari038@gmail.com>
Hi Tejas,
kernel test robot noticed the following build errors:
[auto build test ERROR on staging/staging-testing]
url: https://github.com/intel-lab-lkp/linux/commits/Tejas-Chaudhari/staging-sm750fb-make-g_fbmode-array-fully-const/20251224-031344
base: staging/staging-testing
patch link: https://lore.kernel.org/r/20251223191141.14206-1-tejaschaudhari038%40gmail.com
patch subject: [PATCH] staging: sm750fb: make g_fbmode array fully const
config: x86_64-randconfig-003-20251224 (https://download.01.org/0day-ci/archive/20251224/202512242055.7j6y6sD6-lkp@intel.com/config)
compiler: clang version 20.1.8 (https://github.com/llvm/llvm-project 87f0227cb60147a26a1eeb4fb06e3b505e9c7261)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20251224/202512242055.7j6y6sD6-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202512242055.7j6y6sD6-lkp@intel.com/
All errors (new ones prefixed by >>):
>> drivers/staging/sm750fb/sm750.c:795:19: error: cannot assign to variable 'g_fbmode' with const-qualified type 'const char *const[2]'
795 | g_fbmode[index] = g_def_fbmode;
| ~~~~~~~~~~~~~~~ ^
drivers/staging/sm750fb/sm750.c:36:27: note: variable 'g_fbmode' declared const here
36 | static const char * const g_fbmode[] = {NULL, NULL};
| ~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~
drivers/staging/sm750fb/sm750.c:797:20: error: cannot assign to variable 'g_fbmode' with const-qualified type 'const char *const[2]'
797 | g_fbmode[index] = g_fbmode[0];
| ~~~~~~~~~~~~~~~ ^
drivers/staging/sm750fb/sm750.c:36:27: note: variable 'g_fbmode' declared const here
36 | static const char * const g_fbmode[] = {NULL, NULL};
| ~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~
drivers/staging/sm750fb/sm750.c:958:17: error: cannot assign to variable 'g_fbmode' with const-qualified type 'const char *const[2]'
958 | g_fbmode[0] = opt;
| ~~~~~~~~~~~ ^
drivers/staging/sm750fb/sm750.c:36:27: note: variable 'g_fbmode' declared const here
36 | static const char * const g_fbmode[] = {NULL, NULL};
| ~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~
drivers/staging/sm750fb/sm750.c:962:17: error: cannot assign to variable 'g_fbmode' with const-qualified type 'const char *const[2]'
962 | g_fbmode[1] = opt;
| ~~~~~~~~~~~ ^
drivers/staging/sm750fb/sm750.c:36:27: note: variable 'g_fbmode' declared const here
36 | static const char * const g_fbmode[] = {NULL, NULL};
| ~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~
4 errors generated.
vim +795 drivers/staging/sm750fb/sm750.c
81dee67e215b23 Sudip Mukherjee 2015-03-03 722
81dee67e215b23 Sudip Mukherjee 2015-03-03 723 static int lynxfb_set_fbinfo(struct fb_info *info, int index)
81dee67e215b23 Sudip Mukherjee 2015-03-03 724 {
81dee67e215b23 Sudip Mukherjee 2015-03-03 725 int i;
81dee67e215b23 Sudip Mukherjee 2015-03-03 726 struct lynxfb_par *par;
e359b6a863e19f Mike Rapoport 2015-10-26 727 struct sm750_dev *sm750_dev;
81dee67e215b23 Sudip Mukherjee 2015-03-03 728 struct lynxfb_crtc *crtc;
81dee67e215b23 Sudip Mukherjee 2015-03-03 729 struct lynxfb_output *output;
81dee67e215b23 Sudip Mukherjee 2015-03-03 730 struct fb_var_screeninfo *var;
81dee67e215b23 Sudip Mukherjee 2015-03-03 731 struct fb_fix_screeninfo *fix;
81dee67e215b23 Sudip Mukherjee 2015-03-03 732
81dee67e215b23 Sudip Mukherjee 2015-03-03 733 const struct fb_videomode *pdb[] = {
81dee67e215b23 Sudip Mukherjee 2015-03-03 734 lynx750_ext, NULL, vesa_modes,
81dee67e215b23 Sudip Mukherjee 2015-03-03 735 };
81dee67e215b23 Sudip Mukherjee 2015-03-03 736 int cdb[] = {ARRAY_SIZE(lynx750_ext), 0, VESA_MODEDB_SIZE};
d5d66cfea2ca28 Kelsey Skunberg 2019-04-27 737 static const char * const mdb_desc[] = {
81dee67e215b23 Sudip Mukherjee 2015-03-03 738 "driver prepared modes",
81dee67e215b23 Sudip Mukherjee 2015-03-03 739 "kernel prepared default modedb",
81dee67e215b23 Sudip Mukherjee 2015-03-03 740 "kernel HELPERS prepared vesa_modes",
81dee67e215b23 Sudip Mukherjee 2015-03-03 741 };
81dee67e215b23 Sudip Mukherjee 2015-03-03 742
8c475735085a7d Tim Wassink 2025-12-21 743 static const char *fix_id[2] = {
81dee67e215b23 Sudip Mukherjee 2015-03-03 744 "sm750_fb1", "sm750_fb2",
81dee67e215b23 Sudip Mukherjee 2015-03-03 745 };
81dee67e215b23 Sudip Mukherjee 2015-03-03 746
81dee67e215b23 Sudip Mukherjee 2015-03-03 747 int ret, line_length;
81dee67e215b23 Sudip Mukherjee 2015-03-03 748
81dee67e215b23 Sudip Mukherjee 2015-03-03 749 ret = 0;
81dee67e215b23 Sudip Mukherjee 2015-03-03 750 par = (struct lynxfb_par *)info->par;
e359b6a863e19f Mike Rapoport 2015-10-26 751 sm750_dev = par->dev;
81dee67e215b23 Sudip Mukherjee 2015-03-03 752 crtc = &par->crtc;
81dee67e215b23 Sudip Mukherjee 2015-03-03 753 output = &par->output;
81dee67e215b23 Sudip Mukherjee 2015-03-03 754 var = &info->var;
81dee67e215b23 Sudip Mukherjee 2015-03-03 755 fix = &info->fix;
81dee67e215b23 Sudip Mukherjee 2015-03-03 756
81dee67e215b23 Sudip Mukherjee 2015-03-03 757 /* set index */
81dee67e215b23 Sudip Mukherjee 2015-03-03 758 par->index = index;
81dee67e215b23 Sudip Mukherjee 2015-03-03 759 output->channel = &crtc->channel;
81dee67e215b23 Sudip Mukherjee 2015-03-03 760 sm750fb_set_drv(par);
81dee67e215b23 Sudip Mukherjee 2015-03-03 761
d11ac7cbcc266c Sudip Mukherjee 2015-08-07 762 /*
d11ac7cbcc266c Sudip Mukherjee 2015-08-07 763 * set current cursor variable and proc pointer,
d11ac7cbcc266c Sudip Mukherjee 2015-08-07 764 * must be set after crtc member initialized
d11ac7cbcc266c Sudip Mukherjee 2015-08-07 765 */
fdc234d85210d9 Benjamin Philip 2021-07-28 766 crtc->cursor.offset = crtc->o_screen + crtc->vidmem_size - 1024;
e359b6a863e19f Mike Rapoport 2015-10-26 767 crtc->cursor.mmio = sm750_dev->pvReg +
e359b6a863e19f Mike Rapoport 2015-10-26 768 0x800f0 + (int)crtc->channel * 0x140;
81dee67e215b23 Sudip Mukherjee 2015-03-03 769
81dee67e215b23 Sudip Mukherjee 2015-03-03 770 pr_info("crtc->cursor.mmio = %p\n", crtc->cursor.mmio);
cd33da26036ea5 Christopher Carbone 2022-08-23 771 crtc->cursor.max_h = 64;
cd33da26036ea5 Christopher Carbone 2022-08-23 772 crtc->cursor.max_w = 64;
39f9137268ee3d Benjamin Philip 2021-07-26 773 crtc->cursor.size = crtc->cursor.max_h * crtc->cursor.max_w * 2 / 8;
e359b6a863e19f Mike Rapoport 2015-10-26 774 crtc->cursor.vstart = sm750_dev->pvMem + crtc->cursor.offset;
81dee67e215b23 Sudip Mukherjee 2015-03-03 775
3de08a2d14ff8c Lorenzo Stoakes 2015-03-20 776 memset_io(crtc->cursor.vstart, 0, crtc->cursor.size);
f7c8a046577e09 Thomas Zimmermann 2023-11-27 777 if (!g_hwcursor)
52d0744d751d8f Arnd Bergmann 2016-11-09 778 sm750_hw_cursor_disable(&crtc->cursor);
81dee67e215b23 Sudip Mukherjee 2015-03-03 779
81dee67e215b23 Sudip Mukherjee 2015-03-03 780 /* set info->fbops, must be set before fb_find_mode */
e359b6a863e19f Mike Rapoport 2015-10-26 781 if (!sm750_dev->accel_off) {
81dee67e215b23 Sudip Mukherjee 2015-03-03 782 /* use 2d acceleration */
f7c8a046577e09 Thomas Zimmermann 2023-11-27 783 if (!g_hwcursor)
f7c8a046577e09 Thomas Zimmermann 2023-11-27 784 info->fbops = &lynxfb_ops_accel;
f7c8a046577e09 Thomas Zimmermann 2023-11-27 785 else
f7c8a046577e09 Thomas Zimmermann 2023-11-27 786 info->fbops = &lynxfb_ops_accel_with_cursor;
f7c8a046577e09 Thomas Zimmermann 2023-11-27 787 } else {
f7c8a046577e09 Thomas Zimmermann 2023-11-27 788 if (!g_hwcursor)
81dee67e215b23 Sudip Mukherjee 2015-03-03 789 info->fbops = &lynxfb_ops;
f7c8a046577e09 Thomas Zimmermann 2023-11-27 790 else
f7c8a046577e09 Thomas Zimmermann 2023-11-27 791 info->fbops = &lynxfb_ops_with_cursor;
f7c8a046577e09 Thomas Zimmermann 2023-11-27 792 }
81dee67e215b23 Sudip Mukherjee 2015-03-03 793
81dee67e215b23 Sudip Mukherjee 2015-03-03 794 if (!g_fbmode[index]) {
81dee67e215b23 Sudip Mukherjee 2015-03-03 @795 g_fbmode[index] = g_def_fbmode;
81dee67e215b23 Sudip Mukherjee 2015-03-03 796 if (index)
81dee67e215b23 Sudip Mukherjee 2015-03-03 797 g_fbmode[index] = g_fbmode[0];
81dee67e215b23 Sudip Mukherjee 2015-03-03 798 }
81dee67e215b23 Sudip Mukherjee 2015-03-03 799
81dee67e215b23 Sudip Mukherjee 2015-03-03 800 for (i = 0; i < 3; i++) {
81dee67e215b23 Sudip Mukherjee 2015-03-03 801 ret = fb_find_mode(var, info, g_fbmode[index],
81dee67e215b23 Sudip Mukherjee 2015-03-03 802 pdb[i], cdb[i], NULL, 8);
81dee67e215b23 Sudip Mukherjee 2015-03-03 803
81dee67e215b23 Sudip Mukherjee 2015-03-03 804 if (ret == 1) {
81dee67e215b23 Sudip Mukherjee 2015-03-03 805 pr_info("success! use specified mode:%s in %s\n",
81dee67e215b23 Sudip Mukherjee 2015-03-03 806 g_fbmode[index],
81dee67e215b23 Sudip Mukherjee 2015-03-03 807 mdb_desc[i]);
81dee67e215b23 Sudip Mukherjee 2015-03-03 808 break;
81dee67e215b23 Sudip Mukherjee 2015-03-03 809 } else if (ret == 2) {
81dee67e215b23 Sudip Mukherjee 2015-03-03 810 pr_warn("use specified mode:%s in %s,with an ignored refresh rate\n",
81dee67e215b23 Sudip Mukherjee 2015-03-03 811 g_fbmode[index],
81dee67e215b23 Sudip Mukherjee 2015-03-03 812 mdb_desc[i]);
81dee67e215b23 Sudip Mukherjee 2015-03-03 813 break;
81dee67e215b23 Sudip Mukherjee 2015-03-03 814 } else if (ret == 3) {
81dee67e215b23 Sudip Mukherjee 2015-03-03 815 pr_warn("wanna use default mode\n");
4bd9503d0becdb Michel von Czettritz 2015-03-26 816 /*break;*/
81dee67e215b23 Sudip Mukherjee 2015-03-03 817 } else if (ret == 4) {
81dee67e215b23 Sudip Mukherjee 2015-03-03 818 pr_warn("fall back to any valid mode\n");
81dee67e215b23 Sudip Mukherjee 2015-03-03 819 } else {
3318bb5e945f70 Michel von Czettritz 2015-03-26 820 pr_warn("ret = %d,fb_find_mode failed,with %s\n",
3318bb5e945f70 Michel von Czettritz 2015-03-26 821 ret,
3318bb5e945f70 Michel von Czettritz 2015-03-26 822 mdb_desc[i]);
81dee67e215b23 Sudip Mukherjee 2015-03-03 823 }
81dee67e215b23 Sudip Mukherjee 2015-03-03 824 }
81dee67e215b23 Sudip Mukherjee 2015-03-03 825
81dee67e215b23 Sudip Mukherjee 2015-03-03 826 /* some member of info->var had been set by fb_find_mode */
81dee67e215b23 Sudip Mukherjee 2015-03-03 827
271dbae3c6a1da Prasant Jalan 2017-04-01 828 pr_info("Member of info->var is :\n"
271dbae3c6a1da Prasant Jalan 2017-04-01 829 "xres=%d\n"
271dbae3c6a1da Prasant Jalan 2017-04-01 830 "yres=%d\n"
271dbae3c6a1da Prasant Jalan 2017-04-01 831 "xres_virtual=%d\n"
271dbae3c6a1da Prasant Jalan 2017-04-01 832 "yres_virtual=%d\n"
271dbae3c6a1da Prasant Jalan 2017-04-01 833 "xoffset=%d\n"
271dbae3c6a1da Prasant Jalan 2017-04-01 834 "yoffset=%d\n"
271dbae3c6a1da Prasant Jalan 2017-04-01 835 "bits_per_pixel=%d\n"
271dbae3c6a1da Prasant Jalan 2017-04-01 836 " ...\n",
3318bb5e945f70 Michel von Czettritz 2015-03-26 837 var->xres,
3318bb5e945f70 Michel von Czettritz 2015-03-26 838 var->yres,
3318bb5e945f70 Michel von Czettritz 2015-03-26 839 var->xres_virtual,
3318bb5e945f70 Michel von Czettritz 2015-03-26 840 var->yres_virtual,
3318bb5e945f70 Michel von Czettritz 2015-03-26 841 var->xoffset,
3318bb5e945f70 Michel von Czettritz 2015-03-26 842 var->yoffset,
3318bb5e945f70 Michel von Czettritz 2015-03-26 843 var->bits_per_pixel);
81dee67e215b23 Sudip Mukherjee 2015-03-03 844
81dee67e215b23 Sudip Mukherjee 2015-03-03 845 /* set par */
81dee67e215b23 Sudip Mukherjee 2015-03-03 846 par->info = info;
81dee67e215b23 Sudip Mukherjee 2015-03-03 847
81dee67e215b23 Sudip Mukherjee 2015-03-03 848 /* set info */
e3a3f9f5123683 Mike Rapoport 2015-10-26 849 line_length = ALIGN((var->xres_virtual * var->bits_per_pixel / 8),
e3a3f9f5123683 Mike Rapoport 2015-10-26 850 crtc->line_pad);
81dee67e215b23 Sudip Mukherjee 2015-03-03 851
81dee67e215b23 Sudip Mukherjee 2015-03-03 852 info->pseudo_palette = &par->pseudo_palette[0];
cc59bde1c920ab Benjamin Philip 2021-07-28 853 info->screen_base = crtc->v_screen;
81dee67e215b23 Sudip Mukherjee 2015-03-03 854 pr_debug("screen_base vaddr = %p\n", info->screen_base);
81dee67e215b23 Sudip Mukherjee 2015-03-03 855 info->screen_size = line_length * var->yres_virtual;
81dee67e215b23 Sudip Mukherjee 2015-03-03 856
81dee67e215b23 Sudip Mukherjee 2015-03-03 857 /* set info->fix */
81dee67e215b23 Sudip Mukherjee 2015-03-03 858 fix->type = FB_TYPE_PACKED_PIXELS;
81dee67e215b23 Sudip Mukherjee 2015-03-03 859 fix->type_aux = 0;
81dee67e215b23 Sudip Mukherjee 2015-03-03 860 fix->xpanstep = crtc->xpanstep;
81dee67e215b23 Sudip Mukherjee 2015-03-03 861 fix->ypanstep = crtc->ypanstep;
81dee67e215b23 Sudip Mukherjee 2015-03-03 862 fix->ywrapstep = crtc->ywrapstep;
81dee67e215b23 Sudip Mukherjee 2015-03-03 863 fix->accel = FB_ACCEL_SMI;
81dee67e215b23 Sudip Mukherjee 2015-03-03 864
8c475735085a7d Tim Wassink 2025-12-21 865 strscpy(fix->id, fix_id[index], sizeof(fix->id));
81dee67e215b23 Sudip Mukherjee 2015-03-03 866
fdc234d85210d9 Benjamin Philip 2021-07-28 867 fix->smem_start = crtc->o_screen + sm750_dev->vidmem_start;
81dee67e215b23 Sudip Mukherjee 2015-03-03 868 pr_info("fix->smem_start = %lx\n", fix->smem_start);
d11ac7cbcc266c Sudip Mukherjee 2015-08-07 869 /*
d11ac7cbcc266c Sudip Mukherjee 2015-08-07 870 * according to mmap experiment from user space application,
81dee67e215b23 Sudip Mukherjee 2015-03-03 871 * fix->mmio_len should not larger than virtual size
81dee67e215b23 Sudip Mukherjee 2015-03-03 872 * (xres_virtual x yres_virtual x ByPP)
81dee67e215b23 Sudip Mukherjee 2015-03-03 873 * Below line maybe buggy when user mmap fb dev node and write
81dee67e215b23 Sudip Mukherjee 2015-03-03 874 * data into the bound over virtual size
d11ac7cbcc266c Sudip Mukherjee 2015-08-07 875 */
81dee67e215b23 Sudip Mukherjee 2015-03-03 876 fix->smem_len = crtc->vidmem_size;
81dee67e215b23 Sudip Mukherjee 2015-03-03 877 pr_info("fix->smem_len = %x\n", fix->smem_len);
81dee67e215b23 Sudip Mukherjee 2015-03-03 878 info->screen_size = fix->smem_len;
81dee67e215b23 Sudip Mukherjee 2015-03-03 879 fix->line_length = line_length;
e359b6a863e19f Mike Rapoport 2015-10-26 880 fix->mmio_start = sm750_dev->vidreg_start;
81dee67e215b23 Sudip Mukherjee 2015-03-03 881 pr_info("fix->mmio_start = %lx\n", fix->mmio_start);
e359b6a863e19f Mike Rapoport 2015-10-26 882 fix->mmio_len = sm750_dev->vidreg_size;
81dee67e215b23 Sudip Mukherjee 2015-03-03 883 pr_info("fix->mmio_len = %x\n", fix->mmio_len);
b610e1193a917f Matej Dujava 2020-04-30 884
b610e1193a917f Matej Dujava 2020-04-30 885 lynxfb_set_visual_mode(info);
81dee67e215b23 Sudip Mukherjee 2015-03-03 886
81dee67e215b23 Sudip Mukherjee 2015-03-03 887 /* set var */
81dee67e215b23 Sudip Mukherjee 2015-03-03 888 var->activate = FB_ACTIVATE_NOW;
81dee67e215b23 Sudip Mukherjee 2015-03-03 889 var->accel_flags = 0;
81dee67e215b23 Sudip Mukherjee 2015-03-03 890 var->vmode = FB_VMODE_NONINTERLACED;
81dee67e215b23 Sudip Mukherjee 2015-03-03 891
81dee67e215b23 Sudip Mukherjee 2015-03-03 892 pr_debug("#1 show info->cmap :\nstart=%d,len=%d,red=%p,green=%p,blue=%p,transp=%p\n",
81dee67e215b23 Sudip Mukherjee 2015-03-03 893 info->cmap.start, info->cmap.len,
81dee67e215b23 Sudip Mukherjee 2015-03-03 894 info->cmap.red, info->cmap.green, info->cmap.blue,
81dee67e215b23 Sudip Mukherjee 2015-03-03 895 info->cmap.transp);
81dee67e215b23 Sudip Mukherjee 2015-03-03 896
61c507cf652da1 Michel von Czettritz 2015-03-26 897 ret = fb_alloc_cmap(&info->cmap, 256, 0);
61c507cf652da1 Michel von Czettritz 2015-03-26 898 if (ret < 0) {
008272072d61a8 Masanari Iida 2015-05-28 899 pr_err("Could not allocate memory for cmap.\n");
81dee67e215b23 Sudip Mukherjee 2015-03-03 900 goto exit;
81dee67e215b23 Sudip Mukherjee 2015-03-03 901 }
81dee67e215b23 Sudip Mukherjee 2015-03-03 902
81dee67e215b23 Sudip Mukherjee 2015-03-03 903 pr_debug("#2 show info->cmap :\nstart=%d,len=%d,red=%p,green=%p,blue=%p,transp=%p\n",
81dee67e215b23 Sudip Mukherjee 2015-03-03 904 info->cmap.start, info->cmap.len,
81dee67e215b23 Sudip Mukherjee 2015-03-03 905 info->cmap.red, info->cmap.green, info->cmap.blue,
81dee67e215b23 Sudip Mukherjee 2015-03-03 906 info->cmap.transp);
81dee67e215b23 Sudip Mukherjee 2015-03-03 907
81dee67e215b23 Sudip Mukherjee 2015-03-03 908 exit:
81dee67e215b23 Sudip Mukherjee 2015-03-03 909 lynxfb_ops_check_var(var, info);
81dee67e215b23 Sudip Mukherjee 2015-03-03 910 return ret;
81dee67e215b23 Sudip Mukherjee 2015-03-03 911 }
81dee67e215b23 Sudip Mukherjee 2015-03-03 912
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply
* Re: [PATCH v2] fbdev: bitblit: bound-check glyph index in bit_putcs*
From: Vitaly Chikunov @ 2025-12-25 22:29 UTC (permalink / raw)
To: Junjie Cao
Cc: Thomas Zimmermann, Simona Vetter, Helge Deller, Zsolt Kajtar,
Albin Babu Varghese, linux-fbdev, dri-devel, linux-kernel, stable,
regressions
In-Reply-To: <20251020134701.84082-1-junjie.cao@intel.com>
Dear linux-fbdev, stable,
On Mon, Oct 20, 2025 at 09:47:01PM +0800, Junjie Cao wrote:
> bit_putcs_aligned()/unaligned() derived the glyph pointer from the
> character value masked by 0xff/0x1ff, which may exceed the actual font's
> glyph count and read past the end of the built-in font array.
> Clamp the index to the actual glyph count before computing the address.
>
> This fixes a global out-of-bounds read reported by syzbot.
>
> Reported-by: syzbot+793cf822d213be1a74f2@syzkaller.appspotmail.com
> Closes: https://syzkaller.appspot.com/bug?extid=793cf822d213be1a74f2
> Tested-by: syzbot+793cf822d213be1a74f2@syzkaller.appspotmail.com
> Signed-off-by: Junjie Cao <junjie.cao@intel.com>
This commit is applied to v5.10.247 and causes a regression: when
switching VT with ctrl-alt-f2 the screen is blank or completely filled
with angle characters, then new text is not appearing (or not visible).
This commit is found with git bisect from v5.10.246 to v5.10.247:
0998a6cb232674408a03e8561dc15aa266b2f53b is the first bad commit
commit 0998a6cb232674408a03e8561dc15aa266b2f53b
Author: Junjie Cao <junjie.cao@intel.com>
AuthorDate: 2025-10-20 21:47:01 +0800
Commit: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
CommitDate: 2025-12-07 06:08:07 +0900
fbdev: bitblit: bound-check glyph index in bit_putcs*
commit 18c4ef4e765a798b47980555ed665d78b71aeadf upstream.
bit_putcs_aligned()/unaligned() derived the glyph pointer from the
character value masked by 0xff/0x1ff, which may exceed the actual font's
glyph count and read past the end of the built-in font array.
Clamp the index to the actual glyph count before computing the address.
This fixes a global out-of-bounds read reported by syzbot.
Reported-by: syzbot+793cf822d213be1a74f2@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=793cf822d213be1a74f2
Tested-by: syzbot+793cf822d213be1a74f2@syzkaller.appspotmail.com
Signed-off-by: Junjie Cao <junjie.cao@intel.com>
Reviewed-by: Thomas Zimmermann <tzimmermann@suse.de>
Signed-off-by: Helge Deller <deller@gmx.de>
Cc: stable@vger.kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/video/fbdev/core/bitblit.c | 16 ++++++++++++----
1 file changed, 12 insertions(+), 4 deletions(-)
The minimal reproducer in cli, after kernel is booted:
date >/dev/tty2; chvt 2
and the date does not appear.
Thanks,
#regzbot introduced: 0998a6cb232674408a03e8561dc15aa266b2f53b
> ---
> v1: https://lore.kernel.org/linux-fbdev/5d237d1a-a528-4205-a4d8-71709134f1e1@suse.de/
> v1 -> v2:
> - Fix indentation and add blank line after declarations with the .pl helper
> - No functional changes
>
> drivers/video/fbdev/core/bitblit.c | 16 ++++++++++++----
> 1 file changed, 12 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/video/fbdev/core/bitblit.c b/drivers/video/fbdev/core/bitblit.c
> index 9d2e59796c3e..085ffb44c51a 100644
> --- a/drivers/video/fbdev/core/bitblit.c
> +++ b/drivers/video/fbdev/core/bitblit.c
> @@ -79,12 +79,16 @@ static inline void bit_putcs_aligned(struct vc_data *vc, struct fb_info *info,
> struct fb_image *image, u8 *buf, u8 *dst)
> {
> u16 charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
> + unsigned int charcnt = vc->vc_font.charcount;
> u32 idx = vc->vc_font.width >> 3;
> u8 *src;
>
> while (cnt--) {
> - src = vc->vc_font.data + (scr_readw(s++)&
> - charmask)*cellsize;
> + u16 ch = scr_readw(s++) & charmask;
> +
> + if (ch >= charcnt)
> + ch = 0;
> + src = vc->vc_font.data + (unsigned int)ch * cellsize;
>
> if (attr) {
> update_attr(buf, src, attr, vc);
> @@ -112,14 +116,18 @@ static inline void bit_putcs_unaligned(struct vc_data *vc,
> u8 *dst)
> {
> u16 charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
> + unsigned int charcnt = vc->vc_font.charcount;
> u32 shift_low = 0, mod = vc->vc_font.width % 8;
> u32 shift_high = 8;
> u32 idx = vc->vc_font.width >> 3;
> u8 *src;
>
> while (cnt--) {
> - src = vc->vc_font.data + (scr_readw(s++)&
> - charmask)*cellsize;
> + u16 ch = scr_readw(s++) & charmask;
> +
> + if (ch >= charcnt)
> + ch = 0;
> + src = vc->vc_font.data + (unsigned int)ch * cellsize;
>
> if (attr) {
> update_attr(buf, src, attr, vc);
> --
> 2.48.1
>
^ permalink raw reply
* [PATCH] staging: sm750fb: fix const array warning
From: MottiKumar @ 2025-12-26 12:04 UTC (permalink / raw)
To: sudipm.mukherjee, teddy.wang, gregkh
Cc: skhan, linux-kernel-mentees, linux-fbdev, linux-staging,
linux-kernel, mottikumarbabu
Add a missing const to g_fbmode to fix a checkpatch warning:
"static const char * array should probably be static const char * const"
Signed-off-by: MottiKumar <mottikumarbabu@gmail.com>
---
drivers/staging/sm750fb/sm750.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/staging/sm750fb/sm750.c b/drivers/staging/sm750fb/sm750.c
index d100b9e1d3d5..7afb58561a0c 100644
--- a/drivers/staging/sm750fb/sm750.c
+++ b/drivers/staging/sm750fb/sm750.c
@@ -33,7 +33,7 @@
static int g_hwcursor = 1;
static int g_noaccel;
static int g_nomtrr;
-static const char *g_fbmode[] = {NULL, NULL};
+static const char * const g_fbmode[] = {NULL, NULL};
static const char *g_def_fbmode = "1024x768-32@60";
static char *g_settings;
static int g_dualview;
--
2.43.0
^ permalink raw reply related
* Re: [PATCH v2] fbdev: bitblit: bound-check glyph index in bit_putcs*
From: Vitaly Chikunov @ 2025-12-26 12:21 UTC (permalink / raw)
To: Junjie Cao, Thomas Zimmermann, Greg Kroah-Hartman
Cc: Peilin Ye, Daniel Vetter, Shigeru Yoshida, Simona Vetter,
Helge Deller, Zsolt Kajtar, Albin Babu Varghese, linux-fbdev,
dri-devel, linux-kernel, stable, regressions
In-Reply-To: <aU23brU4lZqIkw4Z@altlinux.org>
Dear linux-fbdev, stable,
On Fri, Dec 26, 2025 at 01:29:13AM +0300, Vitaly Chikunov wrote:
>
> On Mon, Oct 20, 2025 at 09:47:01PM +0800, Junjie Cao wrote:
> > bit_putcs_aligned()/unaligned() derived the glyph pointer from the
> > character value masked by 0xff/0x1ff, which may exceed the actual font's
> > glyph count and read past the end of the built-in font array.
> > Clamp the index to the actual glyph count before computing the address.
> >
> > This fixes a global out-of-bounds read reported by syzbot.
> >
> > Reported-by: syzbot+793cf822d213be1a74f2@syzkaller.appspotmail.com
> > Closes: https://syzkaller.appspot.com/bug?extid=793cf822d213be1a74f2
> > Tested-by: syzbot+793cf822d213be1a74f2@syzkaller.appspotmail.com
> > Signed-off-by: Junjie Cao <junjie.cao@intel.com>
>
> This commit is applied to v5.10.247 and causes a regression: when
> switching VT with ctrl-alt-f2 the screen is blank or completely filled
> with angle characters, then new text is not appearing (or not visible).
>
> This commit is found with git bisect from v5.10.246 to v5.10.247:
>
> 0998a6cb232674408a03e8561dc15aa266b2f53b is the first bad commit
> commit 0998a6cb232674408a03e8561dc15aa266b2f53b
> Author: Junjie Cao <junjie.cao@intel.com>
> AuthorDate: 2025-10-20 21:47:01 +0800
> Commit: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> CommitDate: 2025-12-07 06:08:07 +0900
>
> fbdev: bitblit: bound-check glyph index in bit_putcs*
>
> commit 18c4ef4e765a798b47980555ed665d78b71aeadf upstream.
>
> bit_putcs_aligned()/unaligned() derived the glyph pointer from the
> character value masked by 0xff/0x1ff, which may exceed the actual font's
> glyph count and read past the end of the built-in font array.
> Clamp the index to the actual glyph count before computing the address.
>
> This fixes a global out-of-bounds read reported by syzbot.
>
> Reported-by: syzbot+793cf822d213be1a74f2@syzkaller.appspotmail.com
> Closes: https://syzkaller.appspot.com/bug?extid=793cf822d213be1a74f2
> Tested-by: syzbot+793cf822d213be1a74f2@syzkaller.appspotmail.com
> Signed-off-by: Junjie Cao <junjie.cao@intel.com>
> Reviewed-by: Thomas Zimmermann <tzimmermann@suse.de>
> Signed-off-by: Helge Deller <deller@gmx.de>
> Cc: stable@vger.kernel.org
> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
>
> drivers/video/fbdev/core/bitblit.c | 16 ++++++++++++----
> 1 file changed, 12 insertions(+), 4 deletions(-)
>
> The minimal reproducer in cli, after kernel is booted:
>
> date >/dev/tty2; chvt 2
>
> and the date does not appear.
>
> Thanks,
>
> #regzbot introduced: 0998a6cb232674408a03e8561dc15aa266b2f53b
>
> > ---
> > v1: https://lore.kernel.org/linux-fbdev/5d237d1a-a528-4205-a4d8-71709134f1e1@suse.de/
> > v1 -> v2:
> > - Fix indentation and add blank line after declarations with the .pl helper
> > - No functional changes
> >
> > drivers/video/fbdev/core/bitblit.c | 16 ++++++++++++----
> > 1 file changed, 12 insertions(+), 4 deletions(-)
> >
> > diff --git a/drivers/video/fbdev/core/bitblit.c b/drivers/video/fbdev/core/bitblit.c
> > index 9d2e59796c3e..085ffb44c51a 100644
> > --- a/drivers/video/fbdev/core/bitblit.c
> > +++ b/drivers/video/fbdev/core/bitblit.c
> > @@ -79,12 +79,16 @@ static inline void bit_putcs_aligned(struct vc_data *vc, struct fb_info *info,
> > struct fb_image *image, u8 *buf, u8 *dst)
> > {
> > u16 charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
> > + unsigned int charcnt = vc->vc_font.charcount;
Perhaps, vc->vc_font.charcount (which is relied upon in the following
comparison) is not always set correctly in v5.10.247. At least two
commits that set vc_font.charcount are missing from v5.10.247:
a1ac250a82a5 ("fbcon: Avoid using FNTCHARCNT() and hard-coded built-in font charcount")
a5a923038d70 ("fbdev: fbcon: Properly revert changes when vc_resize() failed")
Thanks,
> > u32 idx = vc->vc_font.width >> 3;
> > u8 *src;
> >
> > while (cnt--) {
> > - src = vc->vc_font.data + (scr_readw(s++)&
> > - charmask)*cellsize;
> > + u16 ch = scr_readw(s++) & charmask;
> > +
> > + if (ch >= charcnt)
> > + ch = 0;
> > + src = vc->vc_font.data + (unsigned int)ch * cellsize;
> >
> > if (attr) {
> > update_attr(buf, src, attr, vc);
> > @@ -112,14 +116,18 @@ static inline void bit_putcs_unaligned(struct vc_data *vc,
> > u8 *dst)
> > {
> > u16 charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
> > + unsigned int charcnt = vc->vc_font.charcount;
> > u32 shift_low = 0, mod = vc->vc_font.width % 8;
> > u32 shift_high = 8;
> > u32 idx = vc->vc_font.width >> 3;
> > u8 *src;
> >
> > while (cnt--) {
> > - src = vc->vc_font.data + (scr_readw(s++)&
> > - charmask)*cellsize;
> > + u16 ch = scr_readw(s++) & charmask;
> > +
> > + if (ch >= charcnt)
> > + ch = 0;
> > + src = vc->vc_font.data + (unsigned int)ch * cellsize;
> >
> > if (attr) {
> > update_attr(buf, src, attr, vc);
> > --
> > 2.48.1
> >
^ permalink raw reply
* Re: [PATCH v2] fbdev: bitblit: bound-check glyph index in bit_putcs*
From: Barry K. Nathan @ 2025-12-27 2:04 UTC (permalink / raw)
To: Vitaly Chikunov, Junjie Cao, Thomas Zimmermann,
Greg Kroah-Hartman
Cc: Peilin Ye, Daniel Vetter, Shigeru Yoshida, Simona Vetter,
Helge Deller, Zsolt Kajtar, Albin Babu Varghese, linux-fbdev,
dri-devel, linux-kernel, stable, regressions
In-Reply-To: <aU58SeZZPxScVPad@altlinux.org>
On 12/26/25 4:21 AM, Vitaly Chikunov wrote:
> Dear linux-fbdev, stable,
>
> On Fri, Dec 26, 2025 at 01:29:13AM +0300, Vitaly Chikunov wrote:
>>
>> On Mon, Oct 20, 2025 at 09:47:01PM +0800, Junjie Cao wrote:
>>> bit_putcs_aligned()/unaligned() derived the glyph pointer from the
>>> character value masked by 0xff/0x1ff, which may exceed the actual font's
>>> glyph count and read past the end of the built-in font array.
>>> Clamp the index to the actual glyph count before computing the address.
>>>
>>> This fixes a global out-of-bounds read reported by syzbot.
>>>
>>> Reported-by: syzbot+793cf822d213be1a74f2@syzkaller.appspotmail.com
>>> Closes: https://syzkaller.appspot.com/bug?extid=793cf822d213be1a74f2
>>> Tested-by: syzbot+793cf822d213be1a74f2@syzkaller.appspotmail.com
>>> Signed-off-by: Junjie Cao <junjie.cao@intel.com>
>>
>> This commit is applied to v5.10.247 and causes a regression: when
>> switching VT with ctrl-alt-f2 the screen is blank or completely filled
>> with angle characters, then new text is not appearing (or not visible).
>>
>> This commit is found with git bisect from v5.10.246 to v5.10.247:
>>
>> 0998a6cb232674408a03e8561dc15aa266b2f53b is the first bad commit
>> commit 0998a6cb232674408a03e8561dc15aa266b2f53b
>> Author: Junjie Cao <junjie.cao@intel.com>
>> AuthorDate: 2025-10-20 21:47:01 +0800
>> Commit: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
>> CommitDate: 2025-12-07 06:08:07 +0900
>>
>> fbdev: bitblit: bound-check glyph index in bit_putcs*
>>
>> commit 18c4ef4e765a798b47980555ed665d78b71aeadf upstream.
>>
>> bit_putcs_aligned()/unaligned() derived the glyph pointer from the
>> character value masked by 0xff/0x1ff, which may exceed the actual font's
>> glyph count and read past the end of the built-in font array.
>> Clamp the index to the actual glyph count before computing the address.
>>
>> This fixes a global out-of-bounds read reported by syzbot.
>>
>> Reported-by: syzbot+793cf822d213be1a74f2@syzkaller.appspotmail.com
>> Closes: https://syzkaller.appspot.com/bug?extid=793cf822d213be1a74f2
>> Tested-by: syzbot+793cf822d213be1a74f2@syzkaller.appspotmail.com
>> Signed-off-by: Junjie Cao <junjie.cao@intel.com>
>> Reviewed-by: Thomas Zimmermann <tzimmermann@suse.de>
>> Signed-off-by: Helge Deller <deller@gmx.de>
>> Cc: stable@vger.kernel.org
>> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
>>
>> drivers/video/fbdev/core/bitblit.c | 16 ++++++++++++----
>> 1 file changed, 12 insertions(+), 4 deletions(-)
>>
>> The minimal reproducer in cli, after kernel is booted:
>>
>> date >/dev/tty2; chvt 2
>>
>> and the date does not appear.
>>
>> Thanks,
>>
>> #regzbot introduced: 0998a6cb232674408a03e8561dc15aa266b2f53b
>>
>>> ---
>>> v1: https://lore.kernel.org/linux-fbdev/5d237d1a-a528-4205-a4d8-71709134f1e1@suse.de/
>>> v1 -> v2:
>>> - Fix indentation and add blank line after declarations with the .pl helper
>>> - No functional changes
>>>
>>> drivers/video/fbdev/core/bitblit.c | 16 ++++++++++++----
>>> 1 file changed, 12 insertions(+), 4 deletions(-)
>>>
>>> diff --git a/drivers/video/fbdev/core/bitblit.c b/drivers/video/fbdev/core/bitblit.c
>>> index 9d2e59796c3e..085ffb44c51a 100644
>>> --- a/drivers/video/fbdev/core/bitblit.c
>>> +++ b/drivers/video/fbdev/core/bitblit.c
>>> @@ -79,12 +79,16 @@ static inline void bit_putcs_aligned(struct vc_data *vc, struct fb_info *info,
>>> struct fb_image *image, u8 *buf, u8 *dst)
>>> {
>>> u16 charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
>>> + unsigned int charcnt = vc->vc_font.charcount;
>
> Perhaps, vc->vc_font.charcount (which is relied upon in the following
> comparison) is not always set correctly in v5.10.247. At least two
> commits that set vc_font.charcount are missing from v5.10.247:
>
> a1ac250a82a5 ("fbcon: Avoid using FNTCHARCNT() and hard-coded built-in font charcount")
> a5a923038d70 ("fbdev: fbcon: Properly revert changes when vc_resize() failed")
>
> Thanks,
I was just about to report this.
I found two ways to fix this bug. One is to revert this patch; the other
is to apply the following 3 patches, which are already present in 5.11
and later:
7a089ec7d77fe7d50f6bb7b178fa25eec9fd822b
console: Delete unused con_font_copy() callback implementations
4ee573086bd88ff3060dda07873bf755d332e9ba
Fonts: Add charcount field to font_desc
a1ac250a82a5e97db71f14101ff7468291a6aaef
fbcon: Avoid using FNTCHARCNT() and hard-coded built-in font
charcount
(Oh, by the way, this same regression also affects 5.4.302, and the same
3 patches fix the regression on 5.4 as well, once you manually fix merge
conflicts. Maybe it would be better to backport other additional commits
instead of fixing the merge conflicts manually, but since 5.4 is now EOL
I didn't dig that deep.)
Once these 3 patches are applied, I wonder if a5a923038d70 now becomes
necessary for 5.10.y. For what it's worth, it applies fine and the
resulting kernel seems to run OK in brief testing.
--
-Barry K. Nathan <barryn@pobox.com>
^ permalink raw reply
* [PATCH 1/3] drivers: video: fbdev: Remove hyperv_fb driver
From: Prasanna Kumar T S M @ 2025-12-27 4:24 UTC (permalink / raw)
To: linux-fbdev, dri-devel, linux-hyperv, ssengar, mhklinux, wei.liu,
ptsm, tzimmermann, deller, kys, haiyangz, decui
Cc: mrathor, rdunlap, soci, hsukrut3, linux-kernel
The HyperV DRM driver is available since 5.14. This makes the hyperv_fb
driver redundant, remove it.
Signed-off-by: Prasanna Kumar T S M <ptsm@linux.microsoft.com>
---
MAINTAINERS | 10 -
drivers/video/fbdev/Kconfig | 11 -
drivers/video/fbdev/Makefile | 1 -
drivers/video/fbdev/hyperv_fb.c | 1388 -------------------------------
4 files changed, 1410 deletions(-)
delete mode 100644 drivers/video/fbdev/hyperv_fb.c
diff --git a/MAINTAINERS b/MAINTAINERS
index dc731d37c8fe..73073551048e 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -11762,16 +11762,6 @@ F: include/uapi/rdma/mana-abi.h
F: net/vmw_vsock/hyperv_transport.c
F: tools/hv/
-HYPER-V FRAMEBUFFER DRIVER
-M: "K. Y. Srinivasan" <kys@microsoft.com>
-M: Haiyang Zhang <haiyangz@microsoft.com>
-M: Wei Liu <wei.liu@kernel.org>
-M: Dexuan Cui <decui@microsoft.com>
-L: linux-hyperv@vger.kernel.org
-S: Obsolete
-T: git git://git.kernel.org/pub/scm/linux/kernel/git/hyperv/linux.git
-F: drivers/video/fbdev/hyperv_fb.c
-
HYPERBUS SUPPORT
M: Vignesh Raghavendra <vigneshr@ti.com>
R: Tudor Ambarus <tudor.ambarus@linaro.org>
diff --git a/drivers/video/fbdev/Kconfig b/drivers/video/fbdev/Kconfig
index a733f90eca55..45733522ff48 100644
--- a/drivers/video/fbdev/Kconfig
+++ b/drivers/video/fbdev/Kconfig
@@ -1770,17 +1770,6 @@ config FB_BROADSHEET
and could also have been called by other names when coupled with
a bridge adapter.
-config FB_HYPERV
- tristate "Microsoft Hyper-V Synthetic Video support (DEPRECATED)"
- depends on FB && HYPERV_VMBUS
- select DMA_CMA if HAVE_DMA_CONTIGUOUS && CMA
- select FB_IOMEM_HELPERS_DEFERRED
- help
- This framebuffer driver supports Microsoft Hyper-V Synthetic Video.
-
- This driver is deprecated, please use the Hyper-V DRM driver at
- drivers/gpu/drm/hyperv (CONFIG_DRM_HYPERV) instead.
-
config FB_SIMPLE
tristate "Simple framebuffer support"
depends on FB
diff --git a/drivers/video/fbdev/Makefile b/drivers/video/fbdev/Makefile
index b3d12f977c06..36a18d958ba0 100644
--- a/drivers/video/fbdev/Makefile
+++ b/drivers/video/fbdev/Makefile
@@ -111,7 +111,6 @@ obj-y += omap2/
obj-$(CONFIG_XEN_FBDEV_FRONTEND) += xen-fbfront.o
obj-$(CONFIG_FB_CARMINE) += carminefb.o
obj-$(CONFIG_FB_MB862XX) += mb862xx/
-obj-$(CONFIG_FB_HYPERV) += hyperv_fb.o
obj-$(CONFIG_FB_OPENCORES) += ocfb.o
obj-$(CONFIG_FB_SM712) += sm712fb.o
diff --git a/drivers/video/fbdev/hyperv_fb.c b/drivers/video/fbdev/hyperv_fb.c
deleted file mode 100644
index c99e2ea4b3de..000000000000
--- a/drivers/video/fbdev/hyperv_fb.c
+++ /dev/null
@@ -1,1388 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Copyright (c) 2012, Microsoft Corporation.
- *
- * Author:
- * Haiyang Zhang <haiyangz@microsoft.com>
- */
-
-/*
- * Hyper-V Synthetic Video Frame Buffer Driver
- *
- * This is the driver for the Hyper-V Synthetic Video, which supports
- * screen resolution up to Full HD 1920x1080 with 32 bit color on Windows
- * Server 2012, and 1600x1200 with 16 bit color on Windows Server 2008 R2
- * or earlier.
- *
- * It also solves the double mouse cursor issue of the emulated video mode.
- *
- * The default screen resolution is 1152x864, which may be changed by a
- * kernel parameter:
- * video=hyperv_fb:<width>x<height>
- * For example: video=hyperv_fb:1280x1024
- *
- * Portrait orientation is also supported:
- * For example: video=hyperv_fb:864x1152
- *
- * When a Windows 10 RS5+ host is used, the virtual machine screen
- * resolution is obtained from the host. The "video=hyperv_fb" option is
- * not needed, but still can be used to overwrite what the host specifies.
- * The VM resolution on the host could be set by executing the powershell
- * "set-vmvideo" command. For example
- * set-vmvideo -vmname name -horizontalresolution:1920 \
- * -verticalresolution:1200 -resolutiontype single
- *
- * Gen 1 VMs also support direct using VM's physical memory for framebuffer.
- * It could improve the efficiency and performance for framebuffer and VM.
- * This requires to allocate contiguous physical memory from Linux kernel's
- * CMA memory allocator. To enable this, supply a kernel parameter to give
- * enough memory space to CMA allocator for framebuffer. For example:
- * cma=130m
- * This gives 130MB memory to CMA allocator that can be allocated to
- * framebuffer. For reference, 8K resolution (7680x4320) takes about
- * 127MB memory.
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/aperture.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/vmalloc.h>
-#include <linux/init.h>
-#include <linux/completion.h>
-#include <linux/fb.h>
-#include <linux/pci.h>
-#include <linux/panic_notifier.h>
-#include <linux/efi.h>
-#include <linux/console.h>
-
-#include <linux/hyperv.h>
-
-/* Hyper-V Synthetic Video Protocol definitions and structures */
-#define MAX_VMBUS_PKT_SIZE 0x4000
-
-#define SYNTHVID_VERSION(major, minor) ((minor) << 16 | (major))
-/* Support for VERSION_WIN7 is removed. #define is retained for reference. */
-#define SYNTHVID_VERSION_WIN7 SYNTHVID_VERSION(3, 0)
-#define SYNTHVID_VERSION_WIN8 SYNTHVID_VERSION(3, 2)
-#define SYNTHVID_VERSION_WIN10 SYNTHVID_VERSION(3, 5)
-
-#define SYNTHVID_VER_GET_MAJOR(ver) (ver & 0x0000ffff)
-#define SYNTHVID_VER_GET_MINOR(ver) ((ver & 0xffff0000) >> 16)
-
-#define SYNTHVID_DEPTH_WIN8 32
-#define SYNTHVID_FB_SIZE_WIN8 (8 * 1024 * 1024)
-
-enum pipe_msg_type {
- PIPE_MSG_INVALID,
- PIPE_MSG_DATA,
- PIPE_MSG_MAX
-};
-
-struct pipe_msg_hdr {
- u32 type;
- u32 size; /* size of message after this field */
-} __packed;
-
-
-enum synthvid_msg_type {
- SYNTHVID_ERROR = 0,
- SYNTHVID_VERSION_REQUEST = 1,
- SYNTHVID_VERSION_RESPONSE = 2,
- SYNTHVID_VRAM_LOCATION = 3,
- SYNTHVID_VRAM_LOCATION_ACK = 4,
- SYNTHVID_SITUATION_UPDATE = 5,
- SYNTHVID_SITUATION_UPDATE_ACK = 6,
- SYNTHVID_POINTER_POSITION = 7,
- SYNTHVID_POINTER_SHAPE = 8,
- SYNTHVID_FEATURE_CHANGE = 9,
- SYNTHVID_DIRT = 10,
- SYNTHVID_RESOLUTION_REQUEST = 13,
- SYNTHVID_RESOLUTION_RESPONSE = 14,
-
- SYNTHVID_MAX = 15
-};
-
-#define SYNTHVID_EDID_BLOCK_SIZE 128
-#define SYNTHVID_MAX_RESOLUTION_COUNT 64
-
-struct hvd_screen_info {
- u16 width;
- u16 height;
-} __packed;
-
-struct synthvid_msg_hdr {
- u32 type;
- u32 size; /* size of this header + payload after this field*/
-} __packed;
-
-struct synthvid_version_req {
- u32 version;
-} __packed;
-
-struct synthvid_version_resp {
- u32 version;
- u8 is_accepted;
- u8 max_video_outputs;
-} __packed;
-
-struct synthvid_supported_resolution_req {
- u8 maximum_resolution_count;
-} __packed;
-
-struct synthvid_supported_resolution_resp {
- u8 edid_block[SYNTHVID_EDID_BLOCK_SIZE];
- u8 resolution_count;
- u8 default_resolution_index;
- u8 is_standard;
- struct hvd_screen_info
- supported_resolution[SYNTHVID_MAX_RESOLUTION_COUNT];
-} __packed;
-
-struct synthvid_vram_location {
- u64 user_ctx;
- u8 is_vram_gpa_specified;
- u64 vram_gpa;
-} __packed;
-
-struct synthvid_vram_location_ack {
- u64 user_ctx;
-} __packed;
-
-struct video_output_situation {
- u8 active;
- u32 vram_offset;
- u8 depth_bits;
- u32 width_pixels;
- u32 height_pixels;
- u32 pitch_bytes;
-} __packed;
-
-struct synthvid_situation_update {
- u64 user_ctx;
- u8 video_output_count;
- struct video_output_situation video_output[1];
-} __packed;
-
-struct synthvid_situation_update_ack {
- u64 user_ctx;
-} __packed;
-
-struct synthvid_pointer_position {
- u8 is_visible;
- u8 video_output;
- s32 image_x;
- s32 image_y;
-} __packed;
-
-
-#define CURSOR_MAX_X 96
-#define CURSOR_MAX_Y 96
-#define CURSOR_ARGB_PIXEL_SIZE 4
-#define CURSOR_MAX_SIZE (CURSOR_MAX_X * CURSOR_MAX_Y * CURSOR_ARGB_PIXEL_SIZE)
-#define CURSOR_COMPLETE (-1)
-
-struct synthvid_pointer_shape {
- u8 part_idx;
- u8 is_argb;
- u32 width; /* CURSOR_MAX_X at most */
- u32 height; /* CURSOR_MAX_Y at most */
- u32 hot_x; /* hotspot relative to upper-left of pointer image */
- u32 hot_y;
- u8 data[4];
-} __packed;
-
-struct synthvid_feature_change {
- u8 is_dirt_needed;
- u8 is_ptr_pos_needed;
- u8 is_ptr_shape_needed;
- u8 is_situ_needed;
-} __packed;
-
-struct rect {
- s32 x1, y1; /* top left corner */
- s32 x2, y2; /* bottom right corner, exclusive */
-} __packed;
-
-struct synthvid_dirt {
- u8 video_output;
- u8 dirt_count;
- struct rect rect[1];
-} __packed;
-
-struct synthvid_msg {
- struct pipe_msg_hdr pipe_hdr;
- struct synthvid_msg_hdr vid_hdr;
- union {
- struct synthvid_version_req ver_req;
- struct synthvid_version_resp ver_resp;
- struct synthvid_vram_location vram;
- struct synthvid_vram_location_ack vram_ack;
- struct synthvid_situation_update situ;
- struct synthvid_situation_update_ack situ_ack;
- struct synthvid_pointer_position ptr_pos;
- struct synthvid_pointer_shape ptr_shape;
- struct synthvid_feature_change feature_chg;
- struct synthvid_dirt dirt;
- struct synthvid_supported_resolution_req resolution_req;
- struct synthvid_supported_resolution_resp resolution_resp;
- };
-} __packed;
-
-
-/* FB driver definitions and structures */
-#define HVFB_WIDTH 1152 /* default screen width */
-#define HVFB_HEIGHT 864 /* default screen height */
-#define HVFB_WIDTH_MIN 640
-#define HVFB_HEIGHT_MIN 480
-
-#define RING_BUFSIZE (256 * 1024)
-#define VSP_TIMEOUT (10 * HZ)
-#define HVFB_UPDATE_DELAY (HZ / 20)
-#define HVFB_ONDEMAND_THROTTLE (HZ / 20)
-
-struct hvfb_par {
- struct fb_info *info;
- struct resource *mem;
- bool fb_ready; /* fb device is ready */
- struct completion wait;
- u32 synthvid_version;
-
- struct delayed_work dwork;
- bool update;
- bool update_saved; /* The value of 'update' before hibernation */
-
- u32 pseudo_palette[16];
- u8 init_buf[MAX_VMBUS_PKT_SIZE];
- u8 recv_buf[MAX_VMBUS_PKT_SIZE];
-
- /* If true, the VSC notifies the VSP on every framebuffer change */
- bool synchronous_fb;
-
- /* If true, need to copy from deferred IO mem to framebuffer mem */
- bool need_docopy;
-
- struct notifier_block hvfb_panic_nb;
-
- /* Memory for deferred IO and frame buffer itself */
- unsigned char *dio_vp;
- unsigned char *mmio_vp;
- phys_addr_t mmio_pp;
-
- /* Dirty rectangle, protected by delayed_refresh_lock */
- int x1, y1, x2, y2;
- bool delayed_refresh;
- spinlock_t delayed_refresh_lock;
-};
-
-static uint screen_width = HVFB_WIDTH;
-static uint screen_height = HVFB_HEIGHT;
-static uint screen_depth;
-static uint screen_fb_size;
-static uint dio_fb_size; /* FB size for deferred IO */
-
-static void hvfb_putmem(struct fb_info *info);
-
-/* Send message to Hyper-V host */
-static inline int synthvid_send(struct hv_device *hdev,
- struct synthvid_msg *msg)
-{
- static atomic64_t request_id = ATOMIC64_INIT(0);
- int ret;
-
- msg->pipe_hdr.type = PIPE_MSG_DATA;
- msg->pipe_hdr.size = msg->vid_hdr.size;
-
- ret = vmbus_sendpacket(hdev->channel, msg,
- msg->vid_hdr.size + sizeof(struct pipe_msg_hdr),
- atomic64_inc_return(&request_id),
- VM_PKT_DATA_INBAND, 0);
-
- if (ret)
- pr_err_ratelimited("Unable to send packet via vmbus; error %d\n", ret);
-
- return ret;
-}
-
-
-/* Send screen resolution info to host */
-static int synthvid_send_situ(struct hv_device *hdev)
-{
- struct fb_info *info = hv_get_drvdata(hdev);
- struct synthvid_msg msg;
-
- if (!info)
- return -ENODEV;
-
- memset(&msg, 0, sizeof(struct synthvid_msg));
-
- msg.vid_hdr.type = SYNTHVID_SITUATION_UPDATE;
- msg.vid_hdr.size = sizeof(struct synthvid_msg_hdr) +
- sizeof(struct synthvid_situation_update);
- msg.situ.user_ctx = 0;
- msg.situ.video_output_count = 1;
- msg.situ.video_output[0].active = 1;
- msg.situ.video_output[0].vram_offset = 0;
- msg.situ.video_output[0].depth_bits = info->var.bits_per_pixel;
- msg.situ.video_output[0].width_pixels = info->var.xres;
- msg.situ.video_output[0].height_pixels = info->var.yres;
- msg.situ.video_output[0].pitch_bytes = info->fix.line_length;
-
- synthvid_send(hdev, &msg);
-
- return 0;
-}
-
-/* Send mouse pointer info to host */
-static int synthvid_send_ptr(struct hv_device *hdev)
-{
- struct synthvid_msg msg;
-
- memset(&msg, 0, sizeof(struct synthvid_msg));
- msg.vid_hdr.type = SYNTHVID_POINTER_POSITION;
- msg.vid_hdr.size = sizeof(struct synthvid_msg_hdr) +
- sizeof(struct synthvid_pointer_position);
- msg.ptr_pos.is_visible = 1;
- msg.ptr_pos.video_output = 0;
- msg.ptr_pos.image_x = 0;
- msg.ptr_pos.image_y = 0;
- synthvid_send(hdev, &msg);
-
- memset(&msg, 0, sizeof(struct synthvid_msg));
- msg.vid_hdr.type = SYNTHVID_POINTER_SHAPE;
- msg.vid_hdr.size = sizeof(struct synthvid_msg_hdr) +
- sizeof(struct synthvid_pointer_shape);
- msg.ptr_shape.part_idx = CURSOR_COMPLETE;
- msg.ptr_shape.is_argb = 1;
- msg.ptr_shape.width = 1;
- msg.ptr_shape.height = 1;
- msg.ptr_shape.hot_x = 0;
- msg.ptr_shape.hot_y = 0;
- msg.ptr_shape.data[0] = 0;
- msg.ptr_shape.data[1] = 1;
- msg.ptr_shape.data[2] = 1;
- msg.ptr_shape.data[3] = 1;
- synthvid_send(hdev, &msg);
-
- return 0;
-}
-
-/* Send updated screen area (dirty rectangle) location to host */
-static int
-synthvid_update(struct fb_info *info, int x1, int y1, int x2, int y2)
-{
- struct hv_device *hdev = device_to_hv_device(info->device);
- struct synthvid_msg msg;
-
- memset(&msg, 0, sizeof(struct synthvid_msg));
- if (x2 == INT_MAX)
- x2 = info->var.xres;
- if (y2 == INT_MAX)
- y2 = info->var.yres;
-
- msg.vid_hdr.type = SYNTHVID_DIRT;
- msg.vid_hdr.size = sizeof(struct synthvid_msg_hdr) +
- sizeof(struct synthvid_dirt);
- msg.dirt.video_output = 0;
- msg.dirt.dirt_count = 1;
- msg.dirt.rect[0].x1 = (x1 > x2) ? 0 : x1;
- msg.dirt.rect[0].y1 = (y1 > y2) ? 0 : y1;
- msg.dirt.rect[0].x2 =
- (x2 < x1 || x2 > info->var.xres) ? info->var.xres : x2;
- msg.dirt.rect[0].y2 =
- (y2 < y1 || y2 > info->var.yres) ? info->var.yres : y2;
-
- synthvid_send(hdev, &msg);
-
- return 0;
-}
-
-static void hvfb_docopy(struct hvfb_par *par,
- unsigned long offset,
- unsigned long size)
-{
- if (!par || !par->mmio_vp || !par->dio_vp || !par->fb_ready ||
- size == 0 || offset >= dio_fb_size)
- return;
-
- if (offset + size > dio_fb_size)
- size = dio_fb_size - offset;
-
- memcpy(par->mmio_vp + offset, par->dio_vp + offset, size);
-}
-
-/* Deferred IO callback */
-static void synthvid_deferred_io(struct fb_info *p, struct list_head *pagereflist)
-{
- struct hvfb_par *par = p->par;
- struct fb_deferred_io_pageref *pageref;
- unsigned long start, end;
- int y1, y2, miny, maxy;
-
- miny = INT_MAX;
- maxy = 0;
-
- /*
- * Merge dirty pages. It is possible that last page cross
- * over the end of frame buffer row yres. This is taken care of
- * in synthvid_update function by clamping the y2
- * value to yres.
- */
- list_for_each_entry(pageref, pagereflist, list) {
- start = pageref->offset;
- end = start + PAGE_SIZE - 1;
- y1 = start / p->fix.line_length;
- y2 = end / p->fix.line_length;
- miny = min_t(int, miny, y1);
- maxy = max_t(int, maxy, y2);
-
- /* Copy from dio space to mmio address */
- if (par->fb_ready && par->need_docopy)
- hvfb_docopy(par, start, PAGE_SIZE);
- }
-
- if (par->fb_ready && par->update)
- synthvid_update(p, 0, miny, p->var.xres, maxy + 1);
-}
-
-static struct fb_deferred_io synthvid_defio = {
- .delay = HZ / 20,
- .deferred_io = synthvid_deferred_io,
-};
-
-/*
- * Actions on received messages from host:
- * Complete the wait event.
- * Or, reply with screen and cursor info.
- */
-static void synthvid_recv_sub(struct hv_device *hdev)
-{
- struct fb_info *info = hv_get_drvdata(hdev);
- struct hvfb_par *par;
- struct synthvid_msg *msg;
-
- if (!info)
- return;
-
- par = info->par;
- msg = (struct synthvid_msg *)par->recv_buf;
-
- /* Complete the wait event */
- if (msg->vid_hdr.type == SYNTHVID_VERSION_RESPONSE ||
- msg->vid_hdr.type == SYNTHVID_RESOLUTION_RESPONSE ||
- msg->vid_hdr.type == SYNTHVID_VRAM_LOCATION_ACK) {
- memcpy(par->init_buf, msg, MAX_VMBUS_PKT_SIZE);
- complete(&par->wait);
- return;
- }
-
- /* Reply with screen and cursor info */
- if (msg->vid_hdr.type == SYNTHVID_FEATURE_CHANGE) {
- if (par->fb_ready) {
- synthvid_send_ptr(hdev);
- synthvid_send_situ(hdev);
- }
-
- par->update = msg->feature_chg.is_dirt_needed;
- if (par->update)
- schedule_delayed_work(&par->dwork, HVFB_UPDATE_DELAY);
- }
-}
-
-/* Receive callback for messages from the host */
-static void synthvid_receive(void *ctx)
-{
- struct hv_device *hdev = ctx;
- struct fb_info *info = hv_get_drvdata(hdev);
- struct hvfb_par *par;
- struct synthvid_msg *recv_buf;
- u32 bytes_recvd;
- u64 req_id;
- int ret;
-
- if (!info)
- return;
-
- par = info->par;
- recv_buf = (struct synthvid_msg *)par->recv_buf;
-
- do {
- ret = vmbus_recvpacket(hdev->channel, recv_buf,
- MAX_VMBUS_PKT_SIZE,
- &bytes_recvd, &req_id);
- if (bytes_recvd > 0 &&
- recv_buf->pipe_hdr.type == PIPE_MSG_DATA)
- synthvid_recv_sub(hdev);
- } while (bytes_recvd > 0 && ret == 0);
-}
-
-/* Check if the ver1 version is equal or greater than ver2 */
-static inline bool synthvid_ver_ge(u32 ver1, u32 ver2)
-{
- if (SYNTHVID_VER_GET_MAJOR(ver1) > SYNTHVID_VER_GET_MAJOR(ver2) ||
- (SYNTHVID_VER_GET_MAJOR(ver1) == SYNTHVID_VER_GET_MAJOR(ver2) &&
- SYNTHVID_VER_GET_MINOR(ver1) >= SYNTHVID_VER_GET_MINOR(ver2)))
- return true;
-
- return false;
-}
-
-/* Check synthetic video protocol version with the host */
-static int synthvid_negotiate_ver(struct hv_device *hdev, u32 ver)
-{
- struct fb_info *info = hv_get_drvdata(hdev);
- struct hvfb_par *par = info->par;
- struct synthvid_msg *msg = (struct synthvid_msg *)par->init_buf;
- int ret = 0;
- unsigned long t;
-
- memset(msg, 0, sizeof(struct synthvid_msg));
- msg->vid_hdr.type = SYNTHVID_VERSION_REQUEST;
- msg->vid_hdr.size = sizeof(struct synthvid_msg_hdr) +
- sizeof(struct synthvid_version_req);
- msg->ver_req.version = ver;
- synthvid_send(hdev, msg);
-
- t = wait_for_completion_timeout(&par->wait, VSP_TIMEOUT);
- if (!t) {
- pr_err("Time out on waiting version response\n");
- ret = -ETIMEDOUT;
- goto out;
- }
- if (!msg->ver_resp.is_accepted) {
- ret = -ENODEV;
- goto out;
- }
-
- par->synthvid_version = ver;
- pr_info("Synthvid Version major %d, minor %d\n",
- SYNTHVID_VER_GET_MAJOR(ver), SYNTHVID_VER_GET_MINOR(ver));
-
-out:
- return ret;
-}
-
-/* Get current resolution from the host */
-static int synthvid_get_supported_resolution(struct hv_device *hdev)
-{
- struct fb_info *info = hv_get_drvdata(hdev);
- struct hvfb_par *par = info->par;
- struct synthvid_msg *msg = (struct synthvid_msg *)par->init_buf;
- int ret = 0;
- unsigned long t;
- u8 index;
-
- memset(msg, 0, sizeof(struct synthvid_msg));
- msg->vid_hdr.type = SYNTHVID_RESOLUTION_REQUEST;
- msg->vid_hdr.size = sizeof(struct synthvid_msg_hdr) +
- sizeof(struct synthvid_supported_resolution_req);
-
- msg->resolution_req.maximum_resolution_count =
- SYNTHVID_MAX_RESOLUTION_COUNT;
- synthvid_send(hdev, msg);
-
- t = wait_for_completion_timeout(&par->wait, VSP_TIMEOUT);
- if (!t) {
- pr_err("Time out on waiting resolution response\n");
- ret = -ETIMEDOUT;
- goto out;
- }
-
- if (msg->resolution_resp.resolution_count == 0) {
- pr_err("No supported resolutions\n");
- ret = -ENODEV;
- goto out;
- }
-
- index = msg->resolution_resp.default_resolution_index;
- if (index >= msg->resolution_resp.resolution_count) {
- pr_err("Invalid resolution index: %d\n", index);
- ret = -ENODEV;
- goto out;
- }
-
- screen_width =
- msg->resolution_resp.supported_resolution[index].width;
- screen_height =
- msg->resolution_resp.supported_resolution[index].height;
-
-out:
- return ret;
-}
-
-/* Connect to VSP (Virtual Service Provider) on host */
-static int synthvid_connect_vsp(struct hv_device *hdev)
-{
- struct fb_info *info = hv_get_drvdata(hdev);
- struct hvfb_par *par = info->par;
- int ret;
-
- ret = vmbus_open(hdev->channel, RING_BUFSIZE, RING_BUFSIZE,
- NULL, 0, synthvid_receive, hdev);
- if (ret) {
- pr_err("Unable to open vmbus channel\n");
- return ret;
- }
-
- /* Negotiate the protocol version with host */
- switch (vmbus_proto_version) {
- case VERSION_WIN10:
- case VERSION_WIN10_V5:
- ret = synthvid_negotiate_ver(hdev, SYNTHVID_VERSION_WIN10);
- if (!ret)
- break;
- fallthrough;
- case VERSION_WIN8:
- case VERSION_WIN8_1:
- ret = synthvid_negotiate_ver(hdev, SYNTHVID_VERSION_WIN8);
- break;
- default:
- ret = synthvid_negotiate_ver(hdev, SYNTHVID_VERSION_WIN10);
- break;
- }
-
- if (ret) {
- pr_err("Synthetic video device version not accepted\n");
- goto error;
- }
-
- screen_depth = SYNTHVID_DEPTH_WIN8;
- if (synthvid_ver_ge(par->synthvid_version, SYNTHVID_VERSION_WIN10)) {
- ret = synthvid_get_supported_resolution(hdev);
- if (ret)
- pr_info("Failed to get supported resolution from host, use default\n");
- }
-
- screen_fb_size = hdev->channel->offermsg.offer.
- mmio_megabytes * 1024 * 1024;
-
- return 0;
-
-error:
- vmbus_close(hdev->channel);
- return ret;
-}
-
-/* Send VRAM and Situation messages to the host */
-static int synthvid_send_config(struct hv_device *hdev)
-{
- struct fb_info *info = hv_get_drvdata(hdev);
- struct hvfb_par *par = info->par;
- struct synthvid_msg *msg = (struct synthvid_msg *)par->init_buf;
- int ret = 0;
- unsigned long t;
-
- /* Send VRAM location */
- memset(msg, 0, sizeof(struct synthvid_msg));
- msg->vid_hdr.type = SYNTHVID_VRAM_LOCATION;
- msg->vid_hdr.size = sizeof(struct synthvid_msg_hdr) +
- sizeof(struct synthvid_vram_location);
- msg->vram.user_ctx = msg->vram.vram_gpa = par->mmio_pp;
- msg->vram.is_vram_gpa_specified = 1;
- synthvid_send(hdev, msg);
-
- t = wait_for_completion_timeout(&par->wait, VSP_TIMEOUT);
- if (!t) {
- pr_err("Time out on waiting vram location ack\n");
- ret = -ETIMEDOUT;
- goto out;
- }
- if (msg->vram_ack.user_ctx != par->mmio_pp) {
- pr_err("Unable to set VRAM location\n");
- ret = -ENODEV;
- goto out;
- }
-
- /* Send pointer and situation update */
- synthvid_send_ptr(hdev);
- synthvid_send_situ(hdev);
-
-out:
- return ret;
-}
-
-
-/*
- * Delayed work callback:
- * It is scheduled to call whenever update request is received and it has
- * not been called in last HVFB_ONDEMAND_THROTTLE time interval.
- */
-static void hvfb_update_work(struct work_struct *w)
-{
- struct hvfb_par *par = container_of(w, struct hvfb_par, dwork.work);
- struct fb_info *info = par->info;
- unsigned long flags;
- int x1, x2, y1, y2;
- int j;
-
- spin_lock_irqsave(&par->delayed_refresh_lock, flags);
- /* Reset the request flag */
- par->delayed_refresh = false;
-
- /* Store the dirty rectangle to local variables */
- x1 = par->x1;
- x2 = par->x2;
- y1 = par->y1;
- y2 = par->y2;
-
- /* Clear dirty rectangle */
- par->x1 = par->y1 = INT_MAX;
- par->x2 = par->y2 = 0;
-
- spin_unlock_irqrestore(&par->delayed_refresh_lock, flags);
-
- if (x1 > info->var.xres || x2 > info->var.xres ||
- y1 > info->var.yres || y2 > info->var.yres || x2 <= x1)
- return;
-
- /* Copy the dirty rectangle to frame buffer memory */
- if (par->need_docopy)
- for (j = y1; j < y2; j++)
- hvfb_docopy(par,
- j * info->fix.line_length +
- (x1 * screen_depth / 8),
- (x2 - x1) * screen_depth / 8);
-
- /* Refresh */
- if (par->fb_ready && par->update)
- synthvid_update(info, x1, y1, x2, y2);
-}
-
-/*
- * Control the on-demand refresh frequency. It schedules a delayed
- * screen update if it has not yet.
- */
-static void hvfb_ondemand_refresh_throttle(struct hvfb_par *par,
- int x1, int y1, int w, int h)
-{
- unsigned long flags;
- int x2 = x1 + w;
- int y2 = y1 + h;
-
- spin_lock_irqsave(&par->delayed_refresh_lock, flags);
-
- /* Merge dirty rectangle */
- par->x1 = min_t(int, par->x1, x1);
- par->y1 = min_t(int, par->y1, y1);
- par->x2 = max_t(int, par->x2, x2);
- par->y2 = max_t(int, par->y2, y2);
-
- /* Schedule a delayed screen update if not yet */
- if (par->delayed_refresh == false) {
- schedule_delayed_work(&par->dwork,
- HVFB_ONDEMAND_THROTTLE);
- par->delayed_refresh = true;
- }
-
- spin_unlock_irqrestore(&par->delayed_refresh_lock, flags);
-}
-
-static int hvfb_on_panic(struct notifier_block *nb,
- unsigned long e, void *p)
-{
- struct hv_device *hdev;
- struct hvfb_par *par;
- struct fb_info *info;
-
- par = container_of(nb, struct hvfb_par, hvfb_panic_nb);
- info = par->info;
- hdev = device_to_hv_device(info->device);
-
- if (hv_ringbuffer_spinlock_busy(hdev->channel))
- return NOTIFY_DONE;
-
- par->synchronous_fb = true;
- if (par->need_docopy)
- hvfb_docopy(par, 0, dio_fb_size);
- synthvid_update(info, 0, 0, INT_MAX, INT_MAX);
-
- return NOTIFY_DONE;
-}
-
-/* Framebuffer operation handlers */
-
-static int hvfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
-{
- if (var->xres < HVFB_WIDTH_MIN || var->yres < HVFB_HEIGHT_MIN ||
- var->xres > screen_width || var->yres > screen_height ||
- var->bits_per_pixel != screen_depth)
- return -EINVAL;
-
- var->xres_virtual = var->xres;
- var->yres_virtual = var->yres;
-
- return 0;
-}
-
-static int hvfb_set_par(struct fb_info *info)
-{
- struct hv_device *hdev = device_to_hv_device(info->device);
-
- return synthvid_send_situ(hdev);
-}
-
-
-static inline u32 chan_to_field(u32 chan, struct fb_bitfield *bf)
-{
- return ((chan & 0xffff) >> (16 - bf->length)) << bf->offset;
-}
-
-static int hvfb_setcolreg(unsigned regno, unsigned red, unsigned green,
- unsigned blue, unsigned transp, struct fb_info *info)
-{
- u32 *pal = info->pseudo_palette;
-
- if (regno > 15)
- return -EINVAL;
-
- pal[regno] = chan_to_field(red, &info->var.red)
- | chan_to_field(green, &info->var.green)
- | chan_to_field(blue, &info->var.blue)
- | chan_to_field(transp, &info->var.transp);
-
- return 0;
-}
-
-static int hvfb_blank(int blank, struct fb_info *info)
-{
- return 1; /* get fb_blank to set the colormap to all black */
-}
-
-static void hvfb_ops_damage_range(struct fb_info *info, off_t off, size_t len)
-{
- /* TODO: implement damage handling */
-}
-
-static void hvfb_ops_damage_area(struct fb_info *info, u32 x, u32 y, u32 width, u32 height)
-{
- struct hvfb_par *par = info->par;
-
- if (par->synchronous_fb)
- synthvid_update(info, 0, 0, INT_MAX, INT_MAX);
- else
- hvfb_ondemand_refresh_throttle(par, x, y, width, height);
-}
-
-/*
- * fb_ops.fb_destroy is called by the last put_fb_info() call at the end
- * of unregister_framebuffer() or fb_release(). Do any cleanup related to
- * framebuffer here.
- */
-static void hvfb_destroy(struct fb_info *info)
-{
- hvfb_putmem(info);
- framebuffer_release(info);
-}
-
-/*
- * TODO: GEN1 codepaths allocate from system or DMA-able memory. Fix the
- * driver to use the _SYSMEM_ or _DMAMEM_ helpers in these cases.
- */
-FB_GEN_DEFAULT_DEFERRED_IOMEM_OPS(hvfb_ops,
- hvfb_ops_damage_range,
- hvfb_ops_damage_area)
-
-static const struct fb_ops hvfb_ops = {
- .owner = THIS_MODULE,
- FB_DEFAULT_DEFERRED_OPS(hvfb_ops),
- .fb_check_var = hvfb_check_var,
- .fb_set_par = hvfb_set_par,
- .fb_setcolreg = hvfb_setcolreg,
- .fb_blank = hvfb_blank,
- .fb_destroy = hvfb_destroy,
-};
-
-/* Get options from kernel paramenter "video=" */
-static void hvfb_get_option(struct fb_info *info)
-{
- struct hvfb_par *par = info->par;
- char *opt = NULL, *p;
- uint x = 0, y = 0;
-
- if (fb_get_options(KBUILD_MODNAME, &opt) || !opt || !*opt)
- return;
-
- p = strsep(&opt, "x");
- if (!*p || kstrtouint(p, 0, &x) ||
- !opt || !*opt || kstrtouint(opt, 0, &y)) {
- pr_err("Screen option is invalid: skipped\n");
- return;
- }
-
- if (x < HVFB_WIDTH_MIN || y < HVFB_HEIGHT_MIN ||
- (synthvid_ver_ge(par->synthvid_version, SYNTHVID_VERSION_WIN10) &&
- (x * y * screen_depth / 8 > screen_fb_size)) ||
- (par->synthvid_version == SYNTHVID_VERSION_WIN8 &&
- x * y * screen_depth / 8 > SYNTHVID_FB_SIZE_WIN8)) {
- pr_err("Screen resolution option is out of range: skipped\n");
- return;
- }
-
- screen_width = x;
- screen_height = y;
- return;
-}
-
-/*
- * Allocate enough contiguous physical memory.
- * Return physical address if succeeded or -1 if failed.
- */
-static phys_addr_t hvfb_get_phymem(struct hv_device *hdev,
- unsigned int request_size)
-{
- struct page *page = NULL;
- dma_addr_t dma_handle;
- void *vmem;
- phys_addr_t paddr = 0;
- unsigned int order = get_order(request_size);
-
- if (request_size == 0)
- return -1;
-
- if (order <= MAX_PAGE_ORDER) {
- /* Call alloc_pages if the size is less than 2^MAX_PAGE_ORDER */
- page = alloc_pages(GFP_KERNEL | __GFP_ZERO, order);
- if (!page)
- return -1;
-
- paddr = (page_to_pfn(page) << PAGE_SHIFT);
- } else {
- /* Allocate from CMA */
- hdev->device.coherent_dma_mask = DMA_BIT_MASK(64);
-
- vmem = dma_alloc_coherent(&hdev->device,
- round_up(request_size, PAGE_SIZE),
- &dma_handle,
- GFP_KERNEL | __GFP_NOWARN);
-
- if (!vmem)
- return -1;
-
- paddr = virt_to_phys(vmem);
- }
-
- return paddr;
-}
-
-/* Release contiguous physical memory */
-static void hvfb_release_phymem(struct device *device,
- phys_addr_t paddr, unsigned int size)
-{
- unsigned int order = get_order(size);
-
- if (order <= MAX_PAGE_ORDER)
- __free_pages(pfn_to_page(paddr >> PAGE_SHIFT), order);
- else
- dma_free_coherent(device,
- round_up(size, PAGE_SIZE),
- phys_to_virt(paddr),
- paddr);
-}
-
-
-/* Get framebuffer memory from Hyper-V video pci space */
-static int hvfb_getmem(struct hv_device *hdev, struct fb_info *info)
-{
- struct hvfb_par *par = info->par;
- struct pci_dev *pdev = NULL;
- void __iomem *fb_virt;
- int gen2vm = efi_enabled(EFI_BOOT);
- resource_size_t base = 0;
- resource_size_t size = 0;
- phys_addr_t paddr;
- int ret;
-
- if (!gen2vm) {
- pdev = pci_get_device(PCI_VENDOR_ID_MICROSOFT,
- PCI_DEVICE_ID_HYPERV_VIDEO, NULL);
- if (!pdev) {
- pr_err("Unable to find PCI Hyper-V video\n");
- return -ENODEV;
- }
-
- base = pci_resource_start(pdev, 0);
- size = pci_resource_len(pdev, 0);
- aperture_remove_conflicting_devices(base, size, KBUILD_MODNAME);
-
- /*
- * For Gen 1 VM, we can directly use the contiguous memory
- * from VM. If we succeed, deferred IO happens directly
- * on this allocated framebuffer memory, avoiding extra
- * memory copy.
- */
- paddr = hvfb_get_phymem(hdev, screen_fb_size);
- if (paddr != (phys_addr_t) -1) {
- par->mmio_pp = paddr;
- par->mmio_vp = par->dio_vp = __va(paddr);
-
- info->fix.smem_start = paddr;
- info->fix.smem_len = screen_fb_size;
- info->screen_base = par->mmio_vp;
- info->screen_size = screen_fb_size;
-
- par->need_docopy = false;
- goto getmem_done;
- }
- pr_info("Unable to allocate enough contiguous physical memory on Gen 1 VM. Using MMIO instead.\n");
- } else {
- aperture_remove_all_conflicting_devices(KBUILD_MODNAME);
- }
-
- /*
- * Cannot use contiguous physical memory, so allocate MMIO space for
- * the framebuffer. At this point in the function, conflicting devices
- * that might have claimed the framebuffer MMIO space based on
- * screen_info.lfb_base must have already been removed so that
- * vmbus_allocate_mmio() does not allocate different MMIO space. If the
- * kdump image were to be loaded using kexec_file_load(), the
- * framebuffer location in the kdump image would be set from
- * screen_info.lfb_base at the time that kdump is enabled. If the
- * framebuffer has moved elsewhere, this could be the wrong location,
- * causing kdump to hang when efifb (for example) loads.
- */
- dio_fb_size =
- screen_width * screen_height * screen_depth / 8;
-
- ret = vmbus_allocate_mmio(&par->mem, hdev, 0, -1,
- screen_fb_size, 0x100000, true);
- if (ret != 0) {
- pr_err("Unable to allocate framebuffer memory\n");
- goto err1;
- }
-
- /*
- * Map the VRAM cacheable for performance. This is also required for
- * VM Connect to display properly for ARM64 Linux VM, as the host also
- * maps the VRAM cacheable.
- */
- fb_virt = ioremap_cache(par->mem->start, screen_fb_size);
- if (!fb_virt)
- goto err2;
-
- /* Allocate memory for deferred IO */
- par->dio_vp = vzalloc(round_up(dio_fb_size, PAGE_SIZE));
- if (par->dio_vp == NULL)
- goto err3;
-
- /* Physical address of FB device */
- par->mmio_pp = par->mem->start;
- /* Virtual address of FB device */
- par->mmio_vp = (unsigned char *) fb_virt;
-
- info->fix.smem_start = par->mem->start;
- info->fix.smem_len = dio_fb_size;
- info->screen_base = par->dio_vp;
- info->screen_size = dio_fb_size;
-
-getmem_done:
- if (!gen2vm)
- pci_dev_put(pdev);
-
- return 0;
-
-err3:
- iounmap(fb_virt);
-err2:
- vmbus_free_mmio(par->mem->start, screen_fb_size);
- par->mem = NULL;
-err1:
- if (!gen2vm)
- pci_dev_put(pdev);
-
- return -ENOMEM;
-}
-
-/* Release the framebuffer */
-static void hvfb_putmem(struct fb_info *info)
-{
- struct hvfb_par *par = info->par;
-
- if (par->need_docopy) {
- vfree(par->dio_vp);
- iounmap(par->mmio_vp);
- vmbus_free_mmio(par->mem->start, screen_fb_size);
- } else {
- hvfb_release_phymem(info->device, info->fix.smem_start,
- screen_fb_size);
- }
-
- par->mem = NULL;
-}
-
-
-static int hvfb_probe(struct hv_device *hdev,
- const struct hv_vmbus_device_id *dev_id)
-{
- struct fb_info *info;
- struct hvfb_par *par;
- int ret;
-
- info = framebuffer_alloc(sizeof(struct hvfb_par), &hdev->device);
- if (!info)
- return -ENOMEM;
-
- par = info->par;
- par->info = info;
- par->fb_ready = false;
- par->need_docopy = true;
- init_completion(&par->wait);
- INIT_DELAYED_WORK(&par->dwork, hvfb_update_work);
-
- par->delayed_refresh = false;
- spin_lock_init(&par->delayed_refresh_lock);
- par->x1 = par->y1 = INT_MAX;
- par->x2 = par->y2 = 0;
-
- /* Connect to VSP */
- hv_set_drvdata(hdev, info);
- ret = synthvid_connect_vsp(hdev);
- if (ret) {
- pr_err("Unable to connect to VSP\n");
- goto error1;
- }
-
- hvfb_get_option(info);
- pr_info("Screen resolution: %dx%d, Color depth: %d, Frame buffer size: %d\n",
- screen_width, screen_height, screen_depth, screen_fb_size);
-
- ret = hvfb_getmem(hdev, info);
- if (ret) {
- pr_err("No memory for framebuffer\n");
- goto error2;
- }
-
- /* Set up fb_info */
- info->var.xres_virtual = info->var.xres = screen_width;
- info->var.yres_virtual = info->var.yres = screen_height;
- info->var.bits_per_pixel = screen_depth;
-
- if (info->var.bits_per_pixel == 16) {
- info->var.red = (struct fb_bitfield){11, 5, 0};
- info->var.green = (struct fb_bitfield){5, 6, 0};
- info->var.blue = (struct fb_bitfield){0, 5, 0};
- info->var.transp = (struct fb_bitfield){0, 0, 0};
- } else {
- info->var.red = (struct fb_bitfield){16, 8, 0};
- info->var.green = (struct fb_bitfield){8, 8, 0};
- info->var.blue = (struct fb_bitfield){0, 8, 0};
- info->var.transp = (struct fb_bitfield){24, 8, 0};
- }
-
- info->var.activate = FB_ACTIVATE_NOW;
- info->var.height = -1;
- info->var.width = -1;
- info->var.vmode = FB_VMODE_NONINTERLACED;
-
- strcpy(info->fix.id, KBUILD_MODNAME);
- info->fix.type = FB_TYPE_PACKED_PIXELS;
- info->fix.visual = FB_VISUAL_TRUECOLOR;
- info->fix.line_length = screen_width * screen_depth / 8;
- info->fix.accel = FB_ACCEL_NONE;
-
- info->fbops = &hvfb_ops;
- info->pseudo_palette = par->pseudo_palette;
-
- /* Initialize deferred IO */
- info->fbdefio = &synthvid_defio;
- fb_deferred_io_init(info);
-
- /* Send config to host */
- ret = synthvid_send_config(hdev);
- if (ret)
- goto error;
-
- ret = devm_register_framebuffer(&hdev->device, info);
- if (ret) {
- pr_err("Unable to register framebuffer\n");
- goto error;
- }
-
- par->fb_ready = true;
-
- par->synchronous_fb = false;
-
- /*
- * We need to be sure this panic notifier runs _before_ the
- * vmbus disconnect, so order it by priority. It must execute
- * before the function hv_panic_vmbus_unload() [drivers/hv/vmbus_drv.c],
- * which is almost at the end of list, with priority = INT_MIN + 1.
- */
- par->hvfb_panic_nb.notifier_call = hvfb_on_panic;
- par->hvfb_panic_nb.priority = INT_MIN + 10;
- atomic_notifier_chain_register(&panic_notifier_list,
- &par->hvfb_panic_nb);
-
- return 0;
-
-error:
- fb_deferred_io_cleanup(info);
- hvfb_putmem(info);
-error2:
- vmbus_close(hdev->channel);
-error1:
- cancel_delayed_work_sync(&par->dwork);
- hv_set_drvdata(hdev, NULL);
- framebuffer_release(info);
- return ret;
-}
-
-static void hvfb_remove(struct hv_device *hdev)
-{
- struct fb_info *info = hv_get_drvdata(hdev);
- struct hvfb_par *par = info->par;
-
- atomic_notifier_chain_unregister(&panic_notifier_list,
- &par->hvfb_panic_nb);
-
- par->update = false;
- par->fb_ready = false;
-
- fb_deferred_io_cleanup(info);
-
- cancel_delayed_work_sync(&par->dwork);
-
- vmbus_close(hdev->channel);
- hv_set_drvdata(hdev, NULL);
-}
-
-static int hvfb_suspend(struct hv_device *hdev)
-{
- struct fb_info *info = hv_get_drvdata(hdev);
- struct hvfb_par *par = info->par;
-
- console_lock();
-
- /* 1 means do suspend */
- fb_set_suspend(info, 1);
-
- cancel_delayed_work_sync(&par->dwork);
- cancel_delayed_work_sync(&info->deferred_work);
-
- par->update_saved = par->update;
- par->update = false;
- par->fb_ready = false;
-
- vmbus_close(hdev->channel);
-
- console_unlock();
-
- return 0;
-}
-
-static int hvfb_resume(struct hv_device *hdev)
-{
- struct fb_info *info = hv_get_drvdata(hdev);
- struct hvfb_par *par = info->par;
- int ret;
-
- console_lock();
-
- ret = synthvid_connect_vsp(hdev);
- if (ret != 0)
- goto out;
-
- ret = synthvid_send_config(hdev);
- if (ret != 0) {
- vmbus_close(hdev->channel);
- goto out;
- }
-
- par->fb_ready = true;
- par->update = par->update_saved;
-
- schedule_delayed_work(&info->deferred_work, info->fbdefio->delay);
- schedule_delayed_work(&par->dwork, HVFB_UPDATE_DELAY);
-
- /* 0 means do resume */
- fb_set_suspend(info, 0);
-
-out:
- console_unlock();
-
- return ret;
-}
-
-
-static const struct pci_device_id pci_stub_id_table[] = {
- {
- .vendor = PCI_VENDOR_ID_MICROSOFT,
- .device = PCI_DEVICE_ID_HYPERV_VIDEO,
- },
- { /* end of list */ }
-};
-
-static const struct hv_vmbus_device_id id_table[] = {
- /* Synthetic Video Device GUID */
- {HV_SYNTHVID_GUID},
- {}
-};
-
-MODULE_DEVICE_TABLE(pci, pci_stub_id_table);
-MODULE_DEVICE_TABLE(vmbus, id_table);
-
-static struct hv_driver hvfb_drv = {
- .name = KBUILD_MODNAME,
- .id_table = id_table,
- .probe = hvfb_probe,
- .remove = hvfb_remove,
- .suspend = hvfb_suspend,
- .resume = hvfb_resume,
- .driver = {
- .probe_type = PROBE_PREFER_ASYNCHRONOUS,
- },
-};
-
-static int hvfb_pci_stub_probe(struct pci_dev *pdev,
- const struct pci_device_id *ent)
-{
- return 0;
-}
-
-static void hvfb_pci_stub_remove(struct pci_dev *pdev)
-{
-}
-
-static struct pci_driver hvfb_pci_stub_driver = {
- .name = KBUILD_MODNAME,
- .id_table = pci_stub_id_table,
- .probe = hvfb_pci_stub_probe,
- .remove = hvfb_pci_stub_remove,
- .driver = {
- .probe_type = PROBE_PREFER_ASYNCHRONOUS,
- }
-};
-
-static int __init hvfb_drv_init(void)
-{
- int ret;
-
- pr_warn("Deprecated: use Hyper-V DRM driver instead\n");
-
- if (fb_modesetting_disabled("hyper_fb"))
- return -ENODEV;
-
- ret = vmbus_driver_register(&hvfb_drv);
- if (ret != 0)
- return ret;
-
- ret = pci_register_driver(&hvfb_pci_stub_driver);
- if (ret != 0) {
- vmbus_driver_unregister(&hvfb_drv);
- return ret;
- }
-
- return 0;
-}
-
-static void __exit hvfb_drv_exit(void)
-{
- pci_unregister_driver(&hvfb_pci_stub_driver);
- vmbus_driver_unregister(&hvfb_drv);
-}
-
-module_init(hvfb_drv_init);
-module_exit(hvfb_drv_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("Microsoft Hyper-V Synthetic Video Frame Buffer Driver");
--
2.49.0
^ permalink raw reply related
* Re: [PATCH v2 2/4] staging: fbtft: Make FB_DEVICE dependency optional
From: Andy Shevchenko @ 2025-12-27 14:15 UTC (permalink / raw)
To: Chintan Patel
Cc: linux-fbdev, linux-staging, linux-omap, linux-kernel, dri-devel,
tzimmermann, andy, deller, gregkh
In-Reply-To: <20251219054320.447281-3-chintanlike@gmail.com>
On Fri, Dec 19, 2025 at 7:43 AM Chintan Patel <chintanlike@gmail.com> wrote:
>
> fbtft provides sysfs interfaces for debugging and gamma configuration,
> but these are not required for the core driver.
>
> Drop the hard dependency on CONFIG_FB_DEVICE and make sysfs support
> optional by using dev_of_fbinfo() at runtime. When FB_DEVICE is disabled,
> sysfs operations are skipped while the code remains buildable and
> type-checked.
>
> v2:
> - Replace CONFIG_FB_DEVICE ifdefs with runtime checks
> - Use dev_of_fbinfo() to guard sysfs creation and removal
>
> Suggested-by: Thomas Zimmermann <tzimmermann@suse.de>
> Suggested-by: Helge Deller <deller@gmx.de>
> Signed-off-by: Chintan Patel <chintanlike@gmail.com>
> ---
> drivers/staging/fbtft/Kconfig | 5 ++++-
> drivers/staging/fbtft/fbtft-sysfs.c | 18 ++++++++++++++----
> 2 files changed, 18 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/staging/fbtft/Kconfig b/drivers/staging/fbtft/Kconfig
> index c2655768209a..578412a2f379 100644
> --- a/drivers/staging/fbtft/Kconfig
> +++ b/drivers/staging/fbtft/Kconfig
> @@ -2,11 +2,14 @@
> menuconfig FB_TFT
> tristate "Support for small TFT LCD display modules"
> depends on FB && SPI
> - depends on FB_DEVICE
> depends on BACKLIGHT_CLASS_DEVICE
> depends on GPIOLIB || COMPILE_TEST
> select FB_BACKLIGHT
> select FB_SYSMEM_HELPERS_DEFERRED
> + help
> + Support for small TFT LCD display modules over SPI bus. FB_DEVICE
> + is not required, but if enabled, provides sysfs interface for debugging
> + and gamma curve configuration.
>
> if FB_TFT
>
> diff --git a/drivers/staging/fbtft/fbtft-sysfs.c b/drivers/staging/fbtft/fbtft-sysfs.c
> index e45c90a03a90..848702fc871a 100644
> --- a/drivers/staging/fbtft/fbtft-sysfs.c
> +++ b/drivers/staging/fbtft/fbtft-sysfs.c
> @@ -203,14 +203,24 @@ static struct device_attribute debug_device_attr =
>
> void fbtft_sysfs_init(struct fbtft_par *par)
> {
> - device_create_file(par->info->dev, &debug_device_attr);
> + struct device *dev = dev_of_fbinfo(par->info);
> +
> + if (!dev)
> + return;
> +
> + device_create_file(dev, &debug_device_attr);
> if (par->gamma.curves && par->fbtftops.set_gamma)
> - device_create_file(par->info->dev, &gamma_device_attrs[0]);
> + device_create_file(dev, &gamma_device_attrs[0]);
> }
>
> void fbtft_sysfs_exit(struct fbtft_par *par)
> {
> - device_remove_file(par->info->dev, &debug_device_attr);
> + struct device *dev = dev_of_fbinfo(par->info);
> +
> + if (!dev)
> + return;
> +
> + device_remove_file(dev, &debug_device_attr);
> if (par->gamma.curves && par->fbtftops.set_gamma)
> - device_remove_file(par->info->dev, &gamma_device_attrs[0]);
> + device_remove_file(dev, &gamma_device_attrs[0]);
> }
> --
> 2.43.0
>
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply
* Re: [PATCH v2 2/4] staging: fbtft: Make FB_DEVICE dependency optional
From: Andy Shevchenko @ 2025-12-27 14:19 UTC (permalink / raw)
To: Chintan Patel
Cc: linux-fbdev, linux-staging, linux-omap, linux-kernel, dri-devel,
tzimmermann, andy, deller, gregkh
In-Reply-To: <20251219054320.447281-3-chintanlike@gmail.com>
On Fri, Dec 19, 2025 at 7:43 AM Chintan Patel <chintanlike@gmail.com> wrote:
>
> fbtft provides sysfs interfaces for debugging and gamma configuration,
> but these are not required for the core driver.
>
> Drop the hard dependency on CONFIG_FB_DEVICE and make sysfs support
> optional by using dev_of_fbinfo() at runtime. When FB_DEVICE is disabled,
> sysfs operations are skipped while the code remains buildable and
> type-checked.
> v2:
> - Replace CONFIG_FB_DEVICE ifdefs with runtime checks
> - Use dev_of_fbinfo() to guard sysfs creation and removal
The place for the change log is either a cover letter, or...
> Suggested-by: Thomas Zimmermann <tzimmermann@suse.de>
> Suggested-by: Helge Deller <deller@gmx.de>
> Signed-off-by: Chintan Patel <chintanlike@gmail.com>
> ---
...a comment block here. It's not so important to be in the Git
history since we have a lore.kernel.org archive.
> drivers/staging/fbtft/Kconfig | 5 ++++-
> drivers/staging/fbtft/fbtft-sysfs.c | 18 ++++++++++++++----
...
> void fbtft_sysfs_init(struct fbtft_par *par)
> {
> - device_create_file(par->info->dev, &debug_device_attr);
> + struct device *dev = dev_of_fbinfo(par->info);
> +
> + if (!dev)
> + return;
The better way is to decouple the definition and the assignment in the
cases when it's followed by a conditional (validation check). In this
case any new code added in between doesn't affect readability and
maintenance efforts.
struct device *dev;
dev = dev_of_fbinfo(par->info);
if (!dev)
return;
> + device_create_file(dev, &debug_device_attr);
> if (par->gamma.curves && par->fbtftops.set_gamma)
> - device_create_file(par->info->dev, &gamma_device_attrs[0]);
> + device_create_file(dev, &gamma_device_attrs[0]);
> }
Ditto for the rest.
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply
* Re: [PATCH v2 4/4] fbdev: sh_mobile_lcdc: Make FB_DEVICE dependency optional
From: Andy Shevchenko @ 2025-12-27 14:21 UTC (permalink / raw)
To: Chintan Patel
Cc: linux-fbdev, linux-staging, linux-omap, linux-kernel, dri-devel,
tzimmermann, andy, deller, gregkh
In-Reply-To: <20251219054320.447281-5-chintanlike@gmail.com>
On Fri, Dec 19, 2025 at 7:43 AM Chintan Patel <chintanlike@gmail.com> wrote:
>
> The sh_mobile_lcdc driver exposes overlay configuration via sysfs, but the
> core driver does not require CONFIG_FB_DEVICE.
>
> Make sysfs support optional by defining overlay_sysfs_groups as NULL when
> FB_DEVICE is disabled. The driver always sets .dev_groups, and the kernel
> naturally skips NULL attribute groups while the code remains buildable
> and type-checked.
> v2:
> - Replace CONFIG_FB_DEVICE ifdefs with NULL overlay_sysfs_groups
> - Always populate .dev_groups
Same comment about the changelog in the commit messages.
...
> +#ifdef CONFIG_FB_DEVICE
> ATTRIBUTE_GROUPS(overlay_sysfs);
> +#else
> +/*
> + * When CONFIG_FB_DEVICE is disabled, define overlay_sysfs_groups as NULL.
> + * The compiler will optimize out the sysfs code paths when dev_groups is NULL.
> + */
> +static const struct attribute_group *overlay_sysfs_groups[] = { NULL };
> +#endif
Hmm... I'm wondering if PTR_IF() can anyhow help here.
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply
* Re: [PATCH v2 1/4] fb: Add dev_of_fbinfo() helper for optional sysfs support
From: Andy Shevchenko @ 2025-12-27 14:23 UTC (permalink / raw)
To: Chintan Patel
Cc: linux-fbdev, linux-staging, linux-omap, linux-kernel, dri-devel,
tzimmermann, andy, deller, gregkh
In-Reply-To: <20251219054320.447281-2-chintanlike@gmail.com>
On Fri, Dec 19, 2025 at 7:43 AM Chintan Patel <chintanlike@gmail.com> wrote:
>
> Add dev_of_fbinfo() to return the framebuffer struct device when
> CONFIG_FB_DEVICE is enabled, or NULL otherwise.
>
> This allows fbdev drivers to use sysfs interfaces via runtime checks
> instead of CONFIG_FB_DEVICE ifdefs, keeping the code clean while
> remaining fully buildable.
Reviewed-by: Andy Shevchenko <andy@kernel.org>
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply
* Re: [PATCH v2 0/4] fbdev: Make CONFIG_FB_DEVICE optional for drivers
From: Andy Shevchenko @ 2025-12-27 14:24 UTC (permalink / raw)
To: Chintan Patel
Cc: linux-fbdev, linux-staging, linux-omap, linux-kernel, dri-devel,
tzimmermann, andy, deller, gregkh
In-Reply-To: <20251219054320.447281-1-chintanlike@gmail.com>
On Fri, Dec 19, 2025 at 7:43 AM Chintan Patel <chintanlike@gmail.com> wrote:
>
> This series makes CONFIG_FB_DEVICE optional for fbdev drivers that use
> it only for sysfs interfaces, addressing Thomas Zimmermann’s TODO to
> remove hard FB_DEVICE dependencies.
>
> The series introduces a small helper, dev_of_fbinfo(), which returns
> NULL when CONFIG_FB_DEVICE=n. This allows sysfs code paths to be skipped
> via runtime checks, avoids #ifdef CONFIG_FB_DEVICE clutter, and keeps
> full compile-time syntax checking.
Please, address my comments and I give a tag for v3. I pretty much
like the series, thanks!
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply
* Re: [PATCH v2 2/4] staging: fbtft: Make FB_DEVICE dependency optional
From: Chintan Patel @ 2025-12-28 3:36 UTC (permalink / raw)
To: Andy Shevchenko
Cc: linux-fbdev, linux-staging, linux-omap, linux-kernel, dri-devel,
tzimmermann, andy, deller, gregkh
In-Reply-To: <CAHp75VeLF8nd-JiPFnxJ2H43ZS=oYgW4=BTZjR_GuUuj03gyRg@mail.gmail.com>
Hi Andy,
On 12/27/25 06:19, Andy Shevchenko wrote:
> On Fri, Dec 19, 2025 at 7:43 AM Chintan Patel <chintanlike@gmail.com> wrote:
>>
>> fbtft provides sysfs interfaces for debugging and gamma configuration,
>> but these are not required for the core driver.
>>
>> Drop the hard dependency on CONFIG_FB_DEVICE and make sysfs support
>> optional by using dev_of_fbinfo() at runtime. When FB_DEVICE is disabled,
>> sysfs operations are skipped while the code remains buildable and
>> type-checked.
>
>> v2:
>> - Replace CONFIG_FB_DEVICE ifdefs with runtime checks
>> - Use dev_of_fbinfo() to guard sysfs creation and removal
>
> The place for the change log is either a cover letter, or...
>
>> Suggested-by: Thomas Zimmermann <tzimmermann@suse.de>
>> Suggested-by: Helge Deller <deller@gmx.de>
>> Signed-off-by: Chintan Patel <chintanlike@gmail.com>
>> ---
>
> ...a comment block here. It's not so important to be in the Git
> history since we have a lore.kernel.org archive.
Thank you for suggestion! Will move to coverletter.
>> drivers/staging/fbtft/Kconfig | 5 ++++-
>> drivers/staging/fbtft/fbtft-sysfs.c | 18 ++++++++++++++----
>
> ...
>
>> void fbtft_sysfs_init(struct fbtft_par *par)
>> {
>> - device_create_file(par->info->dev, &debug_device_attr);
>> + struct device *dev = dev_of_fbinfo(par->info);
>> +
>> + if (!dev)
>> + return;
>
>
> The better way is to decouple the definition and the assignment in the
> cases when it's followed by a conditional (validation check). In this
> case any new code added in between doesn't affect readability and
> maintenance efforts.
>
> struct device *dev;
>
> dev = dev_of_fbinfo(par->info);
> if (!dev)
> return;
>
>> + device_create_file(dev, &debug_device_attr);
>> if (par->gamma.curves && par->fbtftops.set_gamma)
>> - device_create_file(par->info->dev, &gamma_device_attrs[0]);
>> + device_create_file(dev, &gamma_device_attrs[0]);
>> }
>
> Ditto for the rest.
Will do v3 and re-send. Thanks for reviews!
^ permalink raw reply
* [PATCH] fbdev: smscufx: properly copy ioctl memory to kernelspace
From: Greg Kroah-Hartman @ 2025-12-28 13:17 UTC (permalink / raw)
To: linux-fbdev, dri-devel
Cc: linux-kernel, Greg Kroah-Hartman, Tianchu Chen, stable,
Steve Glendinning, Helge Deller
The UFX_IOCTL_REPORT_DAMAGE ioctl does not properly copy data from
userspace to kernelspace, and instead directly references the memory,
which can cause problems if invalid data is passed from userspace. Fix
this all up by correctly copying the memory before accessing it within
the kernel.
Reported-by: Tianchu Chen <flynnnchen@tencent.com>
Cc: stable <stable@kernel.org>
Cc: Steve Glendinning <steve.glendinning@shawell.net>
Cc: Helge Deller <deller@gmx.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/video/fbdev/smscufx.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/drivers/video/fbdev/smscufx.c b/drivers/video/fbdev/smscufx.c
index 5f0dd01fd834..891ce7b76d63 100644
--- a/drivers/video/fbdev/smscufx.c
+++ b/drivers/video/fbdev/smscufx.c
@@ -932,7 +932,6 @@ static int ufx_ops_ioctl(struct fb_info *info, unsigned int cmd,
unsigned long arg)
{
struct ufx_data *dev = info->par;
- struct dloarea *area = NULL;
if (!atomic_read(&dev->usb_active))
return 0;
@@ -947,6 +946,10 @@ static int ufx_ops_ioctl(struct fb_info *info, unsigned int cmd,
/* TODO: Help propose a standard fb.h ioctl to report mmap damage */
if (cmd == UFX_IOCTL_REPORT_DAMAGE) {
+ struct dloarea *area __free(kfree) = kmalloc(sizeof(*area), GFP_KERNEL);
+ if (!area)
+ return -ENOMEM;
+
/* If we have a damage-aware client, turn fb_defio "off"
* To avoid perf imact of unnecessary page fault handling.
* Done by resetting the delay for this fb_info to a very
@@ -956,7 +959,8 @@ static int ufx_ops_ioctl(struct fb_info *info, unsigned int cmd,
if (info->fbdefio)
info->fbdefio->delay = UFX_DEFIO_WRITE_DISABLE;
- area = (struct dloarea *)arg;
+ if (copy_from_user(area, (u8 __user *)arg, sizeof(*area)))
+ return -EFAULT;
if (area->x < 0)
area->x = 0;
--
2.52.0
^ permalink raw reply related
* [PATCH] Replace udelay() with usleep_range() in PLL initialization code. According to Documentation/timers/timers-howto.rst, usleep_range() is preferred for delays "10us - 20ms"
From: Alexandru Costin @ 2025-12-29 1:08 UTC (permalink / raw)
To: andy, gregkh
Cc: dri-devel, linux-fbdev, linux-staging, linux-kernel,
Alexandru Costin
Resolves checkpatch warnings:
WARNING: usleep_range is preferred over udelay
Signed-off-by: Alexandru Costin <spxxky.dev@gmail.com>
---
drivers/staging/fbtft/fb_ra8875.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/drivers/staging/fbtft/fb_ra8875.c b/drivers/staging/fbtft/fb_ra8875.c
index 0ab1de6647d0..130150b0f07f 100644
--- a/drivers/staging/fbtft/fb_ra8875.c
+++ b/drivers/staging/fbtft/fb_ra8875.c
@@ -210,7 +210,8 @@ static void write_reg8_bus8(struct fbtft_par *par, int len, ...)
}
len--;
- udelay(100);
+ usleep_range(100, 120);
+
if (len) {
buf = (u8 *)par->buf;
@@ -231,7 +232,7 @@ static void write_reg8_bus8(struct fbtft_par *par, int len, ...)
/* restore user spi-speed */
par->fbtftops.write = fbtft_write_spi;
- udelay(100);
+ usleep_range(100, 120);
}
static int write_vmem16_bus8(struct fbtft_par *par, size_t offset, size_t len)
--
2.43.0
^ permalink raw reply related
* Re: [PATCH] Replace udelay() with usleep_range() in PLL initialization code. According to Documentation/timers/timers-howto.rst, usleep_range() is preferred for delays "10us - 20ms"
From: Andy Shevchenko @ 2025-12-29 7:41 UTC (permalink / raw)
To: Alexandru Costin
Cc: andy, gregkh, dri-devel, linux-fbdev, linux-staging, linux-kernel
In-Reply-To: <20251229010814.94255-1-spxxky.dev@gmail.com>
On Mon, Dec 29, 2025 at 3:09 AM Alexandru Costin <spxxky.dev@gmail.com> wrote:
>
> Resolves checkpatch warnings:
> WARNING: usleep_range is preferred over udelay
First of all, fix checkpatch to point to a newer API, i.e. fsleep().
...
> @@ -210,7 +210,8 @@ static void write_reg8_bus8(struct fbtft_par *par, int len, ...)
> - udelay(100);
> + usleep_range(100, 120);
> @@ -231,7 +232,7 @@ static void write_reg8_bus8(struct fbtft_par *par, int len, ...)
> - udelay(100);
> + usleep_range(100, 120);
This is an IO function for the hardware in question. Have you tested
it? How do you know that this is a non-atomic context?
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply
* [PATCH 01/12] video/aperture: Add sysfb restore on DRM probe failure
From: Zack Rusin @ 2025-12-29 21:58 UTC (permalink / raw)
To: dri-devel
Cc: Ard Biesheuvel, Thomas Zimmermann, Javier Martinez Canillas,
Helge Deller, linux-efi, linux-kernel, linux-fbdev
In-Reply-To: <20251229215906.3688205-1-zack.rusin@broadcom.com>
When a DRM driver calls aperture_remove_conflicting_pci_devices(), the
firmware framebuffer (EFI, VESA, etc.) is disabled and its platform
device is unregistered. If the DRM driver's probe subsequently fails,
the user is left with no display output.
Add sysfb_restore() to re-enable the Generic System Framebuffers
support and re-create the platform device that was previously
unregistered by sysfb_disable().
Add devm_aperture_remove_conflicting_pci_devices() which wraps the
existing function and registers a devm action to automatically call
sysfb_restore() if the driver's probe fails or the driver is unloaded.
Drivers can call devm_aperture_remove_conflicting_pci_devices_done()
after successful probe to cancel the automatic restore.
Refactor sysfb_init() to use a shared __sysfb_create_device() helper
that can be called from both sysfb_init() and sysfb_restore(). Add a
quirks_applied flag to handle the edge case where a driver calls
sysfb_disable() before sysfb_init() runs, in this case sysfb_restore()
defers device creation to sysfb_init() since the __init quirk functions
cannot be called after init memory is freed.
Signed-off-by: Zack Rusin <zack.rusin@broadcom.com>
Cc: Ard Biesheuvel <ardb@kernel.org>
Cc: Thomas Zimmermann <tzimmermann@suse.de>
Cc: Javier Martinez Canillas <javierm@redhat.com>
Cc: Helge Deller <deller@gmx.de>
Cc: linux-efi@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Cc: dri-devel@lists.freedesktop.org
Cc: linux-fbdev@vger.kernel.org
---
drivers/firmware/efi/sysfb_efi.c | 2 +-
drivers/firmware/sysfb.c | 191 +++++++++++++++++++-----------
drivers/firmware/sysfb_simplefb.c | 10 +-
drivers/video/aperture.c | 54 +++++++++
include/linux/aperture.h | 14 +++
include/linux/sysfb.h | 6 +
6 files changed, 201 insertions(+), 76 deletions(-)
diff --git a/drivers/firmware/efi/sysfb_efi.c b/drivers/firmware/efi/sysfb_efi.c
index 1e509595ac03..3fe7c57ad849 100644
--- a/drivers/firmware/efi/sysfb_efi.c
+++ b/drivers/firmware/efi/sysfb_efi.c
@@ -365,7 +365,7 @@ __init void sysfb_apply_efi_quirks(void)
}
}
-__init void sysfb_set_efifb_fwnode(struct platform_device *pd)
+void sysfb_set_efifb_fwnode(struct platform_device *pd)
{
if (screen_info.orig_video_isVGA == VIDEO_TYPE_EFI && IS_ENABLED(CONFIG_PCI)) {
fwnode_init(&efifb_fwnode, &efifb_fwnode_ops);
diff --git a/drivers/firmware/sysfb.c b/drivers/firmware/sysfb.c
index 889e5b05c739..c45b6f487103 100644
--- a/drivers/firmware/sysfb.c
+++ b/drivers/firmware/sysfb.c
@@ -38,6 +38,7 @@
static struct platform_device *pd;
static DEFINE_MUTEX(disable_lock);
static bool disabled;
+static bool quirks_applied;
static struct device *sysfb_parent_dev(const struct screen_info *si);
@@ -79,6 +80,121 @@ void sysfb_disable(struct device *dev)
}
EXPORT_SYMBOL_GPL(sysfb_disable);
+/* Caller must hold disable_lock */
+static int __sysfb_create_device(bool restore)
+{
+ struct screen_info *si = &screen_info;
+ struct device *parent;
+ unsigned int type;
+ struct simplefb_platform_data mode;
+ const char *name;
+ bool compatible;
+ int ret = 0;
+
+ if (!IS_ERR_OR_NULL(pd))
+ return 0;
+
+ /*
+ * If quirks haven't been applied yet, sysfb_init() hasn't run.
+ * Don't create the device now - let sysfb_init() do it after
+ * applying the necessary fixups and quirks. We can't call
+ * sysfb_apply_efi_quirks() here because it's __init.
+ */
+ if (!quirks_applied)
+ return 0;
+
+ parent = sysfb_parent_dev(si);
+ if (IS_ERR(parent))
+ return PTR_ERR(parent);
+
+ type = screen_info_video_type(si);
+
+ /* try to create a simple-framebuffer device */
+ compatible = sysfb_parse_mode(si, &mode);
+ if (compatible) {
+ pd = sysfb_create_simplefb(si, &mode, parent);
+ if (!IS_ERR(pd)) {
+ if (restore)
+ pr_info("sysfb: restored simple-framebuffer device\n");
+ goto put_device;
+ }
+ }
+
+ /* if the FB is incompatible, create a legacy framebuffer device */
+ switch (type) {
+ case VIDEO_TYPE_EGAC:
+ name = "ega-framebuffer";
+ break;
+ case VIDEO_TYPE_VGAC:
+ name = "vga-framebuffer";
+ break;
+ case VIDEO_TYPE_VLFB:
+ name = "vesa-framebuffer";
+ break;
+ case VIDEO_TYPE_EFI:
+ name = "efi-framebuffer";
+ break;
+ default:
+ name = "platform-framebuffer";
+ break;
+ }
+
+ pd = platform_device_alloc(name, 0);
+ if (!pd) {
+ ret = -ENOMEM;
+ goto put_device;
+ }
+
+ pd->dev.parent = parent;
+
+ sysfb_set_efifb_fwnode(pd);
+
+ ret = platform_device_add_data(pd, si, sizeof(*si));
+ if (ret)
+ goto err;
+
+ ret = platform_device_add(pd);
+ if (ret)
+ goto err;
+
+ if (restore)
+ pr_info("sysfb: restored %s device\n", name);
+ goto put_device;
+err:
+ platform_device_put(pd);
+ pd = NULL;
+put_device:
+ put_device(parent);
+ return ret;
+}
+
+/**
+ * sysfb_restore() - restore the Generic System Framebuffer
+ *
+ * This function re-enables the Generic System Framebuffers support and
+ * re-creates the platform device that was previously unregistered by
+ * sysfb_disable(). This is intended for use by DRM drivers that need to
+ * restore the fallback framebuffer when their probe fails after having
+ * called aperture_remove_conflicting_devices() or similar.
+ *
+ * Context: The function can sleep. A @disable_lock mutex is acquired.
+ *
+ * Returns:
+ * 0 on success, or a negative errno value otherwise.
+ */
+int sysfb_restore(void)
+{
+ int ret;
+
+ mutex_lock(&disable_lock);
+ disabled = false;
+ ret = __sysfb_create_device(true);
+ mutex_unlock(&disable_lock);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(sysfb_restore);
+
/**
* sysfb_handles_screen_info() - reports if sysfb handles the global screen_info
*
@@ -141,82 +257,17 @@ static struct device *sysfb_parent_dev(const struct screen_info *si)
static __init int sysfb_init(void)
{
- struct screen_info *si = &screen_info;
- struct device *parent;
- unsigned int type;
- struct simplefb_platform_data mode;
- const char *name;
- bool compatible;
int ret = 0;
screen_info_apply_fixups();
-
- mutex_lock(&disable_lock);
- if (disabled)
- goto unlock_mutex;
-
sysfb_apply_efi_quirks();
- parent = sysfb_parent_dev(si);
- if (IS_ERR(parent)) {
- ret = PTR_ERR(parent);
- goto unlock_mutex;
- }
-
- /* try to create a simple-framebuffer device */
- compatible = sysfb_parse_mode(si, &mode);
- if (compatible) {
- pd = sysfb_create_simplefb(si, &mode, parent);
- if (!IS_ERR(pd))
- goto put_device;
- }
-
- type = screen_info_video_type(si);
-
- /* if the FB is incompatible, create a legacy framebuffer device */
- switch (type) {
- case VIDEO_TYPE_EGAC:
- name = "ega-framebuffer";
- break;
- case VIDEO_TYPE_VGAC:
- name = "vga-framebuffer";
- break;
- case VIDEO_TYPE_VLFB:
- name = "vesa-framebuffer";
- break;
- case VIDEO_TYPE_EFI:
- name = "efi-framebuffer";
- break;
- default:
- name = "platform-framebuffer";
- break;
- }
-
- pd = platform_device_alloc(name, 0);
- if (!pd) {
- ret = -ENOMEM;
- goto put_device;
- }
-
- pd->dev.parent = parent;
-
- sysfb_set_efifb_fwnode(pd);
-
- ret = platform_device_add_data(pd, si, sizeof(*si));
- if (ret)
- goto err;
-
- ret = platform_device_add(pd);
- if (ret)
- goto err;
-
- goto put_device;
-err:
- platform_device_put(pd);
-put_device:
- put_device(parent);
-unlock_mutex:
+ mutex_lock(&disable_lock);
+ quirks_applied = true;
+ if (!disabled)
+ ret = __sysfb_create_device(false);
mutex_unlock(&disable_lock);
+
return ret;
}
diff --git a/drivers/firmware/sysfb_simplefb.c b/drivers/firmware/sysfb_simplefb.c
index 592d8a644619..6fcbc3ae17d5 100644
--- a/drivers/firmware/sysfb_simplefb.c
+++ b/drivers/firmware/sysfb_simplefb.c
@@ -24,8 +24,8 @@ static const char simplefb_resname[] = "BOOTFB";
static const struct simplefb_format formats[] = SIMPLEFB_FORMATS;
/* try parsing screen_info into a simple-framebuffer mode struct */
-__init bool sysfb_parse_mode(const struct screen_info *si,
- struct simplefb_platform_data *mode)
+bool sysfb_parse_mode(const struct screen_info *si,
+ struct simplefb_platform_data *mode)
{
__u8 type;
u32 bits_per_pixel;
@@ -61,9 +61,9 @@ __init bool sysfb_parse_mode(const struct screen_info *si,
return false;
}
-__init struct platform_device *sysfb_create_simplefb(const struct screen_info *si,
- const struct simplefb_platform_data *mode,
- struct device *parent)
+struct platform_device *sysfb_create_simplefb(const struct screen_info *si,
+ const struct simplefb_platform_data *mode,
+ struct device *parent)
{
struct platform_device *pd;
struct resource res;
diff --git a/drivers/video/aperture.c b/drivers/video/aperture.c
index 2b5a1e666e9b..4de6dc04a3fd 100644
--- a/drivers/video/aperture.c
+++ b/drivers/video/aperture.c
@@ -372,3 +372,57 @@ int aperture_remove_conflicting_pci_devices(struct pci_dev *pdev, const char *na
}
EXPORT_SYMBOL(aperture_remove_conflicting_pci_devices);
+
+static void devm_aperture_restore_sysfb(void *unused)
+{
+ sysfb_restore();
+}
+
+/**
+ * devm_aperture_remove_conflicting_pci_devices - remove existing framebuffers
+ * with sysfb restore on failure
+ * @pdev: PCI device
+ * @name: a descriptive name of the requesting driver
+ *
+ * This function removes devices that own apertures within any of @pdev's
+ * memory bars, similar to aperture_remove_conflicting_pci_devices().
+ *
+ * Additionally, it registers a devm action that will restore the system
+ * framebuffer if the driver's probe fails or the driver is unloaded. This
+ * ensures the user doesn't lose display output if the DRM driver probe fails
+ * after removing the firmware framebuffer.
+ *
+ * This function should be called early in the driver's probe function. The
+ * driver must call devm_aperture_remove_conflicting_pci_devices_done() after
+ * successfully completing probe to cancel the automatic restore.
+ *
+ * Returns:
+ * 0 on success, or a negative errno code otherwise
+ */
+int devm_aperture_remove_conflicting_pci_devices(struct pci_dev *pdev,
+ const char *name)
+{
+ int ret;
+
+ ret = aperture_remove_conflicting_pci_devices(pdev, name);
+ if (ret)
+ return ret;
+
+ return devm_add_action_or_reset(&pdev->dev, devm_aperture_restore_sysfb,
+ NULL);
+}
+EXPORT_SYMBOL(devm_aperture_remove_conflicting_pci_devices);
+
+/**
+ * devm_aperture_remove_conflicting_pci_devices_done - cancel sysfb restore
+ * @pdev: PCI device
+ *
+ * Cancels the automatic sysfb restore action registered by
+ * devm_aperture_remove_conflicting_pci_devices(). Call this after the
+ * driver has successfully completed probe and registered its display.
+ */
+void devm_aperture_remove_conflicting_pci_devices_done(struct pci_dev *pdev)
+{
+ devm_remove_action(&pdev->dev, devm_aperture_restore_sysfb, NULL);
+}
+EXPORT_SYMBOL(devm_aperture_remove_conflicting_pci_devices_done);
diff --git a/include/linux/aperture.h b/include/linux/aperture.h
index 1a9a88b11584..ea0ece7f777e 100644
--- a/include/linux/aperture.h
+++ b/include/linux/aperture.h
@@ -19,6 +19,10 @@ int aperture_remove_conflicting_devices(resource_size_t base, resource_size_t si
int __aperture_remove_legacy_vga_devices(struct pci_dev *pdev);
int aperture_remove_conflicting_pci_devices(struct pci_dev *pdev, const char *name);
+
+int devm_aperture_remove_conflicting_pci_devices(struct pci_dev *pdev,
+ const char *name);
+void devm_aperture_remove_conflicting_pci_devices_done(struct pci_dev *pdev);
#else
static inline int devm_aperture_acquire_for_platform_device(struct platform_device *pdev,
resource_size_t base,
@@ -42,6 +46,16 @@ static inline int aperture_remove_conflicting_pci_devices(struct pci_dev *pdev,
{
return 0;
}
+
+static inline int devm_aperture_remove_conflicting_pci_devices(struct pci_dev *pdev,
+ const char *name)
+{
+ return 0;
+}
+
+static inline void devm_aperture_remove_conflicting_pci_devices_done(struct pci_dev *pdev)
+{
+}
#endif
/**
diff --git a/include/linux/sysfb.h b/include/linux/sysfb.h
index b449665c686a..c0ade38bcf99 100644
--- a/include/linux/sysfb.h
+++ b/include/linux/sysfb.h
@@ -63,6 +63,7 @@ struct efifb_dmi_info {
#ifdef CONFIG_SYSFB
void sysfb_disable(struct device *dev);
+int sysfb_restore(void);
bool sysfb_handles_screen_info(void);
@@ -72,6 +73,11 @@ static inline void sysfb_disable(struct device *dev)
{
}
+static inline int sysfb_restore(void)
+{
+ return -ENODEV;
+}
+
static inline bool sysfb_handles_screen_info(void)
{
return false;
--
2.48.1
^ permalink raw reply related
* [PATCH 00/12] Recover sysfb after DRM probe failure
From: Zack Rusin @ 2025-12-29 21:58 UTC (permalink / raw)
To: dri-devel
Cc: Alex Deucher, amd-gfx, Ard Biesheuvel, Ce Sun, Chia-I Wu,
Christian König, Danilo Krummrich, Dave Airlie, Deepak Rawat,
Dmitry Osipenko, Gerd Hoffmann, Gurchetan Singh, Hans de Goede,
Hawking Zhang, Helge Deller, intel-gfx, intel-xe, Jani Nikula,
Javier Martinez Canillas, Jocelyn Falempe, Joonas Lahtinen,
Lijo Lazar, linux-efi, linux-fbdev, linux-hyperv, linux-kernel,
Lucas De Marchi, Lyude Paul, Maarten Lankhorst,
Mario Limonciello (AMD), Mario Limonciello, Maxime Ripard,
nouveau, Rodrigo Vivi, Simona Vetter, spice-devel,
Thomas Hellström, Thomas Zimmermann, Timur Kristóf,
Tvrtko Ursulin, virtualization, Vitaly Prosyak
Almost a rite of passage for every DRM developer and most Linux users
is upgrading your DRM driver/updating boot flags/changing some config
and having DRM driver fail at probe resulting in a blank screen.
Currently there's no way to recover from DRM driver probe failure. PCI
DRM driver explicitly throw out the existing sysfb to get exclusive
access to PCI resources so if the probe fails the system is left without
a functioning display driver.
Add code to sysfb to recever system framebuffer when DRM driver's probe
fails. This means that a DRM driver that fails to load reloads the system
framebuffer driver.
This works best with simpledrm. Without it Xorg won't recover because
it still tries to load the vendor specific driver which ends up usually
not working at all. With simpledrm the system recovers really nicely
ending up with a working console and not a blank screen.
There's a caveat in that some hardware might require some special magic
register write to recover EFI display. I'd appreciate it a lot if
maintainers could introduce a temporary failure in their drivers
probe to validate that the sysfb recovers and they get a working console.
The easiest way to double check it is by adding:
/* XXX: Temporary failure to test sysfb restore - REMOVE BEFORE COMMIT */
dev_info(&pdev->dev, "Testing sysfb restore: forcing probe failure\n");
ret = -EINVAL;
goto out_error;
or such right after the devm_aperture_remove_conflicting_pci_devices .
Cc: Alex Deucher <alexander.deucher@amd.com>
Cc: amd-gfx@lists.freedesktop.org
Cc: Ard Biesheuvel <ardb@kernel.org>
Cc: Ce Sun <cesun102@amd.com>
Cc: Chia-I Wu <olvaffe@gmail.com>
Cc: "Christian König" <christian.koenig@amd.com>
Cc: Danilo Krummrich <dakr@kernel.org>
Cc: Dave Airlie <airlied@redhat.com>
Cc: Deepak Rawat <drawat.floss@gmail.com>
Cc: Dmitry Osipenko <dmitry.osipenko@collabora.com>
Cc: dri-devel@lists.freedesktop.org
Cc: Gerd Hoffmann <kraxel@redhat.com>
Cc: Gurchetan Singh <gurchetansingh@chromium.org>
Cc: Hans de Goede <hansg@kernel.org>
Cc: Hawking Zhang <Hawking.Zhang@amd.com>
Cc: Helge Deller <deller@gmx.de>
Cc: intel-gfx@lists.freedesktop.org
Cc: intel-xe@lists.freedesktop.org
Cc: Jani Nikula <jani.nikula@linux.intel.com>
Cc: Javier Martinez Canillas <javierm@redhat.com>
Cc: Jocelyn Falempe <jfalempe@redhat.com>
Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Cc: Lijo Lazar <lijo.lazar@amd.com>
Cc: linux-efi@vger.kernel.org
Cc: linux-fbdev@vger.kernel.org
Cc: linux-hyperv@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Cc: Lucas De Marchi <lucas.demarchi@intel.com>
Cc: Lyude Paul <lyude@redhat.com>
Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Cc: "Mario Limonciello (AMD)" <superm1@kernel.org>
Cc: Mario Limonciello <mario.limonciello@amd.com>
Cc: Maxime Ripard <mripard@kernel.org>
Cc: nouveau@lists.freedesktop.org
Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
Cc: Simona Vetter <simona@ffwll.ch>
Cc: spice-devel@lists.freedesktop.org
Cc: "Thomas Hellström" <thomas.hellstrom@linux.intel.com>
Cc: Thomas Zimmermann <tzimmermann@suse.de>
Cc: "Timur Kristóf" <timur.kristof@gmail.com>
Cc: Tvrtko Ursulin <tursulin@ursulin.net>
Cc: virtualization@lists.linux.dev
Cc: Vitaly Prosyak <vitaly.prosyak@amd.com>
Zack Rusin (12):
video/aperture: Add sysfb restore on DRM probe failure
drm/vmwgfx: Use devm aperture helpers for sysfb restore on probe
failure
drm/xe: Use devm aperture helpers for sysfb restore on probe failure
drm/amdgpu: Use devm aperture helpers for sysfb restore on probe
failure
drm/virtio: Add sysfb restore on probe failure
drm/nouveau: Use devm aperture helpers for sysfb restore on probe
failure
drm/qxl: Use devm aperture helpers for sysfb restore on probe failure
drm/vboxvideo: Use devm aperture helpers for sysfb restore on probe
failure
drm/hyperv: Add sysfb restore on probe failure
drm/ast: Use devm aperture helpers for sysfb restore on probe failure
drm/radeon: Use devm aperture helpers for sysfb restore on probe
failure
drm/i915: Use devm aperture helpers for sysfb restore on probe failure
drivers/firmware/efi/sysfb_efi.c | 2 +-
drivers/firmware/sysfb.c | 191 +++++++++++++--------
drivers/firmware/sysfb_simplefb.c | 10 +-
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 9 +-
drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 7 +
drivers/gpu/drm/ast/ast_drv.c | 13 +-
drivers/gpu/drm/hyperv/hyperv_drm_drv.c | 23 +++
drivers/gpu/drm/i915/i915_driver.c | 13 +-
drivers/gpu/drm/nouveau/nouveau_drm.c | 16 +-
drivers/gpu/drm/qxl/qxl_drv.c | 14 +-
drivers/gpu/drm/radeon/radeon_drv.c | 15 +-
drivers/gpu/drm/vboxvideo/vbox_drv.c | 13 +-
drivers/gpu/drm/virtio/virtgpu_drv.c | 29 ++++
drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 13 +-
drivers/gpu/drm/xe/xe_device.c | 7 +-
drivers/gpu/drm/xe/xe_pci.c | 7 +
drivers/video/aperture.c | 54 ++++++
include/linux/aperture.h | 14 ++
include/linux/sysfb.h | 6 +
19 files changed, 368 insertions(+), 88 deletions(-)
--
2.48.1
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox