@@ -295,21 +295,20 @@ struct pci_sriov {
bool drivers_autoprobe; /* Auto probing of VFs by driver */
};
-/* pci_dev priv_flags */
-#define PCI_DEV_DISCONNECTED 0
-#define PCI_DEV_ADDED 1
-
static inline int pci_dev_set_disconnected(struct pci_dev *dev, void *unused)
{
- set_bit(PCI_DEV_DISCONNECTED, &dev->priv_flags);
+ dev->error_state = pci_channel_io_perm_failure;
return 0;
}
static inline bool pci_dev_is_disconnected(const struct pci_dev *dev)
{
- return test_bit(PCI_DEV_DISCONNECTED, &dev->priv_flags);
+ return dev->error_state == pci_channel_io_perm_failure;
}
+/* pci_dev priv_flags */
+#define PCI_DEV_ADDED 0
+
static inline void pci_dev_assign_added(struct pci_dev *dev, bool added)
{
assign_bit(PCI_DEV_ADDED, &dev->priv_flags, added);
@@ -52,9 +52,9 @@ static int report_error_detected(struct pci_dev *dev,
const struct pci_error_handlers *err_handler;
device_lock(&dev->dev);
- dev->error_state = state;
- if (!dev->driver ||
+ if (!cmpxchg(&dev->error_state, state, pci_channel_io_normal) ||
+ !dev->driver ||
!dev->driver->err_handler ||
!dev->driver->err_handler->error_detected) {
/*
@@ -130,11 +130,18 @@ static int report_resume(struct pci_dev *dev, void *data)
const struct pci_error_handlers *err_handler;
device_lock(&dev->dev);
- dev->error_state = pci_channel_io_normal;
+ cmpxchg(&dev->error_state, pci_channel_io_normal,
+ pci_channel_io_frozen);
+
+ /*
+ * If channel is offline, hotplug handling is taking care of this
+ * device.
+ */
if (!dev->driver ||
!dev->driver->err_handler ||
- !dev->driver->err_handler->resume)
+ !dev->driver->err_handler->resume ||
+ pci_channel_offline(dev))
goto out;
err_handler = dev->driver->err_handler;
This patch brings surprise removals and permanent failures together so we no longer need separate flags. The error handling will not be able to override a surprise removal's permanent channel failure by doing an atomic compare and exchange operation on the error state. Signed-off-by: Keith Busch <keith.busch@intel.com> --- drivers/pci/pci.h | 11 +++++------ drivers/pci/pcie/err.c | 15 +++++++++++---- 2 files changed, 16 insertions(+), 10 deletions(-)