dri-devel.lists.freedesktop.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/8] firmware/sysfb: Track parent device for screen_info
@ 2024-01-17 12:39 Thomas Zimmermann
  2024-01-17 12:39 ` [PATCH 1/8] video: Add helpers for decoding screen_info Thomas Zimmermann
                   ` (7 more replies)
  0 siblings, 8 replies; 22+ messages in thread
From: Thomas Zimmermann @ 2024-01-17 12:39 UTC (permalink / raw)
  To: javierm, pjones, deller, ardb; +Cc: linux-fbdev, Thomas Zimmermann, dri-devel

Detect the firmware framebuffer's parent device from the global
screen_info state and set up the framebuffer's device accordingly.
Remove the equivalent functionality from efifb. Other drivers for
firmware framebuffers, such as simpledrm or vesafb, now add these
new features.

Patches 1 and 2 provide a set of helper functions to avoid parsing
the screen_info values manually. Decoding screen_info is fragile and
many drivers get it wrong. We should later adopt these helpers in
existing drivers, such as efifb, vesafb, as well.

Patches 3 and 4 set the firmware framebuffer's parent device. There
is code in efifb to do something similar for power management. That
is now obsolete and being cleaned up. Setting the parent device makes
Linux track the power management correctly.

Patches 5 and 6 track the parent device's enable state. We don't
create framebuffer devices if the underlying hardware device has been
disabled. Remove the functionality from efifb.

Patches 7 and 8 track the parent device's PCI BAR location. It can
happen on aarch64 that the firmware framebuffer moves its location
during the kernel's boot. We now fix up the screen_info state to
point to the correct location. Again remove such functionality from
efifb.

Thomas Zimmermann (8):
  video: Add helpers for decoding screen_info
  video: Provide screen_info_get_pci_dev() to find screen_info's PCI
    device
  firmware/sysfb: Set firmware-framebuffer parent device
  fbdev/efifb: Remove PM for parent device
  firmware/sysfb: Create firmware device only for enabled PCI devices
  fbdev/efifb: Do not track parent device status
  firmware/sysfb: Update screen_info for relocated EFI framebuffers
  fbdev/efifb: Remove framebuffer relocation tracking

 drivers/firmware/Kconfig            |   1 +
 drivers/firmware/sysfb.c            |  37 ++++++-
 drivers/firmware/sysfb_simplefb.c   |   5 +-
 drivers/video/Kconfig               |   4 +
 drivers/video/Makefile              |   4 +
 drivers/video/fbdev/efifb.c         |  97 +-----------------
 drivers/video/screen_info_generic.c | 148 ++++++++++++++++++++++++++++
 drivers/video/screen_info_pci.c     | 142 ++++++++++++++++++++++++++
 include/linux/screen_info.h         | 126 +++++++++++++++++++++++
 include/linux/sysfb.h               |   3 +-
 10 files changed, 472 insertions(+), 95 deletions(-)
 create mode 100644 drivers/video/screen_info_generic.c
 create mode 100644 drivers/video/screen_info_pci.c

-- 
2.43.0


^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCH 1/8] video: Add helpers for decoding screen_info
  2024-01-17 12:39 [PATCH 0/8] firmware/sysfb: Track parent device for screen_info Thomas Zimmermann
@ 2024-01-17 12:39 ` Thomas Zimmermann
  2024-01-29 10:41   ` Javier Martinez Canillas
  2024-01-17 12:39 ` [PATCH 2/8] video: Provide screen_info_get_pci_dev() to find screen_info's PCI device Thomas Zimmermann
                   ` (6 subsequent siblings)
  7 siblings, 1 reply; 22+ messages in thread
From: Thomas Zimmermann @ 2024-01-17 12:39 UTC (permalink / raw)
  To: javierm, pjones, deller, ardb; +Cc: linux-fbdev, Thomas Zimmermann, dri-devel

The plain values as stored in struct screen_info need to be decoded
before being used. Add helpers that decode the type of video output
and the framebuffer I/O aperture.

Old or non-x86 systems may not set the type of video directly, but
only indicate the presence by storing 0x01 in orig_video_isVGA. The
decoding logic in screen_info_video_type() takes this into account.
It then follows similar code in vgacon's vgacon_startup() to detect
the video type from the given values.

A call to screen_info_resources() returns all known resources of the
given screen_info. The resources' values have been taken from existing
code in vgacon and vga16fb. These drivers can later be converted to
use the new interfaces.

Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
---
 drivers/firmware/Kconfig            |   1 +
 drivers/video/Kconfig               |   4 +
 drivers/video/Makefile              |   3 +
 drivers/video/screen_info_generic.c | 148 ++++++++++++++++++++++++++++
 include/linux/screen_info.h         | 100 +++++++++++++++++++
 5 files changed, 256 insertions(+)
 create mode 100644 drivers/video/screen_info_generic.c

diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
index 4a98a859d44d..deba323178cc 100644
--- a/drivers/firmware/Kconfig
+++ b/drivers/firmware/Kconfig
@@ -191,6 +191,7 @@ config MTK_ADSP_IPC
 config SYSFB
 	bool
 	select BOOT_VESA_SUPPORT
+	select SCREEN_INFO
 
 config SYSFB_SIMPLEFB
 	bool "Mark VGA/VBE/EFI FB as generic system framebuffer"
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index b694d7669d32..1eb755a94940 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -11,6 +11,10 @@ config APERTURE_HELPERS
 	  Support tracking and hand-over of aperture ownership. Required
 	  by graphics drivers for firmware-provided framebuffers.
 
+config SCREEN_INFO
+	bool
+	default n
+
 config STI_CORE
 	bool
 	depends on PARISC
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 6bbc03950899..b929b664d52c 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -1,12 +1,15 @@
 # SPDX-License-Identifier: GPL-2.0
 
 obj-$(CONFIG_APERTURE_HELPERS)    += aperture.o
+obj-$(CONFIG_SCREEN_INFO)         += screen_info.o
 obj-$(CONFIG_STI_CORE)            += sticore.o
 obj-$(CONFIG_VGASTATE)            += vgastate.o
 obj-$(CONFIG_VIDEO_CMDLINE)       += cmdline.o
 obj-$(CONFIG_VIDEO_NOMODESET)     += nomodeset.o
 obj-$(CONFIG_HDMI)                += hdmi.o
 
+screen_info-y			  := screen_info_generic.o
+
 obj-$(CONFIG_VT)		  += console/
 obj-$(CONFIG_FB_STI)		  += console/
 obj-$(CONFIG_LOGO)		  += logo/
diff --git a/drivers/video/screen_info_generic.c b/drivers/video/screen_info_generic.c
new file mode 100644
index 000000000000..4be26941b2d9
--- /dev/null
+++ b/drivers/video/screen_info_generic.c
@@ -0,0 +1,148 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <linux/export.h>
+#include <linux/ioport.h>
+#include <linux/screen_info.h>
+#include <linux/string.h>
+
+static void resource_init_named(struct resource *r,
+				resource_size_t start, resource_size_t size,
+				const char *name, unsigned int flags)
+{
+	memset(r, 0, sizeof(*r));
+
+	r->start = start;
+	r->end = start + size - 1;
+	r->name = name;
+	r->flags = flags;
+}
+
+static void resource_init_io_named(struct resource *r,
+				   resource_size_t start, resource_size_t size,
+				   const char *name)
+{
+	resource_init_named(r, start, size, name, IORESOURCE_IO);
+}
+
+static void resource_init_mem_named(struct resource *r,
+				   resource_size_t start, resource_size_t size,
+				   const char *name)
+{
+	resource_init_named(r, start, size, name, IORESOURCE_MEM);
+}
+
+static inline bool __screen_info_has_ega_gfx(unsigned int mode)
+{
+	switch (mode) {
+	case 0x0d:	/* 320x200-4 */
+	case 0x0e:	/* 640x200-4 */
+	case 0x0f:	/* 640x350-1 */
+	case 0x10:	/* 640x350-4 */
+		return true;
+	default:
+		return false;
+	}
+}
+
+static inline bool __screen_info_has_vga_gfx(unsigned int mode)
+{
+	switch (mode) {
+	case 0x10:	/* 640x480-1 */
+	case 0x12:	/* 640x480-4 */
+	case 0x13:	/* 320-200-8 */
+	case 0x6a:	/* 800x600-4 (VESA) */
+		return true;
+	default:
+		return __screen_info_has_ega_gfx(mode);
+	}
+}
+
+/**
+ * screen_info_resources() - Get resources from screen_info structure
+ * @si: the screen_info
+ * @r: pointer to an array of resource structures
+ * @num: number of elements in @r:
+ *
+ * Returns:
+ * The number of resources stored in @r on success, or a negative errno code otherwise.
+ *
+ * A call to screen_info_resources() returns the resources consumed by the
+ * screen_info's device or framebuffer. The result is stored in the caller-supplied
+ * array @r with up to @num elements. The function returns the number of
+ * initialized elements.
+ */
+int screen_info_resources(const struct screen_info *si, struct resource *r, size_t num)
+{
+	struct resource *pos = r;
+	unsigned int type = screen_info_video_type(si);
+	u64 base, size;
+
+	switch (type) {
+	case VIDEO_TYPE_MDA:
+		if (num > 0)
+			resource_init_io_named(pos++, 0x3b0, 12, "mda");
+		if (num > 1)
+			resource_init_io_named(pos++, 0x3bf, 0x01, "mda");
+		if (num > 2)
+			resource_init_mem_named(pos++, 0xb0000, 0x2000, "mda");
+		break;
+	case VIDEO_TYPE_CGA:
+		if (num > 0)
+			resource_init_io_named(pos++, 0x3d4, 0x02, "cga");
+		if (num > 1)
+			resource_init_mem_named(pos++, 0xb8000, 0x2000, "cga");
+		break;
+	case VIDEO_TYPE_EGAM:
+		if (num > 0)
+			resource_init_io_named(pos++, 0x3bf, 0x10, "ega");
+		if (num > 1)
+			resource_init_mem_named(pos++, 0xb0000, 0x8000, "ega");
+		break;
+	case VIDEO_TYPE_EGAC:
+		if (num > 0)
+			resource_init_io_named(pos++, 0x3c0, 0x20, "ega");
+		if (num > 1) {
+			if (__screen_info_has_ega_gfx(si->orig_video_mode))
+				resource_init_mem_named(pos++, 0xa0000, 0x10000, "ega");
+			else
+				resource_init_mem_named(pos++, 0xb8000, 0x8000, "ega");
+		}
+		break;
+	case VIDEO_TYPE_VGAC:
+		if (num > 0)
+			resource_init_io_named(pos++, 0x3c0, 0x20, "vga+");
+		if (num > 1) {
+			if (__screen_info_has_vga_gfx(si->orig_video_mode))
+				resource_init_mem_named(pos++, 0xa0000, 0x10000, "vga+");
+			else
+				resource_init_mem_named(pos++, 0xb8000, 0x8000, "vga+");
+		}
+		break;
+	case VIDEO_TYPE_VLFB:
+	case VIDEO_TYPE_EFI:
+		if (!__screen_info_has_lfb(type))
+			break;
+		base = __screen_info_lfb_base(si);
+		if (!base)
+			break;
+		size = __screen_info_lfb_size(si, type);
+		if (!size)
+			break;
+		if (num > 0)
+			resource_init_mem_named(pos++, base, size, "lfb");
+		break;
+	case VIDEO_TYPE_PICA_S3:
+	case VIDEO_TYPE_MIPS_G364:
+	case VIDEO_TYPE_SGI:
+	case VIDEO_TYPE_TGAC:
+	case VIDEO_TYPE_SUN:
+	case VIDEO_TYPE_SUNPCI:
+	case VIDEO_TYPE_PMAC:
+	default:
+		/* not supported */
+		return -EINVAL;
+	}
+
+	return pos - r;
+}
+EXPORT_SYMBOL(screen_info_resources);
diff --git a/include/linux/screen_info.h b/include/linux/screen_info.h
index eab7081392d5..d4d45395df19 100644
--- a/include/linux/screen_info.h
+++ b/include/linux/screen_info.h
@@ -4,6 +4,106 @@
 
 #include <uapi/linux/screen_info.h>
 
+/**
+ * SCREEN_INFO_MAX_RESOURCES - maximum number of resources per screen_info
+ */
+#define SCREEN_INFO_MAX_RESOURCES	3
+
+struct resource;
+
+static inline bool __screen_info_has_lfb(unsigned int type)
+{
+	return (type == VIDEO_TYPE_VLFB) || (type == VIDEO_TYPE_EFI);
+}
+
+static inline u64 __screen_info_lfb_base(const struct screen_info *si)
+{
+	u64 lfb_base = si->lfb_base;
+
+	if (si->capabilities & VIDEO_CAPABILITY_64BIT_BASE)
+		lfb_base |= (u64)si->ext_lfb_base << 32;
+
+	return lfb_base;
+}
+
+static inline u64 __screen_info_lfb_size(const struct screen_info *si, unsigned int type)
+{
+	u64 lfb_size = si->lfb_size;
+
+	if (type == VIDEO_TYPE_VLFB)
+		lfb_size <<= 16;
+	return lfb_size;
+}
+
+static inline unsigned int __screen_info_video_type(unsigned int type)
+{
+	switch (type) {
+	case VIDEO_TYPE_MDA:
+	case VIDEO_TYPE_CGA:
+	case VIDEO_TYPE_EGAM:
+	case VIDEO_TYPE_EGAC:
+	case VIDEO_TYPE_VGAC:
+	case VIDEO_TYPE_VLFB:
+	case VIDEO_TYPE_PICA_S3:
+	case VIDEO_TYPE_MIPS_G364:
+	case VIDEO_TYPE_SGI:
+	case VIDEO_TYPE_TGAC:
+	case VIDEO_TYPE_SUN:
+	case VIDEO_TYPE_SUNPCI:
+	case VIDEO_TYPE_PMAC:
+	case VIDEO_TYPE_EFI:
+		return type;
+	default:
+		return 0;
+	}
+}
+
+/**
+ * screen_info_video_type() - Decodes the video type from struct screen_info
+ * @si: an instance of struct screen_info
+ *
+ * Returns:
+ * A VIDEO_TYPE_ constant representing si's type of video display, or 0 otherwise.
+ */
+static inline unsigned int screen_info_video_type(const struct screen_info *si)
+{
+	unsigned int type;
+
+	// check if display output is on
+	if (!si->orig_video_isVGA)
+		return 0;
+
+	// check for a known VIDEO_TYPE_ constant
+	type = __screen_info_video_type(si->orig_video_isVGA);
+	if (type)
+		return si->orig_video_isVGA;
+
+	// check if text mode has been initialized
+	if (!si->orig_video_lines || !si->orig_video_cols)
+		return 0;
+
+	// 80x25 text, mono
+	if (si->orig_video_mode == 0x07) {
+		if ((si->orig_video_ega_bx & 0xff) != 0x10)
+			return VIDEO_TYPE_EGAM;
+		else
+			return VIDEO_TYPE_MDA;
+	}
+
+	// EGA/VGA, 16 colors
+	if ((si->orig_video_ega_bx & 0xff) != 0x10) {
+		if (si->orig_video_isVGA)
+			return VIDEO_TYPE_VGAC;
+		else
+			return VIDEO_TYPE_EGAC;
+	}
+
+	// the rest...
+	return VIDEO_TYPE_CGA;
+}
+
+int screen_info_resources(const struct screen_info *si, struct resource *r, size_t num);
+
 extern struct screen_info screen_info;
 
 #endif /* _SCREEN_INFO_H */
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 2/8] video: Provide screen_info_get_pci_dev() to find screen_info's PCI device
  2024-01-17 12:39 [PATCH 0/8] firmware/sysfb: Track parent device for screen_info Thomas Zimmermann
  2024-01-17 12:39 ` [PATCH 1/8] video: Add helpers for decoding screen_info Thomas Zimmermann
@ 2024-01-17 12:39 ` Thomas Zimmermann
  2024-01-29 11:04   ` Javier Martinez Canillas
  2024-01-17 12:39 ` [PATCH 3/8] firmware/sysfb: Set firmware-framebuffer parent device Thomas Zimmermann
                   ` (5 subsequent siblings)
  7 siblings, 1 reply; 22+ messages in thread
From: Thomas Zimmermann @ 2024-01-17 12:39 UTC (permalink / raw)
  To: javierm, pjones, deller, ardb; +Cc: linux-fbdev, Thomas Zimmermann, dri-devel

Add screen_info_get_pci_dev() to find the PCI device of an instance
of screen_info. Does nothing on systems without PCI bus.

Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
---
 drivers/video/Makefile          |  1 +
 drivers/video/screen_info_pci.c | 54 +++++++++++++++++++++++++++++++++
 include/linux/screen_info.h     | 10 ++++++
 3 files changed, 65 insertions(+)
 create mode 100644 drivers/video/screen_info_pci.c

diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index b929b664d52c..6bbf87c1b579 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -9,6 +9,7 @@ obj-$(CONFIG_VIDEO_NOMODESET)     += nomodeset.o
 obj-$(CONFIG_HDMI)                += hdmi.o
 
 screen_info-y			  := screen_info_generic.o
+screen_info-$(CONFIG_PCI)         += screen_info_pci.o
 
 obj-$(CONFIG_VT)		  += console/
 obj-$(CONFIG_FB_STI)		  += console/
diff --git a/drivers/video/screen_info_pci.c b/drivers/video/screen_info_pci.c
new file mode 100644
index 000000000000..16fe4afa3377
--- /dev/null
+++ b/drivers/video/screen_info_pci.c
@@ -0,0 +1,54 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <linux/pci.h>
+#include <linux/screen_info.h>
+
+static struct pci_dev *__screen_info_pci_dev(struct resource *res)
+{
+	struct pci_dev *pdev;
+
+	if (!(res->flags & IORESOURCE_MEM))
+		return NULL;
+
+	for_each_pci_dev(pdev) {
+		const struct resource *r;
+
+		if ((pdev->class >> 16) != PCI_BASE_CLASS_DISPLAY)
+			continue;
+
+		r = pci_find_resource(pdev, res);
+		if (r)
+			return pdev;
+	}
+
+	return NULL;
+}
+
+/**
+ * screen_info_pci_dev() - Return PCI parent device that contains screen_info's framebuffer
+ * @si: the screen_info
+ *
+ * Returns:
+ * The screen_info's parent device on success, or NULL otherwise.
+ */
+struct pci_dev *screen_info_pci_dev(const struct screen_info *si)
+{
+	struct resource res[SCREEN_INFO_MAX_RESOURCES];
+	size_t i, numres;
+	int ret;
+
+	ret = screen_info_resources(si, res, ARRAY_SIZE(res));
+	if (ret < 0)
+		return ERR_PTR(ret);
+	numres = ret;
+
+	for (i = 0; i < numres; ++i) {
+		struct pci_dev *pdev = __screen_info_pci_dev(&res[i]);
+
+		if (pdev)
+			return pdev;
+	}
+
+	return NULL;
+}
+EXPORT_SYMBOL(screen_info_pci_dev);
diff --git a/include/linux/screen_info.h b/include/linux/screen_info.h
index d4d45395df19..746645b8ee83 100644
--- a/include/linux/screen_info.h
+++ b/include/linux/screen_info.h
@@ -9,6 +9,7 @@
  */
 #define SCREEN_INFO_MAX_RESOURCES	3
 
+struct pci_dev;
 struct resource;
 
 static inline bool __screen_info_has_lfb(unsigned int type)
@@ -104,6 +105,15 @@ static inline unsigned int screen_info_video_type(const struct screen_info *si)
 
 int screen_info_resources(const struct screen_info *si, struct resource *r, size_t num);
 
+#if defined(CONFIG_PCI)
+struct pci_dev *screen_info_pci_dev(const struct screen_info *si);
+#else
+static inline struct pci_dev *screen_info_pci_dev(const struct screen_info *si)
+{
+	return NULL;
+}
+#endif
+
 extern struct screen_info screen_info;
 
 #endif /* _SCREEN_INFO_H */
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 3/8] firmware/sysfb: Set firmware-framebuffer parent device
  2024-01-17 12:39 [PATCH 0/8] firmware/sysfb: Track parent device for screen_info Thomas Zimmermann
  2024-01-17 12:39 ` [PATCH 1/8] video: Add helpers for decoding screen_info Thomas Zimmermann
  2024-01-17 12:39 ` [PATCH 2/8] video: Provide screen_info_get_pci_dev() to find screen_info's PCI device Thomas Zimmermann
@ 2024-01-17 12:39 ` Thomas Zimmermann
  2024-01-29 11:28   ` Javier Martinez Canillas
  2024-01-17 12:39 ` [PATCH 4/8] fbdev/efifb: Remove PM for " Thomas Zimmermann
                   ` (4 subsequent siblings)
  7 siblings, 1 reply; 22+ messages in thread
From: Thomas Zimmermann @ 2024-01-17 12:39 UTC (permalink / raw)
  To: javierm, pjones, deller, ardb; +Cc: linux-fbdev, Thomas Zimmermann, dri-devel

Set the firmware framebuffer's parent device, which usually is the
graphics hardware's physical device. Integrates the framebuffer in
the Linux device hierarchy and lets Linux handle dependencies among
devices. For example, the graphics hardware won't be suspended while
the firmware device is still active.

Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
---
 drivers/firmware/sysfb.c          | 11 ++++++++++-
 drivers/firmware/sysfb_simplefb.c |  5 ++++-
 include/linux/sysfb.h             |  3 ++-
 3 files changed, 16 insertions(+), 3 deletions(-)

diff --git a/drivers/firmware/sysfb.c b/drivers/firmware/sysfb.c
index 19706bd2642a..8a42da3f67a9 100644
--- a/drivers/firmware/sysfb.c
+++ b/drivers/firmware/sysfb.c
@@ -29,6 +29,7 @@
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
+#include <linux/pci.h>
 #include <linux/platform_data/simplefb.h>
 #include <linux/platform_device.h>
 #include <linux/screen_info.h>
@@ -72,6 +73,8 @@ EXPORT_SYMBOL_GPL(sysfb_disable);
 static __init int sysfb_init(void)
 {
 	const struct screen_info *si = &screen_info;
+	struct device *parent = NULL;
+	struct pci_dev *pparent;
 	struct simplefb_platform_data mode;
 	const char *name;
 	bool compatible;
@@ -83,10 +86,14 @@ static __init int sysfb_init(void)
 
 	sysfb_apply_efi_quirks();
 
+	pparent = screen_info_pci_dev(si);
+	if (pparent)
+		parent = &pparent->dev;
+
 	/* try to create a simple-framebuffer device */
 	compatible = sysfb_parse_mode(si, &mode);
 	if (compatible) {
-		pd = sysfb_create_simplefb(si, &mode);
+		pd = sysfb_create_simplefb(si, &mode, parent);
 		if (!IS_ERR(pd))
 			goto unlock_mutex;
 	}
@@ -109,6 +116,8 @@ static __init int sysfb_init(void)
 		goto unlock_mutex;
 	}
 
+	pd->dev.parent = parent;
+
 	sysfb_set_efifb_fwnode(pd);
 
 	ret = platform_device_add_data(pd, si, sizeof(*si));
diff --git a/drivers/firmware/sysfb_simplefb.c b/drivers/firmware/sysfb_simplefb.c
index 74363ed7501f..75a186bf8f8e 100644
--- a/drivers/firmware/sysfb_simplefb.c
+++ b/drivers/firmware/sysfb_simplefb.c
@@ -91,7 +91,8 @@ __init bool sysfb_parse_mode(const struct screen_info *si,
 }
 
 __init struct platform_device *sysfb_create_simplefb(const struct screen_info *si,
-						     const struct simplefb_platform_data *mode)
+						     const struct simplefb_platform_data *mode,
+						     struct device *parent)
 {
 	struct platform_device *pd;
 	struct resource res;
@@ -143,6 +144,8 @@ __init struct platform_device *sysfb_create_simplefb(const struct screen_info *s
 	if (!pd)
 		return ERR_PTR(-ENOMEM);
 
+	pd->dev.parent = parent;
+
 	sysfb_set_efifb_fwnode(pd);
 
 	ret = platform_device_add_resources(pd, &res, 1);
diff --git a/include/linux/sysfb.h b/include/linux/sysfb.h
index 19cb803dd5ec..6ee3ade3f8b0 100644
--- a/include/linux/sysfb.h
+++ b/include/linux/sysfb.h
@@ -91,7 +91,8 @@ static inline void sysfb_set_efifb_fwnode(struct platform_device *pd)
 bool sysfb_parse_mode(const struct screen_info *si,
 		      struct simplefb_platform_data *mode);
 struct platform_device *sysfb_create_simplefb(const struct screen_info *si,
-					      const struct simplefb_platform_data *mode);
+					      const struct simplefb_platform_data *mode,
+					      struct device *parent);
 
 #else /* CONFIG_SYSFB_SIMPLE */
 
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 4/8] fbdev/efifb: Remove PM for parent device
  2024-01-17 12:39 [PATCH 0/8] firmware/sysfb: Track parent device for screen_info Thomas Zimmermann
                   ` (2 preceding siblings ...)
  2024-01-17 12:39 ` [PATCH 3/8] firmware/sysfb: Set firmware-framebuffer parent device Thomas Zimmermann
@ 2024-01-17 12:39 ` Thomas Zimmermann
  2024-01-29 11:30   ` Javier Martinez Canillas
  2024-01-17 12:39 ` [PATCH 5/8] firmware/sysfb: Create firmware device only for enabled PCI devices Thomas Zimmermann
                   ` (3 subsequent siblings)
  7 siblings, 1 reply; 22+ messages in thread
From: Thomas Zimmermann @ 2024-01-17 12:39 UTC (permalink / raw)
  To: javierm, pjones, deller, ardb; +Cc: linux-fbdev, Thomas Zimmermann, dri-devel

The EFI device has the correct parent device set. This allows Linux
to handle the power management internally. Hence, remove the manual
PM management for the parent device from efifb.

Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
---
 drivers/video/fbdev/efifb.c | 16 +++-------------
 1 file changed, 3 insertions(+), 13 deletions(-)

diff --git a/drivers/video/fbdev/efifb.c b/drivers/video/fbdev/efifb.c
index 10fc14ad5d12..e66ef35fa6b6 100644
--- a/drivers/video/fbdev/efifb.c
+++ b/drivers/video/fbdev/efifb.c
@@ -17,7 +17,6 @@
 #include <linux/platform_device.h>
 #include <linux/printk.h>
 #include <linux/screen_info.h>
-#include <linux/pm_runtime.h>
 #include <video/vga.h>
 #include <asm/efi.h>
 #include <drm/drm_utils.h> /* For drm_get_panel_orientation_quirk */
@@ -258,9 +257,6 @@ static void efifb_destroy(struct fb_info *info)
 {
 	struct efifb_par *par = info->par;
 
-	if (efifb_pci_dev)
-		pm_runtime_put(&efifb_pci_dev->dev);
-
 	if (info->screen_base) {
 		if (mem_flags & (EFI_MEMORY_UC | EFI_MEMORY_WC))
 			iounmap(info->screen_base);
@@ -598,26 +594,20 @@ static int efifb_probe(struct platform_device *dev)
 		goto err_groups;
 	}
 
-	if (efifb_pci_dev)
-		WARN_ON(pm_runtime_get_sync(&efifb_pci_dev->dev) < 0);
-
 	err = devm_aperture_acquire_for_platform_device(dev, par->base, par->size);
 	if (err) {
 		pr_err("efifb: cannot acquire aperture\n");
-		goto err_put_rpm_ref;
+		goto err_fb_dealloc_cmap;
 	}
 	err = register_framebuffer(info);
 	if (err < 0) {
 		pr_err("efifb: cannot register framebuffer\n");
-		goto err_put_rpm_ref;
+		goto err_fb_dealloc_cmap;
 	}
 	fb_info(info, "%s frame buffer device\n", info->fix.id);
 	return 0;
 
-err_put_rpm_ref:
-	if (efifb_pci_dev)
-		pm_runtime_put(&efifb_pci_dev->dev);
-
+err_fb_dealloc_cmap:
 	fb_dealloc_cmap(&info->cmap);
 err_groups:
 	sysfs_remove_groups(&dev->dev.kobj, efifb_groups);
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 5/8] firmware/sysfb: Create firmware device only for enabled PCI devices
  2024-01-17 12:39 [PATCH 0/8] firmware/sysfb: Track parent device for screen_info Thomas Zimmermann
                   ` (3 preceding siblings ...)
  2024-01-17 12:39 ` [PATCH 4/8] fbdev/efifb: Remove PM for " Thomas Zimmermann
@ 2024-01-17 12:39 ` Thomas Zimmermann
  2024-01-29 11:36   ` Javier Martinez Canillas
  2024-01-17 12:39 ` [PATCH 6/8] fbdev/efifb: Do not track parent device status Thomas Zimmermann
                   ` (2 subsequent siblings)
  7 siblings, 1 reply; 22+ messages in thread
From: Thomas Zimmermann @ 2024-01-17 12:39 UTC (permalink / raw)
  To: javierm, pjones, deller, ardb; +Cc: linux-fbdev, Thomas Zimmermann, dri-devel

Test if the firmware framebuffer's parent PCI device, if any, has
been enabled. If not, the firmware framebuffer is most likely not
working. Hence, do not create a device for the firmware framebuffer
on disabled PCI devices.

So far, efifb tracked the status of the PCI parent device internally
and did not bind if it was disabled. This patch implements the
functionality for all firmware framebuffers.

Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
---
 drivers/firmware/sysfb.c | 26 +++++++++++++++++++++++++-
 1 file changed, 25 insertions(+), 1 deletion(-)

diff --git a/drivers/firmware/sysfb.c b/drivers/firmware/sysfb.c
index 8a42da3f67a9..48a550bd1a93 100644
--- a/drivers/firmware/sysfb.c
+++ b/drivers/firmware/sysfb.c
@@ -70,6 +70,27 @@ void sysfb_disable(void)
 }
 EXPORT_SYMBOL_GPL(sysfb_disable);
 
+static __init bool sysfb_pci_dev_is_enabled(struct pci_dev *pdev)
+{
+#if defined(CONFIG_PCI)
+	/*
+	 * TODO: Try to integrate this code into the PCI subsystem
+	 */
+	int ret;
+	u16 command;
+
+	ret = pci_read_config_word(pdev, PCI_COMMAND, &command);
+	if (ret != PCIBIOS_SUCCESSFUL)
+		return false;
+	if (!(command & PCI_COMMAND_MEMORY))
+		return false;
+	return true;
+#else
+	// Getting here without PCI support is probably a bug.
+	return false;
+#endif
+}
+
 static __init int sysfb_init(void)
 {
 	const struct screen_info *si = &screen_info;
@@ -87,8 +108,11 @@ static __init int sysfb_init(void)
 	sysfb_apply_efi_quirks();
 
 	pparent = screen_info_pci_dev(si);
-	if (pparent)
+	if (pparent) {
+		if (!sysfb_pci_dev_is_enabled(pparent))
+			goto unlock_mutex;
 		parent = &pparent->dev;
+	}
 
 	/* try to create a simple-framebuffer device */
 	compatible = sysfb_parse_mode(si, &mode);
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 6/8] fbdev/efifb: Do not track parent device status
  2024-01-17 12:39 [PATCH 0/8] firmware/sysfb: Track parent device for screen_info Thomas Zimmermann
                   ` (4 preceding siblings ...)
  2024-01-17 12:39 ` [PATCH 5/8] firmware/sysfb: Create firmware device only for enabled PCI devices Thomas Zimmermann
@ 2024-01-17 12:39 ` Thomas Zimmermann
  2024-01-29 11:38   ` Javier Martinez Canillas
  2024-01-17 12:39 ` [PATCH 7/8] firmware/sysfb: Update screen_info for relocated EFI framebuffers Thomas Zimmermann
  2024-01-17 12:39 ` [PATCH 8/8] fbdev/efifb: Remove framebuffer relocation tracking Thomas Zimmermann
  7 siblings, 1 reply; 22+ messages in thread
From: Thomas Zimmermann @ 2024-01-17 12:39 UTC (permalink / raw)
  To: javierm, pjones, deller, ardb; +Cc: linux-fbdev, Thomas Zimmermann, dri-devel

There will be no EFI framebuffer device for disabled parent devices
and thus we never probe efifb in that case. Hence remove the tracking
code from efifb.

Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
---
 drivers/video/fbdev/efifb.c | 5 +----
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/drivers/video/fbdev/efifb.c b/drivers/video/fbdev/efifb.c
index e66ef35fa6b6..f76b7ae00751 100644
--- a/drivers/video/fbdev/efifb.c
+++ b/drivers/video/fbdev/efifb.c
@@ -348,8 +348,6 @@ static struct attribute *efifb_attrs[] = {
 };
 ATTRIBUTE_GROUPS(efifb);
 
-static bool pci_dev_disabled;	/* FB base matches BAR of a disabled device */
-
 static struct resource *bar_resource;
 static u64 bar_offset;
 
@@ -377,7 +375,7 @@ static int efifb_probe(struct platform_device *dev)
 	if (!si)
 		return -ENOMEM;
 
-	if (si->orig_video_isVGA != VIDEO_TYPE_EFI || pci_dev_disabled)
+	if (si->orig_video_isVGA != VIDEO_TYPE_EFI)
 		return -ENODEV;
 
 	if (fb_get_options("efifb", &option))
@@ -653,7 +651,6 @@ static void record_efifb_bar_resource(struct pci_dev *dev, int idx, u64 offset)
 
 	pci_read_config_word(dev, PCI_COMMAND, &word);
 	if (!(word & PCI_COMMAND_MEMORY)) {
-		pci_dev_disabled = true;
 		dev_err(&dev->dev,
 			"BAR %d: assigned to efifb but device is disabled!\n",
 			idx);
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 7/8] firmware/sysfb: Update screen_info for relocated EFI framebuffers
  2024-01-17 12:39 [PATCH 0/8] firmware/sysfb: Track parent device for screen_info Thomas Zimmermann
                   ` (5 preceding siblings ...)
  2024-01-17 12:39 ` [PATCH 6/8] fbdev/efifb: Do not track parent device status Thomas Zimmermann
@ 2024-01-17 12:39 ` Thomas Zimmermann
  2024-01-29 11:52   ` Javier Martinez Canillas
  2024-01-17 12:39 ` [PATCH 8/8] fbdev/efifb: Remove framebuffer relocation tracking Thomas Zimmermann
  7 siblings, 1 reply; 22+ messages in thread
From: Thomas Zimmermann @ 2024-01-17 12:39 UTC (permalink / raw)
  To: javierm, pjones, deller, ardb; +Cc: linux-fbdev, Thomas Zimmermann, dri-devel

On ARM PCI systems, the PCI hierarchy might be reconfigured during
boot and the firmware framebuffer might move as a result of that.
The values in screen_info will then be invalid.

Work around this problem by tracking the framebuffer's initial
location before it get relocated; then fix the screen_info state
between reloaction and creating the firmware framebuffer's device.

This functionality has been lifted from efifb. See the commit message
of commit 55d728a40d36 ("efi/fb: Avoid reconfiguration of BAR that
covers the framebuffer") for more information.

Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
---
 drivers/firmware/sysfb.c        |  2 +
 drivers/video/screen_info_pci.c | 88 +++++++++++++++++++++++++++++++++
 include/linux/screen_info.h     | 16 ++++++
 3 files changed, 106 insertions(+)

diff --git a/drivers/firmware/sysfb.c b/drivers/firmware/sysfb.c
index 48a550bd1a93..5791f9dc47df 100644
--- a/drivers/firmware/sysfb.c
+++ b/drivers/firmware/sysfb.c
@@ -101,6 +101,8 @@ static __init int sysfb_init(void)
 	bool compatible;
 	int ret = 0;
 
+	screen_info_apply_fixups();
+
 	mutex_lock(&disable_lock);
 	if (disabled)
 		goto unlock_mutex;
diff --git a/drivers/video/screen_info_pci.c b/drivers/video/screen_info_pci.c
index 16fe4afa3377..a546681b2d15 100644
--- a/drivers/video/screen_info_pci.c
+++ b/drivers/video/screen_info_pci.c
@@ -1,7 +1,95 @@
 // SPDX-License-Identifier: GPL-2.0
 
 #include <linux/pci.h>
+#include <linux/printk.h>
 #include <linux/screen_info.h>
+#include <linux/string.h>
+
+static struct pci_dev *screen_info_lfb_pdev;
+static size_t screen_info_lfb_bar;
+static resource_size_t screen_info_lfb_offset;
+static struct resource screen_info_lfb_res = DEFINE_RES_MEM(0, 0);
+
+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 = &screen_info;
+
+	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 void screen_info_fixup_lfb(struct pci_dev *pdev)
+{
+	unsigned int type;
+	struct resource res[SCREEN_INFO_MAX_RESOURCES];
+	size_t i, numres;
+	int ret;
+	const struct screen_info *si = &screen_info;
+
+	if (screen_info_lfb_pdev)
+		return; // already found
+
+	type = screen_info_video_type(si);
+	if (type != VIDEO_TYPE_EFI)
+		return; // only applies to EFI
+
+	ret = screen_info_resources(si, res, ARRAY_SIZE(res));
+	if (ret < 0)
+		return;
+	numres = ret;
+
+	for (i = 0; i < numres; ++i) {
+		struct resource *r = &res[i];
+		const struct resource *pr;
+
+		if (!(r->flags & IORESOURCE_MEM))
+			continue;
+		pr = pci_find_resource(pdev, r);
+		if (!pr)
+			continue;
+
+		/*
+		 * 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;
+		memcpy(&screen_info_lfb_res, r, sizeof(screen_info_lfb_res));
+	}
+}
+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 746645b8ee83..80b348137492 100644
--- a/include/linux/screen_info.h
+++ b/include/linux/screen_info.h
@@ -4,6 +4,8 @@
 
 #include <uapi/linux/screen_info.h>
 
+#include <linux/bits.h>
+
 /**
  * SCREEN_INFO_MAX_RESOURCES - maximum number of resources per screen_info
  */
@@ -27,6 +29,17 @@ static inline u64 __screen_info_lfb_base(const struct screen_info *si)
 	return lfb_base;
 }
 
+static inline void __screen_info_set_lfb_base(struct screen_info *si, u64 lfb_base)
+{
+	si->lfb_base = lfb_base & GENMASK_ULL(31, 0);
+	si->ext_lfb_base = (lfb_base & GENMASK_ULL(63, 32)) >> 32;
+
+	if (si->ext_lfb_base)
+		si->capabilities |= VIDEO_CAPABILITY_64BIT_BASE;
+	else
+		si->capabilities &= ~VIDEO_CAPABILITY_64BIT_BASE;
+}
+
 static inline u64 __screen_info_lfb_size(const struct screen_info *si, unsigned int type)
 {
 	u64 lfb_size = si->lfb_size;
@@ -106,8 +119,11 @@ static inline unsigned int screen_info_video_type(const struct screen_info *si)
 int screen_info_resources(const struct screen_info *si, struct resource *r, size_t num);
 
 #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.43.0


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 8/8] fbdev/efifb: Remove framebuffer relocation tracking
  2024-01-17 12:39 [PATCH 0/8] firmware/sysfb: Track parent device for screen_info Thomas Zimmermann
                   ` (6 preceding siblings ...)
  2024-01-17 12:39 ` [PATCH 7/8] firmware/sysfb: Update screen_info for relocated EFI framebuffers Thomas Zimmermann
@ 2024-01-17 12:39 ` Thomas Zimmermann
  2024-01-29 12:03   ` Javier Martinez Canillas
  7 siblings, 1 reply; 22+ messages in thread
From: Thomas Zimmermann @ 2024-01-17 12:39 UTC (permalink / raw)
  To: javierm, pjones, deller, ardb; +Cc: linux-fbdev, Thomas Zimmermann, dri-devel

If the firmware framebuffer has been reloacted, the sysfb code
fixes the screen_info state before it creates the framebuffer's
platform device. Efifb will automatically receive a screen_info
with updated values. Hence remove the tracking from efifb.

Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
---
 drivers/video/fbdev/efifb.c | 76 +------------------------------------
 1 file changed, 1 insertion(+), 75 deletions(-)

diff --git a/drivers/video/fbdev/efifb.c b/drivers/video/fbdev/efifb.c
index f76b7ae00751..8dd82afb3452 100644
--- a/drivers/video/fbdev/efifb.c
+++ b/drivers/video/fbdev/efifb.c
@@ -13,7 +13,6 @@
 #include <linux/efi-bgrt.h>
 #include <linux/errno.h>
 #include <linux/fb.h>
-#include <linux/pci.h>
 #include <linux/platform_device.h>
 #include <linux/printk.h>
 #include <linux/screen_info.h>
@@ -47,8 +46,6 @@ static bool use_bgrt = true;
 static bool request_mem_succeeded = false;
 static u64 mem_flags = EFI_MEMORY_WC | EFI_MEMORY_UC;
 
-static struct pci_dev *efifb_pci_dev;	/* dev with BAR covering the efifb */
-
 struct efifb_par {
 	u32 pseudo_palette[16];
 	resource_size_t base;
@@ -348,9 +345,6 @@ static struct attribute *efifb_attrs[] = {
 };
 ATTRIBUTE_GROUPS(efifb);
 
-static struct resource *bar_resource;
-static u64 bar_offset;
-
 static int efifb_probe(struct platform_device *dev)
 {
 	struct screen_info *si;
@@ -411,21 +405,7 @@ static int efifb_probe(struct platform_device *dev)
 		si->rsvd_pos = 24;
 	}
 
-	efifb_fix.smem_start = si->lfb_base;
-
-	if (si->capabilities & VIDEO_CAPABILITY_64BIT_BASE) {
-		u64 ext_lfb_base;
-
-		ext_lfb_base = (u64)(unsigned long)si->ext_lfb_base << 32;
-		efifb_fix.smem_start |= ext_lfb_base;
-	}
-
-	if (bar_resource &&
-	    bar_resource->start + bar_offset != efifb_fix.smem_start) {
-		dev_info(&efifb_pci_dev->dev,
-			 "BAR has moved, updating efifb address\n");
-		efifb_fix.smem_start = bar_resource->start + bar_offset;
-	}
+	efifb_fix.smem_start = __screen_info_lfb_base(si);
 
 	efifb_defined.bits_per_pixel = si->lfb_depth;
 	efifb_defined.xres = si->lfb_width;
@@ -640,57 +620,3 @@ static struct platform_driver efifb_driver = {
 };
 
 builtin_platform_driver(efifb_driver);
-
-#if defined(CONFIG_PCI)
-
-static void record_efifb_bar_resource(struct pci_dev *dev, int idx, u64 offset)
-{
-	u16 word;
-
-	efifb_pci_dev = dev;
-
-	pci_read_config_word(dev, PCI_COMMAND, &word);
-	if (!(word & PCI_COMMAND_MEMORY)) {
-		dev_err(&dev->dev,
-			"BAR %d: assigned to efifb but device is disabled!\n",
-			idx);
-		return;
-	}
-
-	bar_resource = &dev->resource[idx];
-	bar_offset = offset;
-
-	dev_info(&dev->dev, "BAR %d: assigned to efifb\n", idx);
-}
-
-static void efifb_fixup_resources(struct pci_dev *dev)
-{
-	u64 base = screen_info.lfb_base;
-	u64 size = screen_info.lfb_size;
-	int i;
-
-	if (efifb_pci_dev || screen_info.orig_video_isVGA != VIDEO_TYPE_EFI)
-		return;
-
-	if (screen_info.capabilities & VIDEO_CAPABILITY_64BIT_BASE)
-		base |= (u64)screen_info.ext_lfb_base << 32;
-
-	if (!base)
-		return;
-
-	for (i = 0; i < PCI_STD_NUM_BARS; i++) {
-		struct resource *res = &dev->resource[i];
-
-		if (!(res->flags & IORESOURCE_MEM))
-			continue;
-
-		if (res->start <= base && res->end >= base + size - 1) {
-			record_efifb_bar_resource(dev, i, base - res->start);
-			break;
-		}
-	}
-}
-DECLARE_PCI_FIXUP_CLASS_HEADER(PCI_ANY_ID, PCI_ANY_ID, PCI_BASE_CLASS_DISPLAY,
-			       16, efifb_fixup_resources);
-
-#endif
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* Re: [PATCH 1/8] video: Add helpers for decoding screen_info
  2024-01-17 12:39 ` [PATCH 1/8] video: Add helpers for decoding screen_info Thomas Zimmermann
@ 2024-01-29 10:41   ` Javier Martinez Canillas
  2024-01-30 13:12     ` Thomas Zimmermann
  0 siblings, 1 reply; 22+ messages in thread
From: Javier Martinez Canillas @ 2024-01-29 10:41 UTC (permalink / raw)
  To: Thomas Zimmermann, pjones, deller, ardb
  Cc: linux-fbdev, Thomas Zimmermann, dri-devel

Thomas Zimmermann <tzimmermann@suse.de> writes:

Hello Thomas,

> The plain values as stored in struct screen_info need to be decoded
> before being used. Add helpers that decode the type of video output
> and the framebuffer I/O aperture.
>
> Old or non-x86 systems may not set the type of video directly, but
> only indicate the presence by storing 0x01 in orig_video_isVGA. The
> decoding logic in screen_info_video_type() takes this into account.

I always disliked how the orig_video_isVGA variable lost its meaning.

> It then follows similar code in vgacon's vgacon_startup() to detect
> the video type from the given values.
>
> A call to screen_info_resources() returns all known resources of the
> given screen_info. The resources' values have been taken from existing
> code in vgacon and vga16fb. These drivers can later be converted to
> use the new interfaces.
>
> Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
> ---

Thanks for doing this! It's quite useful to have these helpers, since as
you mention the screen_info data decoding is complex and the variables
used to store the video type and modes are confusing / misleading.

Reviewed-by: Javier Martinez Canillas <javierm@redhat.com>

I just have a few comments below:

> +static inline bool __screen_info_has_ega_gfx(unsigned int mode)
> +{
> +	switch (mode) {
> +	case 0x0d:	/* 320x200-4 */
> +	case 0x0e:	/* 640x200-4 */
> +	case 0x0f:	/* 640x350-1 */
> +	case 0x10:	/* 640x350-4 */

I wonder if makes sense to define some constant macros for these modes? I
know that check_mode_supported() in drivers/video/fbdev/vga16fb.c also use
magic numbers but I believe that it could ease readability.

> +		return true;
> +	default:
> +		return false;
> +	}
> +}
> +
> +static inline bool __screen_info_has_vga_gfx(unsigned int mode)
> +{
> +	switch (mode) {
> +	case 0x10:	/* 640x480-1 */
> +	case 0x12:	/* 640x480-4 */
> +	case 0x13:	/* 320-200-8 */
> +	case 0x6a:	/* 800x600-4 (VESA) */
> +		return true;

And same for these.

It can be a follow-up patch though.

[...]

> +int screen_info_resources(const struct screen_info *si, struct resource *r, size_t num)
> +{
> +	struct resource *pos = r;
> +	unsigned int type = screen_info_video_type(si);
> +	u64 base, size;
> +
> +	switch (type) {
> +	case VIDEO_TYPE_MDA:
> +		if (num > 0)
> +			resource_init_io_named(pos++, 0x3b0, 12, "mda");

I see that drivers/video/fbdev/i740_reg.h has a #define MDA_BASE
0x3B0. Maybe move to a header in include/video along with the other
constants mentioned above ?

> +		if (num > 1)
> +			resource_init_io_named(pos++, 0x3bf, 0x01, "mda");
> +		if (num > 2)
> +			resource_init_mem_named(pos++, 0xb0000, 0x2000, "mda");

Same for these start addresses. I see that are also used by mdacon_startup()
in drivers/video/console/mdacon.c, so some constants defined somewhere might
be useful for that console driver too.

The comment also applies to all the other start addresses, since I see
that those are used by other drivers (i810, vgacon, etc).

-- 
Best regards,

Javier Martinez Canillas
Core Platforms
Red Hat


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 2/8] video: Provide screen_info_get_pci_dev() to find screen_info's PCI device
  2024-01-17 12:39 ` [PATCH 2/8] video: Provide screen_info_get_pci_dev() to find screen_info's PCI device Thomas Zimmermann
@ 2024-01-29 11:04   ` Javier Martinez Canillas
  2024-01-30 10:12     ` Thomas Zimmermann
  0 siblings, 1 reply; 22+ messages in thread
From: Javier Martinez Canillas @ 2024-01-29 11:04 UTC (permalink / raw)
  To: Thomas Zimmermann, pjones, deller, ardb
  Cc: linux-fbdev, Thomas Zimmermann, dri-devel

Thomas Zimmermann <tzimmermann@suse.de> writes:

> Add screen_info_get_pci_dev() to find the PCI device of an instance
> of screen_info. Does nothing on systems without PCI bus.
>
> Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
> ---

[...]

> +struct pci_dev *screen_info_pci_dev(const struct screen_info *si)
> +{
> +	struct resource res[SCREEN_INFO_MAX_RESOURCES];
> +	size_t i, numres;
> +	int ret;
> +
> +	ret = screen_info_resources(si, res, ARRAY_SIZE(res));
> +	if (ret < 0)
> +		return ERR_PTR(ret);
> +	numres = ret;
> +

I would just drop the ret variable and assign the screen_info_resources()
return value to numres. I think that makes the code easier to follow.

Reviewed-by: Javier Martinez Canillas <javierm@redhat.com>

-- 
Best regards,

Javier Martinez Canillas
Core Platforms
Red Hat


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 3/8] firmware/sysfb: Set firmware-framebuffer parent device
  2024-01-17 12:39 ` [PATCH 3/8] firmware/sysfb: Set firmware-framebuffer parent device Thomas Zimmermann
@ 2024-01-29 11:28   ` Javier Martinez Canillas
  0 siblings, 0 replies; 22+ messages in thread
From: Javier Martinez Canillas @ 2024-01-29 11:28 UTC (permalink / raw)
  To: Thomas Zimmermann, pjones, deller, ardb
  Cc: linux-fbdev, Thomas Zimmermann, dri-devel

Thomas Zimmermann <tzimmermann@suse.de> writes:

> Set the firmware framebuffer's parent device, which usually is the
> graphics hardware's physical device. Integrates the framebuffer in
> the Linux device hierarchy and lets Linux handle dependencies among
> devices. For example, the graphics hardware won't be suspended while
> the firmware device is still active.
>
> Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
> ---
>  drivers/firmware/sysfb.c          | 11 ++++++++++-
>  drivers/firmware/sysfb_simplefb.c |  5 ++++-
>  include/linux/sysfb.h             |  3 ++-
>  3 files changed, 16 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/firmware/sysfb.c b/drivers/firmware/sysfb.c
> index 19706bd2642a..8a42da3f67a9 100644
> --- a/drivers/firmware/sysfb.c
> +++ b/drivers/firmware/sysfb.c
> @@ -29,6 +29,7 @@
>  #include <linux/init.h>
>  #include <linux/kernel.h>
>  #include <linux/mm.h>
> +#include <linux/pci.h>
>  #include <linux/platform_data/simplefb.h>
>  #include <linux/platform_device.h>
>  #include <linux/screen_info.h>
> @@ -72,6 +73,8 @@ EXPORT_SYMBOL_GPL(sysfb_disable);
>  static __init int sysfb_init(void)
>  {
>  	const struct screen_info *si = &screen_info;
> +	struct device *parent = NULL;
> +	struct pci_dev *pparent;

Maybe pci_parent? It's easier to read than pparent IMO.

Reviewed-by: Javier Martinez Canillas <javierm@redhat.com>

-- 
Best regards,

Javier Martinez Canillas
Core Platforms
Red Hat


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 4/8] fbdev/efifb: Remove PM for parent device
  2024-01-17 12:39 ` [PATCH 4/8] fbdev/efifb: Remove PM for " Thomas Zimmermann
@ 2024-01-29 11:30   ` Javier Martinez Canillas
  0 siblings, 0 replies; 22+ messages in thread
From: Javier Martinez Canillas @ 2024-01-29 11:30 UTC (permalink / raw)
  To: Thomas Zimmermann, pjones, deller, ardb
  Cc: linux-fbdev, Thomas Zimmermann, dri-devel

Thomas Zimmermann <tzimmermann@suse.de> writes:

> The EFI device has the correct parent device set. This allows Linux
> to handle the power management internally. Hence, remove the manual
> PM management for the parent device from efifb.
>
> Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
> ---

Reviewed-by: Javier Martinez Canillas <javierm@redhat.com>

-- 
Best regards,

Javier Martinez Canillas
Core Platforms
Red Hat


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 5/8] firmware/sysfb: Create firmware device only for enabled PCI devices
  2024-01-17 12:39 ` [PATCH 5/8] firmware/sysfb: Create firmware device only for enabled PCI devices Thomas Zimmermann
@ 2024-01-29 11:36   ` Javier Martinez Canillas
  2024-01-30 12:52     ` Thomas Zimmermann
  0 siblings, 1 reply; 22+ messages in thread
From: Javier Martinez Canillas @ 2024-01-29 11:36 UTC (permalink / raw)
  To: Thomas Zimmermann, pjones, deller, ardb
  Cc: linux-fbdev, Thomas Zimmermann, dri-devel

Thomas Zimmermann <tzimmermann@suse.de> writes:

> Test if the firmware framebuffer's parent PCI device, if any, has
> been enabled. If not, the firmware framebuffer is most likely not
> working. Hence, do not create a device for the firmware framebuffer
> on disabled PCI devices.
>
> So far, efifb tracked the status of the PCI parent device internally
> and did not bind if it was disabled. This patch implements the
> functionality for all firmware framebuffers.
>
> Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
> ---

[...]

>  
> +static __init bool sysfb_pci_dev_is_enabled(struct pci_dev *pdev)
> +{
> +#if defined(CONFIG_PCI)
> +	/*
> +	 * TODO: Try to integrate this code into the PCI subsystem
> +	 */
> +	int ret;
> +	u16 command;
> +
> +	ret = pci_read_config_word(pdev, PCI_COMMAND, &command);
> +	if (ret != PCIBIOS_SUCCESSFUL)
> +		return false;
> +	if (!(command & PCI_COMMAND_MEMORY))
> +		return false;
> +	return true;
> +#else
> +	// Getting here without PCI support is probably a bug.
> +	return false;

Should we warn before return in this case ?

Reviewed-by: Javier Martinez Canillas <javierm@redhat.com>

-- 
Best regards,

Javier Martinez Canillas
Core Platforms
Red Hat


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 6/8] fbdev/efifb: Do not track parent device status
  2024-01-17 12:39 ` [PATCH 6/8] fbdev/efifb: Do not track parent device status Thomas Zimmermann
@ 2024-01-29 11:38   ` Javier Martinez Canillas
  0 siblings, 0 replies; 22+ messages in thread
From: Javier Martinez Canillas @ 2024-01-29 11:38 UTC (permalink / raw)
  To: Thomas Zimmermann, pjones, deller, ardb
  Cc: linux-fbdev, Thomas Zimmermann, dri-devel

Thomas Zimmermann <tzimmermann@suse.de> writes:

> There will be no EFI framebuffer device for disabled parent devices
> and thus we never probe efifb in that case. Hence remove the tracking
> code from efifb.
>
> Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
> ---

Nice cleanup.

Reviewed-by: Javier Martinez Canillas <javierm@redhat.com>

-- 
Best regards,

Javier Martinez Canillas
Core Platforms
Red Hat


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 7/8] firmware/sysfb: Update screen_info for relocated EFI framebuffers
  2024-01-17 12:39 ` [PATCH 7/8] firmware/sysfb: Update screen_info for relocated EFI framebuffers Thomas Zimmermann
@ 2024-01-29 11:52   ` Javier Martinez Canillas
  2024-01-29 12:03     ` Javier Martinez Canillas
  0 siblings, 1 reply; 22+ messages in thread
From: Javier Martinez Canillas @ 2024-01-29 11:52 UTC (permalink / raw)
  To: Thomas Zimmermann, pjones, deller, ardb
  Cc: linux-fbdev, Thomas Zimmermann, dri-devel

Thomas Zimmermann <tzimmermann@suse.de> writes:

> On ARM PCI systems, the PCI hierarchy might be reconfigured during
> boot and the firmware framebuffer might move as a result of that.
> The values in screen_info will then be invalid.
>
> Work around this problem by tracking the framebuffer's initial
> location before it get relocated; then fix the screen_info state
> between reloaction and creating the firmware framebuffer's device.
>
> This functionality has been lifted from efifb. See the commit message
> of commit 55d728a40d36 ("efi/fb: Avoid reconfiguration of BAR that
> covers the framebuffer") for more information.
>
> Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
> ---

[...]

>  #if defined(CONFIG_PCI)

Shouldn't this be && !defined(CONFIG_X86) ? Or maybe &&
defined(CONFIG_ARM64), although I don't know if the same
also applies to other EFI platforms (e.g: CONFIG_RISCV).

Reviewed-by: Javier Martinez Canillas <javierm@redhat.com>

-- 
Best regards,

Javier Martinez Canillas
Core Platforms
Red Hat


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 7/8] firmware/sysfb: Update screen_info for relocated EFI framebuffers
  2024-01-29 11:52   ` Javier Martinez Canillas
@ 2024-01-29 12:03     ` Javier Martinez Canillas
  0 siblings, 0 replies; 22+ messages in thread
From: Javier Martinez Canillas @ 2024-01-29 12:03 UTC (permalink / raw)
  To: Thomas Zimmermann, pjones, deller, ardb
  Cc: linux-fbdev, Thomas Zimmermann, dri-devel

Javier Martinez Canillas <javierm@redhat.com> writes:

> Thomas Zimmermann <tzimmermann@suse.de> writes:
>
>> On ARM PCI systems, the PCI hierarchy might be reconfigured during
>> boot and the firmware framebuffer might move as a result of that.
>> The values in screen_info will then be invalid.
>>
>> Work around this problem by tracking the framebuffer's initial
>> location before it get relocated; then fix the screen_info state
>> between reloaction and creating the firmware framebuffer's device.
>>
>> This functionality has been lifted from efifb. See the commit message
>> of commit 55d728a40d36 ("efi/fb: Avoid reconfiguration of BAR that
>> covers the framebuffer") for more information.
>>
>> Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
>> ---
>
> [...]
>
>>  #if defined(CONFIG_PCI)
>
> Shouldn't this be && !defined(CONFIG_X86) ? Or maybe &&
> defined(CONFIG_ARM64), although I don't know if the same
> also applies to other EFI platforms (e.g: CONFIG_RISCV).
>

Answering my own question, the !defined(CONFIG_X86) was dropped in the commit
dcf8f5ce3165 ("drivers/fbdev/efifb: Allow BAR to be moved instead of claiming
it"). The rationale is explained in that commit message:

    While this is less likely to occur on x86, given that the firmware's
    PCI resource allocation is more likely to be preserved, this is a
    worthwhile sanity check to have in place, and so let's remove the
    preprocessor conditional that makes it !X86 only.

So it is OK to just guard with #if defined(CONFIG_PCI).

-- 
Best regards,

Javier Martinez Canillas
Core Platforms
Red Hat


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 8/8] fbdev/efifb: Remove framebuffer relocation tracking
  2024-01-17 12:39 ` [PATCH 8/8] fbdev/efifb: Remove framebuffer relocation tracking Thomas Zimmermann
@ 2024-01-29 12:03   ` Javier Martinez Canillas
  0 siblings, 0 replies; 22+ messages in thread
From: Javier Martinez Canillas @ 2024-01-29 12:03 UTC (permalink / raw)
  To: Thomas Zimmermann, pjones, deller, ardb
  Cc: linux-fbdev, Thomas Zimmermann, dri-devel

Thomas Zimmermann <tzimmermann@suse.de> writes:

> If the firmware framebuffer has been reloacted, the sysfb code
> fixes the screen_info state before it creates the framebuffer's
> platform device. Efifb will automatically receive a screen_info
> with updated values. Hence remove the tracking from efifb.
>
> Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
> ---

Reviewed-by: Javier Martinez Canillas <javierm@redhat.com>

-- 
Best regards,

Javier Martinez Canillas
Core Platforms
Red Hat


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 2/8] video: Provide screen_info_get_pci_dev() to find screen_info's PCI device
  2024-01-29 11:04   ` Javier Martinez Canillas
@ 2024-01-30 10:12     ` Thomas Zimmermann
  2024-01-30 10:23       ` Javier Martinez Canillas
  0 siblings, 1 reply; 22+ messages in thread
From: Thomas Zimmermann @ 2024-01-30 10:12 UTC (permalink / raw)
  To: Javier Martinez Canillas, pjones, deller, ardb; +Cc: linux-fbdev, dri-devel


[-- Attachment #1.1: Type: text/plain, Size: 1377 bytes --]

Hi

Am 29.01.24 um 12:04 schrieb Javier Martinez Canillas:
> Thomas Zimmermann <tzimmermann@suse.de> writes:
> 
>> Add screen_info_get_pci_dev() to find the PCI device of an instance
>> of screen_info. Does nothing on systems without PCI bus.
>>
>> Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
>> ---
> 
> [...]
> 
>> +struct pci_dev *screen_info_pci_dev(const struct screen_info *si)
>> +{
>> +	struct resource res[SCREEN_INFO_MAX_RESOURCES];
>> +	size_t i, numres;
>> +	int ret;
>> +
>> +	ret = screen_info_resources(si, res, ARRAY_SIZE(res));
>> +	if (ret < 0)
>> +		return ERR_PTR(ret);
>> +	numres = ret;
>> +
> 
> I would just drop the ret variable and assign the screen_info_resources()
> return value to numres. I think that makes the code easier to follow.

The value of ret could be an errno code. We would effectively return 
NULL for errors. And I just noticed that the function docs imply this. 
But NULL is also a valid value if there is no PCI device. I'd prefer to 
keep the errno-pointer around.

Best regards
Thomas

> 
> Reviewed-by: Javier Martinez Canillas <javierm@redhat.com>
> 

-- 
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)

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 840 bytes --]

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 2/8] video: Provide screen_info_get_pci_dev() to find screen_info's PCI device
  2024-01-30 10:12     ` Thomas Zimmermann
@ 2024-01-30 10:23       ` Javier Martinez Canillas
  0 siblings, 0 replies; 22+ messages in thread
From: Javier Martinez Canillas @ 2024-01-30 10:23 UTC (permalink / raw)
  To: Thomas Zimmermann, pjones, deller, ardb; +Cc: linux-fbdev, dri-devel

Thomas Zimmermann <tzimmermann@suse.de> writes:

> Hi
>
> Am 29.01.24 um 12:04 schrieb Javier Martinez Canillas:
>> Thomas Zimmermann <tzimmermann@suse.de> writes:
>> 
>>> Add screen_info_get_pci_dev() to find the PCI device of an instance
>>> of screen_info. Does nothing on systems without PCI bus.
>>>
>>> Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
>>> ---
>> 
>> [...]
>> 
>>> +struct pci_dev *screen_info_pci_dev(const struct screen_info *si)
>>> +{
>>> +	struct resource res[SCREEN_INFO_MAX_RESOURCES];
>>> +	size_t i, numres;
>>> +	int ret;
>>> +
>>> +	ret = screen_info_resources(si, res, ARRAY_SIZE(res));
>>> +	if (ret < 0)
>>> +		return ERR_PTR(ret);
>>> +	numres = ret;
>>> +
>> 
>> I would just drop the ret variable and assign the screen_info_resources()
>> return value to numres. I think that makes the code easier to follow.
>
> The value of ret could be an errno code. We would effectively return 
> NULL for errors. And I just noticed that the function docs imply this. 
> But NULL is also a valid value if there is no PCI device. I'd prefer to 
> keep the errno-pointer around.
>

Yes. I meant making numres an int instead of size_t (SCREEN_INFO_MAX_RESOURCES
is only 3 after all). That way you could just return ERR_PTR(numres) if is < 0.

No strong preference, just think that the code is easier to read in that case.

-- 
Best regards,

Javier Martinez Canillas
Core Platforms
Red Hat


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 5/8] firmware/sysfb: Create firmware device only for enabled PCI devices
  2024-01-29 11:36   ` Javier Martinez Canillas
@ 2024-01-30 12:52     ` Thomas Zimmermann
  0 siblings, 0 replies; 22+ messages in thread
From: Thomas Zimmermann @ 2024-01-30 12:52 UTC (permalink / raw)
  To: Javier Martinez Canillas, pjones, deller, ardb; +Cc: linux-fbdev, dri-devel


[-- Attachment #1.1: Type: text/plain, Size: 1683 bytes --]

Hi

Am 29.01.24 um 12:36 schrieb Javier Martinez Canillas:
> Thomas Zimmermann <tzimmermann@suse.de> writes:
> 
>> Test if the firmware framebuffer's parent PCI device, if any, has
>> been enabled. If not, the firmware framebuffer is most likely not
>> working. Hence, do not create a device for the firmware framebuffer
>> on disabled PCI devices.
>>
>> So far, efifb tracked the status of the PCI parent device internally
>> and did not bind if it was disabled. This patch implements the
>> functionality for all firmware framebuffers.
>>
>> Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
>> ---
> 
> [...]
> 
>>   
>> +static __init bool sysfb_pci_dev_is_enabled(struct pci_dev *pdev)
>> +{
>> +#if defined(CONFIG_PCI)
>> +	/*
>> +	 * TODO: Try to integrate this code into the PCI subsystem
>> +	 */
>> +	int ret;
>> +	u16 command;
>> +
>> +	ret = pci_read_config_word(pdev, PCI_COMMAND, &command);
>> +	if (ret != PCIBIOS_SUCCESSFUL)
>> +		return false;
>> +	if (!(command & PCI_COMMAND_MEMORY))
>> +		return false;
>> +	return true;
>> +#else
>> +	// Getting here without PCI support is probably a bug.
>> +	return false;
> 
> Should we warn before return in this case ?

I would not do so as the bug is not here, but in screen_info_pci_dev(). 
I'm going to update this chunk such that the non-PCI case is a separate 
function.

> 
> Reviewed-by: Javier Martinez Canillas <javierm@redhat.com>
> 

-- 
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)

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 840 bytes --]

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 1/8] video: Add helpers for decoding screen_info
  2024-01-29 10:41   ` Javier Martinez Canillas
@ 2024-01-30 13:12     ` Thomas Zimmermann
  0 siblings, 0 replies; 22+ messages in thread
From: Thomas Zimmermann @ 2024-01-30 13:12 UTC (permalink / raw)
  To: Javier Martinez Canillas, pjones, deller, ardb; +Cc: linux-fbdev, dri-devel


[-- Attachment #1.1: Type: text/plain, Size: 3961 bytes --]

Hi

Am 29.01.24 um 11:41 schrieb Javier Martinez Canillas:
> Thomas Zimmermann <tzimmermann@suse.de> writes:
> 
> Hello Thomas,
> 
>> The plain values as stored in struct screen_info need to be decoded
>> before being used. Add helpers that decode the type of video output
>> and the framebuffer I/O aperture.
>>
>> Old or non-x86 systems may not set the type of video directly, but
>> only indicate the presence by storing 0x01 in orig_video_isVGA. The
>> decoding logic in screen_info_video_type() takes this into account.
> 
> I always disliked how the orig_video_isVGA variable lost its meaning.
> 
>> It then follows similar code in vgacon's vgacon_startup() to detect
>> the video type from the given values.
>>
>> A call to screen_info_resources() returns all known resources of the
>> given screen_info. The resources' values have been taken from existing
>> code in vgacon and vga16fb. These drivers can later be converted to
>> use the new interfaces.
>>
>> Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
>> ---
> 
> Thanks for doing this! It's quite useful to have these helpers, since as
> you mention the screen_info data decoding is complex and the variables
> used to store the video type and modes are confusing / misleading.
> 
> Reviewed-by: Javier Martinez Canillas <javierm@redhat.com>
> 
> I just have a few comments below:
> 
>> +static inline bool __screen_info_has_ega_gfx(unsigned int mode)
>> +{
>> +	switch (mode) {
>> +	case 0x0d:	/* 320x200-4 */
>> +	case 0x0e:	/* 640x200-4 */
>> +	case 0x0f:	/* 640x350-1 */
>> +	case 0x10:	/* 640x350-4 */
> 
> I wonder if makes sense to define some constant macros for these modes? I
> know that check_mode_supported() in drivers/video/fbdev/vga16fb.c also use
> magic numbers but I believe that it could ease readability.

They are known by their numbers, but have no names. There's also no 
common practice or precedence I'm aware of.

OTOH, drivers like vga16fb should no longer have to test magic numbers 
at all. They bind to a certain type of device, such as ega-txt and 
vga-gfx, which implies a correctly set mode.

> 
>> +		return true;
>> +	default:
>> +		return false;
>> +	}
>> +}
>> +
>> +static inline bool __screen_info_has_vga_gfx(unsigned int mode)
>> +{
>> +	switch (mode) {
>> +	case 0x10:	/* 640x480-1 */
>> +	case 0x12:	/* 640x480-4 */
>> +	case 0x13:	/* 320-200-8 */
>> +	case 0x6a:	/* 800x600-4 (VESA) */
>> +		return true;
> 
> And same for these.
> 
> It can be a follow-up patch though.
> 
> [...]
> 
>> +int screen_info_resources(const struct screen_info *si, struct resource *r, size_t num)
>> +{
>> +	struct resource *pos = r;
>> +	unsigned int type = screen_info_video_type(si);
>> +	u64 base, size;
>> +
>> +	switch (type) {
>> +	case VIDEO_TYPE_MDA:
>> +		if (num > 0)
>> +			resource_init_io_named(pos++, 0x3b0, 12, "mda");
> 
> I see that drivers/video/fbdev/i740_reg.h has a #define MDA_BASE
> 0x3B0. Maybe move to a header in include/video along with the other
> constants mentioned above ?

That could go into <video/vga.h>. MDA_BASE (and CGA_BASE) from the same 
file are unused though.

Best regards
Thomas

> 
>> +		if (num > 1)
>> +			resource_init_io_named(pos++, 0x3bf, 0x01, "mda");
>> +		if (num > 2)
>> +			resource_init_mem_named(pos++, 0xb0000, 0x2000, "mda");
> 
> Same for these start addresses. I see that are also used by mdacon_startup()
> in drivers/video/console/mdacon.c, so some constants defined somewhere might
> be useful for that console driver too.
> 
> The comment also applies to all the other start addresses, since I see
> that those are used by other drivers (i810, vgacon, etc).
> 

-- 
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)

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 840 bytes --]

^ permalink raw reply	[flat|nested] 22+ messages in thread

end of thread, other threads:[~2024-01-30 13:12 UTC | newest]

Thread overview: 22+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-01-17 12:39 [PATCH 0/8] firmware/sysfb: Track parent device for screen_info Thomas Zimmermann
2024-01-17 12:39 ` [PATCH 1/8] video: Add helpers for decoding screen_info Thomas Zimmermann
2024-01-29 10:41   ` Javier Martinez Canillas
2024-01-30 13:12     ` Thomas Zimmermann
2024-01-17 12:39 ` [PATCH 2/8] video: Provide screen_info_get_pci_dev() to find screen_info's PCI device Thomas Zimmermann
2024-01-29 11:04   ` Javier Martinez Canillas
2024-01-30 10:12     ` Thomas Zimmermann
2024-01-30 10:23       ` Javier Martinez Canillas
2024-01-17 12:39 ` [PATCH 3/8] firmware/sysfb: Set firmware-framebuffer parent device Thomas Zimmermann
2024-01-29 11:28   ` Javier Martinez Canillas
2024-01-17 12:39 ` [PATCH 4/8] fbdev/efifb: Remove PM for " Thomas Zimmermann
2024-01-29 11:30   ` Javier Martinez Canillas
2024-01-17 12:39 ` [PATCH 5/8] firmware/sysfb: Create firmware device only for enabled PCI devices Thomas Zimmermann
2024-01-29 11:36   ` Javier Martinez Canillas
2024-01-30 12:52     ` Thomas Zimmermann
2024-01-17 12:39 ` [PATCH 6/8] fbdev/efifb: Do not track parent device status Thomas Zimmermann
2024-01-29 11:38   ` Javier Martinez Canillas
2024-01-17 12:39 ` [PATCH 7/8] firmware/sysfb: Update screen_info for relocated EFI framebuffers Thomas Zimmermann
2024-01-29 11:52   ` Javier Martinez Canillas
2024-01-29 12:03     ` Javier Martinez Canillas
2024-01-17 12:39 ` [PATCH 8/8] fbdev/efifb: Remove framebuffer relocation tracking Thomas Zimmermann
2024-01-29 12:03   ` Javier Martinez Canillas

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).