summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/pci/hotplug/pciehp_pci.c6
-rw-r--r--drivers/pci/pci.h14
-rw-r--r--drivers/pci/pcie/pcie-dpc.c5
-rw-r--r--include/linux/pci.h2
4 files changed, 27 insertions, 0 deletions
diff --git a/drivers/pci/hotplug/pciehp_pci.c b/drivers/pci/hotplug/pciehp_pci.c
index 9e69403be632..19f30a9f461d 100644
--- a/drivers/pci/hotplug/pciehp_pci.c
+++ b/drivers/pci/hotplug/pciehp_pci.c
@@ -109,6 +109,12 @@ int pciehp_unconfigure_device(struct slot *p_slot)
break;
}
}
+ if (!presence) {
+ pci_dev_set_disconnected(dev, NULL);
+ if (pci_has_subordinate(dev))
+ pci_walk_bus(dev->subordinate,
+ pci_dev_set_disconnected, NULL);
+ }
pci_stop_and_remove_bus_device(dev);
/*
* Ensure that no new Requests will be generated from
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index 8dd38e69d6f2..245719c3e409 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -274,6 +274,20 @@ struct pci_sriov {
resource_size_t barsz[PCI_SRIOV_NUM_BARS]; /* VF BAR size */
};
+/* pci_dev priv_flags */
+#define PCI_DEV_DISCONNECTED 0
+
+static inline int pci_dev_set_disconnected(struct pci_dev *dev, void *unused)
+{
+ set_bit(PCI_DEV_DISCONNECTED, &dev->priv_flags);
+ return 0;
+}
+
+static inline bool pci_dev_is_disconnected(const struct pci_dev *dev)
+{
+ return test_bit(PCI_DEV_DISCONNECTED, &dev->priv_flags);
+}
+
#ifdef CONFIG_PCI_ATS
void pci_restore_ats_state(struct pci_dev *dev);
#else
diff --git a/drivers/pci/pcie/pcie-dpc.c b/drivers/pci/pcie/pcie-dpc.c
index d4d70ef4a2d7..77d2ca99d2ec 100644
--- a/drivers/pci/pcie/pcie-dpc.c
+++ b/drivers/pci/pcie/pcie-dpc.c
@@ -14,6 +14,7 @@
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/pcieport_if.h>
+#include "../pci.h"
struct dpc_dev {
struct pcie_device *dev;
@@ -66,6 +67,10 @@ static void interrupt_event_handler(struct work_struct *work)
list_for_each_entry_safe_reverse(dev, temp, &parent->devices,
bus_list) {
pci_dev_get(dev);
+ pci_dev_set_disconnected(dev, NULL);
+ if (pci_has_subordinate(dev))
+ pci_walk_bus(dev->subordinate,
+ pci_dev_set_disconnected, NULL);
pci_stop_and_remove_bus_device(dev);
pci_dev_put(dev);
}
diff --git a/include/linux/pci.h b/include/linux/pci.h
index d705f3088ff9..2887933329a2 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -396,6 +396,8 @@ struct pci_dev {
phys_addr_t rom; /* Physical address of ROM if it's not from the BAR */
size_t romlen; /* Length of ROM if it's not from the BAR */
char *driver_override; /* Driver name to force a match */
+
+ unsigned long priv_flags; /* Private flags for the pci driver */
};
static inline struct pci_dev *pci_physfn(struct pci_dev *dev)