Skip to contentSkip to conversation

PCI: of: Fix handling 64-bit PCI resources on non-LPAE kernels

PATCH Superseded Pavel Fedin 2 participants 4 messages Oct 7, 2015 – Oct 8, 2015

Subsystems (2)

v1 of 2 Superseded Latest is v2 →

lore
Share & tools
lore
#0 lore raw

cover PCI: of: Fix handling 64-bit PCI resources on non-LPAE kernels

The initial aim of this series is to fix long-standing problem with generic PCI host controller, triggered by ARM "virt" machine in the recent qemu. Since v2.4.50 qemu adds support for the second, large PCI MMIO window, which resides in 64-bit address space. This series addresses problems, which are triggered on non-LPAE kernels by this configuration.

These patches do not depend on each other and can be applied individually. The first adds missing recognition of 64-bit resources (which is actually a bug). The second one changes the code to ignore unaccessible resources instead of completely bailing out. Since it touches generic of_pci code, the fix is expected to be applied to all drivers which use of_pci_get_host_bridge_resources().

Pavel Fedin (2):
PCI: of: Add 64-bit address recognition without LPAE support
PCI: of: Ignore resources with failed translation

 drivers/of/address.c | 6 ++++++
 drivers/of/of_pci.c  | 6 ++++--
 2 files changed, 10 insertions(+), 2 deletions(-)
Signature · 1 line
2.4.4
#1 lore raw

PATCH 1/2 PCI: of: Add 64-bit address recognition without LPAE support

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.

---
 drivers/of/address.c | 6 ++++++
 1 file changed, 6 insertions(+)
drivers/of/address.c +6 -0
index 384574c..9a8f8c3 100644
@@ -330,6 +330,12 @@ int of_pci_range_to_resource(struct of_pci_range *range,
 		}
 		res->start = port;
 	} else {
+#ifndef CONFIG_PHYS_ADDR_T_64BIT
+		if (upper_32_bits(range->cpu_addr)) {
+			err = -EINVAL;
+			goto invalid_range;
+		}
+#endif
 		res->start = range->cpu_addr;
 	}
 	res->end = res->start + range->size - 1;
Signature · 1 line
2.4.4
maintainer
#2 lore raw

Re: [PATCH 1/2] PCI: of: Add 64-bit address recognition without LPAE support

Quoted 28 lines · Pavel Fedin

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.

---
 drivers/of/address.c | 6 ++++++
 1 file changed, 6 insertions(+)
drivers/of/address.c +0 -0
index 384574c..9a8f8c3 100644

drivers/of/address.c int of_pci_range_to_resource(struct of_pci_range *range, · line 334

Quoted 5 lines
drivers/of/address.c +2 -0
@@ -330,6 +330,12 @@ int of_pci_range_to_resource(struct of_pci_range *range,
                }
                res->start = port;
        } else {
+#ifndef CONFIG_PHYS_ADDR_T_64BIT
+               if (upper_32_bits(range->cpu_addr)) {

Drop the ifdef:

if ((sizeof(phys_addr_t) > 4) && upper_32_bits(range->cpu_addr)) {

Seems fine otherwise.

Quoted 10 lines
drivers/of/address.c +4 -1
+                       err = -EINVAL;
+                       goto invalid_range;
+               }
+#endif
                res->start = range->cpu_addr;
        }
        res->end = res->start + range->size - 1;
--

2.4.4

#3 lore raw

PATCH 2/2 PCI: of: Ignore resources with failed translation

In reply to Pavel Fedin

This patch allows PCI host controller to function even if part of resources is unusable for some reason. An example is non-LPAE kernel on a machine which has some 64-bit resources. Unusable resources will be just skipped instead of a complete failure.

---
 drivers/of/of_pci.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)
drivers/of/of_pci.c +4 -2
index 5751dc5..ea7c2b6 100644
@@ -223,8 +223,10 @@ int of_pci_get_host_bridge_resources(struct device_node *dev,
 		}
 
 		err = of_pci_range_to_resource(&range, dev, res);
-		if (err)
-			goto conversion_failed;
+		if (err) {
+			kfree(res);
+			continue;
+		}
 
 		if (resource_type(res) == IORESOURCE_IO) {
 			if (!io_base) {
Signature · 1 line
2.4.4