[PATCH] PCI: lock upstream bridge in pci_try_reset_function()

Runyu Xiao <[email protected]>
Newsgroups org.kernel.vger.linux-pci,org.kernel.vger.linux-kernel,org.kernel.vger.stable
Message-ID <[email protected]>
pci_try_reset_function() may fall back to a secondary-bus reset below
an upstream bridge. Unlike pci_reset_function(), it only trylocks the
target device, so bridge configuration access is left unlocked across
that reset path.

Mirror pci_reset_function() and trylock the upstream bridge before the
device. This keeps bridge config access serialized on the secondary-bus
reset fallback and avoids the unlocked secondary bus reset warning.

Fixes: 61cf16d8bd38 ("PCI: Add pci_try_reset_function(), pci_try_reset_slot(), pci_try_reset_bus()")
Cc: [email protected]
Signed-off-by: Runyu Xiao <[email protected]>
---
 drivers/pci/pci.c | 15 ++++++++++++++-
 1 file changed, 14 insertions(+), 1 deletion(-)

diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index e128696d5b76..6da8ac8a2459 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -5342,20 +5342,33 @@ EXPORT_SYMBOL_GPL(pci_reset_function_locked);
  */
 int pci_try_reset_function(struct pci_dev *dev)
 {
+	struct pci_dev *bridge;
 	int rc;
 
 	if (!pci_reset_supported(dev))
 		return -ENOTTY;
 
-	if (!pci_dev_trylock(dev))
+	bridge = pci_upstream_bridge(dev);
+	if (bridge && !pci_dev_trylock(bridge))
 		return -EAGAIN;
 
+	if (!pci_dev_trylock(dev))
+		goto out_unlock_bridge;
+
 	pci_dev_save_and_disable(dev);
 	rc = __pci_reset_function_locked(dev);
 	pci_dev_restore(dev);
 	pci_dev_unlock(dev);
 
+	if (bridge)
+		pci_dev_unlock(bridge);
+
 	return rc;
+
+out_unlock_bridge:
+	if (bridge)
+		pci_dev_unlock(bridge);
+	return -EAGAIN;
 }
 EXPORT_SYMBOL_GPL(pci_try_reset_function);
 
-- 
2.34.1
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.