Re: [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]

 




On 3/13/24 13:48, Daniel Bryant wrote:
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.

The format of 'range' entry is  <child addr> <parent addr> <size>.

the parent address is (0x82000000 0x24 0x28000000) which is a pci address (not CPU address).

This address should match one of the range entry of its parent.

0x82000000 indicates 32-bit iomem. But the offset is  64-bit. (0x24 0x28000000) which looks odd.

I would suggest to look into lspci -v output as well and debug in of_bus_pci_map() to see why it does not match any entry.


Thanks,

Lizhi

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