diff options
| author | Keith Busch <kbusch@kernel.org> | 2026-01-30 08:59:51 -0800 |
|---|---|---|
| committer | Bjorn Helgaas <bhelgaas@google.com> | 2026-02-06 16:53:27 -0600 |
| commit | 1f5e57c622b4dc9b8e7d291d560138d92cfbe5bf (patch) | |
| tree | 7076eae7af9a31dbbabd59fdec94f5b9047fc3ec /drivers/pci | |
| parent | 9368d1ee62829b08aa31836b3ca003803caf0b72 (diff) | |
PCI: Fix pci_slot_lock () device locking
Like pci_bus_lock(), pci_slot_lock() needs to lock the bridge device to
prevent warnings like:
pcieport 0000:e2:05.0: unlocked secondary bus reset via: pciehp_reset_slot+0x55/0xa0
Take and release the lock for the bridge providing the slot for the
lock/trylock and unlock routines.
Signed-off-by: Keith Busch <kbusch@kernel.org>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Reviewed-by: Dan Williams <dan.j.williams@intel.com>
Link: https://patch.msgid.link/20260130165953.751063-3-kbusch@meta.com
Diffstat (limited to 'drivers/pci')
| -rw-r--r-- | drivers/pci/pci.c | 23 |
1 files changed, 17 insertions, 6 deletions
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 59319e08fca6..57a5b205175f 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -5290,10 +5290,9 @@ unlock: /* Do any devices on or below this slot prevent a bus reset? */ static bool pci_slot_resettable(struct pci_slot *slot) { - struct pci_dev *dev; + struct pci_dev *dev, *bridge = slot->bus->self; - if (slot->bus->self && - (slot->bus->self->dev_flags & PCI_DEV_FLAGS_NO_BUS_RESET)) + if (bridge && (bridge->dev_flags & PCI_DEV_FLAGS_NO_BUS_RESET)) return false; list_for_each_entry(dev, &slot->bus->devices, bus_list) { @@ -5310,7 +5309,10 @@ static bool pci_slot_resettable(struct pci_slot *slot) /* Lock devices from the top of the tree down */ static void pci_slot_lock(struct pci_slot *slot) { - struct pci_dev *dev; + struct pci_dev *dev, *bridge = slot->bus->self; + + if (bridge) + pci_dev_lock(bridge); list_for_each_entry(dev, &slot->bus->devices, bus_list) { if (!dev->slot || dev->slot != slot) @@ -5325,7 +5327,7 @@ static void pci_slot_lock(struct pci_slot *slot) /* Unlock devices from the bottom of the tree up */ static void pci_slot_unlock(struct pci_slot *slot) { - struct pci_dev *dev; + struct pci_dev *dev, *bridge = slot->bus->self; list_for_each_entry(dev, &slot->bus->devices, bus_list) { if (!dev->slot || dev->slot != slot) @@ -5335,12 +5337,18 @@ static void pci_slot_unlock(struct pci_slot *slot) else pci_dev_unlock(dev); } + + if (bridge) + pci_dev_unlock(bridge); } /* Return 1 on successful lock, 0 on contention */ static int pci_slot_trylock(struct pci_slot *slot) { - struct pci_dev *dev; + struct pci_dev *dev, *bridge = slot->bus->self; + + if (bridge && !pci_dev_trylock(bridge)) + return 0; list_for_each_entry(dev, &slot->bus->devices, bus_list) { if (!dev->slot || dev->slot != slot) @@ -5363,6 +5371,9 @@ unlock: else pci_dev_unlock(dev); } + + if (bridge) + pci_dev_unlock(bridge); return 0; } |
