diff options
author | Somnath Kotur <somnath.kotur@emulex.com> | 2013-05-29 18:56:17 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-05-30 19:58:06 -0400 |
commit | 01e5b2c4559d084f4eaf0d160d84cc185db141ba (patch) | |
tree | f6a76bf3fa3f5e39888f5cf960c884d970f6b84b /drivers | |
parent | e38b170695d4108eeb6cd84db36f567fc6de4120 (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.c | 6 | ||||
-rw-r--r-- | drivers/net/ethernet/emulex/benet/be_main.c | 48 |
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 | ||
4099 | static int lancer_recover_func(struct be_adapter *adapter) | 4099 | static 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; |
4128 | err: | 4127 | err: |
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 | ||
4159 | out: | 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 | ||
4164 | static void be_worker(struct work_struct *work) | 4163 | static 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 | ||