Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

PCI: Add pci_scan_root_bus_bridge() interface

The current pci_scan_root_bus() interface is made up of two main code
paths:

- pci_create_root_bus()
- pci_scan_child_bus()

pci_create_root_bus() is a wrapper function that allows to create a struct
pci_host_bridge structure, initialize it with the passed parameters and
register it with the kernel.

As the struct pci_host_bridge require additional struct members,
pci_create_root_bus() parameters list has grown in time, making it unwieldy
to add further parameters to it in case the struct pci_host_bridge gains
more members fields to augment its functionality.

Since PCI core code provides functions to allocate struct pci_host_bridge,
instead of forcing the pci_create_root_bus() interface to add new
parameters to cater for new struct pci_host_bridge functionality, it is
more suitable to add an interface in PCI core code to scan a PCI bus
straight from a struct pci_host_bridge created and customized by each
specific PCI host controller driver.

Add a pci_scan_root_bus_bridge() function to allow PCI host controller
drivers to create and initialize struct pci_host_bridge and scan the
resulting bus.

Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Cc: Arnd Bergmann <arnd@arndb.de>

authored by

Lorenzo Pieralisi and committed by
Bjorn Helgaas
1228c4b6 792abc6e

+40
+39
drivers/pci/probe.c
··· 2426 2426 res, ret ? "can not be" : "is"); 2427 2427 } 2428 2428 2429 + int pci_scan_root_bus_bridge(struct pci_host_bridge *bridge) 2430 + { 2431 + struct resource_entry *window; 2432 + bool found = false; 2433 + struct pci_bus *b; 2434 + int max, bus, ret; 2435 + 2436 + if (!bridge) 2437 + return -EINVAL; 2438 + 2439 + resource_list_for_each_entry(window, &bridge->windows) 2440 + if (window->res->flags & IORESOURCE_BUS) { 2441 + found = true; 2442 + break; 2443 + } 2444 + 2445 + ret = pci_register_host_bridge(bridge); 2446 + if (ret < 0) 2447 + return ret; 2448 + 2449 + b = bridge->bus; 2450 + bus = bridge->busnr; 2451 + 2452 + if (!found) { 2453 + dev_info(&b->dev, 2454 + "No busn resource found for root bus, will use [bus %02x-ff]\n", 2455 + bus); 2456 + pci_bus_insert_busn_res(b, bus, 255); 2457 + } 2458 + 2459 + max = pci_scan_child_bus(b); 2460 + 2461 + if (!found) 2462 + pci_bus_update_busn_res_end(b, max); 2463 + 2464 + return 0; 2465 + } 2466 + EXPORT_SYMBOL(pci_scan_root_bus_bridge); 2467 + 2429 2468 struct pci_bus *pci_scan_root_bus_msi(struct device *parent, int bus, 2430 2469 struct pci_ops *ops, void *sysdata, 2431 2470 struct list_head *resources, struct msi_controller *msi)
+1
include/linux/pci.h
··· 857 857 struct pci_bus *pci_scan_root_bus(struct device *parent, int bus, 858 858 struct pci_ops *ops, void *sysdata, 859 859 struct list_head *resources); 860 + int pci_scan_root_bus_bridge(struct pci_host_bridge *bridge); 860 861 struct pci_bus *pci_add_new_bus(struct pci_bus *parent, struct pci_dev *dev, 861 862 int busnr); 862 863 void pcie_update_link_speed(struct pci_bus *bus, u16 link_status);