Message ID | 20241022224851.340648-5-kbusch@meta.com (mailing list archive) |
---|---|
State | Accepted |
Delegated to: | Bjorn Helgaas |
Headers | show |
Series | pci cleanup/prep patches | expand |
On Tue, Oct 22, 2024 at 03:48:50PM -0700, Keith Busch wrote: > The original implementation purposefully 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 the > implementation is easier to follow. The motivation for changing it now > is to make it easier to introduce finer grain locking in the future. Hm, I find the loss of non-recursive bus walking regrettable. If the solution proposed earlier today... https://lore.kernel.org/all/ZzG5koPOn16KQ8uM@wunner.de/ ... is workable and we find it doesn't need recursive bus walking, perhaps we should consider reverting this change (which is now e24eafdda271 on pci/locking). Thanks, Lukas
diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c index b863b8bdd6ee6..9c552396241e0 100644 --- a/drivers/pci/bus.c +++ b/drivers/pci/bus.c @@ -399,37 +399,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; } /**