| From dead1c845dbe97e0061dae2017eaf3bd8f8f06ee Mon Sep 17 00:00:00 2001 |
| From: Alexey Kardashevskiy <aik@ozlabs.ru> |
| Date: Wed, 26 Jun 2019 12:37:46 +1000 |
| Subject: powerpc/pci/of: Parse unassigned resources |
| |
| From: Alexey Kardashevskiy <aik@ozlabs.ru> |
| |
| commit dead1c845dbe97e0061dae2017eaf3bd8f8f06ee upstream. |
| |
| The pseries platform uses the PCI_PROBE_DEVTREE method of PCI probing |
| which reads "assigned-addresses" of every PCI device and initializes |
| the device resources. 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 remains empty. |
| |
| This adds a fallback which parses the "reg" property in pretty much same |
| way except it marks resources as "unset" which later make Linux assign |
| those resources proper addresses. |
| |
| This has an effect when: |
| 1. a hypervisor failed to assign any resource for a device; |
| 2. /chosen/linux,pci-probe-only=0 is in the DT so the system may try |
| assigning a resource. |
| Neither is likely to happen under PowerVM. |
| |
| Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru> |
| Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> |
| Cc: Guenter Roeck <linux@roeck-us.net> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| arch/powerpc/kernel/pci_of_scan.c | 12 ++++++++++-- |
| 1 file changed, 10 insertions(+), 2 deletions(-) |
| |
| --- a/arch/powerpc/kernel/pci_of_scan.c |
| +++ b/arch/powerpc/kernel/pci_of_scan.c |
| @@ -82,10 +82,16 @@ static void of_pci_parse_addrs(struct de |
| const __be32 *addrs; |
| u32 i; |
| int proplen; |
| + bool mark_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; |
| + mark_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 +116,8 @@ static void of_pci_parse_addrs(struct de |
| continue; |
| } |
| res->flags = flags; |
| + if (mark_unset) |
| + res->flags |= IORESOURCE_UNSET; |
| res->name = pci_name(dev); |
| region.start = base; |
| region.end = base + size - 1; |