|
@@ -207,18 +207,18 @@ static void *eeh_report_error(void *data, void *userdata)
|
|
|
|
|
|
if (!dev || eeh_dev_removed(edev) || eeh_pe_passed(edev->pe))
|
|
if (!dev || eeh_dev_removed(edev) || eeh_pe_passed(edev->pe))
|
|
return NULL;
|
|
return NULL;
|
|
|
|
+
|
|
|
|
+ device_lock(&dev->dev);
|
|
dev->error_state = pci_channel_io_frozen;
|
|
dev->error_state = pci_channel_io_frozen;
|
|
|
|
|
|
driver = eeh_pcid_get(dev);
|
|
driver = eeh_pcid_get(dev);
|
|
- if (!driver) return NULL;
|
|
|
|
|
|
+ if (!driver) goto out_no_dev;
|
|
|
|
|
|
eeh_disable_irq(dev);
|
|
eeh_disable_irq(dev);
|
|
|
|
|
|
if (!driver->err_handler ||
|
|
if (!driver->err_handler ||
|
|
- !driver->err_handler->error_detected) {
|
|
|
|
- eeh_pcid_put(dev);
|
|
|
|
- return NULL;
|
|
|
|
- }
|
|
|
|
|
|
+ !driver->err_handler->error_detected)
|
|
|
|
+ goto out;
|
|
|
|
|
|
rc = driver->err_handler->error_detected(dev, pci_channel_io_frozen);
|
|
rc = driver->err_handler->error_detected(dev, pci_channel_io_frozen);
|
|
|
|
|
|
@@ -227,8 +227,12 @@ static void *eeh_report_error(void *data, void *userdata)
|
|
if (*res == PCI_ERS_RESULT_NONE) *res = rc;
|
|
if (*res == PCI_ERS_RESULT_NONE) *res = rc;
|
|
|
|
|
|
edev->in_error = true;
|
|
edev->in_error = true;
|
|
- eeh_pcid_put(dev);
|
|
|
|
pci_uevent_ers(dev, PCI_ERS_RESULT_NONE);
|
|
pci_uevent_ers(dev, PCI_ERS_RESULT_NONE);
|
|
|
|
+
|
|
|
|
+out:
|
|
|
|
+ eeh_pcid_put(dev);
|
|
|
|
+out_no_dev:
|
|
|
|
+ device_unlock(&dev->dev);
|
|
return NULL;
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -251,15 +255,14 @@ static void *eeh_report_mmio_enabled(void *data, void *userdata)
|
|
if (!dev || eeh_dev_removed(edev) || eeh_pe_passed(edev->pe))
|
|
if (!dev || eeh_dev_removed(edev) || eeh_pe_passed(edev->pe))
|
|
return NULL;
|
|
return NULL;
|
|
|
|
|
|
|
|
+ device_lock(&dev->dev);
|
|
driver = eeh_pcid_get(dev);
|
|
driver = eeh_pcid_get(dev);
|
|
- if (!driver) return NULL;
|
|
|
|
|
|
+ if (!driver) goto out_no_dev;
|
|
|
|
|
|
if (!driver->err_handler ||
|
|
if (!driver->err_handler ||
|
|
!driver->err_handler->mmio_enabled ||
|
|
!driver->err_handler->mmio_enabled ||
|
|
- (edev->mode & EEH_DEV_NO_HANDLER)) {
|
|
|
|
- eeh_pcid_put(dev);
|
|
|
|
- return NULL;
|
|
|
|
- }
|
|
|
|
|
|
+ (edev->mode & EEH_DEV_NO_HANDLER))
|
|
|
|
+ goto out;
|
|
|
|
|
|
rc = driver->err_handler->mmio_enabled(dev);
|
|
rc = driver->err_handler->mmio_enabled(dev);
|
|
|
|
|
|
@@ -267,7 +270,10 @@ static void *eeh_report_mmio_enabled(void *data, void *userdata)
|
|
if (rc == PCI_ERS_RESULT_NEED_RESET) *res = rc;
|
|
if (rc == PCI_ERS_RESULT_NEED_RESET) *res = rc;
|
|
if (*res == PCI_ERS_RESULT_NONE) *res = rc;
|
|
if (*res == PCI_ERS_RESULT_NONE) *res = rc;
|
|
|
|
|
|
|
|
+out:
|
|
eeh_pcid_put(dev);
|
|
eeh_pcid_put(dev);
|
|
|
|
+out_no_dev:
|
|
|
|
+ device_unlock(&dev->dev);
|
|
return NULL;
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -290,20 +296,20 @@ static void *eeh_report_reset(void *data, void *userdata)
|
|
|
|
|
|
if (!dev || eeh_dev_removed(edev) || eeh_pe_passed(edev->pe))
|
|
if (!dev || eeh_dev_removed(edev) || eeh_pe_passed(edev->pe))
|
|
return NULL;
|
|
return NULL;
|
|
|
|
+
|
|
|
|
+ device_lock(&dev->dev);
|
|
dev->error_state = pci_channel_io_normal;
|
|
dev->error_state = pci_channel_io_normal;
|
|
|
|
|
|
driver = eeh_pcid_get(dev);
|
|
driver = eeh_pcid_get(dev);
|
|
- if (!driver) return NULL;
|
|
|
|
|
|
+ if (!driver) goto out_no_dev;
|
|
|
|
|
|
eeh_enable_irq(dev);
|
|
eeh_enable_irq(dev);
|
|
|
|
|
|
if (!driver->err_handler ||
|
|
if (!driver->err_handler ||
|
|
!driver->err_handler->slot_reset ||
|
|
!driver->err_handler->slot_reset ||
|
|
(edev->mode & EEH_DEV_NO_HANDLER) ||
|
|
(edev->mode & EEH_DEV_NO_HANDLER) ||
|
|
- (!edev->in_error)) {
|
|
|
|
- eeh_pcid_put(dev);
|
|
|
|
- return NULL;
|
|
|
|
- }
|
|
|
|
|
|
+ (!edev->in_error))
|
|
|
|
+ goto out;
|
|
|
|
|
|
rc = driver->err_handler->slot_reset(dev);
|
|
rc = driver->err_handler->slot_reset(dev);
|
|
if ((*res == PCI_ERS_RESULT_NONE) ||
|
|
if ((*res == PCI_ERS_RESULT_NONE) ||
|
|
@@ -311,7 +317,10 @@ static void *eeh_report_reset(void *data, void *userdata)
|
|
if (*res == PCI_ERS_RESULT_DISCONNECT &&
|
|
if (*res == PCI_ERS_RESULT_DISCONNECT &&
|
|
rc == PCI_ERS_RESULT_NEED_RESET) *res = rc;
|
|
rc == PCI_ERS_RESULT_NEED_RESET) *res = rc;
|
|
|
|
|
|
|
|
+out:
|
|
eeh_pcid_put(dev);
|
|
eeh_pcid_put(dev);
|
|
|
|
+out_no_dev:
|
|
|
|
+ device_unlock(&dev->dev);
|
|
return NULL;
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -362,10 +371,12 @@ static void *eeh_report_resume(void *data, void *userdata)
|
|
|
|
|
|
if (!dev || eeh_dev_removed(edev) || eeh_pe_passed(edev->pe))
|
|
if (!dev || eeh_dev_removed(edev) || eeh_pe_passed(edev->pe))
|
|
return NULL;
|
|
return NULL;
|
|
|
|
+
|
|
|
|
+ device_lock(&dev->dev);
|
|
dev->error_state = pci_channel_io_normal;
|
|
dev->error_state = pci_channel_io_normal;
|
|
|
|
|
|
driver = eeh_pcid_get(dev);
|
|
driver = eeh_pcid_get(dev);
|
|
- if (!driver) return NULL;
|
|
|
|
|
|
+ if (!driver) goto out_no_dev;
|
|
|
|
|
|
was_in_error = edev->in_error;
|
|
was_in_error = edev->in_error;
|
|
edev->in_error = false;
|
|
edev->in_error = false;
|
|
@@ -375,18 +386,20 @@ static void *eeh_report_resume(void *data, void *userdata)
|
|
!driver->err_handler->resume ||
|
|
!driver->err_handler->resume ||
|
|
(edev->mode & EEH_DEV_NO_HANDLER) || !was_in_error) {
|
|
(edev->mode & EEH_DEV_NO_HANDLER) || !was_in_error) {
|
|
edev->mode &= ~EEH_DEV_NO_HANDLER;
|
|
edev->mode &= ~EEH_DEV_NO_HANDLER;
|
|
- eeh_pcid_put(dev);
|
|
|
|
- return NULL;
|
|
|
|
|
|
+ goto out;
|
|
}
|
|
}
|
|
|
|
|
|
driver->err_handler->resume(dev);
|
|
driver->err_handler->resume(dev);
|
|
|
|
|
|
- eeh_pcid_put(dev);
|
|
|
|
pci_uevent_ers(dev, PCI_ERS_RESULT_RECOVERED);
|
|
pci_uevent_ers(dev, PCI_ERS_RESULT_RECOVERED);
|
|
|
|
+out:
|
|
|
|
+ eeh_pcid_put(dev);
|
|
#ifdef CONFIG_PCI_IOV
|
|
#ifdef CONFIG_PCI_IOV
|
|
if (eeh_ops->notify_resume && eeh_dev_to_pdn(edev))
|
|
if (eeh_ops->notify_resume && eeh_dev_to_pdn(edev))
|
|
eeh_ops->notify_resume(eeh_dev_to_pdn(edev));
|
|
eeh_ops->notify_resume(eeh_dev_to_pdn(edev));
|
|
#endif
|
|
#endif
|
|
|
|
+out_no_dev:
|
|
|
|
+ device_unlock(&dev->dev);
|
|
return NULL;
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -406,23 +419,26 @@ static void *eeh_report_failure(void *data, void *userdata)
|
|
|
|
|
|
if (!dev || eeh_dev_removed(edev) || eeh_pe_passed(edev->pe))
|
|
if (!dev || eeh_dev_removed(edev) || eeh_pe_passed(edev->pe))
|
|
return NULL;
|
|
return NULL;
|
|
|
|
+
|
|
|
|
+ device_lock(&dev->dev);
|
|
dev->error_state = pci_channel_io_perm_failure;
|
|
dev->error_state = pci_channel_io_perm_failure;
|
|
|
|
|
|
driver = eeh_pcid_get(dev);
|
|
driver = eeh_pcid_get(dev);
|
|
- if (!driver) return NULL;
|
|
|
|
|
|
+ if (!driver) goto out_no_dev;
|
|
|
|
|
|
eeh_disable_irq(dev);
|
|
eeh_disable_irq(dev);
|
|
|
|
|
|
if (!driver->err_handler ||
|
|
if (!driver->err_handler ||
|
|
- !driver->err_handler->error_detected) {
|
|
|
|
- eeh_pcid_put(dev);
|
|
|
|
- return NULL;
|
|
|
|
- }
|
|
|
|
|
|
+ !driver->err_handler->error_detected)
|
|
|
|
+ goto out;
|
|
|
|
|
|
driver->err_handler->error_detected(dev, pci_channel_io_perm_failure);
|
|
driver->err_handler->error_detected(dev, pci_channel_io_perm_failure);
|
|
|
|
|
|
- eeh_pcid_put(dev);
|
|
|
|
pci_uevent_ers(dev, PCI_ERS_RESULT_DISCONNECT);
|
|
pci_uevent_ers(dev, PCI_ERS_RESULT_DISCONNECT);
|
|
|
|
+out:
|
|
|
|
+ eeh_pcid_put(dev);
|
|
|
|
+out_no_dev:
|
|
|
|
+ device_unlock(&dev->dev);
|
|
return NULL;
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
|