[PATCH v2 03/22] PCI: Inherit bus numbers from previous kernel during Live Update

David Matlack
2026-01-29T21:25:48Z

Inherit bus numbers from the previous kernel during a Live Update when
one or more PCI devices are being preserved. This is necessary so that
preserved devices can DMA through the IOMMU during a Live Update
(changing bus numbers would break IOMMU translation).

Signed-off-by: David Matlack <dmatlack@google.com>
---
drivers/pci/probe.c | 21 ++++++++++++++++++---
1 file changed, 18 insertions(+), 3 deletions(-)

diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index af6356c5a156..ca6e5f79debb 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -1351,6 +1351,20 @@ static bool pci_ea_fixed_busnrs(struct pci_dev *dev, u8 *sec, u8 *sub)
return true;
}

+static bool pci_assign_all_busses(void)
+{
+ /*
+ * During a Live Update where devices are preserved by the previous
+ * kernel, inherit all bus numbers assigned by the previous kernel. Bus
+ * numbers must remain stable for preserved devices so that they can
+ * perform DMA during the Live Update uninterrupted.
+ */
+ if (pci_liveupdate_incoming_nr_devices())
+ return false;
+
+ return pcibios_assign_all_busses();
+}
+
/*
* pci_scan_bridge_extend() - Scan buses behind a bridge
* @bus: Parent bus the bridge is on
@@ -1378,6 +1392,7 @@ static int pci_scan_bridge_extend(struct pci_bus *bus, struct pci_dev *dev,
int max, unsigned int available_buses,
int pass)
{
+ bool assign_all_busses = pci_assign_all_busses();
struct pci_bus *child;
int is_cardbus = (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS);
u32 buses, i, j = 0;
@@ -1424,7 +1439,7 @@ static int pci_scan_bridge_extend(struct pci_bus *bus, struct pci_dev *dev,
pci_write_config_word(dev, PCI_BRIDGE_CONTROL,
bctl & ~PCI_BRIDGE_CTL_MASTER_ABORT);

- if ((secondary || subordinate) && !pcibios_assign_all_busses() &&
+ if ((secondary || subordinate) && !assign_all_busses &&
!is_cardbus && !broken) {
unsigned int cmax, buses;

@@ -1467,7 +1482,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 (assign_all_busses || broken || is_cardbus)

/*
* Temporarily disable forwarding of the
@@ -1542,7 +1557,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 (!assign_all_busses &&
(parent->busn_res.end > max) &&
(parent->busn_res.end <= max+i)) {
j = 1;
--
2.53.0.rc1.225.gd81095ad13-goog