All of lore.kernel.org
 help / color / mirror / Atom feed
From: Ard Biesheuvel <ardb@kernel.org>
To: linux-kernel@vger.kernel.org
Cc: linux-arm-kernel@lists.infradead.org, linux-efi@vger.kernel.org,
	will@kernel.org, bhelgaas@google.com,
	Ard Biesheuvel <ardb@kernel.org>,
	Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	Saravana Kannan <saravanak@google.com>
Subject: [PATCH] efi: arm: defer probe of PCIe backed efifb on DT systems
Date: Tue, 26 Nov 2019 17:29:02 +0100	[thread overview]
Message-ID: <20191126162902.16788-1-ardb@kernel.org> (raw)

The new of_devlink support breaks PCIe probing on ARM platforms booting
via UEFI if the firmware exposes a EFI framebuffer that is backed by a
PCI device. The reason is that the probing order gets reversed,
resulting in a resource conflict on the framebuffer memory window when
the PCIe probes last, causing it to give up entirely.

Given that we rely on PCI quirks to deal with EFI framebuffers that get
moved around in memory, we cannot simply drop the memory reservation, so
instead, let's use the device link infrastructure to register this
dependency, and force the probing to occur in the expected order.

Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Saravana Kannan <saravanak@google.com>
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
---
 drivers/firmware/efi/arm-init.c | 66 ++++++++++++++++++--
 1 file changed, 61 insertions(+), 5 deletions(-)

diff --git a/drivers/firmware/efi/arm-init.c b/drivers/firmware/efi/arm-init.c
index 311cd349a862..617226d50774 100644
--- a/drivers/firmware/efi/arm-init.c
+++ b/drivers/firmware/efi/arm-init.c
@@ -14,6 +14,7 @@
 #include <linux/memblock.h>
 #include <linux/mm_types.h>
 #include <linux/of.h>
+#include <linux/of_address.h>
 #include <linux/of_fdt.h>
 #include <linux/platform_device.h>
 #include <linux/screen_info.h>
@@ -267,15 +268,70 @@ void __init efi_init(void)
 		efi_memmap_unmap();
 }
 
+static bool __init efifb_overlaps_pci_range(const struct of_pci_range *range)
+{
+	u64 fb_base = screen_info.lfb_base;
+
+	if (screen_info.capabilities & VIDEO_CAPABILITY_64BIT_BASE)
+		fb_base |= (u64)(unsigned long)screen_info.ext_lfb_base << 32;
+
+	return fb_base >= range->cpu_addr &&
+	       fb_base < (range->cpu_addr + range->size);
+}
+
 static int __init register_gop_device(void)
 {
-	void *pd;
+	struct platform_device *pd;
+	struct device_node *np;
+	bool found = false;
+	int err;
 
 	if (screen_info.orig_video_isVGA != VIDEO_TYPE_EFI)
 		return 0;
 
-	pd = platform_device_register_data(NULL, "efi-framebuffer", 0,
-					   &screen_info, sizeof(screen_info));
-	return PTR_ERR_OR_ZERO(pd);
+	pd = platform_device_alloc("efi-framebuffer", 0);
+	if (!pd)
+		return -ENOMEM;
+
+	err = platform_device_add_data(pd, &screen_info, sizeof(screen_info));
+	if (err)
+		return err;
+
+	/*
+	 * If the efifb framebuffer is backed by a PCI graphics controller, we
+	 * have to ensure that this relation is expressed using a device link
+	 * when running in DT mode, or the probe order may be reversed,
+	 * resulting in a resource reservation conflict on the memory window
+	 * that the efifb framebuffer steals from the PCIe host bridge.
+	 */
+	for_each_node_by_type(np, "pci") {
+		struct of_pci_range_parser parser;
+		struct of_pci_range range;
+		struct device *sup_dev;
+
+		if (found) {
+			of_node_put(np);
+			break;
+		}
+
+		err = of_pci_range_parser_init(&parser, np);
+		if (err) {
+			pr_warn("of_pci_range_parser_init() failed: %d\n", err);
+			continue;
+		}
+
+		sup_dev = get_dev_from_fwnode(&np->fwnode);
+
+		for_each_of_pci_range(&parser, &range) {
+			if (efifb_overlaps_pci_range(&range)) {
+				found = true;
+				if (!device_link_add(&pd->dev, sup_dev, 0))
+					pr_warn("device_link_add() failed\n");
+				break;
+			}
+		}
+		put_device(sup_dev);
+	}
+	return platform_device_add(pd);
 }
-subsys_initcall(register_gop_device);
+device_initcall(register_gop_device);
-- 
2.20.1


WARNING: multiple messages have this Message-ID (diff)
From: Ard Biesheuvel <ardb@kernel.org>
To: linux-kernel@vger.kernel.org
Cc: linux-efi@vger.kernel.org, Saravana Kannan <saravanak@google.com>,
	Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	bhelgaas@google.com, will@kernel.org,
	Ard Biesheuvel <ardb@kernel.org>,
	linux-arm-kernel@lists.infradead.org
Subject: [PATCH] efi: arm: defer probe of PCIe backed efifb on DT systems
Date: Tue, 26 Nov 2019 17:29:02 +0100	[thread overview]
Message-ID: <20191126162902.16788-1-ardb@kernel.org> (raw)

The new of_devlink support breaks PCIe probing on ARM platforms booting
via UEFI if the firmware exposes a EFI framebuffer that is backed by a
PCI device. The reason is that the probing order gets reversed,
resulting in a resource conflict on the framebuffer memory window when
the PCIe probes last, causing it to give up entirely.

Given that we rely on PCI quirks to deal with EFI framebuffers that get
moved around in memory, we cannot simply drop the memory reservation, so
instead, let's use the device link infrastructure to register this
dependency, and force the probing to occur in the expected order.

Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Saravana Kannan <saravanak@google.com>
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
---
 drivers/firmware/efi/arm-init.c | 66 ++++++++++++++++++--
 1 file changed, 61 insertions(+), 5 deletions(-)

diff --git a/drivers/firmware/efi/arm-init.c b/drivers/firmware/efi/arm-init.c
index 311cd349a862..617226d50774 100644
--- a/drivers/firmware/efi/arm-init.c
+++ b/drivers/firmware/efi/arm-init.c
@@ -14,6 +14,7 @@
 #include <linux/memblock.h>
 #include <linux/mm_types.h>
 #include <linux/of.h>
+#include <linux/of_address.h>
 #include <linux/of_fdt.h>
 #include <linux/platform_device.h>
 #include <linux/screen_info.h>
@@ -267,15 +268,70 @@ void __init efi_init(void)
 		efi_memmap_unmap();
 }
 
+static bool __init efifb_overlaps_pci_range(const struct of_pci_range *range)
+{
+	u64 fb_base = screen_info.lfb_base;
+
+	if (screen_info.capabilities & VIDEO_CAPABILITY_64BIT_BASE)
+		fb_base |= (u64)(unsigned long)screen_info.ext_lfb_base << 32;
+
+	return fb_base >= range->cpu_addr &&
+	       fb_base < (range->cpu_addr + range->size);
+}
+
 static int __init register_gop_device(void)
 {
-	void *pd;
+	struct platform_device *pd;
+	struct device_node *np;
+	bool found = false;
+	int err;
 
 	if (screen_info.orig_video_isVGA != VIDEO_TYPE_EFI)
 		return 0;
 
-	pd = platform_device_register_data(NULL, "efi-framebuffer", 0,
-					   &screen_info, sizeof(screen_info));
-	return PTR_ERR_OR_ZERO(pd);
+	pd = platform_device_alloc("efi-framebuffer", 0);
+	if (!pd)
+		return -ENOMEM;
+
+	err = platform_device_add_data(pd, &screen_info, sizeof(screen_info));
+	if (err)
+		return err;
+
+	/*
+	 * If the efifb framebuffer is backed by a PCI graphics controller, we
+	 * have to ensure that this relation is expressed using a device link
+	 * when running in DT mode, or the probe order may be reversed,
+	 * resulting in a resource reservation conflict on the memory window
+	 * that the efifb framebuffer steals from the PCIe host bridge.
+	 */
+	for_each_node_by_type(np, "pci") {
+		struct of_pci_range_parser parser;
+		struct of_pci_range range;
+		struct device *sup_dev;
+
+		if (found) {
+			of_node_put(np);
+			break;
+		}
+
+		err = of_pci_range_parser_init(&parser, np);
+		if (err) {
+			pr_warn("of_pci_range_parser_init() failed: %d\n", err);
+			continue;
+		}
+
+		sup_dev = get_dev_from_fwnode(&np->fwnode);
+
+		for_each_of_pci_range(&parser, &range) {
+			if (efifb_overlaps_pci_range(&range)) {
+				found = true;
+				if (!device_link_add(&pd->dev, sup_dev, 0))
+					pr_warn("device_link_add() failed\n");
+				break;
+			}
+		}
+		put_device(sup_dev);
+	}
+	return platform_device_add(pd);
 }
-subsys_initcall(register_gop_device);
+device_initcall(register_gop_device);
-- 
2.20.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

             reply	other threads:[~2019-11-26 16:30 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-11-26 16:29 Ard Biesheuvel [this message]
2019-11-26 16:29 ` [PATCH] efi: arm: defer probe of PCIe backed efifb on DT systems Ard Biesheuvel
2019-11-28 19:28 ` Saravana Kannan
2019-11-28 19:28   ` Saravana Kannan
2019-11-28 20:19   ` Ard Biesheuvel
2019-11-28 20:19     ` Ard Biesheuvel
2019-12-18  2:14     ` Saravana Kannan
2019-12-18  2:14       ` Saravana Kannan
2019-12-18  7:36       ` Ard Biesheuvel
2019-12-18  7:36         ` Ard Biesheuvel

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20191126162902.16788-1-ardb@kernel.org \
    --to=ardb@kernel.org \
    --cc=bhelgaas@google.com \
    --cc=gregkh@linuxfoundation.org \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-efi@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=saravanak@google.com \
    --cc=will@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.