[PATCH v2] PCI: mvebu: Fix use of for_each_of_range() iterator

Klaus Kudielka posted 1 patch 1 day, 5 hours ago
drivers/pci/controller/pci-mvebu.c | 21 ++++-----------------
1 file changed, 4 insertions(+), 17 deletions(-)
[PATCH v2] PCI: mvebu: Fix use of for_each_of_range() iterator
Posted by Klaus Kudielka 1 day, 5 hours ago
The blamed commit simplifies code, by using the for_each_of_range()
iterator. But it results in no pci devices being detected anymore on
Turris Omnia (and probably other mvebu targets).

Issue #1:

To determine range.flags, of_pci_range_parser_one() uses bus->get_flags(),
which resolves to of_bus_pci_get_flags(). That function already returns an
IORESOURCE bit field, and NOT the original flags from the "ranges"
resource.

Then mvebu_get_tgt_attr() attempts the very same conversion again.
But this is a misinterpretation of range.flags.

Remove the misinterpretation of range.flags in mvebu_get_tgt_attr(),
to restore the intended behavior.

Issue #2:

The driver needs target and attributes, which are encoded in the raw
address values of the "/soc/pcie/ranges" resource. According to
of_pci_range_parser_one(), the raw values are stored in range.bus_addr
and range.parent_bus_addr, respectively. range.cpu_addr is a translated
version of range.parent_bus_addr, and not relevant here.

Use the correct range structure member, to extract target and attributes.
This restores the intended behavior.

Signed-off-by: Klaus Kudielka <klaus.kudielka@gmail.com>
Fixes: 5da3d94a23c6 ("PCI: mvebu: Use for_each_of_range() iterator for parsing "ranges"")
Reported-by: Bjorn Helgaas <helgaas@kernel.org>
Closes: https://lore.kernel.org/r/20250820184603.GA633069@bhelgaas/
Reported-by: Jan Palus <jpalus@fastmail.com>
Closes: https://bugzilla.kernel.org/show_bug.cgi?id=220479
---
v2: Fix issue #2, as well.

 drivers/pci/controller/pci-mvebu.c | 21 ++++-----------------
 1 file changed, 4 insertions(+), 17 deletions(-)

diff --git a/drivers/pci/controller/pci-mvebu.c b/drivers/pci/controller/pci-mvebu.c
index 755651f338..a72aa57591 100644
--- a/drivers/pci/controller/pci-mvebu.c
+++ b/drivers/pci/controller/pci-mvebu.c
@@ -1168,12 +1168,6 @@ static void __iomem *mvebu_pcie_map_registers(struct platform_device *pdev,
 	return devm_ioremap_resource(&pdev->dev, &port->regs);
 }
 
-#define DT_FLAGS_TO_TYPE(flags)       (((flags) >> 24) & 0x03)
-#define    DT_TYPE_IO                 0x1
-#define    DT_TYPE_MEM32              0x2
-#define DT_CPUADDR_TO_TARGET(cpuaddr) (((cpuaddr) >> 56) & 0xFF)
-#define DT_CPUADDR_TO_ATTR(cpuaddr)   (((cpuaddr) >> 48) & 0xFF)
-
 static int mvebu_get_tgt_attr(struct device_node *np, int devfn,
 			      unsigned long type,
 			      unsigned int *tgt,
@@ -1189,19 +1183,12 @@ static int mvebu_get_tgt_attr(struct device_node *np, int devfn,
 		return -EINVAL;
 
 	for_each_of_range(&parser, &range) {
-		unsigned long rtype;
 		u32 slot = upper_32_bits(range.bus_addr);
 
-		if (DT_FLAGS_TO_TYPE(range.flags) == DT_TYPE_IO)
-			rtype = IORESOURCE_IO;
-		else if (DT_FLAGS_TO_TYPE(range.flags) == DT_TYPE_MEM32)
-			rtype = IORESOURCE_MEM;
-		else
-			continue;
-
-		if (slot == PCI_SLOT(devfn) && type == rtype) {
-			*tgt = DT_CPUADDR_TO_TARGET(range.cpu_addr);
-			*attr = DT_CPUADDR_TO_ATTR(range.cpu_addr);
+		if (slot == PCI_SLOT(devfn) &&
+		    type == (range.flags & IORESOURCE_TYPE_BITS)) {
+			*tgt = (range.parent_bus_addr >> 56) & 0xFF;
+			*attr = (range.parent_bus_addr >> 48) & 0xFF;
 			return 0;
 		}
 	}
-- 
2.50.1
Re: [PATCH v2] PCI: mvebu: Fix use of for_each_of_range() iterator
Posted by Jan Palus 16 hours ago
On 07.09.2025 12:21, Klaus Kudielka wrote:
> The blamed commit simplifies code, by using the for_each_of_range()
> iterator. But it results in no pci devices being detected anymore on
> Turris Omnia (and probably other mvebu targets).
> 
> Issue #1:
> 
> To determine range.flags, of_pci_range_parser_one() uses bus->get_flags(),
> which resolves to of_bus_pci_get_flags(). That function already returns an
> IORESOURCE bit field, and NOT the original flags from the "ranges"
> resource.
> 
> Then mvebu_get_tgt_attr() attempts the very same conversion again.
> But this is a misinterpretation of range.flags.
> 
> Remove the misinterpretation of range.flags in mvebu_get_tgt_attr(),
> to restore the intended behavior.
> 
> Issue #2:
> 
> The driver needs target and attributes, which are encoded in the raw
> address values of the "/soc/pcie/ranges" resource. According to
> of_pci_range_parser_one(), the raw values are stored in range.bus_addr
> and range.parent_bus_addr, respectively. range.cpu_addr is a translated
> version of range.parent_bus_addr, and not relevant here.
> 
> Use the correct range structure member, to extract target and attributes.
> This restores the intended behavior.
> 
> Signed-off-by: Klaus Kudielka <klaus.kudielka@gmail.com>
> Fixes: 5da3d94a23c6 ("PCI: mvebu: Use for_each_of_range() iterator for parsing "ranges"")
> Reported-by: Bjorn Helgaas <helgaas@kernel.org>
> Closes: https://lore.kernel.org/r/20250820184603.GA633069@bhelgaas/
> Reported-by: Jan Palus <jpalus@fastmail.com>
> Closes: https://bugzilla.kernel.org/show_bug.cgi?id=220479
> ---
> v2: Fix issue #2, as well.
> 
>  drivers/pci/controller/pci-mvebu.c | 21 ++++-----------------
>  1 file changed, 4 insertions(+), 17 deletions(-)

Confirmed the patch applied on top of 6.16.5 fixes all the issues
introduced with 5da3d94a23c6.

Tested-by: Jan Palus <jpalus@fastmail.com>
Re: [PATCH v2] PCI: mvebu: Fix use of for_each_of_range() iterator
Posted by Tony Dinh 16 hours ago
On Sun, Sep 7, 2025 at 4:42 PM Jan Palus <jpalus@fastmail.com> wrote:
>
> On 07.09.2025 12:21, Klaus Kudielka wrote:
> > The blamed commit simplifies code, by using the for_each_of_range()
> > iterator. But it results in no pci devices being detected anymore on
> > Turris Omnia (and probably other mvebu targets).
> >
> > Issue #1:
> >
> > To determine range.flags, of_pci_range_parser_one() uses bus->get_flags(),
> > which resolves to of_bus_pci_get_flags(). That function already returns an
> > IORESOURCE bit field, and NOT the original flags from the "ranges"
> > resource.
> >
> > Then mvebu_get_tgt_attr() attempts the very same conversion again.
> > But this is a misinterpretation of range.flags.
> >
> > Remove the misinterpretation of range.flags in mvebu_get_tgt_attr(),
> > to restore the intended behavior.
> >
> > Issue #2:
> >
> > The driver needs target and attributes, which are encoded in the raw
> > address values of the "/soc/pcie/ranges" resource. According to
> > of_pci_range_parser_one(), the raw values are stored in range.bus_addr
> > and range.parent_bus_addr, respectively. range.cpu_addr is a translated
> > version of range.parent_bus_addr, and not relevant here.
> >
> > Use the correct range structure member, to extract target and attributes.
> > This restores the intended behavior.
> >
> > Signed-off-by: Klaus Kudielka <klaus.kudielka@gmail.com>
> > Fixes: 5da3d94a23c6 ("PCI: mvebu: Use for_each_of_range() iterator for parsing "ranges"")
> > Reported-by: Bjorn Helgaas <helgaas@kernel.org>
> > Closes: https://lore.kernel.org/r/20250820184603.GA633069@bhelgaas/
> > Reported-by: Jan Palus <jpalus@fastmail.com>
> > Closes: https://bugzilla.kernel.org/show_bug.cgi?id=220479
> > ---
> > v2: Fix issue #2, as well.
> >
> >  drivers/pci/controller/pci-mvebu.c | 21 ++++-----------------
> >  1 file changed, 4 insertions(+), 17 deletions(-)
>
> Confirmed the patch applied on top of 6.16.5 fixes all the issues
> introduced with 5da3d94a23c6.
>
> Tested-by: Jan Palus <jpalus@fastmail.com>
>
Sorry, should have said:

Tested on these Marvell Kirkwood SoC boards: Cloudengine Pogoplug
Series 4 (88F6192), ZyXEL NAS325 (88F6282), and Synology DS112
(88F6282) running kernel 6.16.5.

All the best,
Tony
Re: [PATCH v2] PCI: mvebu: Fix use of for_each_of_range() iterator
Posted by Tony Dinh 16 hours ago
On Sun, Sep 7, 2025 at 3:24 AM Klaus Kudielka <klaus.kudielka@gmail.com> wrote:
>
> The blamed commit simplifies code, by using the for_each_of_range()
> iterator. But it results in no pci devices being detected anymore on
> Turris Omnia (and probably other mvebu targets).
>
> Issue #1:
>
> To determine range.flags, of_pci_range_parser_one() uses bus->get_flags(),
> which resolves to of_bus_pci_get_flags(). That function already returns an
> IORESOURCE bit field, and NOT the original flags from the "ranges"
> resource.
>
> Then mvebu_get_tgt_attr() attempts the very same conversion again.
> But this is a misinterpretation of range.flags.
>
> Remove the misinterpretation of range.flags in mvebu_get_tgt_attr(),
> to restore the intended behavior.
>
> Issue #2:
>
> The driver needs target and attributes, which are encoded in the raw
> address values of the "/soc/pcie/ranges" resource. According to
> of_pci_range_parser_one(), the raw values are stored in range.bus_addr
> and range.parent_bus_addr, respectively. range.cpu_addr is a translated
> version of range.parent_bus_addr, and not relevant here.
>
> Use the correct range structure member, to extract target and attributes.
> This restores the intended behavior.
>
> Signed-off-by: Klaus Kudielka <klaus.kudielka@gmail.com>
> Fixes: 5da3d94a23c6 ("PCI: mvebu: Use for_each_of_range() iterator for parsing "ranges"")
> Reported-by: Bjorn Helgaas <helgaas@kernel.org>
> Closes: https://lore.kernel.org/r/20250820184603.GA633069@bhelgaas/
> Reported-by: Jan Palus <jpalus@fastmail.com>
> Closes: https://bugzilla.kernel.org/show_bug.cgi?id=220479
> ---
> v2: Fix issue #2, as well.
>
>  drivers/pci/controller/pci-mvebu.c | 21 ++++-----------------
>  1 file changed, 4 insertions(+), 17 deletions(-)
>
> diff --git a/drivers/pci/controller/pci-mvebu.c b/drivers/pci/controller/pci-mvebu.c
> index 755651f338..a72aa57591 100644
> --- a/drivers/pci/controller/pci-mvebu.c
> +++ b/drivers/pci/controller/pci-mvebu.c
> @@ -1168,12 +1168,6 @@ static void __iomem *mvebu_pcie_map_registers(struct platform_device *pdev,
>         return devm_ioremap_resource(&pdev->dev, &port->regs);
>  }
>
> -#define DT_FLAGS_TO_TYPE(flags)       (((flags) >> 24) & 0x03)
> -#define    DT_TYPE_IO                 0x1
> -#define    DT_TYPE_MEM32              0x2
> -#define DT_CPUADDR_TO_TARGET(cpuaddr) (((cpuaddr) >> 56) & 0xFF)
> -#define DT_CPUADDR_TO_ATTR(cpuaddr)   (((cpuaddr) >> 48) & 0xFF)
> -
>  static int mvebu_get_tgt_attr(struct device_node *np, int devfn,
>                               unsigned long type,
>                               unsigned int *tgt,
> @@ -1189,19 +1183,12 @@ static int mvebu_get_tgt_attr(struct device_node *np, int devfn,
>                 return -EINVAL;
>
>         for_each_of_range(&parser, &range) {
> -               unsigned long rtype;
>                 u32 slot = upper_32_bits(range.bus_addr);
>
> -               if (DT_FLAGS_TO_TYPE(range.flags) == DT_TYPE_IO)
> -                       rtype = IORESOURCE_IO;
> -               else if (DT_FLAGS_TO_TYPE(range.flags) == DT_TYPE_MEM32)
> -                       rtype = IORESOURCE_MEM;
> -               else
> -                       continue;
> -
> -               if (slot == PCI_SLOT(devfn) && type == rtype) {
> -                       *tgt = DT_CPUADDR_TO_TARGET(range.cpu_addr);
> -                       *attr = DT_CPUADDR_TO_ATTR(range.cpu_addr);
> +               if (slot == PCI_SLOT(devfn) &&
> +                   type == (range.flags & IORESOURCE_TYPE_BITS)) {
> +                       *tgt = (range.parent_bus_addr >> 56) & 0xFF;
> +                       *attr = (range.parent_bus_addr >> 48) & 0xFF;
>                         return 0;
>                 }
>         }
> --
> 2.50.1
>
>
Tested on these Marvell Kirkwood SoC boards: Cloudengine Pogoplug
Series 4 (88F6192), ZyXEL NAS325 (88F6282), and Synology DS112
(88F6282).

Tested-by: Tony Dinh <mibodhi@gmail.com>

All the best,
Tony