RE: [PATCH V8 02/13] PCI: host-generic: Add common helpers for parsing Root Port properties
From: Sherry Sun
Date: Tue Mar 17 2026 - 06:38:55 EST
> On Tue, Mar 17, 2026 at 08:01:28AM +0000, Sherry Sun wrote:
> >
> > > On Fri, Mar 13, 2026 at 10:08:12AM +0800, Sherry Sun wrote:
> > > > Introduce generic helper functions to parse Root Port device tree
> > > > nodes and extract common properties like reset GPIOs. This allows
> > > > multiple PCI host controller drivers to share the same parsing logic.
> > > >
> > > > Define struct pci_host_port to hold common Root Port properties
> > > > (currently only reset GPIO descriptor) and add
> > > > pci_host_common_parse_ports() to parse Root Port nodes from device
> > > tree.
> > > >
> > > > Also add the 'ports' list to struct pci_host_bridge for better
> > > > maintain parsed Root Port information.
> > > >
> > > > Signed-off-by: Sherry Sun <sherry.sun@xxxxxxx>
> > > > ---
> > > > drivers/pci/controller/pci-host-common.c | 78
> > > > ++++++++++++++++++++++++ drivers/pci/controller/pci-host-common.h
> > > > ++++++++++++++++++++++++ |
> > > 15 +++++
> > > > drivers/pci/probe.c | 1 +
> > > > include/linux/pci.h | 1 +
> > > > 4 files changed, 95 insertions(+)
> > > >
> > > > diff --git a/drivers/pci/controller/pci-host-common.c
> > > > b/drivers/pci/controller/pci-host-common.c
> > > > index d6258c1cffe5..2f012cf80463 100644
> > > > --- a/drivers/pci/controller/pci-host-common.c
> > > > +++ b/drivers/pci/controller/pci-host-common.c
> > > > @@ -9,6 +9,7 @@
> > > >
> > > > #include <linux/kernel.h>
> > > > #include <linux/module.h>
> > > > +#include <linux/gpio/consumer.h>
> > > > #include <linux/of.h>
> > > > #include <linux/of_address.h>
> > > > #include <linux/of_pci.h>
> > > > @@ -17,6 +18,83 @@
> > > >
> > > > #include "pci-host-common.h"
> > > >
> > > > +/**
> > > > + * pci_host_common_delete_ports - Cleanup function for port list
> > > > + * @data: Pointer to the port list head */ static void
> > > > +pci_host_common_delete_ports(void *data) {
> > > > + struct list_head *ports = data;
> > > > + struct pci_host_port *port, *tmp;
> > > > +
> > > > + list_for_each_entry_safe(port, tmp, ports, list)
> > > > + list_del(&port->list);
> > > > +}
> > > > +
> > > > +/**
> > > > + * pci_host_common_parse_port - Parse a single Root Port node
> > > > + * @dev: Device pointer
> > > > + * @bridge: PCI host bridge
> > > > + * @node: Device tree node of the Root Port
> > > > + *
> > > > + * Returns: 0 on success, negative error code on failure */
> > > > +static int pci_host_common_parse_port(struct device *dev,
> > > > + struct pci_host_bridge *bridge,
> > > > + struct device_node *node) {
> > > > + struct pci_host_port *port;
> > > > + struct gpio_desc *reset;
> > > > +
> > > > + reset = devm_fwnode_gpiod_get(dev, of_fwnode_handle(node),
> > > > + "reset", GPIOD_ASIS, "PERST#");
> > > > + if (IS_ERR(reset))
> > > > + return PTR_ERR(reset);
> > > > +
> > > > + port = devm_kzalloc(dev, sizeof(*port), GFP_KERNEL);
> > > > + if (!port)
> > > > + return -ENOMEM;
> > > > +
> > > > + port->reset = reset;
> > > > + INIT_LIST_HEAD(&port->list);
> > > > + list_add_tail(&port->list, &bridge->ports);
> > > > +
> > > > + return 0;
> > > > +}
> > > > +
> > > > +/**
> > > > + * pci_host_common_parse_ports - Parse Root Port nodes from
> > > > +device tree
> > > > + * @dev: Device pointer
> > > > + * @bridge: PCI host bridge
> > > > + *
> > > > + * This function iterates through child nodes of the host bridge
> > > > +and parses
> > > > + * Root Port properties (currently only reset GPIO).
> > > > + *
> > > > + * Returns: 0 on success, -ENOENT if no ports found, other
> > > > +negative error codes
> > > > + * on failure
> > > > + */
> > > > +int pci_host_common_parse_ports(struct device *dev, struct
> > > > +pci_host_bridge *bridge) {
> > > > + int ret = -ENOENT;
> > > > + int err;
> > > > +
> > > > + for_each_available_child_of_node_scoped(dev->of_node, of_port) {
> > > > + if (!of_node_is_type(of_port, "pci"))
> > > > + continue;
> > > > + ret = pci_host_common_parse_port(dev, bridge, of_port);
> > > > + if (ret)
> > > > + return ret;
> > > > + }
> > > > +
> > >
> > > I think you should just do:
> > >
> > > if (ret)
> > > return ret;
> > >
> > > and get rid of 'err'.
> >
> > Hi Mani, do you mean the following method?
> >
> > int pci_host_common_parse_ports(struct device *dev, struct
> > pci_host_bridge *bridge) {
> > int ret = -ENOENT;
> >
> > for_each_available_child_of_node_scoped(dev->of_node, of_port) {
> > if (!of_node_is_type(of_port, "pci"))
> > continue;
> > ret = pci_host_common_parse_port(dev, bridge, of_port);
> > if (ret)
> > return ret;
> > }
> >
> > if (ret)
> > return ret;
> >
> > ret = devm_add_action_or_reset(dev, pci_host_common_delete_ports,
> > &bridge->ports);
>
> Here, you can do 'return devm_add_action_or_reset()'
Hi Mani, this sounds good to me, will fix this in V9, thanks!
Best Regards
Sherry