[PATCH] fbdev: efifb: do not load efifb if PCI BAR has changed but not fixuped

Subsystems: efifb framebuffer driver, framebuffer layer, the rest

STALE448d

12 messages, 3 authors, 2025-07-07 · open the first message on its own page

[PATCH] fbdev: efifb: do not load efifb if PCI BAR has changed but not fixuped

From: <hidden>
Date: 2025-06-26 09:50:05

From: Shixiong Ou <redacted>

[WHY]
On an ARM machine, the following log is present:
[    0.900884] efifb: framebuffer at 0x1020000000, using 3072k, total 3072k
[    2.297884] amdgpu 0000:04:00.0: remove_conflicting_pci_framebuffers: bar 0: 0x1000000000 -> 0x100fffffff
[    2.297886] amdgpu 0000:04:00.0: remove_conflicting_pci_framebuffers: bar 2: 0x1010000000 -> 0x10101fffff
[    2.297888] amdgpu 0000:04:00.0: remove_conflicting_pci_framebuffers: bar 5: 0x58200000 -> 0x5823ffff

It show that the efifb framebuffer base is out of PCI BAR, and this
results in both efi-framebuffer and amdgpudrmfb co-existing.

The fbcon will be bound to efi-framebuffer by default and cannot be used.

[HOW]
Do not load efifb driver if PCI BAR has changed but not fixuped.
In the following cases:
	1. screen_info_lfb_pdev is NULL.
	2. __screen_info_relocation_is_valid return false.

Signed-off-by: Shixiong Ou <redacted>
---
 drivers/video/fbdev/efifb.c     |  4 ++++
 drivers/video/screen_info_pci.c | 24 ++++++++++++++++++++++++
 include/linux/screen_info.h     |  5 +++++
 3 files changed, 33 insertions(+)
diff --git a/drivers/video/fbdev/efifb.c b/drivers/video/fbdev/efifb.c
index 0e1bd3dba255..de8d016c9a66 100644
--- a/drivers/video/fbdev/efifb.c
+++ b/drivers/video/fbdev/efifb.c
@@ -303,6 +303,10 @@ static void efifb_setup(struct screen_info *si, char *options)
 
 static inline bool fb_base_is_valid(struct screen_info *si)
 {
+	/* check whether fb_base has changed but not fixuped */
+	if (!screen_info_is_useful())
+		return false;
+
 	if (si->lfb_base)
 		return true;
 
diff --git a/drivers/video/screen_info_pci.c b/drivers/video/screen_info_pci.c
index 66bfc1d0a6dc..ac57dcaf0cac 100644
--- a/drivers/video/screen_info_pci.c
+++ b/drivers/video/screen_info_pci.c
@@ -9,6 +9,8 @@ static struct pci_dev *screen_info_lfb_pdev;
 static size_t screen_info_lfb_bar;
 static resource_size_t screen_info_lfb_res_start; // original start of resource
 static resource_size_t screen_info_lfb_offset; // framebuffer offset within resource
+static bool screen_info_changed;
+static bool screen_info_fixuped;
 
 static bool __screen_info_relocation_is_valid(const struct screen_info *si, struct resource *pr)
 {
@@ -24,6 +26,24 @@ static bool __screen_info_relocation_is_valid(const struct screen_info *si, stru
 	return true;
 }
 
+bool screen_info_is_useful(void)
+{
+	unsigned int type;
+	const struct screen_info *si = &screen_info;
+
+	type = screen_info_video_type(si);
+	if (type != VIDEO_TYPE_EFI)
+		return true;
+
+	if (screen_info_changed && !screen_info_fixuped) {
+		pr_warn("The screen_info has changed but not fixuped");
+		return false;
+	}
+
+	pr_info("The screen_info is useful");
+	return true;
+}
+
 void screen_info_apply_fixups(void)
 {
 	struct screen_info *si = &screen_info;
@@ -32,18 +52,22 @@ void screen_info_apply_fixups(void)
 		struct resource *pr = &screen_info_lfb_pdev->resource[screen_info_lfb_bar];
 
 		if (pr->start != screen_info_lfb_res_start) {
+			screen_info_changed = true;
 			if (__screen_info_relocation_is_valid(si, pr)) {
 				/*
 				 * Only update base if we have an actual
 				 * relocation to a valid I/O range.
 				 */
 				__screen_info_set_lfb_base(si, pr->start + screen_info_lfb_offset);
+				screen_info_fixuped = true;
 				pr_info("Relocating firmware framebuffer to offset %pa[d] within %pr\n",
 					&screen_info_lfb_offset, pr);
 			} else {
 				pr_warn("Invalid relocating, disabling firmware framebuffer\n");
 			}
 		}
+	} else {
+		screen_info_changed = true;
 	}
 }
 
diff --git a/include/linux/screen_info.h b/include/linux/screen_info.h
index 923d68e07679..632cdbb1adbe 100644
--- a/include/linux/screen_info.h
+++ b/include/linux/screen_info.h
@@ -138,9 +138,14 @@ ssize_t screen_info_resources(const struct screen_info *si, struct resource *r,
 u32 __screen_info_lfb_bits_per_pixel(const struct screen_info *si);
 
 #if defined(CONFIG_PCI)
+bool screen_info_is_useful(void);
 void screen_info_apply_fixups(void);
 struct pci_dev *screen_info_pci_dev(const struct screen_info *si);
 #else
+bool screen_info_is_useful(void)
+{
+	return true;
+}
 static inline void screen_info_apply_fixups(void)
 { }
 static inline struct pci_dev *screen_info_pci_dev(const struct screen_info *si)
-- 
2.25.1

Re: [PATCH] fbdev: efifb: do not load efifb if PCI BAR has changed but not fixuped

From: Thomas Zimmermann <tzimmermann@suse.de>
Date: 2025-06-26 10:31:41

Hi

Am 26.06.25 um 11:49 schrieb oushixiong1025@163.com:
From: Shixiong Ou <redacted>

[WHY]
On an ARM machine, the following log is present:
[    0.900884] efifb: framebuffer at 0x1020000000, using 3072k, total 3072k
[    2.297884] amdgpu 0000:04:00.0: remove_conflicting_pci_framebuffers: bar 0: 0x1000000000 -> 0x100fffffff
[    2.297886] amdgpu 0000:04:00.0: remove_conflicting_pci_framebuffers: bar 2: 0x1010000000 -> 0x10101fffff
[    2.297888] amdgpu 0000:04:00.0: remove_conflicting_pci_framebuffers: bar 5: 0x58200000 -> 0x5823ffff

It show that the efifb framebuffer base is out of PCI BAR, and this
The patch at

   https://patchwork.freedesktop.org/series/148057/

is supposed to fix the problem. It has been merged with v6.16-rc1 as 
commit 2f29b5c23101 ("video: screen_info: Relocate framebuffers behind 
PCI bridges"). It is in your tree?

Best regards
Thomas
quoted hunk
results in both efi-framebuffer and amdgpudrmfb co-existing.

The fbcon will be bound to efi-framebuffer by default and cannot be used.

[HOW]
Do not load efifb driver if PCI BAR has changed but not fixuped.
In the following cases:
	1. screen_info_lfb_pdev is NULL.
	2. __screen_info_relocation_is_valid return false.

Signed-off-by: Shixiong Ou <redacted>
---
  drivers/video/fbdev/efifb.c     |  4 ++++
  drivers/video/screen_info_pci.c | 24 ++++++++++++++++++++++++
  include/linux/screen_info.h     |  5 +++++
  3 files changed, 33 insertions(+)
diff --git a/drivers/video/fbdev/efifb.c b/drivers/video/fbdev/efifb.c
index 0e1bd3dba255..de8d016c9a66 100644
--- a/drivers/video/fbdev/efifb.c
+++ b/drivers/video/fbdev/efifb.c
@@ -303,6 +303,10 @@ static void efifb_setup(struct screen_info *si, char *options)
  
  static inline bool fb_base_is_valid(struct screen_info *si)
  {
+	/* check whether fb_base has changed but not fixuped */
+	if (!screen_info_is_useful())
+		return false;
+
  	if (si->lfb_base)
  		return true;
  
diff --git a/drivers/video/screen_info_pci.c b/drivers/video/screen_info_pci.c
index 66bfc1d0a6dc..ac57dcaf0cac 100644
--- a/drivers/video/screen_info_pci.c
+++ b/drivers/video/screen_info_pci.c
@@ -9,6 +9,8 @@ static struct pci_dev *screen_info_lfb_pdev;
  static size_t screen_info_lfb_bar;
  static resource_size_t screen_info_lfb_res_start; // original start of resource
  static resource_size_t screen_info_lfb_offset; // framebuffer offset within resource
+static bool screen_info_changed;
+static bool screen_info_fixuped;
  
  static bool __screen_info_relocation_is_valid(const struct screen_info *si, struct resource *pr)
  {
@@ -24,6 +26,24 @@ static bool __screen_info_relocation_is_valid(const struct screen_info *si, stru
  	return true;
  }
  
+bool screen_info_is_useful(void)
+{
+	unsigned int type;
+	const struct screen_info *si = &screen_info;
+
+	type = screen_info_video_type(si);
+	if (type != VIDEO_TYPE_EFI)
+		return true;
+
+	if (screen_info_changed && !screen_info_fixuped) {
+		pr_warn("The screen_info has changed but not fixuped");
+		return false;
+	}
+
+	pr_info("The screen_info is useful");
+	return true;
+}
+
  void screen_info_apply_fixups(void)
  {
  	struct screen_info *si = &screen_info;
@@ -32,18 +52,22 @@ void screen_info_apply_fixups(void)
  		struct resource *pr = &screen_info_lfb_pdev->resource[screen_info_lfb_bar];
  
  		if (pr->start != screen_info_lfb_res_start) {
+			screen_info_changed = true;
  			if (__screen_info_relocation_is_valid(si, pr)) {
  				/*
  				 * Only update base if we have an actual
  				 * relocation to a valid I/O range.
  				 */
  				__screen_info_set_lfb_base(si, pr->start + screen_info_lfb_offset);
+				screen_info_fixuped = true;
  				pr_info("Relocating firmware framebuffer to offset %pa[d] within %pr\n",
  					&screen_info_lfb_offset, pr);
  			} else {
  				pr_warn("Invalid relocating, disabling firmware framebuffer\n");
  			}
  		}
+	} else {
+		screen_info_changed = true;
  	}
  }
  
diff --git a/include/linux/screen_info.h b/include/linux/screen_info.h
index 923d68e07679..632cdbb1adbe 100644
--- a/include/linux/screen_info.h
+++ b/include/linux/screen_info.h
@@ -138,9 +138,14 @@ ssize_t screen_info_resources(const struct screen_info *si, struct resource *r,
  u32 __screen_info_lfb_bits_per_pixel(const struct screen_info *si);
  
  #if defined(CONFIG_PCI)
+bool screen_info_is_useful(void);
  void screen_info_apply_fixups(void);
  struct pci_dev *screen_info_pci_dev(const struct screen_info *si);
  #else
+bool screen_info_is_useful(void)
+{
+	return true;
+}
  static inline void screen_info_apply_fixups(void)
  { }
  static inline struct pci_dev *screen_info_pci_dev(const struct screen_info *si)
-- 
--
Thomas Zimmermann
Graphics Driver Developer
SUSE Software Solutions Germany GmbH
Frankenstrasse 146, 90461 Nuernberg, Germany
GF: Ivo Totev, Andrew Myers, Andrew McDonald, Boudien Moerman
HRB 36809 (AG Nuernberg)

Re: [PATCH] fbdev: efifb: do not load efifb if PCI BAR has changed but not fixuped

From: kernel test robot <hidden>
Date: 2025-06-26 21:17:49

Hi,

kernel test robot noticed the following build errors:

[auto build test ERROR on linus/master]
[also build test ERROR on v6.16-rc3 next-20250626]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/oushixiong1025-163-com/fbdev-efifb-do-not-load-efifb-if-PCI-BAR-has-changed-but-not-fixuped/20250626-175111
base:   linus/master
patch link:    https://lore.kernel.org/r/20250626094937.515552-1-oushixiong1025%40163.com
patch subject: [PATCH] fbdev: efifb: do not load efifb if PCI BAR has changed but not fixuped
config: arm64-allnoconfig (https://download.01.org/0day-ci/archive/20250627/202506270544.iEP67RCm-lkp@intel.com/config)
compiler: aarch64-linux-gcc (GCC) 15.1.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250627/202506270544.iEP67RCm-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 [off-list ref]
| Closes: https://lore.kernel.org/oe-kbuild-all/202506270544.iEP67RCm-lkp@intel.com/

All errors (new ones prefixed by >>):

   aarch64-linux-ld: drivers/video/console/dummycon.o: in function `screen_info_is_useful':
quoted
dummycon.c:(.text+0x90): multiple definition of `screen_info_is_useful'; arch/arm64/kernel/setup.o:setup.c:(.text+0x0): first defined here
-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

Re: [PATCH] fbdev: efifb: do not load efifb if PCI BAR has changed but not fixuped

From: kernel test robot <hidden>
Date: 2025-06-26 21:28:51

Hi,

kernel test robot noticed the following build warnings:

[auto build test WARNING on linus/master]
[also build test WARNING on v6.16-rc3 next-20250626]
[cannot apply to drm-misc/drm-misc-next]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/oushixiong1025-163-com/fbdev-efifb-do-not-load-efifb-if-PCI-BAR-has-changed-but-not-fixuped/20250626-175111
base:   linus/master
patch link:    https://lore.kernel.org/r/20250626094937.515552-1-oushixiong1025%40163.com
patch subject: [PATCH] fbdev: efifb: do not load efifb if PCI BAR has changed but not fixuped
config: arm-allnoconfig (https://download.01.org/0day-ci/archive/20250627/202506270558.awnEnyeN-lkp@intel.com/config)
compiler: clang version 21.0.0git (https://github.com/llvm/llvm-project e04c938cc08a90ae60440ce22d072ebc69d67ee8)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250627/202506270558.awnEnyeN-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 [off-list ref]
| Closes: https://lore.kernel.org/oe-kbuild-all/202506270558.awnEnyeN-lkp@intel.com/

All warnings (new ones prefixed by >>):

   In file included from init/main.c:110:
   In file included from arch/arm/include/asm/setup.h:14:
quoted
include/linux/screen_info.h:145:6: warning: no previous prototype for function 'screen_info_is_useful' [-Wmissing-prototypes]
     145 | bool screen_info_is_useful(void)
         |      ^
   include/linux/screen_info.h:145:1: note: declare 'static' if the function is not intended to be used outside of this translation unit
     145 | bool screen_info_is_useful(void)
         | ^
         | static 
   1 warning generated.


vim +/screen_info_is_useful +145 include/linux/screen_info.h

   139	
   140	#if defined(CONFIG_PCI)
   141	bool screen_info_is_useful(void);
   142	void screen_info_apply_fixups(void);
   143	struct pci_dev *screen_info_pci_dev(const struct screen_info *si);
   144	#else
 > 145	bool screen_info_is_useful(void)
   146	{
   147		return true;
   148	}
   149	static inline void screen_info_apply_fixups(void)
   150	{ }
   151	static inline struct pci_dev *screen_info_pci_dev(const struct screen_info *si)
   152	{
   153		return NULL;
   154	}
   155	#endif
   156	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

Re: [PATCH] fbdev: efifb: do not load efifb if PCI BAR has changed but not fixuped

From: Shixiong Ou <hidden>
Date: 2025-06-27 08:08:13

在 2025/6/26 18:31, Thomas Zimmermann 写道:
Hi

Am 26.06.25 um 11:49 schrieb oushixiong1025@163.com:
quoted
From: Shixiong Ou <redacted>

[WHY]
On an ARM machine, the following log is present:
[    0.900884] efifb: framebuffer at 0x1020000000, using 3072k, total 
3072k
[    2.297884] amdgpu 0000:04:00.0: 
remove_conflicting_pci_framebuffers: bar 0: 0x1000000000 -> 0x100fffffff
[    2.297886] amdgpu 0000:04:00.0: 
remove_conflicting_pci_framebuffers: bar 2: 0x1010000000 -> 0x10101fffff
[    2.297888] amdgpu 0000:04:00.0: 
remove_conflicting_pci_framebuffers: bar 5: 0x58200000 -> 0x5823ffff

It show that the efifb framebuffer base is out of PCI BAR, and this
The patch at

  https://patchwork.freedesktop.org/series/148057/

is supposed to fix the problem. It has been merged with v6.16-rc1 as 
commit 2f29b5c23101 ("video: screen_info: Relocate framebuffers behind 
PCI bridges"). It is in your tree?

Best regards
Thomas
yeah, this patch is in my tree. but do not fix the problem.

this is some message:

kylin@kylin-pc:~$ dmesg | grep BAR
[    0.688192] pci 0000:00:03.0: BAR 15: assigned [mem 
0x1000000000-0x101fffffff 64bit pref]
[    0.688200] pci 0000:00:00.0: BAR 0: assigned [mem 
0x1020000000-0x10200fffff 64bit pref]
[    0.688205] pci 0000:00:00.0: BAR 14: assigned [mem 
0x58000000-0x580fffff]
[    0.688210] pci 0000:00:01.0: BAR 0: assigned [mem 
0x1020100000-0x10201fffff 64bit pref]
[    0.688215] pci 0000:00:02.0: BAR 0: assigned [mem 
0x1020200000-0x10202fffff 64bit pref]
[    0.688221] pci 0000:00:02.0: BAR 14: assigned [mem 
0x58100000-0x581fffff]
[    0.688225] pci 0000:00:03.0: BAR 0: assigned [mem 
0x1020300000-0x10203fffff 64bit pref]
[    0.688231] pci 0000:00:03.0: BAR 14: assigned [mem 
0x58200000-0x585fffff]
[    0.688237] pci 0000:00:04.0: BAR 0: assigned [mem 
0x1020400000-0x10204fffff 64bit pref]
[    0.688243] pci 0000:00:05.0: BAR 0: assigned [mem 
0x1020500000-0x10205fffff 64bit pref]
[    0.688249] pci 0000:00:05.0: BAR 14: assigned [mem 
0x58600000-0x586fffff]
[    0.688253] pci 0000:01:00.0: BAR 0: assigned [mem 
0x58000000-0x58003fff 64bit]
[    0.688290] pci 0000:03:00.0: BAR 6: assigned [mem 
0x58100000-0x5817ffff pref]
[    0.688296] pci 0000:03:00.0: BAR 0: assigned [mem 0x58180000-0x58181fff]
[    0.688303] pci 0000:03:00.0: BAR 5: assigned [mem 0x58182000-0x58183fff]
[    0.688317] pci 0000:04:00.0: BAR 1: assigned [mem 
0x1000000000-0x101fffffff 64bit pref]
[    0.688326] pci 0000:04:00.0: BAR 0: assigned [mem 0x58200000-0x583fffff]
[    0.688332] pci 0000:04:00.0: BAR 6: assigned [mem 
0x58400000-0x584fffff pref]
[    0.688336] pci 0000:04:00.1: BAR 0: assigned [mem 0x58500000-0x58503fff]
[    0.688360] pci 0000:06:00.0: BAR 0: assigned [mem 
0x58600000-0x58601fff 64bit]
kylin@kylin-pc:~$ dmesg | grep framebuffer
[    1.137536] efifb: framebuffer at 0x1020000000, using 3072k, total 3072k

the efifb base address is still at 0x1020000000 after calling 
pcibios_bus_to_resource().

quoted
results in both efi-framebuffer and amdgpudrmfb co-existing.

The fbcon will be bound to efi-framebuffer by default and cannot be 
used.

[HOW]
Do not load efifb driver if PCI BAR has changed but not fixuped.
In the following cases:
    1. screen_info_lfb_pdev is NULL.
    2. __screen_info_relocation_is_valid return false.

Signed-off-by: Shixiong Ou <redacted>
---
  drivers/video/fbdev/efifb.c     |  4 ++++
  drivers/video/screen_info_pci.c | 24 ++++++++++++++++++++++++
  include/linux/screen_info.h     |  5 +++++
  3 files changed, 33 insertions(+)
diff --git a/drivers/video/fbdev/efifb.c b/drivers/video/fbdev/efifb.c
index 0e1bd3dba255..de8d016c9a66 100644
--- a/drivers/video/fbdev/efifb.c
+++ b/drivers/video/fbdev/efifb.c
@@ -303,6 +303,10 @@ static void efifb_setup(struct screen_info *si, 
char *options)
    static inline bool fb_base_is_valid(struct screen_info *si)
  {
+    /* check whether fb_base has changed but not fixuped */
+    if (!screen_info_is_useful())
+        return false;
+
      if (si->lfb_base)
          return true;
  diff --git a/drivers/video/screen_info_pci.c 
b/drivers/video/screen_info_pci.c
index 66bfc1d0a6dc..ac57dcaf0cac 100644
--- a/drivers/video/screen_info_pci.c
+++ b/drivers/video/screen_info_pci.c
@@ -9,6 +9,8 @@ static struct pci_dev *screen_info_lfb_pdev;
  static size_t screen_info_lfb_bar;
  static resource_size_t screen_info_lfb_res_start; // original start 
of resource
  static resource_size_t screen_info_lfb_offset; // framebuffer 
offset within resource
+static bool screen_info_changed;
+static bool screen_info_fixuped;
    static bool __screen_info_relocation_is_valid(const struct 
screen_info *si, struct resource *pr)
  {
@@ -24,6 +26,24 @@ static bool 
__screen_info_relocation_is_valid(const struct screen_info *si, stru
      return true;
  }
  +bool screen_info_is_useful(void)
+{
+    unsigned int type;
+    const struct screen_info *si = &screen_info;
+
+    type = screen_info_video_type(si);
+    if (type != VIDEO_TYPE_EFI)
+        return true;
+
+    if (screen_info_changed && !screen_info_fixuped) {
+        pr_warn("The screen_info has changed but not fixuped");
+        return false;
+    }
+
+    pr_info("The screen_info is useful");
+    return true;
+}
+
  void screen_info_apply_fixups(void)
  {
      struct screen_info *si = &screen_info;
@@ -32,18 +52,22 @@ void screen_info_apply_fixups(void)
          struct resource *pr = 
&screen_info_lfb_pdev->resource[screen_info_lfb_bar];
            if (pr->start != screen_info_lfb_res_start) {
+            screen_info_changed = true;
              if (__screen_info_relocation_is_valid(si, pr)) {
                  /*
                   * Only update base if we have an actual
                   * relocation to a valid I/O range.
                   */
                  __screen_info_set_lfb_base(si, pr->start + 
screen_info_lfb_offset);
+                screen_info_fixuped = true;
                  pr_info("Relocating firmware framebuffer to offset 
%pa[d] within %pr\n",
                      &screen_info_lfb_offset, pr);
              } else {
                  pr_warn("Invalid relocating, disabling firmware 
framebuffer\n");
And should something be done after __screen_info_relocation_is_valid() 
return false?

Best regards
Shixiong.
quoted
              }
          }
+    } else {
+        screen_info_changed = true;
      }
  }
  diff --git a/include/linux/screen_info.h b/include/linux/screen_info.h
index 923d68e07679..632cdbb1adbe 100644
--- a/include/linux/screen_info.h
+++ b/include/linux/screen_info.h
@@ -138,9 +138,14 @@ ssize_t screen_info_resources(const struct 
screen_info *si, struct resource *r,
  u32 __screen_info_lfb_bits_per_pixel(const struct screen_info *si);
    #if defined(CONFIG_PCI)
+bool screen_info_is_useful(void);
  void screen_info_apply_fixups(void);
  struct pci_dev *screen_info_pci_dev(const struct screen_info *si);
  #else
+bool screen_info_is_useful(void)
+{
+    return true;
+}
  static inline void screen_info_apply_fixups(void)
  { }
  static inline struct pci_dev *screen_info_pci_dev(const struct 
screen_info *si)

Re: [PATCH] fbdev: efifb: do not load efifb if PCI BAR has changed but not fixuped

From: Thomas Zimmermann <tzimmermann@suse.de>
Date: 2025-06-27 08:12:56

Hi

Am 27.06.25 um 10:07 schrieb Shixiong Ou:
在 2025/6/26 18:31, Thomas Zimmermann 写道:
quoted
Hi

Am 26.06.25 um 11:49 schrieb oushixiong1025@163.com:
quoted
From: Shixiong Ou <redacted>

[WHY]
On an ARM machine, the following log is present:
[    0.900884] efifb: framebuffer at 0x1020000000, using 3072k, 
total 3072k
[    2.297884] amdgpu 0000:04:00.0: 
remove_conflicting_pci_framebuffers: bar 0: 0x1000000000 -> 
0x100fffffff
[    2.297886] amdgpu 0000:04:00.0: 
remove_conflicting_pci_framebuffers: bar 2: 0x1010000000 -> 
0x10101fffff
[    2.297888] amdgpu 0000:04:00.0: 
remove_conflicting_pci_framebuffers: bar 5: 0x58200000 -> 0x5823ffff

It show that the efifb framebuffer base is out of PCI BAR, and this
The patch at

  https://patchwork.freedesktop.org/series/148057/

is supposed to fix the problem. It has been merged with v6.16-rc1 as 
commit 2f29b5c23101 ("video: screen_info: Relocate framebuffers 
behind PCI bridges"). It is in your tree?

Best regards
Thomas
yeah, this patch is in my tree. but do not fix the problem.
The patch's final revision had a rough development. Just for testing 
purposes, could you revert the commit and instead apply the patch's 
earlier revision from

https://patchwork.freedesktop.org/patch/649527/?series=148057&rev=1

?

Thanks a lot.

Best regards
Thomas
this is some message:

kylin@kylin-pc:~$ dmesg | grep BAR
[    0.688192] pci 0000:00:03.0: BAR 15: assigned [mem 
0x1000000000-0x101fffffff 64bit pref]
[    0.688200] pci 0000:00:00.0: BAR 0: assigned [mem 
0x1020000000-0x10200fffff 64bit pref]
[    0.688205] pci 0000:00:00.0: BAR 14: assigned [mem 
0x58000000-0x580fffff]
[    0.688210] pci 0000:00:01.0: BAR 0: assigned [mem 
0x1020100000-0x10201fffff 64bit pref]
[    0.688215] pci 0000:00:02.0: BAR 0: assigned [mem 
0x1020200000-0x10202fffff 64bit pref]
[    0.688221] pci 0000:00:02.0: BAR 14: assigned [mem 
0x58100000-0x581fffff]
[    0.688225] pci 0000:00:03.0: BAR 0: assigned [mem 
0x1020300000-0x10203fffff 64bit pref]
[    0.688231] pci 0000:00:03.0: BAR 14: assigned [mem 
0x58200000-0x585fffff]
[    0.688237] pci 0000:00:04.0: BAR 0: assigned [mem 
0x1020400000-0x10204fffff 64bit pref]
[    0.688243] pci 0000:00:05.0: BAR 0: assigned [mem 
0x1020500000-0x10205fffff 64bit pref]
[    0.688249] pci 0000:00:05.0: BAR 14: assigned [mem 
0x58600000-0x586fffff]
[    0.688253] pci 0000:01:00.0: BAR 0: assigned [mem 
0x58000000-0x58003fff 64bit]
[    0.688290] pci 0000:03:00.0: BAR 6: assigned [mem 
0x58100000-0x5817ffff pref]
[    0.688296] pci 0000:03:00.0: BAR 0: assigned [mem 
0x58180000-0x58181fff]
[    0.688303] pci 0000:03:00.0: BAR 5: assigned [mem 
0x58182000-0x58183fff]
[    0.688317] pci 0000:04:00.0: BAR 1: assigned [mem 
0x1000000000-0x101fffffff 64bit pref]
[    0.688326] pci 0000:04:00.0: BAR 0: assigned [mem 
0x58200000-0x583fffff]
[    0.688332] pci 0000:04:00.0: BAR 6: assigned [mem 
0x58400000-0x584fffff pref]
[    0.688336] pci 0000:04:00.1: BAR 0: assigned [mem 
0x58500000-0x58503fff]
[    0.688360] pci 0000:06:00.0: BAR 0: assigned [mem 
0x58600000-0x58601fff 64bit]
kylin@kylin-pc:~$ dmesg | grep framebuffer
[    1.137536] efifb: framebuffer at 0x1020000000, using 3072k, total 
3072k

the efifb base address is still at 0x1020000000 after calling 
pcibios_bus_to_resource().

quoted
quoted
results in both efi-framebuffer and amdgpudrmfb co-existing.

The fbcon will be bound to efi-framebuffer by default and cannot be 
used.

[HOW]
Do not load efifb driver if PCI BAR has changed but not fixuped.
In the following cases:
    1. screen_info_lfb_pdev is NULL.
    2. __screen_info_relocation_is_valid return false.

Signed-off-by: Shixiong Ou <redacted>
---
  drivers/video/fbdev/efifb.c     |  4 ++++
  drivers/video/screen_info_pci.c | 24 ++++++++++++++++++++++++
  include/linux/screen_info.h     |  5 +++++
  3 files changed, 33 insertions(+)
diff --git a/drivers/video/fbdev/efifb.c b/drivers/video/fbdev/efifb.c
index 0e1bd3dba255..de8d016c9a66 100644
--- a/drivers/video/fbdev/efifb.c
+++ b/drivers/video/fbdev/efifb.c
@@ -303,6 +303,10 @@ static void efifb_setup(struct screen_info *si, 
char *options)
    static inline bool fb_base_is_valid(struct screen_info *si)
  {
+    /* check whether fb_base has changed but not fixuped */
+    if (!screen_info_is_useful())
+        return false;
+
      if (si->lfb_base)
          return true;
  diff --git a/drivers/video/screen_info_pci.c 
b/drivers/video/screen_info_pci.c
index 66bfc1d0a6dc..ac57dcaf0cac 100644
--- a/drivers/video/screen_info_pci.c
+++ b/drivers/video/screen_info_pci.c
@@ -9,6 +9,8 @@ static struct pci_dev *screen_info_lfb_pdev;
  static size_t screen_info_lfb_bar;
  static resource_size_t screen_info_lfb_res_start; // original 
start of resource
  static resource_size_t screen_info_lfb_offset; // framebuffer 
offset within resource
+static bool screen_info_changed;
+static bool screen_info_fixuped;
    static bool __screen_info_relocation_is_valid(const struct 
screen_info *si, struct resource *pr)
  {
@@ -24,6 +26,24 @@ static bool 
__screen_info_relocation_is_valid(const struct screen_info *si, stru
      return true;
  }
  +bool screen_info_is_useful(void)
+{
+    unsigned int type;
+    const struct screen_info *si = &screen_info;
+
+    type = screen_info_video_type(si);
+    if (type != VIDEO_TYPE_EFI)
+        return true;
+
+    if (screen_info_changed && !screen_info_fixuped) {
+        pr_warn("The screen_info has changed but not fixuped");
+        return false;
+    }
+
+    pr_info("The screen_info is useful");
+    return true;
+}
+
  void screen_info_apply_fixups(void)
  {
      struct screen_info *si = &screen_info;
@@ -32,18 +52,22 @@ void screen_info_apply_fixups(void)
          struct resource *pr = 
&screen_info_lfb_pdev->resource[screen_info_lfb_bar];
            if (pr->start != screen_info_lfb_res_start) {
+            screen_info_changed = true;
              if (__screen_info_relocation_is_valid(si, pr)) {
                  /*
                   * Only update base if we have an actual
                   * relocation to a valid I/O range.
                   */
                  __screen_info_set_lfb_base(si, pr->start + 
screen_info_lfb_offset);
+                screen_info_fixuped = true;
                  pr_info("Relocating firmware framebuffer to offset 
%pa[d] within %pr\n",
                      &screen_info_lfb_offset, pr);
              } else {
                  pr_warn("Invalid relocating, disabling firmware 
framebuffer\n");
And should something be done after __screen_info_relocation_is_valid() 
return false?

Best regards
Shixiong.
quoted
quoted
              }
          }
+    } else {
+        screen_info_changed = true;
      }
  }
  diff --git a/include/linux/screen_info.h 
b/include/linux/screen_info.h
index 923d68e07679..632cdbb1adbe 100644
--- a/include/linux/screen_info.h
+++ b/include/linux/screen_info.h
@@ -138,9 +138,14 @@ ssize_t screen_info_resources(const struct 
screen_info *si, struct resource *r,
  u32 __screen_info_lfb_bits_per_pixel(const struct screen_info *si);
    #if defined(CONFIG_PCI)
+bool screen_info_is_useful(void);
  void screen_info_apply_fixups(void);
  struct pci_dev *screen_info_pci_dev(const struct screen_info *si);
  #else
+bool screen_info_is_useful(void)
+{
+    return true;
+}
  static inline void screen_info_apply_fixups(void)
  { }
  static inline struct pci_dev *screen_info_pci_dev(const struct 
screen_info *si)
-- 
--
Thomas Zimmermann
Graphics Driver Developer
SUSE Software Solutions Germany GmbH
Frankenstrasse 146, 90461 Nuernberg, Germany
GF: Ivo Totev, Andrew Myers, Andrew McDonald, Boudien Moerman
HRB 36809 (AG Nuernberg)

Re: [PATCH] fbdev: efifb: do not load efifb if PCI BAR has changed but not fixuped

From: Thomas Zimmermann <tzimmermann@suse.de>
Date: 2025-06-27 09:10:34

Hi

Am 26.06.25 um 11:49 schrieb oushixiong1025@163.com:
quoted hunk
From: Shixiong Ou <redacted>

[WHY]
On an ARM machine, the following log is present:
[    0.900884] efifb: framebuffer at 0x1020000000, using 3072k, total 3072k
[    2.297884] amdgpu 0000:04:00.0: remove_conflicting_pci_framebuffers: bar 0: 0x1000000000 -> 0x100fffffff
[    2.297886] amdgpu 0000:04:00.0: remove_conflicting_pci_framebuffers: bar 2: 0x1010000000 -> 0x10101fffff
[    2.297888] amdgpu 0000:04:00.0: remove_conflicting_pci_framebuffers: bar 5: 0x58200000 -> 0x5823ffff

It show that the efifb framebuffer base is out of PCI BAR, and this
results in both efi-framebuffer and amdgpudrmfb co-existing.

The fbcon will be bound to efi-framebuffer by default and cannot be used.

[HOW]
Do not load efifb driver if PCI BAR has changed but not fixuped.
In the following cases:
	1. screen_info_lfb_pdev is NULL.
	2. __screen_info_relocation_is_valid return false.

Signed-off-by: Shixiong Ou <redacted>
---
  drivers/video/fbdev/efifb.c     |  4 ++++
  drivers/video/screen_info_pci.c | 24 ++++++++++++++++++++++++
  include/linux/screen_info.h     |  5 +++++
  3 files changed, 33 insertions(+)
diff --git a/drivers/video/fbdev/efifb.c b/drivers/video/fbdev/efifb.c
index 0e1bd3dba255..de8d016c9a66 100644
--- a/drivers/video/fbdev/efifb.c
+++ b/drivers/video/fbdev/efifb.c
@@ -303,6 +303,10 @@ static void efifb_setup(struct screen_info *si, char *options)
  
  static inline bool fb_base_is_valid(struct screen_info *si)
  {
+	/* check whether fb_base has changed but not fixuped */
+	if (!screen_info_is_useful())
+		return false;
+
  	if (si->lfb_base)
  		return true;
  
diff --git a/drivers/video/screen_info_pci.c b/drivers/video/screen_info_pci.c
index 66bfc1d0a6dc..ac57dcaf0cac 100644
--- a/drivers/video/screen_info_pci.c
+++ b/drivers/video/screen_info_pci.c
@@ -9,6 +9,8 @@ static struct pci_dev *screen_info_lfb_pdev;
  static size_t screen_info_lfb_bar;
  static resource_size_t screen_info_lfb_res_start; // original start of resource
  static resource_size_t screen_info_lfb_offset; // framebuffer offset within resource
+static bool screen_info_changed;
+static bool screen_info_fixuped;
  
  static bool __screen_info_relocation_is_valid(const struct screen_info *si, struct resource *pr)
  {
@@ -24,6 +26,24 @@ static bool __screen_info_relocation_is_valid(const struct screen_info *si, stru
  	return true;
  }
  
+bool screen_info_is_useful(void)
+{
+	unsigned int type;
+	const struct screen_info *si = &screen_info;
+
+	type = screen_info_video_type(si);
+	if (type != VIDEO_TYPE_EFI)
+		return true;
+
+	if (screen_info_changed && !screen_info_fixuped) {
+		pr_warn("The screen_info has changed but not fixuped");
+		return false;
+	}
+
+	pr_info("The screen_info is useful");
+	return true;
+}
+
  void screen_info_apply_fixups(void)
  {
  	struct screen_info *si = &screen_info;
@@ -32,18 +52,22 @@ void screen_info_apply_fixups(void)
  		struct resource *pr = &screen_info_lfb_pdev->resource[screen_info_lfb_bar];
  
  		if (pr->start != screen_info_lfb_res_start) {
+			screen_info_changed = true;
  			if (__screen_info_relocation_is_valid(si, pr)) {
  				/*
  				 * Only update base if we have an actual
  				 * relocation to a valid I/O range.
  				 */
  				__screen_info_set_lfb_base(si, pr->start + screen_info_lfb_offset);
+				screen_info_fixuped = true;
  				pr_info("Relocating firmware framebuffer to offset %pa[d] within %pr\n",
  					&screen_info_lfb_offset, pr);
  			} else {
  				pr_warn("Invalid relocating, disabling firmware framebuffer\n");
Here it says to disable the framebuffer, but does not actually disable 
anything. Instead of adding new interfaces, simply do

   screen_info.orig_video_isVGA = 0;

in this branch. Further kernel code will then ignore the framebuffer. 
Also works with VIDEO_TYPE_VLFB.

Best regards
Thomas
quoted hunk
  			}
  		}
+	} else {
+		screen_info_changed = true;
  	}
  }
  
diff --git a/include/linux/screen_info.h b/include/linux/screen_info.h
index 923d68e07679..632cdbb1adbe 100644
--- a/include/linux/screen_info.h
+++ b/include/linux/screen_info.h
@@ -138,9 +138,14 @@ ssize_t screen_info_resources(const struct screen_info *si, struct resource *r,
  u32 __screen_info_lfb_bits_per_pixel(const struct screen_info *si);
  
  #if defined(CONFIG_PCI)
+bool screen_info_is_useful(void);
  void screen_info_apply_fixups(void);
  struct pci_dev *screen_info_pci_dev(const struct screen_info *si);
  #else
+bool screen_info_is_useful(void)
+{
+	return true;
+}
  static inline void screen_info_apply_fixups(void)
  { }
  static inline struct pci_dev *screen_info_pci_dev(const struct screen_info *si)
-- 
--
Thomas Zimmermann
Graphics Driver Developer
SUSE Software Solutions Germany GmbH
Frankenstrasse 146, 90461 Nuernberg, Germany
GF: Ivo Totev, Andrew Myers, Andrew McDonald, Boudien Moerman
HRB 36809 (AG Nuernberg)

Re: [PATCH] fbdev: efifb: do not load efifb if PCI BAR has changed but not fixuped

From: Thomas Zimmermann <tzimmermann@suse.de>
Date: 2025-06-27 09:13:13

Hi

Am 26.06.25 um 11:49 schrieb oushixiong1025@163.com:
From: Shixiong Ou <redacted>

[WHY]
On an ARM machine, the following log is present:
[    0.900884] efifb: framebuffer at 0x1020000000, using 3072k, total 3072k
[    2.297884] amdgpu 0000:04:00.0: remove_conflicting_pci_framebuffers: bar 0: 0x1000000000 -> 0x100fffffff
[    2.297886] amdgpu 0000:04:00.0: remove_conflicting_pci_framebuffers: bar 2: 0x1010000000 -> 0x10101fffff
[    2.297888] amdgpu 0000:04:00.0: remove_conflicting_pci_framebuffers: bar 5: 0x58200000 -> 0x5823ffff

It show that the efifb framebuffer base is out of PCI BAR, and this
results in both efi-framebuffer and amdgpudrmfb co-existing.

The fbcon will be bound to efi-framebuffer by default and cannot be used.

[HOW]
Do not load efifb driver if PCI BAR has changed but not fixuped.
In the following cases:
	1. screen_info_lfb_pdev is NULL.
	2. __screen_info_relocation_is_valid return false.
Apart from ruling out invalid screen_info, did you figure out why the 
relocation tracking didn't work? It would be good to fix this if possible.

Best regards
Thomas
quoted hunk
Signed-off-by: Shixiong Ou <redacted>
---
  drivers/video/fbdev/efifb.c     |  4 ++++
  drivers/video/screen_info_pci.c | 24 ++++++++++++++++++++++++
  include/linux/screen_info.h     |  5 +++++
  3 files changed, 33 insertions(+)
diff --git a/drivers/video/fbdev/efifb.c b/drivers/video/fbdev/efifb.c
index 0e1bd3dba255..de8d016c9a66 100644
--- a/drivers/video/fbdev/efifb.c
+++ b/drivers/video/fbdev/efifb.c
@@ -303,6 +303,10 @@ static void efifb_setup(struct screen_info *si, char *options)
  
  static inline bool fb_base_is_valid(struct screen_info *si)
  {
+	/* check whether fb_base has changed but not fixuped */
+	if (!screen_info_is_useful())
+		return false;
+
  	if (si->lfb_base)
  		return true;
  
diff --git a/drivers/video/screen_info_pci.c b/drivers/video/screen_info_pci.c
index 66bfc1d0a6dc..ac57dcaf0cac 100644
--- a/drivers/video/screen_info_pci.c
+++ b/drivers/video/screen_info_pci.c
@@ -9,6 +9,8 @@ static struct pci_dev *screen_info_lfb_pdev;
  static size_t screen_info_lfb_bar;
  static resource_size_t screen_info_lfb_res_start; // original start of resource
  static resource_size_t screen_info_lfb_offset; // framebuffer offset within resource
+static bool screen_info_changed;
+static bool screen_info_fixuped;
  
  static bool __screen_info_relocation_is_valid(const struct screen_info *si, struct resource *pr)
  {
@@ -24,6 +26,24 @@ static bool __screen_info_relocation_is_valid(const struct screen_info *si, stru
  	return true;
  }
  
+bool screen_info_is_useful(void)
+{
+	unsigned int type;
+	const struct screen_info *si = &screen_info;
+
+	type = screen_info_video_type(si);
+	if (type != VIDEO_TYPE_EFI)
+		return true;
+
+	if (screen_info_changed && !screen_info_fixuped) {
+		pr_warn("The screen_info has changed but not fixuped");
+		return false;
+	}
+
+	pr_info("The screen_info is useful");
+	return true;
+}
+
  void screen_info_apply_fixups(void)
  {
  	struct screen_info *si = &screen_info;
@@ -32,18 +52,22 @@ void screen_info_apply_fixups(void)
  		struct resource *pr = &screen_info_lfb_pdev->resource[screen_info_lfb_bar];
  
  		if (pr->start != screen_info_lfb_res_start) {
+			screen_info_changed = true;
  			if (__screen_info_relocation_is_valid(si, pr)) {
  				/*
  				 * Only update base if we have an actual
  				 * relocation to a valid I/O range.
  				 */
  				__screen_info_set_lfb_base(si, pr->start + screen_info_lfb_offset);
+				screen_info_fixuped = true;
  				pr_info("Relocating firmware framebuffer to offset %pa[d] within %pr\n",
  					&screen_info_lfb_offset, pr);
  			} else {
  				pr_warn("Invalid relocating, disabling firmware framebuffer\n");
  			}
  		}
+	} else {
+		screen_info_changed = true;
  	}
  }
  
diff --git a/include/linux/screen_info.h b/include/linux/screen_info.h
index 923d68e07679..632cdbb1adbe 100644
--- a/include/linux/screen_info.h
+++ b/include/linux/screen_info.h
@@ -138,9 +138,14 @@ ssize_t screen_info_resources(const struct screen_info *si, struct resource *r,
  u32 __screen_info_lfb_bits_per_pixel(const struct screen_info *si);
  
  #if defined(CONFIG_PCI)
+bool screen_info_is_useful(void);
  void screen_info_apply_fixups(void);
  struct pci_dev *screen_info_pci_dev(const struct screen_info *si);
  #else
+bool screen_info_is_useful(void)
+{
+	return true;
+}
  static inline void screen_info_apply_fixups(void)
  { }
  static inline struct pci_dev *screen_info_pci_dev(const struct screen_info *si)
-- 
--
Thomas Zimmermann
Graphics Driver Developer
SUSE Software Solutions Germany GmbH
Frankenstrasse 146, 90461 Nuernberg, Germany
GF: Ivo Totev, Andrew Myers, Andrew McDonald, Boudien Moerman
HRB 36809 (AG Nuernberg)

Re: [PATCH] fbdev: efifb: do not load efifb if PCI BAR has changed but not fixuped

From: Shixiong Ou <hidden>
Date: 2025-07-07 09:24:33

在 2025/6/27 17:13, Thomas Zimmermann 写道:
Hi

Am 26.06.25 um 11:49 schrieb oushixiong1025@163.com:
quoted
From: Shixiong Ou <redacted>

[WHY]
On an ARM machine, the following log is present:
[    0.900884] efifb: framebuffer at 0x1020000000, using 3072k, total 
3072k
[    2.297884] amdgpu 0000:04:00.0: 
remove_conflicting_pci_framebuffers: bar 0: 0x1000000000 -> 0x100fffffff
[    2.297886] amdgpu 0000:04:00.0: 
remove_conflicting_pci_framebuffers: bar 2: 0x1010000000 -> 0x10101fffff
[    2.297888] amdgpu 0000:04:00.0: 
remove_conflicting_pci_framebuffers: bar 5: 0x58200000 -> 0x5823ffff

It show that the efifb framebuffer base is out of PCI BAR, and this
results in both efi-framebuffer and amdgpudrmfb co-existing.

The fbcon will be bound to efi-framebuffer by default and cannot be 
used.

[HOW]
Do not load efifb driver if PCI BAR has changed but not fixuped.
In the following cases:
    1. screen_info_lfb_pdev is NULL.
    2. __screen_info_relocation_is_valid return false.
Apart from ruling out invalid screen_info, did you figure out why the 
relocation tracking didn't work? It would be good to fix this if 
possible.

Best regards
Thomas
I haven’t figure out the root cause yet.

This issue is quite rare and might be related to the EFI firmware.
However, I wonder if we could add some handling when no PCI resources 
are found in screen_info_fixup_lfb(), as a temporary workaround for the 
problem I mentioned earlier.

Best regards
Shixiong Ou
quoted
Signed-off-by: Shixiong Ou <redacted>
---
  drivers/video/fbdev/efifb.c     |  4 ++++
  drivers/video/screen_info_pci.c | 24 ++++++++++++++++++++++++
  include/linux/screen_info.h     |  5 +++++
  3 files changed, 33 insertions(+)
diff --git a/drivers/video/fbdev/efifb.c b/drivers/video/fbdev/efifb.c
index 0e1bd3dba255..de8d016c9a66 100644
--- a/drivers/video/fbdev/efifb.c
+++ b/drivers/video/fbdev/efifb.c
@@ -303,6 +303,10 @@ static void efifb_setup(struct screen_info *si, 
char *options)
    static inline bool fb_base_is_valid(struct screen_info *si)
  {
+    /* check whether fb_base has changed but not fixuped */
+    if (!screen_info_is_useful())
+        return false;
+
      if (si->lfb_base)
          return true;
  diff --git a/drivers/video/screen_info_pci.c 
b/drivers/video/screen_info_pci.c
index 66bfc1d0a6dc..ac57dcaf0cac 100644
--- a/drivers/video/screen_info_pci.c
+++ b/drivers/video/screen_info_pci.c
@@ -9,6 +9,8 @@ static struct pci_dev *screen_info_lfb_pdev;
  static size_t screen_info_lfb_bar;
  static resource_size_t screen_info_lfb_res_start; // original start 
of resource
  static resource_size_t screen_info_lfb_offset; // framebuffer 
offset within resource
+static bool screen_info_changed;
+static bool screen_info_fixuped;
    static bool __screen_info_relocation_is_valid(const struct 
screen_info *si, struct resource *pr)
  {
@@ -24,6 +26,24 @@ static bool 
__screen_info_relocation_is_valid(const struct screen_info *si, stru
      return true;
  }
  +bool screen_info_is_useful(void)
+{
+    unsigned int type;
+    const struct screen_info *si = &screen_info;
+
+    type = screen_info_video_type(si);
+    if (type != VIDEO_TYPE_EFI)
+        return true;
+
+    if (screen_info_changed && !screen_info_fixuped) {
+        pr_warn("The screen_info has changed but not fixuped");
+        return false;
+    }
+
+    pr_info("The screen_info is useful");
+    return true;
+}
+
  void screen_info_apply_fixups(void)
  {
      struct screen_info *si = &screen_info;
@@ -32,18 +52,22 @@ void screen_info_apply_fixups(void)
          struct resource *pr = 
&screen_info_lfb_pdev->resource[screen_info_lfb_bar];
            if (pr->start != screen_info_lfb_res_start) {
+            screen_info_changed = true;
              if (__screen_info_relocation_is_valid(si, pr)) {
                  /*
                   * Only update base if we have an actual
                   * relocation to a valid I/O range.
                   */
                  __screen_info_set_lfb_base(si, pr->start + 
screen_info_lfb_offset);
+                screen_info_fixuped = true;
                  pr_info("Relocating firmware framebuffer to offset 
%pa[d] within %pr\n",
                      &screen_info_lfb_offset, pr);
              } else {
                  pr_warn("Invalid relocating, disabling firmware 
framebuffer\n");
              }
          }
+    } else {
+        screen_info_changed = true;
      }
  }
  diff --git a/include/linux/screen_info.h b/include/linux/screen_info.h
index 923d68e07679..632cdbb1adbe 100644
--- a/include/linux/screen_info.h
+++ b/include/linux/screen_info.h
@@ -138,9 +138,14 @@ ssize_t screen_info_resources(const struct 
screen_info *si, struct resource *r,
  u32 __screen_info_lfb_bits_per_pixel(const struct screen_info *si);
    #if defined(CONFIG_PCI)
+bool screen_info_is_useful(void);
  void screen_info_apply_fixups(void);
  struct pci_dev *screen_info_pci_dev(const struct screen_info *si);
  #else
+bool screen_info_is_useful(void)
+{
+    return true;
+}
  static inline void screen_info_apply_fixups(void)
  { }
  static inline struct pci_dev *screen_info_pci_dev(const struct 
screen_info *si)

Re: [PATCH] fbdev: efifb: do not load efifb if PCI BAR has changed but not fixuped

From: Thomas Zimmermann <tzimmermann@suse.de>
Date: 2025-07-07 09:28:34

Hi

Am 07.07.25 um 11:24 schrieb Shixiong Ou:
在 2025/6/27 17:13, Thomas Zimmermann 写道:
quoted
Hi

Am 26.06.25 um 11:49 schrieb oushixiong1025@163.com:
quoted
From: Shixiong Ou <redacted>

[WHY]
On an ARM machine, the following log is present:
[    0.900884] efifb: framebuffer at 0x1020000000, using 3072k, 
total 3072k
[    2.297884] amdgpu 0000:04:00.0: 
remove_conflicting_pci_framebuffers: bar 0: 0x1000000000 -> 
0x100fffffff
[    2.297886] amdgpu 0000:04:00.0: 
remove_conflicting_pci_framebuffers: bar 2: 0x1010000000 -> 
0x10101fffff
[    2.297888] amdgpu 0000:04:00.0: 
remove_conflicting_pci_framebuffers: bar 5: 0x58200000 -> 0x5823ffff

It show that the efifb framebuffer base is out of PCI BAR, and this
results in both efi-framebuffer and amdgpudrmfb co-existing.

The fbcon will be bound to efi-framebuffer by default and cannot be 
used.

[HOW]
Do not load efifb driver if PCI BAR has changed but not fixuped.
In the following cases:
    1. screen_info_lfb_pdev is NULL.
    2. __screen_info_relocation_is_valid return false.
Apart from ruling out invalid screen_info, did you figure out why the 
relocation tracking didn't work? It would be good to fix this if 
possible.

Best regards
Thomas
I haven’t figure out the root cause yet.

This issue is quite rare and might be related to the EFI firmware.
However, I wonder if we could add some handling when no PCI resources 
are found in screen_info_fixup_lfb(), as a temporary workaround for 
the problem I mentioned earlier.
As I said elsewhere in the thread, you can clear the screen_info's video 
type in the branch at [1] to disable it entirely. We should have 
probably done this anyway. Knowing the cause of the issue would still be 
nice though.

Best regards
Thomas

[1] 
https://elixir.bootlin.com/linux/v6.15.5/source/drivers/video/screen_info_pci.c#L44
Best regards
Shixiong Ou
quoted
quoted
Signed-off-by: Shixiong Ou <redacted>
---
  drivers/video/fbdev/efifb.c     |  4 ++++
  drivers/video/screen_info_pci.c | 24 ++++++++++++++++++++++++
  include/linux/screen_info.h     |  5 +++++
  3 files changed, 33 insertions(+)
diff --git a/drivers/video/fbdev/efifb.c b/drivers/video/fbdev/efifb.c
index 0e1bd3dba255..de8d016c9a66 100644
--- a/drivers/video/fbdev/efifb.c
+++ b/drivers/video/fbdev/efifb.c
@@ -303,6 +303,10 @@ static void efifb_setup(struct screen_info *si, 
char *options)
    static inline bool fb_base_is_valid(struct screen_info *si)
  {
+    /* check whether fb_base has changed but not fixuped */
+    if (!screen_info_is_useful())
+        return false;
+
      if (si->lfb_base)
          return true;
  diff --git a/drivers/video/screen_info_pci.c 
b/drivers/video/screen_info_pci.c
index 66bfc1d0a6dc..ac57dcaf0cac 100644
--- a/drivers/video/screen_info_pci.c
+++ b/drivers/video/screen_info_pci.c
@@ -9,6 +9,8 @@ static struct pci_dev *screen_info_lfb_pdev;
  static size_t screen_info_lfb_bar;
  static resource_size_t screen_info_lfb_res_start; // original 
start of resource
  static resource_size_t screen_info_lfb_offset; // framebuffer 
offset within resource
+static bool screen_info_changed;
+static bool screen_info_fixuped;
    static bool __screen_info_relocation_is_valid(const struct 
screen_info *si, struct resource *pr)
  {
@@ -24,6 +26,24 @@ static bool 
__screen_info_relocation_is_valid(const struct screen_info *si, stru
      return true;
  }
  +bool screen_info_is_useful(void)
+{
+    unsigned int type;
+    const struct screen_info *si = &screen_info;
+
+    type = screen_info_video_type(si);
+    if (type != VIDEO_TYPE_EFI)
+        return true;
+
+    if (screen_info_changed && !screen_info_fixuped) {
+        pr_warn("The screen_info has changed but not fixuped");
+        return false;
+    }
+
+    pr_info("The screen_info is useful");
+    return true;
+}
+
  void screen_info_apply_fixups(void)
  {
      struct screen_info *si = &screen_info;
@@ -32,18 +52,22 @@ void screen_info_apply_fixups(void)
          struct resource *pr = 
&screen_info_lfb_pdev->resource[screen_info_lfb_bar];
            if (pr->start != screen_info_lfb_res_start) {
+            screen_info_changed = true;
              if (__screen_info_relocation_is_valid(si, pr)) {
                  /*
                   * Only update base if we have an actual
                   * relocation to a valid I/O range.
                   */
                  __screen_info_set_lfb_base(si, pr->start + 
screen_info_lfb_offset);
+                screen_info_fixuped = true;
                  pr_info("Relocating firmware framebuffer to offset 
%pa[d] within %pr\n",
                      &screen_info_lfb_offset, pr);
              } else {
                  pr_warn("Invalid relocating, disabling firmware 
framebuffer\n");
              }
          }
+    } else {
+        screen_info_changed = true;
      }
  }
  diff --git a/include/linux/screen_info.h 
b/include/linux/screen_info.h
index 923d68e07679..632cdbb1adbe 100644
--- a/include/linux/screen_info.h
+++ b/include/linux/screen_info.h
@@ -138,9 +138,14 @@ ssize_t screen_info_resources(const struct 
screen_info *si, struct resource *r,
  u32 __screen_info_lfb_bits_per_pixel(const struct screen_info *si);
    #if defined(CONFIG_PCI)
+bool screen_info_is_useful(void);
  void screen_info_apply_fixups(void);
  struct pci_dev *screen_info_pci_dev(const struct screen_info *si);
  #else
+bool screen_info_is_useful(void)
+{
+    return true;
+}
  static inline void screen_info_apply_fixups(void)
  { }
  static inline struct pci_dev *screen_info_pci_dev(const struct 
screen_info *si)
-- 
--
Thomas Zimmermann
Graphics Driver Developer
SUSE Software Solutions Germany GmbH
Frankenstrasse 146, 90461 Nuernberg, Germany
GF: Ivo Totev, Andrew Myers, Andrew McDonald, Boudien Moerman
HRB 36809 (AG Nuernberg)

Re: [PATCH] fbdev: efifb: do not load efifb if PCI BAR has changed but not fixuped

From: Shixiong Ou <hidden>
Date: 2025-07-07 10:03:01

在 2025/7/7 17:28, Thomas Zimmermann 写道:
Hi

Am 07.07.25 um 11:24 schrieb Shixiong Ou:
quoted
在 2025/6/27 17:13, Thomas Zimmermann 写道:
quoted
Hi

Am 26.06.25 um 11:49 schrieb oushixiong1025@163.com:
quoted
From: Shixiong Ou <redacted>

[WHY]
On an ARM machine, the following log is present:
[    0.900884] efifb: framebuffer at 0x1020000000, using 3072k, 
total 3072k
[    2.297884] amdgpu 0000:04:00.0: 
remove_conflicting_pci_framebuffers: bar 0: 0x1000000000 -> 
0x100fffffff
[    2.297886] amdgpu 0000:04:00.0: 
remove_conflicting_pci_framebuffers: bar 2: 0x1010000000 -> 
0x10101fffff
[    2.297888] amdgpu 0000:04:00.0: 
remove_conflicting_pci_framebuffers: bar 5: 0x58200000 -> 0x5823ffff

It show that the efifb framebuffer base is out of PCI BAR, and this
results in both efi-framebuffer and amdgpudrmfb co-existing.

The fbcon will be bound to efi-framebuffer by default and cannot be 
used.

[HOW]
Do not load efifb driver if PCI BAR has changed but not fixuped.
In the following cases:
    1. screen_info_lfb_pdev is NULL.
    2. __screen_info_relocation_is_valid return false.
Apart from ruling out invalid screen_info, did you figure out why 
the relocation tracking didn't work? It would be good to fix this if 
possible.

Best regards
Thomas
I haven’t figure out the root cause yet.

This issue is quite rare and might be related to the EFI firmware.
However, I wonder if we could add some handling when no PCI resources 
are found in screen_info_fixup_lfb(), as a temporary workaround for 
the problem I mentioned earlier.
As I said elsewhere in the thread, you can clear the screen_info's 
video type in the branch at [1] to disable it entirely. We should have 
probably done this anyway. Knowing the cause of the issue would still 
be nice though.

Best regards
Thomas

[1] 
https://elixir.bootlin.com/linux/v6.15.5/source/drivers/video/screen_info_pci.c#L44 
thanks for you suggestion, while there are two cases:
     1. screen_info_lfb_pdev is NULL.
     2. __screen_info_relocation_is_valid return false.

should we do it at [1] too?

Best regards
Shixiong Ou

[1] 
https://elixir.bootlin.com/linux/v6.15.5/source/drivers/video/screen_info_pci.c#L47
quoted
Best regards
Shixiong Ou
quoted
quoted
Signed-off-by: Shixiong Ou <redacted>
---
  drivers/video/fbdev/efifb.c     |  4 ++++
  drivers/video/screen_info_pci.c | 24 ++++++++++++++++++++++++
  include/linux/screen_info.h     |  5 +++++
  3 files changed, 33 insertions(+)
diff --git a/drivers/video/fbdev/efifb.c b/drivers/video/fbdev/efifb.c
index 0e1bd3dba255..de8d016c9a66 100644
--- a/drivers/video/fbdev/efifb.c
+++ b/drivers/video/fbdev/efifb.c
@@ -303,6 +303,10 @@ static void efifb_setup(struct screen_info 
*si, char *options)
    static inline bool fb_base_is_valid(struct screen_info *si)
  {
+    /* check whether fb_base has changed but not fixuped */
+    if (!screen_info_is_useful())
+        return false;
+
      if (si->lfb_base)
          return true;
  diff --git a/drivers/video/screen_info_pci.c 
b/drivers/video/screen_info_pci.c
index 66bfc1d0a6dc..ac57dcaf0cac 100644
--- a/drivers/video/screen_info_pci.c
+++ b/drivers/video/screen_info_pci.c
@@ -9,6 +9,8 @@ static struct pci_dev *screen_info_lfb_pdev;
  static size_t screen_info_lfb_bar;
  static resource_size_t screen_info_lfb_res_start; // original 
start of resource
  static resource_size_t screen_info_lfb_offset; // framebuffer 
offset within resource
+static bool screen_info_changed;
+static bool screen_info_fixuped;
    static bool __screen_info_relocation_is_valid(const struct 
screen_info *si, struct resource *pr)
  {
@@ -24,6 +26,24 @@ static bool 
__screen_info_relocation_is_valid(const struct screen_info *si, stru
      return true;
  }
  +bool screen_info_is_useful(void)
+{
+    unsigned int type;
+    const struct screen_info *si = &screen_info;
+
+    type = screen_info_video_type(si);
+    if (type != VIDEO_TYPE_EFI)
+        return true;
+
+    if (screen_info_changed && !screen_info_fixuped) {
+        pr_warn("The screen_info has changed but not fixuped");
+        return false;
+    }
+
+    pr_info("The screen_info is useful");
+    return true;
+}
+
  void screen_info_apply_fixups(void)
  {
      struct screen_info *si = &screen_info;
@@ -32,18 +52,22 @@ void screen_info_apply_fixups(void)
          struct resource *pr = 
&screen_info_lfb_pdev->resource[screen_info_lfb_bar];
            if (pr->start != screen_info_lfb_res_start) {
+            screen_info_changed = true;
              if (__screen_info_relocation_is_valid(si, pr)) {
                  /*
                   * Only update base if we have an actual
                   * relocation to a valid I/O range.
                   */
                  __screen_info_set_lfb_base(si, pr->start + 
screen_info_lfb_offset);
+                screen_info_fixuped = true;
                  pr_info("Relocating firmware framebuffer to 
offset %pa[d] within %pr\n",
                      &screen_info_lfb_offset, pr);
              } else {
                  pr_warn("Invalid relocating, disabling firmware 
framebuffer\n");
              }
          }
+    } else {
+        screen_info_changed = true;
      }
  }
  diff --git a/include/linux/screen_info.h 
b/include/linux/screen_info.h
index 923d68e07679..632cdbb1adbe 100644
--- a/include/linux/screen_info.h
+++ b/include/linux/screen_info.h
@@ -138,9 +138,14 @@ ssize_t screen_info_resources(const struct 
screen_info *si, struct resource *r,
  u32 __screen_info_lfb_bits_per_pixel(const struct screen_info *si);
    #if defined(CONFIG_PCI)
+bool screen_info_is_useful(void);
  void screen_info_apply_fixups(void);
  struct pci_dev *screen_info_pci_dev(const struct screen_info *si);
  #else
+bool screen_info_is_useful(void)
+{
+    return true;
+}
  static inline void screen_info_apply_fixups(void)
  { }
  static inline struct pci_dev *screen_info_pci_dev(const struct 
screen_info *si)

Re: [PATCH] fbdev: efifb: do not load efifb if PCI BAR has changed but not fixuped

From: Thomas Zimmermann <tzimmermann@suse.de>
Date: 2025-07-07 10:17:16

Hi

Am 07.07.25 um 12:02 schrieb Shixiong Ou:
在 2025/7/7 17:28, Thomas Zimmermann 写道:
quoted
Hi

Am 07.07.25 um 11:24 schrieb Shixiong Ou:
quoted
在 2025/6/27 17:13, Thomas Zimmermann 写道:
quoted
Hi

Am 26.06.25 um 11:49 schrieb oushixiong1025@163.com:
quoted
From: Shixiong Ou <redacted>

[WHY]
On an ARM machine, the following log is present:
[    0.900884] efifb: framebuffer at 0x1020000000, using 3072k, 
total 3072k
[    2.297884] amdgpu 0000:04:00.0: 
remove_conflicting_pci_framebuffers: bar 0: 0x1000000000 -> 
0x100fffffff
[    2.297886] amdgpu 0000:04:00.0: 
remove_conflicting_pci_framebuffers: bar 2: 0x1010000000 -> 
0x10101fffff
[    2.297888] amdgpu 0000:04:00.0: 
remove_conflicting_pci_framebuffers: bar 5: 0x58200000 -> 0x5823ffff

It show that the efifb framebuffer base is out of PCI BAR, and this
results in both efi-framebuffer and amdgpudrmfb co-existing.

The fbcon will be bound to efi-framebuffer by default and cannot 
be used.

[HOW]
Do not load efifb driver if PCI BAR has changed but not fixuped.
In the following cases:
    1. screen_info_lfb_pdev is NULL.
    2. __screen_info_relocation_is_valid return false.
Apart from ruling out invalid screen_info, did you figure out why 
the relocation tracking didn't work? It would be good to fix this 
if possible.

Best regards
Thomas
I haven’t figure out the root cause yet.

This issue is quite rare and might be related to the EFI firmware.
However, I wonder if we could add some handling when no PCI 
resources are found in screen_info_fixup_lfb(), as a temporary 
workaround for the problem I mentioned earlier.
As I said elsewhere in the thread, you can clear the screen_info's 
video type in the branch at [1] to disable it entirely. We should 
have probably done this anyway. Knowing the cause of the issue would 
still be nice though.

Best regards
Thomas

[1] 
https://elixir.bootlin.com/linux/v6.15.5/source/drivers/video/screen_info_pci.c#L44 
thanks for you suggestion, while there are two cases:
    1. screen_info_lfb_pdev is NULL.
    2. __screen_info_relocation_is_valid return false.

should we do it at [1] too?
No. This being NULL is an entirely valid state.

Best regards
Thomas
Best regards
Shixiong Ou

[1] 
https://elixir.bootlin.com/linux/v6.15.5/source/drivers/video/screen_info_pci.c#L47
quoted
quoted
Best regards
Shixiong Ou
quoted
quoted
Signed-off-by: Shixiong Ou <redacted>
---
  drivers/video/fbdev/efifb.c     |  4 ++++
  drivers/video/screen_info_pci.c | 24 ++++++++++++++++++++++++
  include/linux/screen_info.h     |  5 +++++
  3 files changed, 33 insertions(+)
diff --git a/drivers/video/fbdev/efifb.c 
b/drivers/video/fbdev/efifb.c
index 0e1bd3dba255..de8d016c9a66 100644
--- a/drivers/video/fbdev/efifb.c
+++ b/drivers/video/fbdev/efifb.c
@@ -303,6 +303,10 @@ static void efifb_setup(struct screen_info 
*si, char *options)
    static inline bool fb_base_is_valid(struct screen_info *si)
  {
+    /* check whether fb_base has changed but not fixuped */
+    if (!screen_info_is_useful())
+        return false;
+
      if (si->lfb_base)
          return true;
  diff --git a/drivers/video/screen_info_pci.c 
b/drivers/video/screen_info_pci.c
index 66bfc1d0a6dc..ac57dcaf0cac 100644
--- a/drivers/video/screen_info_pci.c
+++ b/drivers/video/screen_info_pci.c
@@ -9,6 +9,8 @@ static struct pci_dev *screen_info_lfb_pdev;
  static size_t screen_info_lfb_bar;
  static resource_size_t screen_info_lfb_res_start; // original 
start of resource
  static resource_size_t screen_info_lfb_offset; // framebuffer 
offset within resource
+static bool screen_info_changed;
+static bool screen_info_fixuped;
    static bool __screen_info_relocation_is_valid(const struct 
screen_info *si, struct resource *pr)
  {
@@ -24,6 +26,24 @@ static bool 
__screen_info_relocation_is_valid(const struct screen_info *si, stru
      return true;
  }
  +bool screen_info_is_useful(void)
+{
+    unsigned int type;
+    const struct screen_info *si = &screen_info;
+
+    type = screen_info_video_type(si);
+    if (type != VIDEO_TYPE_EFI)
+        return true;
+
+    if (screen_info_changed && !screen_info_fixuped) {
+        pr_warn("The screen_info has changed but not fixuped");
+        return false;
+    }
+
+    pr_info("The screen_info is useful");
+    return true;
+}
+
  void screen_info_apply_fixups(void)
  {
      struct screen_info *si = &screen_info;
@@ -32,18 +52,22 @@ void screen_info_apply_fixups(void)
          struct resource *pr = 
&screen_info_lfb_pdev->resource[screen_info_lfb_bar];
            if (pr->start != screen_info_lfb_res_start) {
+            screen_info_changed = true;
              if (__screen_info_relocation_is_valid(si, pr)) {
                  /*
                   * Only update base if we have an actual
                   * relocation to a valid I/O range.
                   */
                  __screen_info_set_lfb_base(si, pr->start + 
screen_info_lfb_offset);
+                screen_info_fixuped = true;
                  pr_info("Relocating firmware framebuffer to 
offset %pa[d] within %pr\n",
                      &screen_info_lfb_offset, pr);
              } else {
                  pr_warn("Invalid relocating, disabling firmware 
framebuffer\n");
              }
          }
+    } else {
+        screen_info_changed = true;
      }
  }
  diff --git a/include/linux/screen_info.h 
b/include/linux/screen_info.h
index 923d68e07679..632cdbb1adbe 100644
--- a/include/linux/screen_info.h
+++ b/include/linux/screen_info.h
@@ -138,9 +138,14 @@ ssize_t screen_info_resources(const struct 
screen_info *si, struct resource *r,
  u32 __screen_info_lfb_bits_per_pixel(const struct screen_info *si);
    #if defined(CONFIG_PCI)
+bool screen_info_is_useful(void);
  void screen_info_apply_fixups(void);
  struct pci_dev *screen_info_pci_dev(const struct screen_info *si);
  #else
+bool screen_info_is_useful(void)
+{
+    return true;
+}
  static inline void screen_info_apply_fixups(void)
  { }
  static inline struct pci_dev *screen_info_pci_dev(const struct 
screen_info *si)
-- 
--
Thomas Zimmermann
Graphics Driver Developer
SUSE Software Solutions Germany GmbH
Frankenstrasse 146, 90461 Nuernberg, Germany
GF: Ivo Totev, Andrew Myers, Andrew McDonald, Boudien Moerman
HRB 36809 (AG Nuernberg)
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help