[BUG] PCI: of: of_pci_make_dev_node() creates ranges that fail address translation

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



I'm using the of_pci_make_dev_node() framework to dynamically create
nodes for the host bridge and attached device, then applying an overlay to
create a simple-bus and children on the endpoint device. The initial problem
is that none of the children create any memory resources.  This is on
a DT-based system, aarch64 hardware.

The overall bus hierarchy is this:

PCIe root port controller -> host bridge -> device -> simple-bus ->
[subdevices].

1. Root port controller is defined by static DT blob.
2. bridge and device of_nodes are created by of_pci_make_dev_node()
3. simple-bus and subdevices are added from a single overlay.

The end result is very similar to the test case in
drivers/of/unittest-data/tests-address.dtsi. I've traced the failure
for this hardware to of_translate_address() always returning
OF_BAD_ADDR for any of the "reg" properties of a subdevice.The
critical difference between the working unit test and the hardware DT
is that the hardware PCIe root port controller has a ranges property
that's not just an identity mapping.

arch/arm64/boot/dts/nvidia/tegra234.dtsi contains the following
definition, note specifically the second ranges entry:

    pcie@14160000 {
        compatible = "nvidia,tegra234-pcie";
        device_type = "pci";
        // ...
        ranges = <0x43000000 0x21 0x40000000 0x21 0x40000000 0x2
0xe8000000>, /* prefetchable memory (11904 MB) */
                <0x02000000 0x0  0x40000000 0x24 0x28000000 0x0
0x08000000>, /* non-prefetchable memory (128 MB) */
                <0x01000000 0x0  0x36100000 0x00 0x36100000 0x0
0x00100000>; /* downstream I/O (1 MB) */
    };

Then when the child bridge is created, a of_node is created with the
following properties:

    pci@0,0 {
            compatible = "pci10de,229c\0pciclass,060400\0pciclass,0604";

            #address-cells = <0x03>;
            #size-cells = <0x02>;
            bus-range = <0x01 0xff>;
            device_type = "pci";

            ranges = <0x82000000 0x24 0x28000000 0x82000000 0x24
0x28000000 0x00 0x200000>;
    };

This ranges entry is a simple passthrough, but it's of the addresses
already translated to the CPU address space, and not the bus address.
This will cause of_translate_address() to fail when it reaches
pcie@14160000 and doesn't match.

As a caveat, I'm currently seeing this on hardware on a downstream
vendor kernel. I'm still working to reproduce on mainline 6.8 (via
qemu, probably?), but I don't yet see anything that would stop this
from being any different there.

Dan




[Index of Archives]     [DMA Engine]     [Linux Coverity]     [Linux USB]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Greybus]

  Powered by Linux