During a PCI EEH/AER error recovery flow, if the device did not successfully
restart, the error_detected() hook may be called a second time with a
"perm_failure" state. This patch skips over driver cleanup for the second
invocation of the callback.
Also, Lancer error recovery code is fixed-up to handle these changes.
Signed-off-by: Kalesh AP <kalesh.purayil@emulex.com>
Signed-off-by: Somnath kotur <somnath.kotur@emulex.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
resource_error = lancer_provisioning_error(adapter);
if (resource_error)
resource_error = lancer_provisioning_error(adapter);
if (resource_error)
status = lancer_wait_ready(adapter);
if (!status) {
status = lancer_wait_ready(adapter);
if (!status) {
* when PF provisions resources.
*/
resource_error = lancer_provisioning_error(adapter);
* when PF provisions resources.
*/
resource_error = lancer_provisioning_error(adapter);
- if (status == -1 && !resource_error)
- adapter->eeh_error = true;
+ if (resource_error)
+ status = -EAGAIN;
static int lancer_recover_func(struct be_adapter *adapter)
{
static int lancer_recover_func(struct be_adapter *adapter)
{
+ struct device *dev = &adapter->pdev->dev;
int status;
status = lancer_test_and_set_rdy_state(adapter);
int status;
status = lancer_test_and_set_rdy_state(adapter);
- adapter->hw_error = false;
- adapter->fw_timeout = false;
+ be_clear_all_error(adapter);
status = be_setup(adapter);
if (status)
status = be_setup(adapter);
if (status)
- dev_err(&adapter->pdev->dev,
- "Adapter SLIPORT recovery succeeded\n");
+ dev_err(dev, "Error recovery successful\n");
- if (adapter->eeh_error)
- dev_err(&adapter->pdev->dev,
- "Adapter SLIPORT recovery failed\n");
+ if (status == -EAGAIN)
+ dev_err(dev, "Waiting for resource provisioning\n");
+ else
+ dev_err(dev, "Error recovery failed\n");
{
struct be_adapter *adapter =
container_of(work, struct be_adapter, func_recovery_work.work);
{
struct be_adapter *adapter =
container_of(work, struct be_adapter, func_recovery_work.work);
be_detect_error(adapter);
if (adapter->hw_error && lancer_chip(adapter)) {
be_detect_error(adapter);
if (adapter->hw_error && lancer_chip(adapter)) {
- if (adapter->eeh_error)
- goto out;
-
rtnl_lock();
netif_device_detach(adapter->netdev);
rtnl_unlock();
status = lancer_recover_func(adapter);
rtnl_lock();
netif_device_detach(adapter->netdev);
rtnl_unlock();
status = lancer_recover_func(adapter);
if (!status)
netif_device_attach(adapter->netdev);
}
if (!status)
netif_device_attach(adapter->netdev);
}
-out:
- schedule_delayed_work(&adapter->func_recovery_work,
- msecs_to_jiffies(1000));
+ /* In Lancer, for all errors other than provisioning error (-EAGAIN),
+ * no need to attempt further recovery.
+ */
+ if (!status || status == -EAGAIN)
+ schedule_delayed_work(&adapter->func_recovery_work,
+ msecs_to_jiffies(1000));
}
static void be_worker(struct work_struct *work)
}
static void be_worker(struct work_struct *work)
dev_err(&adapter->pdev->dev, "EEH error detected\n");
dev_err(&adapter->pdev->dev, "EEH error detected\n");
- adapter->eeh_error = true;
-
- cancel_delayed_work_sync(&adapter->func_recovery_work);
+ if (!adapter->eeh_error) {
+ adapter->eeh_error = true;
- rtnl_lock();
- netif_device_detach(netdev);
- rtnl_unlock();
+ cancel_delayed_work_sync(&adapter->func_recovery_work);
- if (netif_running(netdev)) {
+ netif_device_detach(netdev);
+ if (netif_running(netdev))
+ be_close(netdev);
if (state == pci_channel_io_perm_failure)
return PCI_ERS_RESULT_DISCONNECT;
if (state == pci_channel_io_perm_failure)
return PCI_ERS_RESULT_DISCONNECT;
int status;
dev_info(&adapter->pdev->dev, "EEH reset\n");
int status;
dev_info(&adapter->pdev->dev, "EEH reset\n");
- be_clear_all_error(adapter);
status = pci_enable_device(pdev);
if (status)
status = pci_enable_device(pdev);
if (status)
return PCI_ERS_RESULT_DISCONNECT;
pci_cleanup_aer_uncorrect_error_status(pdev);
return PCI_ERS_RESULT_DISCONNECT;
pci_cleanup_aer_uncorrect_error_status(pdev);
+ be_clear_all_error(adapter);
return PCI_ERS_RESULT_RECOVERED;
}
return PCI_ERS_RESULT_RECOVERED;
}