drivers/of/address.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-)
The function of_dma_get_max_cpu_address() for a device node should choose
the highest cpu address among the ones that subtree nodes can access.
However, there was a bug of choosing the lowest cpu address and this
commit is to fix it.
Signed-off-by: Joonwon Kang <kjw1627@gmail.com>
---
drivers/of/address.c | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/drivers/of/address.c b/drivers/of/address.c
index f0f8f0dd191c..5e984e0d372b 100644
--- a/drivers/of/address.c
+++ b/drivers/of/address.c
@@ -969,6 +969,7 @@ phys_addr_t __init of_dma_get_max_cpu_address(struct device_node *np)
{
phys_addr_t max_cpu_addr = PHYS_ADDR_MAX;
struct of_range_parser parser;
+ phys_addr_t max_subtree_max_addr = PHYS_ADDR_MAX;
phys_addr_t subtree_max_addr;
struct device_node *child;
struct of_range range;
@@ -992,10 +993,17 @@ phys_addr_t __init of_dma_get_max_cpu_address(struct device_node *np)
for_each_available_child_of_node(np, child) {
subtree_max_addr = of_dma_get_max_cpu_address(child);
- if (max_cpu_addr > subtree_max_addr)
- max_cpu_addr = subtree_max_addr;
+ if (subtree_max_addr == PHYS_ADDR_MAX)
+ continue;
+
+ if (max_subtree_max_addr == PHYS_ADDR_MAX)
+ max_subtree_max_addr = subtree_max_addr;
+ else
+ max_subtree_max_addr = max(max_subtree_max_addr, subtree_max_addr);
}
+ max_cpu_addr = min(max_cpu_addr, max_subtree_max_addr);
+
return max_cpu_addr;
}
--
2.46.0
On Sun, Jul 27, 2025 at 1:01 PM Joonwon Kang <kjw1627@gmail.com> wrote:
>
> The function of_dma_get_max_cpu_address() for a device node should choose
> the highest cpu address among the ones that nodes can access.
> However, there was a bug of choosing the lowest cpu address and this
> commit is to fix it.
Please provide a test case in the DT unittests or at least details on
the DT that is affected by the bug.
> Signed-off-by: Joonwon Kang <kjw1627@gmail.com>
> ---
> drivers/of/address.c | 12 ++++++++++--
> 1 file changed, 10 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/of/address.c b/drivers/of/address.c
> index f0f8f0dd191c..5e984e0d372b 100644
> --- a/drivers/of/address.c
> +++ b/drivers/of/address.c
> @@ -969,6 +969,7 @@ phys_addr_t __init of_dma_get_max_cpu_address(struct device_node *np)
> {
> phys_addr_t max_cpu_addr = PHYS_ADDR_MAX;
> struct of_range_parser parser;
> + phys_addr_t max_subtree_max_addr = PHYS_ADDR_MAX;
> phys_addr_t subtree_max_addr;
> struct device_node *child;
> struct of_range range;
> @@ -992,10 +993,17 @@ phys_addr_t __init of_dma_get_max_cpu_address(struct device_node *np)
>
> for_each_available_child_of_node(np, child) {
> subtree_max_addr = of_dma_get_max_cpu_address(child);
> - if (max_cpu_addr > subtree_max_addr)
> - max_cpu_addr = subtree_max_addr;
> + if (subtree_max_addr == PHYS_ADDR_MAX)
> + continue;
> +
> + if (max_subtree_max_addr == PHYS_ADDR_MAX)
> + max_subtree_max_addr = subtree_max_addr;
> + else
> + max_subtree_max_addr = max(max_subtree_max_addr, subtree_max_addr);
> }
>
> + max_cpu_addr = min(max_cpu_addr, max_subtree_max_addr);
> +
> return max_cpu_addr;
> }
>
> --
> 2.46.0
>
On Sun, Jul 27, 2025 at 1:01 PM Joonwon Kang <kjw1627@gmail.com> wrote:
> >
> > The function of_dma_get_max_cpu_address() for a device node should choose
> > the highest cpu address among the ones that nodes can access.
> > However, there was a bug of choosing the lowest cpu address and this
> > commit is to fix it.
>
> Please provide a test case in the DT unittests or at least details on
> the DT that is affected by the bug.
While working on the DT unittests, I got two questions to which I had failed to
have clear answers. Let's assume that the device tree looks as follows.
parent_bus@... {
#address-cells = <1>;
#size-cells = <1>;
dma-ranges = <0x0 0x0 0x1000>;
child_bus@... {
#address-cells = <1>;
#size-cells = <1>;
/* Note that the size part exceeds the `parent_bus`' dma size. */
dma-ranges = <0x0 0x0 0x2000>;
child_device_1@... {
/*
* Note that the size part exceeds the `child_bus`' dma size and
* also the `parent_bus`' dma size.
*/
reg = <0x0 0x3000>;
};
child_device_2@... {
/*
* Note that the address part transitively exceeds the
*`parent_bus`' end address.
*/
reg = <0x1000 0x1000>
};
};
another_child_bus@... {
#address-cells = <1>;
#size-cells = <1>;
dma-ranges = <0x0 0x0 0x300>;
};
};
Q1: What is the expected output of `of_dma_get_max_cpu_address(parent_bus)`?
I think it should be 0xfff since the `dma-ranges` in the `child_bus` should be
capped to the parent max cpu address instead of treating it as if the
`dma-ranges` in the `child_bus` does not exist. The current expectation is
0x2ff which is for `another_child_bus` based on the existing test case
in drivers/of/unittest.c and drivers/of/tests-address.dtsi.
Q2: `of_dma_get_max_cpu_address(child_device_1, reg_prop, &addr, &length)`
returns a success with `addr` set to 0x0 and `length` set to 0x3000. Similarly,
`of_translate_dma_address(child_device_1, reg_prop)` returns a success. On the
other hand, both functions for `child_device_2` return a failure since the
address is out of parent ranges. I think those functions should also fail
for `child_device_1` since the dma "end" address of the `child_device_1` node
is not valid in the first place. Are the current behaviors of both functions
intended?
> > Signed-off-by: Joonwon Kang <kjw1627@gmail.com>
> > ---
> > drivers/of/address.c | 12 ++++++++++--
> > 1 file changed, 10 insertions(+), 2 deletions(-)
> >
> > diff --git a/drivers/of/address.c b/drivers/of/address.c
> > index f0f8f0dd191c..5e984e0d372b 100644
> > --- a/drivers/of/address.c
> > +++ b/drivers/of/address.c
> > @@ -969,6 +969,7 @@ phys_addr_t __init of_dma_get_max_cpu_address(struct device_node *np)
> > {
> > phys_addr_t max_cpu_addr = PHYS_ADDR_MAX;
> > struct of_range_parser parser;
> > + phys_addr_t max_subtree_max_addr = PHYS_ADDR_MAX;
> > phys_addr_t subtree_max_addr;
> > struct device_node *child;
> > struct of_range range;
> > @@ -992,10 +993,17 @@ phys_addr_t __init of_dma_get_max_cpu_address(struct device_node *np)
> >
> > for_each_available_child_of_node(np, child) {
> > subtree_max_addr = of_dma_get_max_cpu_address(child);
> > - if (max_cpu_addr > subtree_max_addr)
> > - max_cpu_addr = subtree_max_addr;
> > + if (subtree_max_addr == PHYS_ADDR_MAX)
> > + continue;
> > +
> > + if (max_subtree_max_addr == PHYS_ADDR_MAX)
> > + max_subtree_max_addr = subtree_max_addr;
> > + else
> > + max_subtree_max_addr = max(max_subtree_max_addr, subtree_max_addr);
> > }
> >
> > + max_cpu_addr = min(max_cpu_addr, max_subtree_max_addr);
> > +
> > return max_cpu_addr;
> > }
> >
> > --
> > 2.46.0
> >
On Mon, Aug 4, 2025 at 11:43 AM Joonwon Kang <kjw1627@gmail.com> wrote:
>
> On Sun, Jul 27, 2025 at 1:01 PM Joonwon Kang <kjw1627@gmail.com> wrote:
> > >
> > > The function of_dma_get_max_cpu_address() for a device node should choose
> > > the highest cpu address among the ones that nodes can access.
> > > However, there was a bug of choosing the lowest cpu address and this
> > > commit is to fix it.
> >
> > Please provide a test case in the DT unittests or at least details on
> > the DT that is affected by the bug.
>
> While working on the DT unittests, I got two questions to which I had failed to
> have clear answers. Let's assume that the device tree looks as follows.
>
> parent_bus@... {
> #address-cells = <1>;
> #size-cells = <1>;
> dma-ranges = <0x0 0x0 0x1000>;
>
> child_bus@... {
> #address-cells = <1>;
> #size-cells = <1>;
> /* Note that the size part exceeds the `parent_bus`' dma size. */
> dma-ranges = <0x0 0x0 0x2000>;
>
> child_device_1@... {
> /*
> * Note that the size part exceeds the `child_bus`' dma size and
> * also the `parent_bus`' dma size.
> */
> reg = <0x0 0x3000>;
dma-ranges is irrelevant for 'reg'. 'ranges' applies to 'reg'.
> };
>
> child_device_2@... {
> /*
> * Note that the address part transitively exceeds the
> *`parent_bus`' end address.
> */
> reg = <0x1000 0x1000>
> };
> };
>
> another_child_bus@... {
> #address-cells = <1>;
> #size-cells = <1>;
> dma-ranges = <0x0 0x0 0x300>;
> };
> };
>
> Q1: What is the expected output of `of_dma_get_max_cpu_address(parent_bus)`?
> I think it should be 0xfff since the `dma-ranges` in the `child_bus` should be
> capped to the parent max cpu address instead of treating it as if the
> `dma-ranges` in the `child_bus` does not exist. The current expectation is
> 0x2ff which is for `another_child_bus` based on the existing test case
> in drivers/of/unittest.c and drivers/of/tests-address.dtsi.
0x2FF is correct. The max address returned is the minimum.
>
> Q2: `of_dma_get_max_cpu_address(child_device_1, reg_prop, &addr, &length)`
> returns a success with `addr` set to 0x0 and `length` set to 0x3000. Similarly,
> `of_translate_dma_address(child_device_1, reg_prop)` returns a success. On the
> other hand, both functions for `child_device_2` return a failure since the
> address is out of parent ranges. I think those functions should also fail
> for `child_device_1` since the dma "end" address of the `child_device_1` node
> is not valid in the first place. Are the current behaviors of both functions
> intended?
Passing in child_device_1 is invalid. It doesn't contain dma-ranges,
so it will return PHYS_ADDR_MAX.
Passing 'reg' into the DMA translation functions is invalid. 'reg' has
0 to do with DMA addresses.
Rob
>
> > > Signed-off-by: Joonwon Kang <kjw1627@gmail.com>
> > > ---
> > > drivers/of/address.c | 12 ++++++++++--
> > > 1 file changed, 10 insertions(+), 2 deletions(-)
> > >
> > > diff --git a/drivers/of/address.c b/drivers/of/address.c
> > > index f0f8f0dd191c..5e984e0d372b 100644
> > > --- a/drivers/of/address.c
> > > +++ b/drivers/of/address.c
> > > @@ -969,6 +969,7 @@ phys_addr_t __init of_dma_get_max_cpu_address(struct device_node *np)
> > > {
> > > phys_addr_t max_cpu_addr = PHYS_ADDR_MAX;
> > > struct of_range_parser parser;
> > > + phys_addr_t max_subtree_max_addr = PHYS_ADDR_MAX;
> > > phys_addr_t subtree_max_addr;
> > > struct device_node *child;
> > > struct of_range range;
> > > @@ -992,10 +993,17 @@ phys_addr_t __init of_dma_get_max_cpu_address(struct device_node *np)
> > >
> > > for_each_available_child_of_node(np, child) {
> > > subtree_max_addr = of_dma_get_max_cpu_address(child);
> > > - if (max_cpu_addr > subtree_max_addr)
> > > - max_cpu_addr = subtree_max_addr;
> > > + if (subtree_max_addr == PHYS_ADDR_MAX)
> > > + continue;
> > > +
> > > + if (max_subtree_max_addr == PHYS_ADDR_MAX)
> > > + max_subtree_max_addr = subtree_max_addr;
> > > + else
> > > + max_subtree_max_addr = max(max_subtree_max_addr, subtree_max_addr);
> > > }
> > >
> > > + max_cpu_addr = min(max_cpu_addr, max_subtree_max_addr);
> > > +
> > > return max_cpu_addr;
> > > }
> > >
> > > --
> > > 2.46.0
> > >
© 2016 - 2026 Red Hat, Inc.