* [PATCH] firmware/sysfb: Avoid simple-framebuffer behind DT PCI host bridges
@ 2026-11-07 8:46 Han Gao via B4 Relay
2026-11-07 17:37 ` Jennifer Berringer
0 siblings, 1 reply; 2+ messages in thread
From: Han Gao via B4 Relay @ 2026-11-07 8:46 UTC (permalink / raw)
To: Ard Biesheuvel, Ilias Apalodimas, Thomas Zimmermann,
Javier Martinez Canillas, Borislav Petkov, Simona Vetter
Cc: linux-efi, linux-kernel, dri-devel, linux-riscv, Han Gao, stable,
Han Gao
From: Han Gao <gaohan@iscas.ac.cn>
With SYSFB_SIMPLEFB, sysfb registers a simple-framebuffer device that
claims the framebuffer memory when it is added. On DT systems, the PCI
host bridge may probe later and then fails to claim its memory window.
On QEMU RISC-V virt with EDK2, a bochs-display and pci-host-generic
built as a module:
[ 0.703813] pci-host-generic 30000000.pci: resource collision: [mem 0x40000000-0x7fffffff] conflicts with BOOTFB [mem 0x40000000-0x403e7fff]
In that case, register an efi-framebuffer device instead. It claims no
memory before it probes, and commit 64c8a0cd0a53 ("efi/arm: Defer probe
of PCIe backed efifb on DT systems") makes it wait for the host bridge.
Tested on a HiFive Unmatched with EDK2 and a PCIe graphics card, and on
QEMU.
Fixes: 8633ef82f101 ("drivers/firmware: consolidate EFI framebuffer setup for all arches")
Cc: stable@vger.kernel.org
Signed-off-by: Han Gao <gaohan@iscas.ac.cn>
---
In QEMU, efifb takes over with SYSFB_SIMPLEFB and efidrm without it.
With pci-host-generic built in, simpledrm is still used.
---
drivers/firmware/efi/sysfb_efi.c | 16 ++++++++++++++++
drivers/firmware/sysfb.c | 8 +++++++-
include/linux/sysfb.h | 6 ++++++
3 files changed, 29 insertions(+), 1 deletion(-)
diff --git a/drivers/firmware/efi/sysfb_efi.c b/drivers/firmware/efi/sysfb_efi.c
index 2338de73c62c..5c2cb87178ff 100644
--- a/drivers/firmware/efi/sysfb_efi.c
+++ b/drivers/firmware/efi/sysfb_efi.c
@@ -421,6 +421,22 @@ __init void sysfb_apply_efi_quirks(struct screen_info *si)
dmi_check_system(efifb_dmi_swap_width_height);
}
+/* Returns true if the EFI framebuffer is in a DT PCI host bridge window */
+__init bool sysfb_efifb_behind_dt_pci(const struct screen_info *si)
+{
+ struct device_node *np;
+
+ if (si->orig_video_isVGA != VIDEO_TYPE_EFI || !IS_ENABLED(CONFIG_PCI))
+ return false;
+
+ np = find_pci_overlap_node();
+ if (!np)
+ return false;
+
+ of_node_put(np);
+ return true;
+}
+
__init void sysfb_set_efifb_fwnode(const struct screen_info *si, struct platform_device *pd)
{
if (si->orig_video_isVGA == VIDEO_TYPE_EFI && IS_ENABLED(CONFIG_PCI)) {
diff --git a/drivers/firmware/sysfb.c b/drivers/firmware/sysfb.c
index 8833582c1883..8853a74560b9 100644
--- a/drivers/firmware/sysfb.c
+++ b/drivers/firmware/sysfb.c
@@ -164,8 +164,14 @@ static __init int sysfb_init(void)
goto unlock_mutex;
}
- /* try to create a simple-framebuffer device */
+ /*
+ * Try to create a simple-framebuffer device. It claims the memory
+ * when it is added, so a DT PCI host bridge that probes later would
+ * fail. Use an efi-framebuffer device there; it waits for the bridge.
+ */
compatible = sysfb_parse_mode(si, &mode);
+ if (compatible && !parent && sysfb_efifb_behind_dt_pci(si))
+ compatible = false;
if (compatible) {
pd = sysfb_create_simplefb(si, &mode, parent);
if (!IS_ERR(pd))
diff --git a/include/linux/sysfb.h b/include/linux/sysfb.h
index ed23d6516223..b136fdebc746 100644
--- a/include/linux/sysfb.h
+++ b/include/linux/sysfb.h
@@ -95,6 +95,7 @@ static inline bool sysfb_handles_screen_info(void)
extern struct efifb_dmi_info efifb_dmi_list[];
void sysfb_apply_efi_quirks(struct screen_info *si);
+bool sysfb_efifb_behind_dt_pci(const struct screen_info *si);
void sysfb_set_efifb_fwnode(const struct screen_info *si, struct platform_device *pd);
#else /* CONFIG_EFI */
@@ -103,6 +104,11 @@ static inline void sysfb_apply_efi_quirks(struct screen_info *si)
{
}
+static inline bool sysfb_efifb_behind_dt_pci(const struct screen_info *si)
+{
+ return false;
+}
+
static inline void sysfb_set_efifb_fwnode(const struct screen_info *si,
struct platform_device *pd)
{
---
base-commit: 6628e7d4c6b25c8d18f1345e3a20d21829aae7e4
change-id: 20261107-sysfb-dt-pci-efifb-d73b08ded4b2
Best regards,
--
Han Gao <gaohan@iscas.ac.cn>
^ permalink raw reply [flat|nested] 2+ messages in thread* Re: [PATCH] firmware/sysfb: Avoid simple-framebuffer behind DT PCI host bridges
2026-11-07 8:46 [PATCH] firmware/sysfb: Avoid simple-framebuffer behind DT PCI host bridges Han Gao via B4 Relay
@ 2026-11-07 17:37 ` Jennifer Berringer
0 siblings, 0 replies; 2+ messages in thread
From: Jennifer Berringer @ 2026-11-07 17:37 UTC (permalink / raw)
To: gaohan
Cc: Ard Biesheuvel, Ilias Apalodimas, Thomas Zimmermann,
Javier Martinez Canillas, Borislav Petkov, Simona Vetter,
linux-efi, linux-kernel, dri-devel, linux-riscv, Han Gao, stable,
Xincheng Ji, Jia Wang
Hi,
On Sat, Nov 07, 2026 at 04:46:40PM +0800, Han Gao via B4 Relay wrote:
> From: Han Gao <gaohan@iscas.ac.cn>
>
> With SYSFB_SIMPLEFB, sysfb registers a simple-framebuffer device that
> claims the framebuffer memory when it is added. On DT systems, the PCI
> host bridge may probe later and then fails to claim its memory window.
> On QEMU RISC-V virt with EDK2, a bochs-display and pci-host-generic
> built as a module:
>
> [ 0.703813] pci-host-generic 30000000.pci: resource collision: [mem 0x40000000-0x7fffffff] conflicts with BOOTFB [mem 0x40000000-0x403e7fff]
>
> In that case, register an efi-framebuffer device instead. It claims no
> memory before it probes, and commit 64c8a0cd0a53 ("efi/arm: Defer probe
> of PCIe backed efifb on DT systems") makes it wait for the host bridge.
>
> Tested on a HiFive Unmatched with EDK2 and a PCIe graphics card, and on
> QEMU.
>
> Fixes: 8633ef82f101 ("drivers/firmware: consolidate EFI framebuffer setup for all arches")
> Cc: stable@vger.kernel.org
> Signed-off-by: Han Gao <gaohan@iscas.ac.cn>
> ---
This issue also affects UltraRISC DP1000 boards such as Milk-V Titan.
For that system, a2d4a2d2479b ("clk: ultrarisc: Register DP1000 clock
provider earlier") was recently added to clk-next and can serve as a
workaround to make its pci driver be able to initialize before sysfb,
but only if both the clock and pci drivers are built in rather than
built as modules.
I confirmed that your patch resolves the issue on Milk-V Titan even when
building with CONFIG_PCIE_ULTRARISC=m, making a PCIe graphics card able
to initialize and function without issue. CC'd the ultrarisc developers.
Tested-by: Jennifer Berringer <jberring@redhat.com> # Milk-V Titan
> In QEMU, efifb takes over with SYSFB_SIMPLEFB and efidrm without it.
> With pci-host-generic built in, simpledrm is still used.
> ---
> drivers/firmware/efi/sysfb_efi.c | 16 ++++++++++++++++
> drivers/firmware/sysfb.c | 8 +++++++-
> include/linux/sysfb.h | 6 ++++++
> 3 files changed, 29 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/firmware/efi/sysfb_efi.c b/drivers/firmware/efi/sysfb_efi.c
> index 2338de73c62c..5c2cb87178ff 100644
> --- a/drivers/firmware/efi/sysfb_efi.c
> +++ b/drivers/firmware/efi/sysfb_efi.c
> @@ -421,6 +421,22 @@ __init void sysfb_apply_efi_quirks(struct screen_info *si)
> dmi_check_system(efifb_dmi_swap_width_height);
> }
>
> +/* Returns true if the EFI framebuffer is in a DT PCI host bridge window */
> +__init bool sysfb_efifb_behind_dt_pci(const struct screen_info *si)
> +{
> + struct device_node *np;
> +
> + if (si->orig_video_isVGA != VIDEO_TYPE_EFI || !IS_ENABLED(CONFIG_PCI))
> + return false;
> +
> + np = find_pci_overlap_node();
> + if (!np)
> + return false;
> +
> + of_node_put(np);
> + return true;
> +}
> +
> __init void sysfb_set_efifb_fwnode(const struct screen_info *si, struct platform_device *pd)
> {
> if (si->orig_video_isVGA == VIDEO_TYPE_EFI && IS_ENABLED(CONFIG_PCI)) {
> diff --git a/drivers/firmware/sysfb.c b/drivers/firmware/sysfb.c
> index 8833582c1883..8853a74560b9 100644
> --- a/drivers/firmware/sysfb.c
> +++ b/drivers/firmware/sysfb.c
> @@ -164,8 +164,14 @@ static __init int sysfb_init(void)
> goto unlock_mutex;
> }
>
> - /* try to create a simple-framebuffer device */
> + /*
> + * Try to create a simple-framebuffer device. It claims the memory
> + * when it is added, so a DT PCI host bridge that probes later would
> + * fail. Use an efi-framebuffer device there; it waits for the bridge.
> + */
> compatible = sysfb_parse_mode(si, &mode);
> + if (compatible && !parent && sysfb_efifb_behind_dt_pci(si))
> + compatible = false;
> if (compatible) {
> pd = sysfb_create_simplefb(si, &mode, parent);
> if (!IS_ERR(pd))
> diff --git a/include/linux/sysfb.h b/include/linux/sysfb.h
> index ed23d6516223..b136fdebc746 100644
> --- a/include/linux/sysfb.h
> +++ b/include/linux/sysfb.h
> @@ -95,6 +95,7 @@ static inline bool sysfb_handles_screen_info(void)
>
> extern struct efifb_dmi_info efifb_dmi_list[];
> void sysfb_apply_efi_quirks(struct screen_info *si);
> +bool sysfb_efifb_behind_dt_pci(const struct screen_info *si);
> void sysfb_set_efifb_fwnode(const struct screen_info *si, struct platform_device *pd);
>
> #else /* CONFIG_EFI */
> @@ -103,6 +104,11 @@ static inline void sysfb_apply_efi_quirks(struct screen_info *si)
> {
> }
>
> +static inline bool sysfb_efifb_behind_dt_pci(const struct screen_info *si)
> +{
> + return false;
> +}
> +
> static inline void sysfb_set_efifb_fwnode(const struct screen_info *si,
> struct platform_device *pd)
> {
>
> ---
> base-commit: 6628e7d4c6b25c8d18f1345e3a20d21829aae7e4
> change-id: 20261107-sysfb-dt-pci-efifb-d73b08ded4b2
>
> Best regards,
> --
> Han Gao <gaohan@iscas.ac.cn>
>
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-11-07 17:38 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-11-07 8:46 [PATCH] firmware/sysfb: Avoid simple-framebuffer behind DT PCI host bridges Han Gao via B4 Relay
2026-11-07 17:37 ` Jennifer Berringer
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®