linux/drivers/of
Herve Codina 99171d81c5 of: address: Fix address translation when address-size is greater than 2
[ Upstream commit 42604f8eb7 ]

With the recent addition of of_pci_prop_ranges() in commit 407d1a5192
("PCI: Create device tree node for bridge"), the ranges property can
have a 3 cells child address, a 3 cells parent address and a 2 cells
child size.

A range item property for a PCI device is filled as follow:
  <BAR_nbr> 0 0 <phys.hi> <phys.mid> <phys.low> <BAR_sizeh> <BAR_sizel>
  <-- Child --> <-- Parent (PCI definition) --> <- BAR size (64bit) -->

This allow to translate BAR addresses from the DT. For instance:
pci@0,0 {
  #address-cells = <0x03>;
  #size-cells = <0x02>;
  device_type = "pci";
  compatible = "pci11ab,100", "pciclass,060400", "pciclass,0604";
  ranges = <0x82000000 0x00 0xe8000000
            0x82000000 0x00 0xe8000000
	    0x00 0x4400000>;
  ...
  dev@0,0 {
    #address-cells = <0x03>;
    #size-cells = <0x02>;
    compatible = "pci1055,9660", "pciclass,020000", "pciclass,0200";
    /* Translations for BAR0 to BAR5 */
    ranges = <0x00 0x00 0x00 0x82010000 0x00 0xe8000000 0x00 0x2000000
              0x01 0x00 0x00 0x82010000 0x00 0xea000000 0x00 0x1000000
              0x02 0x00 0x00 0x82010000 0x00 0xeb000000 0x00 0x800000
              0x03 0x00 0x00 0x82010000 0x00 0xeb800000 0x00 0x800000
              0x04 0x00 0x00 0x82010000 0x00 0xec000000 0x00 0x20000
              0x05 0x00 0x00 0x82010000 0x00 0xec020000 0x00 0x2000>;
    ...
    pci-ep-bus@0 {
      #address-cells = <0x01>;
      #size-cells = <0x01>;
      compatible = "simple-bus";
      /* Translate 0xe2000000 to BAR0 and 0xe0000000 to BAR1 */
      ranges = <0xe2000000 0x00 0x00 0x00 0x2000000
                0xe0000000 0x01 0x00 0x00 0x1000000>;
      ...
    };
  };
};

During the translation process, the "default-flags" map() function is
used to select the matching item in the ranges table and determine the
address offset from this matching item.
This map() function simply calls of_read_number() and when address-size
is greater than 2, the map() function skips the extra high address part
(ie part over 64bit). This lead to a wrong matching item and a wrong
offset computation.
Also during the translation itself, the extra high part related to the
parent address is not present in the translated address.

Fix the "default-flags" map() and translate() in order to take into
account the child extra high address part in map() and the parent extra
high address part in translate() and so having a correct address
translation for ranges patterns such as the one given in the example
above.

Signed-off-by: Herve Codina <herve.codina@bootlin.com>
Link: https://lore.kernel.org/r/20231017110221.189299-2-herve.codina@bootlin.com
Signed-off-by: Rob Herring <robh@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
2023-11-28 17:14:43 +00:00
..
unittest-data of/address: Add support for 3 address cell bus 2023-04-13 17:46:35 -05:00
address.c of: address: Fix address translation when address-size is greater than 2 2023-11-28 17:14:43 +00:00
base.c Char/Misc drivers for 6.4-rc1 2023-04-27 12:07:50 -07:00
cpu.c of: Move CPU node related functions to their own file 2023-04-13 17:46:34 -05:00
device.c of: device: Kill of_device_request_module() 2023-04-05 19:41:11 +02:00
dynamic.c of: dynamic: Fix potential memory leak in of_changeset_action() 2023-10-10 22:03:04 +02:00
fdt_address.c
fdt.c Devicetree fixes for 6.4, part 1: 2023-05-05 13:27:59 -07:00
irq.c of/irq: add missing of_node_put() for interrupt parent node 2023-01-18 11:31:42 -06:00
Kconfig of: make OF_EARLY_FLATTREE depend on HAS_IOMEM 2023-07-10 08:48:35 -06:00
kexec.c mm,ima,kexec,of: use memblock_free_late from ima_free_kexec_buffer 2023-08-18 11:47:45 -05:00
kobj.c of: make of_node_ktype constant 2023-02-06 11:03:00 -06:00
Makefile Char/Misc drivers for 6.4-rc1 2023-04-27 12:07:50 -07:00
module.c of: Move the request module helper logic to module.c 2023-04-05 19:41:10 +02:00
of_numa.c of, numa: Fetch empty NUMA node ID from distance map 2021-10-04 13:13:44 -05:00
of_private.h of: Make devtree_lock declaration private 2023-04-10 18:32:31 -05:00
of_reserved_mem.c of: reserved_mem: Use stable allocation order 2023-06-20 09:34:58 -06:00
overlay.c of: overlay: Call of_changeset_init() early 2023-09-13 09:53:26 +02:00
pdt.c of: Remove struct device_node.type pointer 2019-01-10 16:24:44 -06:00
platform.c of/platform: increase refcount of fwnode 2023-08-21 16:12:28 -05:00
property.c of: property: fw_devlink: Add a devlink for panel followers 2023-09-13 09:53:56 +02:00
resolver.c of: overlay: log the error cause on resolver failure 2020-03-02 11:32:44 -06:00
unittest.c of: unittest: Fix overlay type in apply/revert check 2023-09-13 09:53:27 +02:00