e1000e: add aer support

most if not all of the devices supported by e1000e support
AER (Advanced Error Reporting) so we attempt to register
with the OS that we know how to reset ourselves after
a fatal error.

Signed-off-by: Jesse Brandeburg <jesse.brandeburg@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Jesse Brandeburg 2009-02-10 12:51:20 +00:00 committed by David S. Miller
parent b4ac530fc3
commit 111b9dc5c9

View file

@ -44,6 +44,7 @@
#include <linux/cpu.h> #include <linux/cpu.h>
#include <linux/smp.h> #include <linux/smp.h>
#include <linux/pm_qos_params.h> #include <linux/pm_qos_params.h>
#include <linux/aer.h>
#include "e1000.h" #include "e1000.h"
@ -4521,6 +4522,14 @@ static int e1000_resume(struct pci_dev *pdev)
return err; return err;
} }
/* AER (Advanced Error Reporting) hooks */
err = pci_enable_pcie_error_reporting(pdev);
if (err) {
dev_err(&pdev->dev, "pci_enable_pcie_error_reporting failed "
"0x%x\n", err);
/* non-fatal, continue */
}
pci_set_master(pdev); pci_set_master(pdev);
pci_enable_wake(pdev, PCI_D3hot, 0); pci_enable_wake(pdev, PCI_D3hot, 0);
@ -4615,24 +4624,29 @@ static pci_ers_result_t e1000_io_slot_reset(struct pci_dev *pdev)
struct e1000_adapter *adapter = netdev_priv(netdev); struct e1000_adapter *adapter = netdev_priv(netdev);
struct e1000_hw *hw = &adapter->hw; struct e1000_hw *hw = &adapter->hw;
int err; int err;
pci_ers_result_t result;
e1000e_disable_l1aspm(pdev); e1000e_disable_l1aspm(pdev);
err = pci_enable_device_mem(pdev); err = pci_enable_device_mem(pdev);
if (err) { if (err) {
dev_err(&pdev->dev, dev_err(&pdev->dev,
"Cannot re-enable PCI device after reset.\n"); "Cannot re-enable PCI device after reset.\n");
return PCI_ERS_RESULT_DISCONNECT; result = PCI_ERS_RESULT_DISCONNECT;
} else {
pci_set_master(pdev);
pci_restore_state(pdev);
pci_enable_wake(pdev, PCI_D3hot, 0);
pci_enable_wake(pdev, PCI_D3cold, 0);
e1000e_reset(adapter);
ew32(WUS, ~0);
result = PCI_ERS_RESULT_RECOVERED;
} }
pci_set_master(pdev);
pci_restore_state(pdev);
pci_enable_wake(pdev, PCI_D3hot, 0); pci_cleanup_aer_uncorrect_error_status(pdev);
pci_enable_wake(pdev, PCI_D3cold, 0);
e1000e_reset(adapter); return result;
ew32(WUS, ~0);
return PCI_ERS_RESULT_RECOVERED;
} }
/** /**
@ -5063,6 +5077,7 @@ static void __devexit e1000_remove(struct pci_dev *pdev)
{ {
struct net_device *netdev = pci_get_drvdata(pdev); struct net_device *netdev = pci_get_drvdata(pdev);
struct e1000_adapter *adapter = netdev_priv(netdev); struct e1000_adapter *adapter = netdev_priv(netdev);
int err;
/* /*
* flush_scheduled work may reschedule our watchdog task, so * flush_scheduled work may reschedule our watchdog task, so
@ -5097,6 +5112,12 @@ static void __devexit e1000_remove(struct pci_dev *pdev)
free_netdev(netdev); free_netdev(netdev);
/* AER disable */
err = pci_disable_pcie_error_reporting(pdev);
if (err)
dev_err(&pdev->dev,
"pci_disable_pcie_error_reporting failed 0x%x\n", err);
pci_disable_device(pdev); pci_disable_device(pdev);
} }