PCI: of: Add 64-bit address recognition without LPAE support
authorPavel Fedin <p.fedin@samsung.com>
Thu, 8 Oct 2015 07:24:25 +0000 (10:24 +0300)
committerRob Herring <robh@kernel.org>
Tue, 13 Oct 2015 18:30:37 +0000 (13:30 -0500)
If non-LPAE kernel is booted up on a machine with 64-bit PCI resources,
PCI controller probe fails with:

PCI host bridge /pcie@10000000 ranges:
   IO 0x3eff0000..0x3effffff -> 0x00000000
  MEM 0x10000000..0x3efeffff -> 0x10000000
  MEM 0x8000000000..0xffffffffff -> 0x8000000000
pci-host-generic 3f000000.pcie: resource collision: [mem 0x00000000-0xffffffff] conflicts with /pl011@9000000 [mem 0x09000000-0x09000fff]
pci-host-generic: probe of 3f000000.pcie failed with error -16

This happens because res->start assignment in of_pci_range_to_resource()
truncates the upper part of the address, because res->start is of
phys_addr_t type, which is 32-bit on non-LPAE kernels.

This patch adds explicit recognition of 64-bit resources, preventing from
potential problems when e. g. 0x8000001234 would be converted to
0x00001234.

Signed-off-by: Pavel Fedin <p.fedin@samsung.com>
Signed-off-by: Rob Herring <robh@kernel.org>
drivers/of/address.c

index 384574c3987c337444181d68346ce9d95963f027..cd53fe4a0c8684900a94fb4bee76f9bd668e3837 100644 (file)
@@ -330,6 +330,12 @@ int of_pci_range_to_resource(struct of_pci_range *range,
                }
                res->start = port;
        } else {
+               if ((sizeof(resource_size_t) < 8) &&
+                   upper_32_bits(range->cpu_addr)) {
+                       err = -EINVAL;
+                       goto invalid_range;
+               }
+
                res->start = range->cpu_addr;
        }
        res->end = res->start + range->size - 1;