[PATCH V8 02/13] PCI: host-generic: Add common helpers for parsing Root Port properties

Sherry Sun sherry.sun at nxp.com
Tue Mar 17 03:35:05 PDT 2026


> 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 at nxp.com>
> > > > ---
> > > >  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


More information about the linux-arm-kernel mailing list