aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorSomnath Kotur <somnath.kotur@emulex.com>2013-05-29 18:56:17 -0400
committerDavid S. Miller <davem@davemloft.net>2013-05-30 19:58:06 -0400
commit01e5b2c4559d084f4eaf0d160d84cc185db141ba (patch)
treef6a76bf3fa3f5e39888f5cf960c884d970f6b84b /drivers
parente38b170695d4108eeb6cd84db36f567fc6de4120 (diff)
be2net: Fix crash on 2nd invocation of PCI AER/EEH error_detected hook
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>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/ethernet/emulex/benet/be_cmds.c6
-rw-r--r--drivers/net/ethernet/emulex/benet/be_main.c48
2 files changed, 26 insertions, 28 deletions
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c
index a236ecd27cf3..1db2df61b8af 100644
--- a/drivers/net/ethernet/emulex/benet/be_cmds.c
+++ b/drivers/net/ethernet/emulex/benet/be_cmds.c
@@ -562,7 +562,7 @@ int lancer_test_and_set_rdy_state(struct be_adapter *adapter)
562 562
563 resource_error = lancer_provisioning_error(adapter); 563 resource_error = lancer_provisioning_error(adapter);
564 if (resource_error) 564 if (resource_error)
565 return -1; 565 return -EAGAIN;
566 566
567 status = lancer_wait_ready(adapter); 567 status = lancer_wait_ready(adapter);
568 if (!status) { 568 if (!status) {
@@ -590,8 +590,8 @@ int lancer_test_and_set_rdy_state(struct be_adapter *adapter)
590 * when PF provisions resources. 590 * when PF provisions resources.
591 */ 591 */
592 resource_error = lancer_provisioning_error(adapter); 592 resource_error = lancer_provisioning_error(adapter);
593 if (status == -1 && !resource_error) 593 if (resource_error)
594 adapter->eeh_error = true; 594 status = -EAGAIN;
595 595
596 return status; 596 return status;
597} 597}
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
index 32a6927ca977..8bc1b21b1c79 100644
--- a/drivers/net/ethernet/emulex/benet/be_main.c
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
@@ -4098,6 +4098,7 @@ static int be_get_initial_config(struct be_adapter *adapter)
4098 4098
4099static int lancer_recover_func(struct be_adapter *adapter) 4099static int lancer_recover_func(struct be_adapter *adapter)
4100{ 4100{
4101 struct device *dev = &adapter->pdev->dev;
4101 int status; 4102 int status;
4102 4103
4103 status = lancer_test_and_set_rdy_state(adapter); 4104 status = lancer_test_and_set_rdy_state(adapter);
@@ -4109,8 +4110,7 @@ static int lancer_recover_func(struct be_adapter *adapter)
4109 4110
4110 be_clear(adapter); 4111 be_clear(adapter);
4111 4112
4112 adapter->hw_error = false; 4113 be_clear_all_error(adapter);
4113 adapter->fw_timeout = false;
4114 4114
4115 status = be_setup(adapter); 4115 status = be_setup(adapter);
4116 if (status) 4116 if (status)
@@ -4122,13 +4122,13 @@ static int lancer_recover_func(struct be_adapter *adapter)
4122 goto err; 4122 goto err;
4123 } 4123 }
4124 4124
4125 dev_err(&adapter->pdev->dev, 4125 dev_err(dev, "Error recovery successful\n");
4126 "Adapter SLIPORT recovery succeeded\n");
4127 return 0; 4126 return 0;
4128err: 4127err:
4129 if (adapter->eeh_error) 4128 if (status == -EAGAIN)
4130 dev_err(&adapter->pdev->dev, 4129 dev_err(dev, "Waiting for resource provisioning\n");
4131 "Adapter SLIPORT recovery failed\n"); 4130 else
4131 dev_err(dev, "Error recovery failed\n");
4132 4132
4133 return status; 4133 return status;
4134} 4134}
@@ -4137,28 +4137,27 @@ static void be_func_recovery_task(struct work_struct *work)
4137{ 4137{
4138 struct be_adapter *adapter = 4138 struct be_adapter *adapter =
4139 container_of(work, struct be_adapter, func_recovery_work.work); 4139 container_of(work, struct be_adapter, func_recovery_work.work);
4140 int status; 4140 int status = 0;
4141 4141
4142 be_detect_error(adapter); 4142 be_detect_error(adapter);
4143 4143
4144 if (adapter->hw_error && lancer_chip(adapter)) { 4144 if (adapter->hw_error && lancer_chip(adapter)) {
4145 4145
4146 if (adapter->eeh_error)
4147 goto out;
4148
4149 rtnl_lock(); 4146 rtnl_lock();
4150 netif_device_detach(adapter->netdev); 4147 netif_device_detach(adapter->netdev);
4151 rtnl_unlock(); 4148 rtnl_unlock();
4152 4149
4153 status = lancer_recover_func(adapter); 4150 status = lancer_recover_func(adapter);
4154
4155 if (!status) 4151 if (!status)
4156 netif_device_attach(adapter->netdev); 4152 netif_device_attach(adapter->netdev);
4157 } 4153 }
4158 4154
4159out: 4155 /* In Lancer, for all errors other than provisioning error (-EAGAIN),
4160 schedule_delayed_work(&adapter->func_recovery_work, 4156 * no need to attempt further recovery.
4161 msecs_to_jiffies(1000)); 4157 */
4158 if (!status || status == -EAGAIN)
4159 schedule_delayed_work(&adapter->func_recovery_work,
4160 msecs_to_jiffies(1000));
4162} 4161}
4163 4162
4164static void be_worker(struct work_struct *work) 4163static void be_worker(struct work_struct *work)
@@ -4441,20 +4440,19 @@ static pci_ers_result_t be_eeh_err_detected(struct pci_dev *pdev,
4441 4440
4442 dev_err(&adapter->pdev->dev, "EEH error detected\n"); 4441 dev_err(&adapter->pdev->dev, "EEH error detected\n");
4443 4442
4444 adapter->eeh_error = true; 4443 if (!adapter->eeh_error) {
4445 4444 adapter->eeh_error = true;
4446 cancel_delayed_work_sync(&adapter->func_recovery_work);
4447 4445
4448 rtnl_lock(); 4446 cancel_delayed_work_sync(&adapter->func_recovery_work);
4449 netif_device_detach(netdev);
4450 rtnl_unlock();
4451 4447
4452 if (netif_running(netdev)) {
4453 rtnl_lock(); 4448 rtnl_lock();
4454 be_close(netdev); 4449 netif_device_detach(netdev);
4450 if (netif_running(netdev))
4451 be_close(netdev);
4455 rtnl_unlock(); 4452 rtnl_unlock();
4453
4454 be_clear(adapter);
4456 } 4455 }
4457 be_clear(adapter);
4458 4456
4459 if (state == pci_channel_io_perm_failure) 4457 if (state == pci_channel_io_perm_failure)
4460 return PCI_ERS_RESULT_DISCONNECT; 4458 return PCI_ERS_RESULT_DISCONNECT;
@@ -4479,7 +4477,6 @@ static pci_ers_result_t be_eeh_reset(struct pci_dev *pdev)
4479 int status; 4477 int status;
4480 4478
4481 dev_info(&adapter->pdev->dev, "EEH reset\n"); 4479 dev_info(&adapter->pdev->dev, "EEH reset\n");
4482 be_clear_all_error(adapter);
4483 4480
4484 status = pci_enable_device(pdev); 4481 status = pci_enable_device(pdev);
4485 if (status) 4482 if (status)
@@ -4497,6 +4494,7 @@ static pci_ers_result_t be_eeh_reset(struct pci_dev *pdev)
4497 return PCI_ERS_RESULT_DISCONNECT; 4494 return PCI_ERS_RESULT_DISCONNECT;
4498 4495
4499 pci_cleanup_aer_uncorrect_error_status(pdev); 4496 pci_cleanup_aer_uncorrect_error_status(pdev);
4497 be_clear_all_error(adapter);
4500 return PCI_ERS_RESULT_RECOVERED; 4498 return PCI_ERS_RESULT_RECOVERED;
4501} 4499}
4502 4500