summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorKeith Busch <kbusch@kernel.org>2024-10-22 15:48:50 -0700
committerBjorn Helgaas <bhelgaas@google.com>2024-11-11 13:06:02 -0600
commitee061da777f704976c6d3fdc1707788d11a052c5 (patch)
tree7cb56a23fe60b2c73dbd475540b61a66303c4102 /drivers
parent4d6dcd6c2fa3a80898651d323c150e5ebc03881d (diff)
downloadlinux-ee061da777f704976c6d3fdc1707788d11a052c5.tar.gz
linux-ee061da777f704976c6d3fdc1707788d11a052c5.tar.bz2
linux-ee061da777f704976c6d3fdc1707788d11a052c5.zip
PCI: Convert __pci_walk_bus() to be recursive
The original implementation of __pci_walk_bus() chose a non-recursive walk, presumably as a precaution on stack use. We do recursive bus walking in other places though. For example: pci_bus_resettable() pci_stop_bus_device() pci_remove_bus_device() pci_bus_allocate_dev_resources() So recursive pci bus walking is well tested and safe, and is easier to follow. Convert __pci_walk_bus() to be recursive to make it easier to introduce finer grain locking in the future. Link: https://lore.kernel.org/r/20241022224851.340648-5-kbusch@meta.com Signed-off-by: Keith Busch <kbusch@kernel.org> [bhelgaas: commit log] Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/pci/bus.c36
1 files changed, 11 insertions, 25 deletions
diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c
index 7c07a141e877..8491e9c7f058 100644
--- a/drivers/pci/bus.c
+++ b/drivers/pci/bus.c
@@ -389,37 +389,23 @@ void pci_bus_add_devices(const struct pci_bus *bus)
}
EXPORT_SYMBOL(pci_bus_add_devices);
-static void __pci_walk_bus(struct pci_bus *top, int (*cb)(struct pci_dev *, void *),
- void *userdata)
+static int __pci_walk_bus(struct pci_bus *top, int (*cb)(struct pci_dev *, void *),
+ void *userdata)
{
struct pci_dev *dev;
- struct pci_bus *bus;
- struct list_head *next;
- int retval;
+ int ret = 0;
- bus = top;
- next = top->devices.next;
- for (;;) {
- if (next == &bus->devices) {
- /* end of this bus, go up or finish */
- if (bus == top)
+ list_for_each_entry(dev, &top->devices, bus_list) {
+ ret = cb(dev, userdata);
+ if (ret)
+ break;
+ if (dev->subordinate) {
+ ret = __pci_walk_bus(dev->subordinate, cb, userdata);
+ if (ret)
break;
- next = bus->self->bus_list.next;
- bus = bus->self->bus;
- continue;
}
- dev = list_entry(next, struct pci_dev, bus_list);
- if (dev->subordinate) {
- /* this is a pci-pci bridge, do its devices next */
- next = dev->subordinate->devices.next;
- bus = dev->subordinate;
- } else
- next = dev->bus_list.next;
-
- retval = cb(dev, userdata);
- if (retval)
- break;
}
+ return ret;
}
/**