diff options
| author | Arnd Bergmann <arnd@arndb.de> | 2021-01-27 13:19:01 +0100 |
|---|---|---|
| committer | Arnd Bergmann <arnd@arndb.de> | 2021-03-12 16:01:11 +0100 |
| commit | 997a2bb5a4fcdbf3f5e10032b711f07ea7b7f276 (patch) | |
| tree | 75e5c49b05acc3ffc1f694ae8450da0ff4aa3640 | |
| parent | 130e1a398709fc631f3438fa57c450a4b392603e (diff) | |
| download | playground-997a2bb5a4fcdbf3f5e10032b711f07ea7b7f276.tar.gz | |
pci: add 'bus_assigned_by_firmware' flag
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
| -rw-r--r-- | arch/mips/include/asm/pci.h | 5 | ||||
| -rw-r--r-- | arch/powerpc/kernel/pci_of_scan.c | 2 | ||||
| -rw-r--r-- | arch/x86/include/asm/pci.h | 2 | ||||
| -rw-r--r-- | drivers/pci/controller/pci-hyperv.c | 2 | ||||
| -rw-r--r-- | drivers/pci/probe.c | 51 | ||||
| -rw-r--r-- | include/linux/pci.h | 11 |
6 files changed, 44 insertions, 29 deletions
diff --git a/arch/mips/include/asm/pci.h b/arch/mips/include/asm/pci.h index 6a8d85a69cbbf..692b5ed751edb 100644 --- a/arch/mips/include/asm/pci.h +++ b/arch/mips/include/asm/pci.h @@ -98,10 +98,7 @@ static inline void set_pci_need_domain_info(struct pci_controller *hose, /* Can be used to override the logic in pci_scan_bus for skipping already-configured bus numbers - to be used for buggy BIOSes or architectures with incomplete PCI setup by the loader */ -static inline unsigned int pcibios_assign_all_busses(void) -{ - return 1; -} +#define pcibios_assign_all_busses 1 extern unsigned long PCIBIOS_MIN_IO; extern unsigned long PCIBIOS_MIN_MEM; diff --git a/arch/powerpc/kernel/pci_of_scan.c b/arch/powerpc/kernel/pci_of_scan.c index c3024f1047654..f1eece05290de 100644 --- a/arch/powerpc/kernel/pci_of_scan.c +++ b/arch/powerpc/kernel/pci_of_scan.c @@ -341,7 +341,7 @@ void of_scan_pci_bridge(struct pci_dev *dev) if (mode == PCI_PROBE_DEVTREE) of_scan_bus(node, bus); else if (mode == PCI_PROBE_NORMAL) - pci_scan_child_bus(bus); + pci_scan_child_bus(phb->bridge, bus); } EXPORT_SYMBOL(of_scan_pci_bridge); diff --git a/arch/x86/include/asm/pci.h b/arch/x86/include/asm/pci.h index d2c76c8d8cfdc..39cb6a9458fad 100644 --- a/arch/x86/include/asm/pci.h +++ b/arch/x86/include/asm/pci.h @@ -73,12 +73,12 @@ static inline bool is_vmd(struct pci_bus *bus) /* Can be used to override the logic in pci_scan_bus for skipping already-configured bus numbers - to be used for buggy BIOSes or architectures with incomplete PCI setup by the loader */ - extern unsigned int pcibios_assign_all_busses(void); extern int pci_legacy_init(void); #else static inline int pcibios_assign_all_busses(void) { return 0; } #endif +#define pcibios_assign_all_busses pcibios_assign_all_busses extern unsigned long pci_mem_start; #define PCIBIOS_MIN_IO 0x1000 diff --git a/drivers/pci/controller/pci-hyperv.c b/drivers/pci/controller/pci-hyperv.c index 65a2f882c590b..4970b713877ac 100644 --- a/drivers/pci/controller/pci-hyperv.c +++ b/drivers/pci/controller/pci-hyperv.c @@ -2138,7 +2138,7 @@ static void pci_devices_present_work(struct work_struct *work) * because there may have been changes. */ pci_lock_rescan_remove(); - pci_scan_child_bus(hbus->bridge->bus); + pci_scan_child_bus(hbus->bridge, hbus->bridge->bus); hv_pci_assign_numa_node(hbus); hv_pci_assign_slots(hbus); pci_unlock_rescan_remove(); diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 52bb08cbeb8df..dd97aa96a7463 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -1146,7 +1146,8 @@ static void pci_enable_crs(struct pci_dev *pdev) PCI_EXP_RTCTL_CRSSVE); } -static unsigned int pci_scan_child_bus_extend(struct pci_bus *bus, +static unsigned int pci_scan_child_bus_extend(struct pci_host_bridge *bridge, + struct pci_bus *bus, unsigned int available_buses); /** * pci_ea_fixed_busnrs() - Read fixed Secondary and Subordinate bus @@ -1208,7 +1209,8 @@ static bool pci_ea_fixed_busnrs(struct pci_dev *dev, u8 *sec, u8 *sub) * * Return: New subordinate number covering all buses behind this bridge. */ -static int pci_scan_bridge_extend(struct pci_bus *bus, struct pci_dev *dev, +static int pci_scan_bridge_extend(struct pci_host_bridge *bridge, + struct pci_bus *bus, struct pci_dev *dev, int max, unsigned int available_buses, int pass) { @@ -1260,7 +1262,7 @@ static int pci_scan_bridge_extend(struct pci_bus *bus, struct pci_dev *dev, pci_enable_crs(dev); - if ((secondary || subordinate) && !pcibios_assign_all_busses() && + if ((secondary || subordinate) && !pci_assign_all_busses(bridge) && !is_cardbus && !broken) { unsigned int cmax; @@ -1287,7 +1289,7 @@ static int pci_scan_bridge_extend(struct pci_bus *bus, struct pci_dev *dev, child->bridge_ctl = bctl; } - cmax = pci_scan_child_bus(child); + cmax = pci_scan_child_bus(bridge, child); if (cmax > subordinate) pci_warn(dev, "bridge has subordinate %02x but max busn %02x\n", subordinate, cmax); @@ -1302,7 +1304,7 @@ static int pci_scan_bridge_extend(struct pci_bus *bus, struct pci_dev *dev, * do in the second pass. */ if (!pass) { - if (pcibios_assign_all_busses() || broken || is_cardbus) + if (pci_assign_all_busses(bridge) || broken || is_cardbus) /* * Temporarily disable forwarding of the @@ -1363,7 +1365,8 @@ static int pci_scan_bridge_extend(struct pci_bus *bus, struct pci_dev *dev, if (!is_cardbus) { child->bridge_ctl = bctl; - max = pci_scan_child_bus_extend(child, available_buses); + max = pci_scan_child_bus_extend(bridge, child, + available_buses); } else { /* @@ -1377,7 +1380,7 @@ static int pci_scan_bridge_extend(struct pci_bus *bus, struct pci_dev *dev, max+i+1)) break; while (parent->parent) { - if ((!pcibios_assign_all_busses()) && + if ((!pci_assign_all_busses(bridge)) && (parent->busn_res.end > max) && (parent->busn_res.end <= max+i)) { j = 1; @@ -1455,7 +1458,8 @@ out: */ int pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, int pass) { - return pci_scan_bridge_extend(bus, dev, max, 0, pass); + struct pci_host_bridge *bridge = pci_find_host_bridge(bus); + return pci_scan_bridge_extend(bridge, bus, dev, max, 0, pass); } EXPORT_SYMBOL(pci_scan_bridge); @@ -2791,7 +2795,8 @@ void __weak pcibios_fixup_bus(struct pci_bus *bus) * equally between hotplug-capable bridges to allow future extension of the * hierarchy. */ -static unsigned int pci_scan_child_bus_extend(struct pci_bus *bus, +static unsigned int pci_scan_child_bus_extend(struct pci_host_bridge *bridge, + struct pci_bus *bus, unsigned int available_buses) { unsigned int used_buses, normal_bridges = 0, hotplug_bridges = 0; @@ -2853,7 +2858,7 @@ static unsigned int pci_scan_child_bus_extend(struct pci_bus *bus, */ for_each_pci_bridge(dev, bus) { cmax = max; - max = pci_scan_bridge_extend(bus, dev, max, 0, 0); + max = pci_scan_bridge_extend(bridge, bus, dev, max, 0, 0); /* * Reserve one bus for each bridge now to avoid extending @@ -2888,7 +2893,7 @@ static unsigned int pci_scan_child_bus_extend(struct pci_bus *bus, } cmax = max; - max = pci_scan_bridge_extend(bus, dev, cmax, buses, 1); + max = pci_scan_bridge_extend(bridge, bus, dev, cmax, buses, 1); /* One bus is already accounted so don't add it again */ if (max - cmax > 1) used_buses += max - cmax - 1; @@ -2932,9 +2937,9 @@ static unsigned int pci_scan_child_bus_extend(struct pci_bus *bus, * Scans devices below @bus including subordinate buses. Returns new * subordinate number including all the found devices. */ -unsigned int pci_scan_child_bus(struct pci_bus *bus) +unsigned int pci_scan_child_bus(struct pci_host_bridge *bridge, struct pci_bus *bus) { - return pci_scan_child_bus_extend(bus, 0); + return pci_scan_child_bus_extend(bridge, bus, 0); } EXPORT_SYMBOL_GPL(pci_scan_child_bus); @@ -3084,7 +3089,7 @@ int pci_scan_root_bus_bridge(struct pci_host_bridge *bridge) } if (!bridge->custom_bus_scan) { - max = pci_scan_child_bus(b); + max = pci_scan_child_bus(bridge, b); if (!found) pci_bus_update_busn_res_end(b, max); @@ -3105,14 +3110,16 @@ EXPORT_SYMBOL(pci_scan_root_bus_bridge); * * Returns the max number of subordinate bus discovered. */ -unsigned int pci_rescan_bus_bridge_resize(struct pci_dev *bridge) +unsigned int pci_rescan_bus_bridge_resize(struct pci_dev *bridge_dev) { unsigned int max; - struct pci_bus *bus = bridge->subordinate; + struct pci_bus *bus = bridge_dev->subordinate; + struct pci_host_bridge *host_bridge; - max = pci_scan_child_bus(bus); + host_bridge = pci_find_host_bridge(bridge_dev->bus); + max = pci_scan_child_bus(host_bridge, bus); - pci_assign_unassigned_bridge_resources(bridge); + pci_assign_unassigned_bridge_resources(bridge_dev); pci_bus_add_devices(bus); @@ -3130,9 +3137,10 @@ unsigned int pci_rescan_bus_bridge_resize(struct pci_dev *bridge) */ unsigned int pci_rescan_bus(struct pci_bus *bus) { + struct pci_host_bridge *bridge = pci_find_host_bridge(bus); unsigned int max; - max = pci_scan_child_bus(bus); + max = pci_scan_child_bus(bridge, bus); pci_assign_unassigned_bus_resources(bus); pci_bus_add_devices(bus); @@ -3184,6 +3192,7 @@ void __init pci_sort_breadthfirst(void) int pci_hp_add_bridge(struct pci_dev *dev) { struct pci_bus *parent = dev->bus; + struct pci_host_bridge *bridge = pci_find_host_bridge(parent); int busnr, start = parent->busn_res.start; unsigned int available_buses = 0; int end = parent->busn_res.end; @@ -3198,7 +3207,7 @@ int pci_hp_add_bridge(struct pci_dev *dev) } /* Scan bridges that are already configured */ - busnr = pci_scan_bridge(parent, dev, busnr, 0); + busnr = pci_scan_bridge_extend(bridge, parent, dev, busnr, 0, 0); /* * Distribute the available bus numbers between hotplug-capable @@ -3207,7 +3216,7 @@ int pci_hp_add_bridge(struct pci_dev *dev) available_buses = end - busnr; /* Scan bridges that need to be reconfigured */ - pci_scan_bridge_extend(parent, dev, busnr, available_buses, 1); + pci_scan_bridge_extend(bridge, parent, dev, busnr, available_buses, 1); if (!dev->subordinate) return -1; diff --git a/include/linux/pci.h b/include/linux/pci.h index 3124d572fd2b0..97bd6649bffa7 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -542,6 +542,7 @@ struct pci_host_bridge { void *release_data; struct msi_controller *msi; unsigned int probe_only:1; /* use BIOS assigned resources */ + unsigned int bus_assigned_by_firmware:1; /* use BIOS assigned bus */ unsigned int ignore_reset_delay:1; /* For entire hierarchy */ unsigned int no_ext_tags:1; /* No Extended Tags */ unsigned int native_aer:1; /* OS may use PCIe AER */ @@ -1043,7 +1044,7 @@ static inline void pci_dev_assign_slot(struct pci_dev *dev) { } int pci_scan_slot(struct pci_bus *bus, int devfn); struct pci_dev *pci_scan_single_device(struct pci_bus *bus, int devfn); void pci_device_add(struct pci_dev *dev, struct pci_bus *bus); -unsigned int pci_scan_child_bus(struct pci_bus *bus); +unsigned int pci_scan_child_bus(struct pci_host_bridge *bridge, struct pci_bus *bus); void pci_bus_add_device(struct pci_dev *dev); void pci_read_bridge_bases(struct pci_bus *child); struct resource *pci_find_parent_resource(const struct pci_dev *dev, @@ -1853,6 +1854,14 @@ int pci_iobar_pfn(struct pci_dev *pdev, int bar, struct vm_area_struct *vma); #define pci_root_bus_fwnode(bus) NULL #endif +static inline int pci_assign_all_busses(struct pci_host_bridge *bridge) +{ +#ifdef pcibios_assign_all_busses + return pcibios_assign_all_busses(); +#endif + return !bridge->bus_assigned_by_firmware; +} + /* * These helpers provide future and backwards compatibility * for accessing popular PCI BAR info |
