summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKeith Busch <kbusch@kernel.org>2024-10-22 15:48:48 -0700
committerBjorn Helgaas <bhelgaas@google.com>2024-11-11 13:06:02 -0600
commite3f30d563a388220a7c4e3b9a7b52ac0b0324b26 (patch)
tree8a0fcef5bcf8b3f4618c0e333477e49505d566e7
parent93093ea1f05928b123dae38b710631362bef1601 (diff)
downloadlwn-e3f30d563a388220a7c4e3b9a7b52ac0b0324b26.tar.gz
lwn-e3f30d563a388220a7c4e3b9a7b52ac0b0324b26.zip
PCI: Make pci_destroy_dev() concurrent safe
Use an atomic flag instead of the racy check against the device's kobj parent. We shouldn't be poking into device implementation details at this level anyway. Link: https://lore.kernel.org/r/20241022224851.340648-3-kbusch@meta.com Signed-off-by: Keith Busch <kbusch@kernel.org> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
-rw-r--r--drivers/pci/pci.h6
-rw-r--r--drivers/pci/remove.c2
2 files changed, 7 insertions, 1 deletions
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index 0d9169e0e7d2..187c5c83412d 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -469,6 +469,7 @@ static inline int pci_dev_set_disconnected(struct pci_dev *dev, void *unused)
#define PCI_DEV_ADDED 0
#define PCI_DPC_RECOVERED 1
#define PCI_DPC_RECOVERING 2
+#define PCI_DEV_REMOVED 3
static inline void pci_dev_assign_added(struct pci_dev *dev)
{
@@ -487,6 +488,11 @@ static inline bool pci_dev_is_added(const struct pci_dev *dev)
return test_bit(PCI_DEV_ADDED, &dev->priv_flags);
}
+static inline bool pci_dev_test_and_set_removed(struct pci_dev *dev)
+{
+ return test_and_set_bit(PCI_DEV_REMOVED, &dev->priv_flags);
+}
+
#ifdef CONFIG_PCIEAER
#include <linux/aer.h>
diff --git a/drivers/pci/remove.c b/drivers/pci/remove.c
index 78863f241a88..1f35945459fd 100644
--- a/drivers/pci/remove.c
+++ b/drivers/pci/remove.c
@@ -46,7 +46,7 @@ static void pci_stop_dev(struct pci_dev *dev)
static void pci_destroy_dev(struct pci_dev *dev)
{
- if (!dev->dev.kobj.parent)
+ if (pci_dev_test_and_set_removed(dev))
return;
pci_npem_remove(dev);