|
@@ -11,6 +11,7 @@
|
|
|
#include <linux/ipv6.h>
|
|
|
#include <linux/ethtool.h>
|
|
|
#include <linux/interrupt.h>
|
|
|
+#include <linux/aer.h>
|
|
|
|
|
|
#define QLCNIC_MAX_TX_QUEUES 1
|
|
|
#define RSS_HASHTYPE_IP_TCP 0x3
|
|
@@ -177,6 +178,10 @@ static struct qlcnic_hardware_ops qlcnic_83xx_hw_ops = {
|
|
|
.get_board_info = qlcnic_83xx_get_port_info,
|
|
|
.set_mac_filter_count = qlcnic_83xx_set_mac_filter_count,
|
|
|
.free_mac_list = qlcnic_82xx_free_mac_list,
|
|
|
+ .io_error_detected = qlcnic_83xx_io_error_detected,
|
|
|
+ .io_slot_reset = qlcnic_83xx_io_slot_reset,
|
|
|
+ .io_resume = qlcnic_83xx_io_resume,
|
|
|
+
|
|
|
};
|
|
|
|
|
|
static struct qlcnic_nic_template qlcnic_83xx_ops = {
|
|
@@ -3819,3 +3824,57 @@ int qlcnic_83xx_init_mailbox_work(struct qlcnic_adapter *adapter)
|
|
|
set_bit(QLC_83XX_MBX_READY, &mbx->status);
|
|
|
return 0;
|
|
|
}
|
|
|
+
|
|
|
+pci_ers_result_t qlcnic_83xx_io_error_detected(struct pci_dev *pdev,
|
|
|
+ pci_channel_state_t state)
|
|
|
+{
|
|
|
+ struct qlcnic_adapter *adapter = pci_get_drvdata(pdev);
|
|
|
+
|
|
|
+ if (state == pci_channel_io_perm_failure)
|
|
|
+ return PCI_ERS_RESULT_DISCONNECT;
|
|
|
+
|
|
|
+ if (state == pci_channel_io_normal)
|
|
|
+ return PCI_ERS_RESULT_RECOVERED;
|
|
|
+
|
|
|
+ set_bit(__QLCNIC_AER, &adapter->state);
|
|
|
+ set_bit(__QLCNIC_RESETTING, &adapter->state);
|
|
|
+
|
|
|
+ qlcnic_83xx_aer_stop_poll_work(adapter);
|
|
|
+
|
|
|
+ pci_save_state(pdev);
|
|
|
+ pci_disable_device(pdev);
|
|
|
+
|
|
|
+ return PCI_ERS_RESULT_NEED_RESET;
|
|
|
+}
|
|
|
+
|
|
|
+pci_ers_result_t qlcnic_83xx_io_slot_reset(struct pci_dev *pdev)
|
|
|
+{
|
|
|
+ struct qlcnic_adapter *adapter = pci_get_drvdata(pdev);
|
|
|
+ int err = 0;
|
|
|
+
|
|
|
+ pdev->error_state = pci_channel_io_normal;
|
|
|
+ err = pci_enable_device(pdev);
|
|
|
+ if (err)
|
|
|
+ goto disconnect;
|
|
|
+
|
|
|
+ pci_set_power_state(pdev, PCI_D0);
|
|
|
+ pci_set_master(pdev);
|
|
|
+ pci_restore_state(pdev);
|
|
|
+
|
|
|
+ err = qlcnic_83xx_aer_reset(adapter);
|
|
|
+ if (err == 0)
|
|
|
+ return PCI_ERS_RESULT_RECOVERED;
|
|
|
+disconnect:
|
|
|
+ clear_bit(__QLCNIC_AER, &adapter->state);
|
|
|
+ clear_bit(__QLCNIC_RESETTING, &adapter->state);
|
|
|
+ return PCI_ERS_RESULT_DISCONNECT;
|
|
|
+}
|
|
|
+
|
|
|
+void qlcnic_83xx_io_resume(struct pci_dev *pdev)
|
|
|
+{
|
|
|
+ struct qlcnic_adapter *adapter = pci_get_drvdata(pdev);
|
|
|
+
|
|
|
+ pci_cleanup_aer_uncorrect_error_status(pdev);
|
|
|
+ if (test_and_clear_bit(__QLCNIC_AER, &adapter->state))
|
|
|
+ qlcnic_83xx_aer_start_poll_work(adapter);
|
|
|
+}
|