[U-Boot] [PATCH v3 02/10] dm: pci: Add a way to iterate through all PCI devices

Bin Meng bmeng.cn at gmail.com
Tue Aug 11 06:14:21 CEST 2015


On Mon, Aug 10, 2015 at 9:05 PM, Simon Glass <sjg at chromium.org> wrote:
> These functions allow iteration through all PCI devices including bridges.
> The children of each PCI bus are returned in turn. This can be useful for
> configuring, checking or enumerating all the devices.
>
> Signed-off-by: Simon Glass <sjg at chromium.org>
> ---
>
> Changes in v3:
> - Drop the inner while() loop in skip_to_next_device() - it isn't needed
>
> Changes in v2:
> - Add a comment as to why we need to scan multiple PCI controllers
>
>  drivers/pci/pci-uclass.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++
>  include/pci.h            | 25 ++++++++++++++++++++
>  2 files changed, 85 insertions(+)
>
> diff --git a/drivers/pci/pci-uclass.c b/drivers/pci/pci-uclass.c
> index b79927e..ad65427 100644
> --- a/drivers/pci/pci-uclass.c
> +++ b/drivers/pci/pci-uclass.c
> @@ -775,6 +775,66 @@ static int pci_bridge_write_config(struct udevice *bus, pci_dev_t bdf,
>         return pci_bus_write_config(hose->ctlr, bdf, offset, value, size);
>  }
>
> +static int skip_to_next_device(struct udevice *bus, struct udevice **devp)
> +{
> +       struct udevice *dev;
> +       int ret = 0;
> +
> +       /*
> +        * Scan through all the PCI controllers. On x86 there will only be one
> +        * but that is not necessarily true on other hardware.
> +        */
> +       do {
> +               device_find_first_child(bus, &dev);
> +               if (dev) {
> +                       *devp = dev;
> +                       return 0;
> +               }
> +               ret = uclass_next_device(&bus);
> +               if (ret)
> +                       return ret;
> +       } while (bus);
> +
> +       return 0;
> +}
> +
> +int pci_find_next_device(struct udevice **devp)
> +{
> +       struct udevice *child = *devp;
> +       struct udevice *bus = child->parent;
> +       int ret;
> +
> +       /* First try all the siblings */
> +       *devp = NULL;
> +       while (child) {
> +               device_find_next_child(&child);
> +               if (child) {
> +                       *devp = child;
> +                       return 0;
> +               }
> +       }
> +
> +       /* We ran out of siblings. Try the next bus */
> +       ret = uclass_next_device(&bus);
> +       if (ret)
> +               return ret;
> +
> +       return bus ? skip_to_next_device(bus, devp) : 0;
> +}
> +
> +int pci_find_first_device(struct udevice **devp)
> +{
> +       struct udevice *bus;
> +       int ret;
> +
> +       *devp = NULL;
> +       ret = uclass_first_device(UCLASS_PCI, &bus);
> +       if (ret)
> +               return ret;
> +
> +       return skip_to_next_device(bus, devp);
> +}
> +
>  UCLASS_DRIVER(pci) = {
>         .id             = UCLASS_PCI,
>         .name           = "pci",
> diff --git a/include/pci.h b/include/pci.h
> index d1e2765..488ff44 100644
> --- a/include/pci.h
> +++ b/include/pci.h
> @@ -910,6 +910,31 @@ int pci_bus_find_devfn(struct udevice *bus, pci_dev_t find_devfn,
>                        struct udevice **devp);
>
>  /**
> + * pci_find_first_device() - return the first available PCI device
> + *
> + * This function and pci_find_first_device() allow iteration through all
> + * available PCI devices on all buses. Assuming there are any, this will
> + * return the first one.
> + *
> + * @devp:      Set to the first available device, or NULL if no more are left
> + *             or we got an error
> + * @return 0 if all is OK, -ve on error (e.g. a bus/bridge failed to probe)
> + */
> +int pci_find_first_device(struct udevice **devp);
> +
> +/**
> + * pci_find_next_device() - return the next available PCI device
> + *
> + * Finds the next available PCI device after the one supplied, or sets @devp
> + * to NULL if there are no more.
> + *
> + * @devp:      On entry, the last device returned. Set to the next available
> + *             device, or NULL if no more are left or we got an error
> + * @return 0 if all is OK, -ve on error (e.g. a bus/bridge failed to probe)
> + */
> +int pci_find_next_device(struct udevice **devp);
> +
> +/**
>   * pci_get_ff() - Returns a mask for the given access size
>   *
>   * @size:      Access size
> --

Reviewed-by: Bin Meng <bmeng.cn at gmail.com>


More information about the U-Boot mailing list