[PATCH] nvme: Fix missing inbound DMA offset calculation

Torsten Duwe duwe at lst.de
Wed May 6 11:42:22 CEST 2026


On Wed, 6 May 2026 10:59:55 +0200
Neil Armstrong <neil.armstrong at linaro.org> wrote:

> On 5/6/26 09:52, Neil Armstrong wrote:
> > On 4/30/26 16:54, Torsten Duwe wrote:
[...]
> >> +/*
> >> + * This macro detects the correct inbound DMA offset in both cases:
> >> + *   1) the NVMe is mentioned in the device tree, along with its parent,
> >> + *    and no intermediate PCIe bus node in between.
> >> + *   2) the NVMe was found dynamically by PCI enumeration which has created
> >> + *    an intermediate PCIe bus node. That node will be skipped and the offset
> >> + *    looked up in the grandparent.
> >> + */
> >> +#define DEV_ADDR(a)        (dev_has_ofnode(dev->udev) ? \
> >> +                    dev_phys_to_bus(dev->udev, (a)) : \
> >> +                    dev_phys_to_bus(dev->udev->parent, (a)))
> > 
> > This looks subspicious, what is the state of the rpi5 here ? with a DT node or without ?
> > 
> > AFAIK NVMes are always dynamically detected, it seems the dma_offset is not correctly
> > copied to the nvme udev when created.

Yes, they are _usually_ detected via PCI enumeration, which dynamically
adds a bus node without a corresponding DT node. But it is not prohibited
to explicitly specify an NVMe disk in the device tree, I think. We've seen
this with the RP1 chip (patches yet to come). With and without.

> 
> So to check could you try adding something like:
> 
> ```
> diff --git a/dts/upstream/src/arm64/broadcom/bcm2712-rpi-5-b-base.dtsi b/dts/upstream/src/arm64/broadcom/bcm2712-rpi-5-b-base.dtsi
> index 04738bf281e..640c5987077 100644
> --- a/dts/upstream/src/arm64/broadcom/bcm2712-rpi-5-b-base.dtsi
> +++ b/dts/upstream/src/arm64/broadcom/bcm2712-rpi-5-b-base.dtsi
> @@ -247,6 +247,15 @@
> 
>   &pcie1 {
>          status = "okay";
> +
> +       pci at 0,0 {
> +               reg = <0x0 0x0 0x0 0x0 0x0>;
> +               ranges;
> +               bus-range = <0 1>;
> +               device_type = "pci";
> +               #address-cells = <3>;
> +               #size-cells = <2>;
> +       };
>   };
> 
>   &pcie2 {
> ```

We've had that in a previous version. The downside of this is that it
would have to be done for each platform and each potential m.2 socket.

> or:
> 
> ```
> --- a/drivers/core/device.c
> +++ b/drivers/core/device.c
> @@ -459,7 +459,19 @@ static int device_get_dma_constraints(struct udevice *dev)
>          u64 size = 0;
>          int ret;
> 
> -       if (!CONFIG_IS_ENABLED(DM_DMA) || !parent || !dev_has_ofnode(parent))
> +       if (!CONFIG_IS_ENABLED(DM_DMA) || !parent)
> +               return 0;
> +
> +       /* Look for the first node in the parent chain */
> +       while (parent) {
> +               if (dev_has_ofnode(parent))
> +                       break;
> +
> +               parent = dev_get_parent(parent);
> +       }
> +
> +       /* No parents have a node, bail out */
> +       if (!parent)
>                  return 0;
> 
>          /*
> ```
> Which will try to find the node higher in the parent chain.

Now this looks extremely tempting. It should solve the problem for NVMe
and probably a few other PCI(e) scenarios in the future.

I'll give it a spin...
Thanks,

	Torsten


More information about the U-Boot mailing list