The pseries platform uses the PCI_PROBE_DEVTREE method of PCI probing
which is basically reading "assigned-addresses" of every PCI device.
However if the property is missing or zero sized, then there is
no fallback of any kind and the PCI resources remain undiscovered, i.e.
pdev->resource[] array is empty.

This adds a fallback which parses the "reg" property in pretty much same
way except it marks resources as "unset" which later makes Linux assign
those resources with proper addresses.

Signed-off-by: Alexey Kardashevskiy <a...@ozlabs.ru>
---

This is an attempts to boot linux directly under QEMU without slof/rtas;
the aim is to use petitboot instead and let the guest kernel configure
devices.

QEMU does not allocate resources, it creates correct "reg" and zero length
"assigned-addresses" (which is probably a bug on its own) which is
normally populated by SLOF later but not during this exercise.

---
 arch/powerpc/kernel/pci_of_scan.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/arch/powerpc/kernel/pci_of_scan.c 
b/arch/powerpc/kernel/pci_of_scan.c
index 64ad92016b63..cfe6ec3c6aaf 100644
--- a/arch/powerpc/kernel/pci_of_scan.c
+++ b/arch/powerpc/kernel/pci_of_scan.c
@@ -82,10 +82,18 @@ static void of_pci_parse_addrs(struct device_node *node, 
struct pci_dev *dev)
        const __be32 *addrs;
        u32 i;
        int proplen;
+       bool unset = false;
 
        addrs = of_get_property(node, "assigned-addresses", &proplen);
        if (!addrs)
                return;
+       if (!addrs || !proplen) {
+               addrs = of_get_property(node, "reg", &proplen);
+               if (!addrs || !proplen)
+                       return;
+               unset = true;
+       }
+
        pr_debug("    parse addresses (%d bytes) @ %p\n", proplen, addrs);
        for (; proplen >= 20; proplen -= 20, addrs += 5) {
                flags = pci_parse_of_flags(of_read_number(addrs, 1), 0);
@@ -110,6 +118,8 @@ static void of_pci_parse_addrs(struct device_node *node, 
struct pci_dev *dev)
                        continue;
                }
                res->flags = flags;
+               if (unset)
+                       res->flags |= IORESOURCE_UNSET;
                res->name = pci_name(dev);
                region.start = base;
                region.end = base + size - 1;
-- 
2.17.1

Reply via email to