mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-09 15:29:16 +00:00
PCI: Add device disconnected state
Add a new state to pci_dev to be set when it is unexpectedly disconnected. The PCI driver tear down functions can observe this new device state so they may skip operations that will fail. The pciehp and pcie-dpc drivers are aware when the link is down, so these set the flag when their handlers detect the device is disconnected. Tested-by: Krishna Dhulipala <krishnad@fb.com> Signed-off-by: Keith Busch <keith.busch@intel.com> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Wei Zhang <wzhang@fb.com>
This commit is contained in:
parent
d3881e5015
commit
89ee9f7680
@ -109,6 +109,12 @@ int pciehp_unconfigure_device(struct slot *p_slot)
|
|||||||
break;
|
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);
|
pci_stop_and_remove_bus_device(dev);
|
||||||
/*
|
/*
|
||||||
* Ensure that no new Requests will be generated from
|
* 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 */
|
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
|
#ifdef CONFIG_PCI_ATS
|
||||||
void pci_restore_ats_state(struct pci_dev *dev);
|
void pci_restore_ats_state(struct pci_dev *dev);
|
||||||
#else
|
#else
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/pci.h>
|
#include <linux/pci.h>
|
||||||
#include <linux/pcieport_if.h>
|
#include <linux/pcieport_if.h>
|
||||||
|
#include "../pci.h"
|
||||||
|
|
||||||
struct dpc_dev {
|
struct dpc_dev {
|
||||||
struct pcie_device *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,
|
list_for_each_entry_safe_reverse(dev, temp, &parent->devices,
|
||||||
bus_list) {
|
bus_list) {
|
||||||
pci_dev_get(dev);
|
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_stop_and_remove_bus_device(dev);
|
||||||
pci_dev_put(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 */
|
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 */
|
size_t romlen; /* Length of ROM if it's not from the BAR */
|
||||||
char *driver_override; /* Driver name to force a match */
|
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)
|
static inline struct pci_dev *pci_physfn(struct pci_dev *dev)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user