@@ -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
@@ -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
@@ -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;
@@ -46,6 +47,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);
}
@@ -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)