From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 5E9F3D39401 for ; Thu, 2 Apr 2026 09:23:56 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:Cc:To:From: Reply-To:Content-Type:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=YPCEYbiGOCpx2zUalDos08LGZhiPvMU5VsFjS8QK76U=; b=fescEobeAdG8hYrB0V+1XGf2Qh nix+GtmZi0kXxsStcr1YIvLaCFN4QYSMVVUONDWYIMadDe93IabWpnST1jKoHxs1A86/t/L7gET+V O3SDgUuQ8JcwOpbb7LwGULlTsJghQ+bZFxP//g8YhGIjyKWvfd1zlR2nS5Bto7vjUPFFdXzB9lqTL iMWdFaGeKeY4yd5lsyHJccUon4DVxC20aRbEsBJm94g1XUgzlhnuYgjkbWROFlv7meNMXS9S5wk25 FrcykZZbDQ0aM14n1UsYi+oBJh2b9BB7qLuJP9Pu9ITYfOdPbyPZsjNwBC+QEuzLzQwEerIZfm1wV M5Q0t4MA==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.98.2 #2 (Red Hat Linux)) id 1w8EHF-0000000HFYw-2SlM; Thu, 02 Apr 2026 09:23:49 +0000 Received: from desiato.infradead.org ([2001:8b0:10b:1:d65d:64ff:fe57:4e05]) by bombadil.infradead.org with esmtps (Exim 4.98.2 #2 (Red Hat Linux)) id 1w8EHD-0000000HFVg-2oLM for linux-arm-kernel@bombadil.infradead.org; Thu, 02 Apr 2026 09:23:47 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=desiato.20200630; h=Content-Transfer-Encoding:MIME-Version :References:In-Reply-To:Message-ID:Date:Subject:Cc:To:From:Sender:Reply-To: Content-Type:Content-ID:Content-Description; bh=YPCEYbiGOCpx2zUalDos08LGZhiPvMU5VsFjS8QK76U=; b=Up9uPxTmgcja2D9pCSEWx67LJD u944tyr7vto1l5/OiGaIAp0JPX8ni4/0MYeo/eEmcP1GlRn/r9NKsKp3+RC8Dr9HQiYfMPrTtUyZa ToX5kfk/Xtlt4SQhhL/CDBd4/PSfgynFlYgTa21keqXFXICtaF41ZVAwyYPuXQk+zQ8eO/Siqt94e y17Z7nRPQvIR07QLS7Tpkk+lJ8ZPLjh/Yu7kqdkIv6Jjcfvr/d9Nm3tENS9CozNuhQ1bVkhZVIMzf vk4DV+IjpUqA8xJkr4lr0Ai1d8wiw8WHA1jRpuQwS4Is+cWyKbY5hN5aqE4gHxZTIYEe0EwY2WIyA uPoucXPQ==; Received: from smtp-out2.suse.de ([2a07:de40:b251:101:10:150:64:2]) by desiato.infradead.org with esmtps (Exim 4.98.2 #2 (Red Hat Linux)) id 1w8EH6-000000027eU-2HAs for linux-arm-kernel@lists.infradead.org; Thu, 02 Apr 2026 09:23:44 +0000 Received: from imap1.dmz-prg2.suse.org (unknown [10.150.64.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by smtp-out2.suse.de (Postfix) with ESMTPS id BCFC65BDAC; Thu, 2 Apr 2026 09:23:13 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_rsa; t=1775121793; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=YPCEYbiGOCpx2zUalDos08LGZhiPvMU5VsFjS8QK76U=; b=0js1rDWnH9smqDqLDvIAKHV8/eXXpqQLMMmO2TI8gDpO96XoYOJ31GNYVGDIhbudXFZi9G RQ/O7aJULE82Ey6TA6L6DSH8P2yEi8bpC87AmYkQUvPUMU9qrvfDUU3Q8uptTAtDg3jYPP Io9AeuySbfgnMZqPfHt6jtJYVMlHoo0= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_ed25519; t=1775121793; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=YPCEYbiGOCpx2zUalDos08LGZhiPvMU5VsFjS8QK76U=; b=Tyx81et7F7PdaU5+qsAtZ653DbZ7+SrFuesp7ACsEj//SHAzWobwR7Yrj7KdApo1hOLQaG JiNq8qBG9bZiwyDQ== Authentication-Results: smtp-out2.suse.de; none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_rsa; t=1775121793; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=YPCEYbiGOCpx2zUalDos08LGZhiPvMU5VsFjS8QK76U=; b=0js1rDWnH9smqDqLDvIAKHV8/eXXpqQLMMmO2TI8gDpO96XoYOJ31GNYVGDIhbudXFZi9G RQ/O7aJULE82Ey6TA6L6DSH8P2yEi8bpC87AmYkQUvPUMU9qrvfDUU3Q8uptTAtDg3jYPP Io9AeuySbfgnMZqPfHt6jtJYVMlHoo0= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_ed25519; t=1775121793; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=YPCEYbiGOCpx2zUalDos08LGZhiPvMU5VsFjS8QK76U=; b=Tyx81et7F7PdaU5+qsAtZ653DbZ7+SrFuesp7ACsEj//SHAzWobwR7Yrj7KdApo1hOLQaG JiNq8qBG9bZiwyDQ== Received: from imap1.dmz-prg2.suse.org (localhost [127.0.0.1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by imap1.dmz-prg2.suse.org (Postfix) with ESMTPS id 2C4C74A0B1; Thu, 2 Apr 2026 09:23:13 +0000 (UTC) Received: from dovecot-director2.suse.de ([2a07:de40:b281:106:10:150:64:167]) by imap1.dmz-prg2.suse.org with ESMTPSA id oLbDCIE1zmlVYAAAD6G6ig (envelope-from ); Thu, 02 Apr 2026 09:23:13 +0000 From: Thomas Zimmermann To: javierm@redhat.com, arnd@arndb.de, ardb@kernel.org, ilias.apalodimas@linaro.org, chenhuacai@kernel.org, kernel@xen0n.name, maarten.lankhorst@linux.intel.com, mripard@kernel.org, airlied@gmail.com, simona@ffwll.ch, kys@microsoft.com, haiyangz@microsoft.com, wei.liu@kernel.org, decui@microsoft.com, longli@microsoft.com, deller@gmx.de Cc: linux-arm-kernel@lists.infradead.org, loongarch@lists.linux.dev, linux-efi@vger.kernel.org, linux-riscv@lists.infradead.org, dri-devel@lists.freedesktop.org, linux-hyperv@vger.kernel.org, linux-fbdev@vger.kernel.org, Thomas Zimmermann Subject: [PATCH 5/8] firmware: sysfb: Implement screen_info relocation for primary display Date: Thu, 2 Apr 2026 11:09:19 +0200 Message-ID: <20260402092305.208728-6-tzimmermann@suse.de> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260402092305.208728-1-tzimmermann@suse.de> References: <20260402092305.208728-1-tzimmermann@suse.de> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spamd-Result: default: False [-6.80 / 50.00]; REPLY(-4.00)[]; BAYES_HAM(-3.00)[100.00%]; NEURAL_HAM_LONG(-1.00)[-1.000]; MID_CONTAINS_FROM(1.00)[]; R_MISSING_CHARSET(0.50)[]; NEURAL_HAM_SHORT(-0.20)[-0.995]; MIME_GOOD(-0.10)[text/plain]; ARC_NA(0.00)[]; RCVD_VIA_SMTP_AUTH(0.00)[]; DBL_BLOCKED_OPENRESOLVER(0.00)[suse.de:mid,suse.de:email]; RCPT_COUNT_TWELVE(0.00)[24]; MIME_TRACE(0.00)[0:+]; TO_DN_SOME(0.00)[]; FUZZY_RATELIMITED(0.00)[rspamd.com]; FROM_HAS_DN(0.00)[]; FREEMAIL_TO(0.00)[redhat.com,arndb.de,kernel.org,linaro.org,xen0n.name,linux.intel.com,gmail.com,ffwll.ch,microsoft.com,gmx.de]; RCVD_COUNT_TWO(0.00)[2]; TO_MATCH_ENVRCPT_ALL(0.00)[]; RCVD_TLS_ALL(0.00)[]; FROM_EQ_ENVFROM(0.00)[]; R_RATELIMIT(0.00)[to_ip_from(RLykjg6e7ifkwtw7jmpw7b9yio)]; DKIM_SIGNED(0.00)[suse.de:s=susede2_rsa,suse.de:s=susede2_ed25519]; FREEMAIL_ENVRCPT(0.00)[gmail.com,gmx.de] X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20260402_102342_695772_4914ACDA X-CRM114-Status: GOOD ( 28.49 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Move the relocation tracking for screen_info from the screen_info helpers to sysfb. The relocation code operates on sysfb_primary_display, which belongs to sysfb. The remaining screen_info helpers are now free from global state. Adapt some symbol names. Now prefer early returns in the helper sysfb_apply_screen_info_fixup() over nested branching. Also return an errno code from sysfb_apply_screen_info_fixup() if the relocation failed. In this case, do not create a device for the framebuffer. The original code advertised this behavior in a comment but never implemented it. Framebuffer aperture relocation can happen during boot if the PCI graphics device is located behind a PCI bridge. If the bridge's sub- bus gets relocated, the framebuffer aperture moves accordingly. The helper for tracking these relocations fixes up the values stored in sysfb_primary_display so that they refer to the correct address range again. Generic system-framebuffer drivers would not work otherwise. Signed-off-by: Thomas Zimmermann --- drivers/firmware/sysfb.h | 5 ++ drivers/firmware/sysfb_pci.c | 111 +++++++++++++++++++++++++++++++ drivers/firmware/sysfb_primary.c | 9 ++- drivers/video/screen_info_pci.c | 110 ------------------------------ include/linux/screen_info.h | 3 - 5 files changed, 123 insertions(+), 115 deletions(-) diff --git a/drivers/firmware/sysfb.h b/drivers/firmware/sysfb.h index 9f7fe2e03f68..1eaa3b0fa364 100644 --- a/drivers/firmware/sysfb.h +++ b/drivers/firmware/sysfb.h @@ -8,8 +8,13 @@ struct pci_dev; #ifdef CONFIG_PCI +int sysfb_apply_screen_info_fixups(void); bool sysfb_pci_dev_is_enabled(struct pci_dev *pdev); #else +static inline int sysfb_apply_screen_info_fixups(void) +{ + return 0; +} static inline bool sysfb_pci_dev_is_enabled(struct pci_dev *pdev) { return false; diff --git a/drivers/firmware/sysfb_pci.c b/drivers/firmware/sysfb_pci.c index 8f3adeef4fb1..d972750c6bc6 100644 --- a/drivers/firmware/sysfb_pci.c +++ b/drivers/firmware/sysfb_pci.c @@ -1,9 +1,120 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include +#include +#include +#include #include "sysfb.h" +static struct pci_dev *sysfb_lfb_pdev; +static size_t sysfb_lfb_bar; +static resource_size_t sysfb_lfb_res_start; // original start of resource +static resource_size_t sysfb_lfb_offset; // framebuffer offset within resource + +static bool __sysfb_relocation_is_valid(const struct screen_info *si, struct resource *pr) +{ + u64 size = __screen_info_lfb_size(si, screen_info_video_type(si)); + + if (sysfb_lfb_offset > resource_size(pr)) + return false; + if (size > resource_size(pr)) + return false; + if (resource_size(pr) - size < sysfb_lfb_offset) + return false; + + return true; +} + +int sysfb_apply_screen_info_fixups(void) +{ + struct screen_info *si = &sysfb_primary_display.screen; + struct resource *pr; + + if (!sysfb_lfb_pdev) + return 0; /* primary display is not on a PCI device */ + + pr = &sysfb_lfb_pdev->resource[sysfb_lfb_bar]; + + if (pr->start == sysfb_lfb_res_start) + return 0; /* no relocation took place */ + + if (!__sysfb_relocation_is_valid(si, pr)) + return -ENXIO; + + /* + * Only update base if we have an actual relocation to a valid I/O range. + */ + __screen_info_set_lfb_base(si, pr->start + sysfb_lfb_offset); + pr_info("Relocating firmware framebuffer to offset %pa[d] within %pr\n", + &sysfb_lfb_offset, pr); + + return 0; +} + +static int __screen_info_lfb_pci_bus_region(const struct screen_info *si, unsigned int type, + struct pci_bus_region *r) +{ + u64 base, size; + + base = __screen_info_lfb_base(si); + if (!base) + return -EINVAL; + + size = __screen_info_lfb_size(si, type); + if (!size) + return -EINVAL; + + r->start = base; + r->end = base + size - 1; + + return 0; +} + +static void sysfb_fixup_lfb(struct pci_dev *pdev) +{ + unsigned int type; + struct pci_bus_region bus_region; + int ret; + struct resource r = { + .flags = IORESOURCE_MEM, + }; + const struct resource *pr; + const struct screen_info *si = &sysfb_primary_display.screen; + + if (sysfb_lfb_pdev) + return; // already found + + type = screen_info_video_type(si); + if (!__screen_info_has_lfb(type)) + return; // only applies to EFI; maybe VESA + + ret = __screen_info_lfb_pci_bus_region(si, type, &bus_region); + if (ret < 0) + return; + + /* + * Translate the PCI bus address to resource. Account for an offset if + * the framebuffer is behind a PCI host bridge. + */ + pcibios_bus_to_resource(pdev->bus, &r, &bus_region); + + pr = pci_find_resource(pdev, &r); + if (!pr) + return; + + /* + * We've found a PCI device with the framebuffer resource. Store away + * the parameters to track relocation of the framebuffer aperture. + */ + sysfb_lfb_pdev = pdev; + sysfb_lfb_bar = pr - pdev->resource; + sysfb_lfb_offset = r.start - pr->start; + sysfb_lfb_res_start = bus_region.start; +} +DECLARE_PCI_FIXUP_CLASS_HEADER(PCI_ANY_ID, PCI_ANY_ID, PCI_BASE_CLASS_DISPLAY, 16, + sysfb_fixup_lfb); + bool sysfb_pci_dev_is_enabled(struct pci_dev *pdev) { /* diff --git a/drivers/firmware/sysfb_primary.c b/drivers/firmware/sysfb_primary.c index ab8d7fc468bb..298f87a43a7e 100644 --- a/drivers/firmware/sysfb_primary.c +++ b/drivers/firmware/sysfb_primary.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -127,11 +128,15 @@ static __init int sysfb_init(void) struct simplefb_platform_data mode; const char *name; bool compatible; - int ret = 0; + int ret; - screen_info_apply_fixups(); + ret = sysfb_apply_screen_info_fixups(); mutex_lock(&disable_lock); + if (ret) { + pr_warn("Invalid relocation, disabling system framebuffer\n"); + disabled = true; /* screen_info relocation failed */ + } if (disabled) goto unlock_mutex; diff --git a/drivers/video/screen_info_pci.c b/drivers/video/screen_info_pci.c index 8f34d8a74f09..d8985a54ce71 100644 --- a/drivers/video/screen_info_pci.c +++ b/drivers/video/screen_info_pci.c @@ -1,117 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 #include -#include #include -#include -#include - -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_relocation_is_valid(const struct screen_info *si, struct resource *pr) -{ - u64 size = __screen_info_lfb_size(si, screen_info_video_type(si)); - - if (screen_info_lfb_offset > resource_size(pr)) - return false; - if (size > resource_size(pr)) - return false; - if (resource_size(pr) - size < screen_info_lfb_offset) - return false; - - return true; -} - -void screen_info_apply_fixups(void) -{ - struct screen_info *si = &sysfb_primary_display.screen; - - if (screen_info_lfb_pdev) { - struct resource *pr = &screen_info_lfb_pdev->resource[screen_info_lfb_bar]; - - if (pr->start != screen_info_lfb_res_start) { - 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); - 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"); - } - } - } -} - -static int __screen_info_lfb_pci_bus_region(const struct screen_info *si, unsigned int type, - struct pci_bus_region *r) -{ - u64 base, size; - - base = __screen_info_lfb_base(si); - if (!base) - return -EINVAL; - - size = __screen_info_lfb_size(si, type); - if (!size) - return -EINVAL; - - r->start = base; - r->end = base + size - 1; - - return 0; -} - -static void screen_info_fixup_lfb(struct pci_dev *pdev) -{ - unsigned int type; - struct pci_bus_region bus_region; - int ret; - struct resource r = { - .flags = IORESOURCE_MEM, - }; - const struct resource *pr; - const struct screen_info *si = &sysfb_primary_display.screen; - - if (screen_info_lfb_pdev) - return; // already found - - type = screen_info_video_type(si); - if (!__screen_info_has_lfb(type)) - return; // only applies to EFI; maybe VESA - - ret = __screen_info_lfb_pci_bus_region(si, type, &bus_region); - if (ret < 0) - return; - - /* - * Translate the PCI bus address to resource. Account - * for an offset if the framebuffer is behind a PCI host - * bridge. - */ - pcibios_bus_to_resource(pdev->bus, &r, &bus_region); - - pr = pci_find_resource(pdev, &r); - if (!pr) - return; - - /* - * We've found a PCI device with the framebuffer - * resource. Store away the parameters to track - * relocation of the framebuffer aperture. - */ - screen_info_lfb_pdev = pdev; - screen_info_lfb_bar = pr - pdev->resource; - screen_info_lfb_offset = r.start - pr->start; - screen_info_lfb_res_start = bus_region.start; -} -DECLARE_PCI_FIXUP_CLASS_HEADER(PCI_ANY_ID, PCI_ANY_ID, PCI_BASE_CLASS_DISPLAY, 16, - screen_info_fixup_lfb); static struct pci_dev *__screen_info_pci_dev(struct resource *res) { diff --git a/include/linux/screen_info.h b/include/linux/screen_info.h index c022403c599a..2adbe25b88d8 100644 --- a/include/linux/screen_info.h +++ b/include/linux/screen_info.h @@ -140,11 +140,8 @@ u32 __screen_info_lfb_bits_per_pixel(const struct screen_info *si); int screen_info_pixel_format(const struct screen_info *si, struct pixel_format *f); #if defined(CONFIG_PCI) -void screen_info_apply_fixups(void); struct pci_dev *screen_info_pci_dev(const struct screen_info *si); #else -static inline void screen_info_apply_fixups(void) -{ } static inline struct pci_dev *screen_info_pci_dev(const struct screen_info *si) { return NULL; -- 2.53.0