Hi all!
The ominous warning about pci_root_buses in drivers/pci/probe.c caught
my attention. Looking closer, I found that there are uses in four
arch-specific files left before we can stop exposing that symbol outside
of drivers/pci.
Finish off the job that Yinghai Lu started in 2013 - see
https://msgid.link/1359265003-16166-23-git-send-email-yinghai@kernel.org/
The entire series has been compile-tested only - with defconfigs on
alpha, arm, powerpc, and x86.
Signed-off-by: Gerd Bayer <gbayer@linux.ibm.com>
---
Gerd Bayer (5):
alpha/pci: Use official API to iterate over PCI buses
arm/pci: Use official API to iterate over PCI buses
powerpc/pci: Use official API to iterate over PCI buses
x86/pci: Use official API to iterate over PCI buses
PCI: Make pci_root_buses private to PCI core
arch/alpha/kernel/pci.c | 4 ++--
arch/arm/kernel/bios32.c | 4 ++--
arch/powerpc/kernel/pci-common.c | 7 ++++---
arch/powerpc/kernel/pci_64.c | 4 ++--
arch/x86/pci/i386.c | 14 ++++++++------
drivers/pci/pci.h | 3 +++
drivers/pci/probe.c | 2 --
include/linux/pci.h | 4 ----
8 files changed, 21 insertions(+), 21 deletions(-)
---
base-commit: 5d6919055dec134de3c40167a490f33c74c12581
change-id: 20260508-priv_root_buses-0263ef2679ad
Best regards,
--
Gerd Bayer [off-list ref]
Replace iterating over pci_root_buses with the official
pci_find_next_bus() call provided by PCI core. This allows to make
pci_root_buses private to PCI core.
Signed-off-by: Gerd Bayer <gbayer@linux.ibm.com>
---
arch/powerpc/kernel/pci-common.c | 7 ++++---
arch/powerpc/kernel/pci_64.c | 4 ++--
2 files changed, 6 insertions(+), 5 deletions(-)
@@ -227,7 +227,7 @@ SYSCALL_DEFINE3(pciconfig_iobase, long, which, unsigned long, in_bus,unsignedlong,in_devfn){structpci_controller*hose;-structpci_bus*tmp_bus,*bus=NULL;+structpci_bus*tmp_bus=NULL,*bus=NULL;structdevice_node*hose_node;/* Argh ! Please forgive me for that hack, but that's the
Replace iterating over pci_root_buses with the official
pci_find_next_bus() call provided by PCI core. This allows to make
pci_root_buses private to PCI core.
Signed-off-by: Gerd Bayer <gbayer@linux.ibm.com>
---
arch/arm/kernel/bios32.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
Replace iterating over pci_root_buses with the official
pci_find_next_bus() call provided by PCI core. This allows to make
pci_root_buses private to PCI core.
Signed-off-by: Gerd Bayer <gbayer@linux.ibm.com>
---
arch/alpha/kernel/pci.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
Replace iterating over pci_root_buses with the official
pci_find_next_bus() call provided by PCI core. This allows to make
pci_root_buses private to PCI core.
Signed-off-by: Gerd Bayer <gbayer@linux.ibm.com>
---
arch/x86/pci/i386.c | 14 ++++++++------
1 file changed, 8 insertions(+), 6 deletions(-)
@@ -390,16 +390,18 @@ void pcibios_resource_survey_bus(struct pci_bus *bus)void__initpcibios_resource_survey(void){-structpci_bus*bus;+structpci_bus*bus=NULL;DBG("PCI: Allocating resources\n");-list_for_each_entry(bus,&pci_root_buses,node)+while((bus=pci_find_next_bus(bus))!=NULL)pcibios_allocate_bus_resources(bus);-list_for_each_entry(bus,&pci_root_buses,node)+bus=NULL;/* start all over */+while((bus=pci_find_next_bus(bus))!=NULL)pcibios_allocate_resources(bus,0);-list_for_each_entry(bus,&pci_root_buses,node)+bus=NULL;/* start all over */+while((bus=pci_find_next_bus(bus))!=NULL)pcibios_allocate_resources(bus,1);e820__reserve_resources_late();
After all users of pci_root_buses external to PCI core have been
converted to using pci_find_next_bus(), move its declaration to the
PCI core code and stop exporting the symbol.
Signed-off-by: Gerd Bayer <gbayer@linux.ibm.com>
---
drivers/pci/pci.h | 3 +++
drivers/pci/probe.c | 2 --
include/linux/pci.h | 4 ----
3 files changed, 3 insertions(+), 6 deletions(-)
@@ -366,6 +366,9 @@ static inline void pci_create_legacy_files(struct pci_bus *bus) { }staticinlinevoidpci_remove_legacy_files(structpci_bus*bus){}#endif+/* List of all known PCI buses */+externstructlist_headpci_root_buses;+/* Lock for read/write access to pci device and bus lists */externstructrw_semaphorepci_bus_sem;externstructmutexpci_slot_mutex;
@@ -33,9 +33,7 @@ static struct resource busn_resource = {.flags=IORESOURCE_BUS,};-/* Ugh. Need to stop exporting this to modules. */LIST_HEAD(pci_root_buses);-EXPORT_SYMBOL(pci_root_buses);staticLIST_HEAD(pci_domain_busn_res_list);
@@ -1192,10 +1192,6 @@ extern enum pcie_bus_config_types pcie_bus_config;externconststructbus_typepci_bus_type;-/* Do NOT directly access these two variables, unless you are arch-specific PCI-*code,orPCIcorecode.*/-externstructlist_headpci_root_buses;/* List of all known PCI buses */-voidpcibios_resource_survey_bus(structpci_bus*bus);voidpcibios_bus_add_device(structpci_dev*pdev);voidpcibios_add_bus(structpci_bus*bus);
From: Dave Hansen <hidden> Date: 2026-05-15 15:13:15
On 5/15/26 07:22, Gerd Bayer wrote:
quoted hunk
static int __init pcibios_assign_resources(void) {- struct pci_bus *bus;+ struct pci_bus *bus = NULL; if (!(pci_probe & PCI_ASSIGN_ROMS))- list_for_each_entry(bus, &pci_root_buses, node)+ while ((bus = pci_find_next_bus(bus)) != NULL) pcibios_allocate_rom_resources(bus);
What's with the 'bus = NULL'? I thought there was some crazy macro magic
going on or something, but pci_find_next_bus() looks like a normal
function that's just taking a pointer and not _modifying_ the pointer value.
Also, wouldn't this be a more readable way of writing what you have?
while (bus = pci_find_next_bus(bus))
For that matter isn't the kernel idiom for these things:
for_each_pci_bus(bus) {
// do bus stuff
}
I'm kinda surprised there isn't one of those already.
On Fri, 2026-05-15 at 08:13 -0700, Dave Hansen wrote:
On 5/15/26 07:22, Gerd Bayer wrote:
quoted
static int __init pcibios_assign_resources(void) {- struct pci_bus *bus;+ struct pci_bus *bus = NULL; if (!(pci_probe & PCI_ASSIGN_ROMS))- list_for_each_entry(bus, &pci_root_buses, node)+ while ((bus = pci_find_next_bus(bus)) != NULL) pcibios_allocate_rom_resources(bus);
What's with the 'bus = NULL'? I thought there was some crazy macro magic
going on or something, but pci_find_next_bus() looks like a normal
function that's just taking a pointer and not _modifying_ the pointer value.
Initializing 'bus = NULL" makes sure, that pci_find_next_bus() starts
at the list head; list_for_each_entry() did that implicitly. I didn't
want to rely on implicit zero-init for local var's on all the various
architectures. But I'm fine to drop it here, if you prefer.
Also, wouldn't this be a more readable way of writing what you have?
while (bus = pci_find_next_bus(bus))
Yeah, another occasion of me being (overly?) verbose.
arch/sparc/kernel/pci.c was my blueprint. Again, something that I'm ok
to drop.
For that matter isn't the kernel idiom for these things:
for_each_pci_bus(bus) {
// do bus stuff
}
I'm kinda surprised there isn't one of those already.
Just guessing: There was too little use of pci_find_next_bus() to
warrant that short-cut. But I can make a proposal in the next
iteration.
Thanks,
Gerd
On Fri, 2026-05-15 at 16:22 +0200, Gerd Bayer wrote:
quoted hunk
Replace iterating over pci_root_buses with the official
pci_find_next_bus() call provided by PCI core. This allows to make
pci_root_buses private to PCI core.
Signed-off-by: Gerd Bayer <gbayer@linux.ibm.com>
---
arch/arm/kernel/bios32.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
Since pci_find_next_bus() unconditionally acquires the pci_bus_sem read-write
semaphore using down_read(), this introduces a blocking operation into that
atomic path:
dc21285_abort_irq() [hardirq context]
pcibios_report_status()
pci_find_next_bus()
down_read(&pci_bus_sem) [sleeps]
Does this path need an alternative approach to safely iterate over the buses
without taking a sleeping lock?
IMHO, it looks like this entire pcibios_report_status() iterating over
all PCI buses and all their devices would be better off if moved
outside of the hardirq context?
Or could pcibios_report_status() be converted to use
for_each_pci_device()?
Any suggestions welcome...
Gerd