mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-01-16 09:56:46 +00:00
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>
This commit is contained in:
parent
4d6dcd6c2f
commit
ee061da777
@ -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)
|
||||
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)
|
||||
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;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
x
Reference in New Issue
Block a user