The pseries and powernv pcibios_bus_add_device() hooks insert the device
into the EEH PE tree with bare list manipulation that
arch/powerpc/kernel/eeh.c itself flags as unlocked, and for SR-IOV the
pseries hook attaches every VF's eeh_dev to the shared physfn PE. Every
caller is serialized by enumeration context today; an upcoming change
runs pci_bus_add_device() for sibling VFs concurrently and makes the race
reachable.
Serialize the platform hook dispatch with an arch-local mutex. Exclusion
against the EEH recovery thread stays carried by pci_rescan_remove_lock,
and on probe-path enables the residue folds into the pre-existing
exposure described in a later patch in this series ("PCI/IOV: Initialize
virtual functions in parallel"). A proper PE-tree lock is a larger EEH
cleanup, so eeh_pe.c is left alone.
Assisted-by: LLM
Signed-off-by: Pavol Sakac <[email protected]>
---
arch/powerpc/kernel/pci-common.c | 14 +++++++++++++-
1 file changed, 13 insertions(+), 1 deletion(-)
diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c
index 4fc52c21fe5d..21cccd0e97f8 100644
--- a/arch/powerpc/kernel/pci-common.c
+++ b/arch/powerpc/kernel/pci-common.c
@@ -1046,6 +1046,15 @@ void pcibios_setup_bus_self(struct pci_bus *bus)
phb->controller_ops.dma_bus_setup(bus);
}
+/*
+ * The pseries/powernv hooks update the shared EEH PE tree with no
+ * internal locking; serialize concurrent sibling VF additions.
+ * Removal-side updates do not take this lock: additions are
+ * drained before any unwind, and the sysfs enable and EEH paths
+ * hold pci_rescan_remove_lock.
+ */
+static DEFINE_MUTEX(pcibios_bus_add_device_lock);
+
void pcibios_bus_add_device(struct pci_dev *dev)
{
struct pci_controller *phb;
@@ -1068,8 +1077,11 @@ void pcibios_bus_add_device(struct pci_dev *dev)
if (ppc_md.pci_irq_fixup)
ppc_md.pci_irq_fixup(dev);
- if (ppc_md.pcibios_bus_add_device)
+ if (ppc_md.pcibios_bus_add_device) {
+ mutex_lock(&pcibios_bus_add_device_lock);
ppc_md.pcibios_bus_add_device(dev);
+ mutex_unlock(&pcibios_bus_add_device_lock);
+ }
}
int pcibios_device_add(struct pci_dev *dev)
--
2.47.3