aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArnd Bergmann <arnd@arndb.de>2021-01-27 13:19:01 +0100
committerArnd Bergmann <arnd@arndb.de>2021-03-12 16:01:11 +0100
commit997a2bb5a4fcdbf3f5e10032b711f07ea7b7f276 (patch)
tree75e5c49b05acc3ffc1f694ae8450da0ff4aa3640
parent130e1a398709fc631f3438fa57c450a4b392603e (diff)
downloadplayground-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.h5
-rw-r--r--arch/powerpc/kernel/pci_of_scan.c2
-rw-r--r--arch/x86/include/asm/pci.h2
-rw-r--r--drivers/pci/controller/pci-hyperv.c2
-rw-r--r--drivers/pci/probe.c51
-rw-r--r--include/linux/pci.h11
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