[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20250804164329.98971-1-kjw1627@gmail.com>
Date: Tue, 5 Aug 2025 00:43:14 +0800
From: Joonwon Kang <kjw1627@...il.com>
To: robh@...nel.org
Cc: devicetree@...r.kernel.org,
kjw1627@...il.com,
linux-kernel@...r.kernel.org,
nsaenzjulienne@...e.de,
saravanak@...gle.com
Subject: Re: [PATCH] of: address: Fix bug to get the highest cpu address of subtrees for dma
On Sun, Jul 27, 2025 at 1:01 PM Joonwon Kang <kjw1627@...il.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@...il.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
> >
Powered by blists - more mailing lists