aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorBruce Allan <bruce.w.allan@intel.com>2013-01-23 04:00:03 -0500
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>2013-01-27 03:49:42 -0500
commit94fb848bf43fae3410639fb2110a783200e9e1da (patch)
tree3b96797dfae519568a10f188d9349cd182cc98f6 /drivers/net
parentd89777bf0e42e7cb6ce8eae35190b9375c3b4211 (diff)
e1000e: enable ECC on I217/I218 to catch packet buffer memory errors
In rare instances, memory errors have been detected in the internal packet buffer memory on I217/I218 when stressed under certain environmental conditions. Enable Error Correcting Code (ECC) in hardware to catch both correctable and uncorrectable errors. Correctable errors will be handled by the hardware. Uncorrectable errors in the packet buffer will cause the packet to be received with an error indication in the buffer descriptor causing the packet to be discarded. If the uncorrectable error is in the descriptor itself, the hardware will stop and interrupt the driver indicating the error. The driver will then reset the hardware in order to clear the error and restart. Both types of errors will be accounted for in statistics counters. Signed-off-by: Bruce Allan <bruce.w.allan@intel.com> Tested-by: Jeff Pieper <jeffrey.e.pieper@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/ethernet/intel/e1000e/defines.h9
-rw-r--r--drivers/net/ethernet/intel/e1000e/e1000.h2
-rw-r--r--drivers/net/ethernet/intel/e1000e/ethtool.c2
-rw-r--r--drivers/net/ethernet/intel/e1000e/hw.h1
-rw-r--r--drivers/net/ethernet/intel/e1000e/ich8lan.c11
-rw-r--r--drivers/net/ethernet/intel/e1000e/netdev.c46
6 files changed, 71 insertions, 0 deletions
diff --git a/drivers/net/ethernet/intel/e1000e/defines.h b/drivers/net/ethernet/intel/e1000e/defines.h
index 5cb7441dca2a..f0452311c95a 100644
--- a/drivers/net/ethernet/intel/e1000e/defines.h
+++ b/drivers/net/ethernet/intel/e1000e/defines.h
@@ -233,6 +233,7 @@
233#define E1000_CTRL_FRCDPX 0x00001000 /* Force Duplex */ 233#define E1000_CTRL_FRCDPX 0x00001000 /* Force Duplex */
234#define E1000_CTRL_LANPHYPC_OVERRIDE 0x00010000 /* SW control of LANPHYPC */ 234#define E1000_CTRL_LANPHYPC_OVERRIDE 0x00010000 /* SW control of LANPHYPC */
235#define E1000_CTRL_LANPHYPC_VALUE 0x00020000 /* SW value of LANPHYPC */ 235#define E1000_CTRL_LANPHYPC_VALUE 0x00020000 /* SW value of LANPHYPC */
236#define E1000_CTRL_MEHE 0x00080000 /* Memory Error Handling Enable */
236#define E1000_CTRL_SWDPIN0 0x00040000 /* SWDPIN 0 value */ 237#define E1000_CTRL_SWDPIN0 0x00040000 /* SWDPIN 0 value */
237#define E1000_CTRL_SWDPIN1 0x00080000 /* SWDPIN 1 value */ 238#define E1000_CTRL_SWDPIN1 0x00080000 /* SWDPIN 1 value */
238#define E1000_CTRL_SWDPIO0 0x00400000 /* SWDPIN 0 Input or output */ 239#define E1000_CTRL_SWDPIO0 0x00400000 /* SWDPIN 0 Input or output */
@@ -394,6 +395,12 @@
394 395
395#define E1000_PBS_16K E1000_PBA_16K 396#define E1000_PBS_16K E1000_PBA_16K
396 397
398/* Uncorrectable/correctable ECC Error counts and enable bits */
399#define E1000_PBECCSTS_CORR_ERR_CNT_MASK 0x000000FF
400#define E1000_PBECCSTS_UNCORR_ERR_CNT_MASK 0x0000FF00
401#define E1000_PBECCSTS_UNCORR_ERR_CNT_SHIFT 8
402#define E1000_PBECCSTS_ECC_ENABLE 0x00010000
403
397#define IFS_MAX 80 404#define IFS_MAX 80
398#define IFS_MIN 40 405#define IFS_MIN 40
399#define IFS_RATIO 4 406#define IFS_RATIO 4
@@ -413,6 +420,7 @@
413#define E1000_ICR_RXSEQ 0x00000008 /* Rx sequence error */ 420#define E1000_ICR_RXSEQ 0x00000008 /* Rx sequence error */
414#define E1000_ICR_RXDMT0 0x00000010 /* Rx desc min. threshold (0) */ 421#define E1000_ICR_RXDMT0 0x00000010 /* Rx desc min. threshold (0) */
415#define E1000_ICR_RXT0 0x00000080 /* Rx timer intr (ring 0) */ 422#define E1000_ICR_RXT0 0x00000080 /* Rx timer intr (ring 0) */
423#define E1000_ICR_ECCER 0x00400000 /* Uncorrectable ECC Error */
416#define E1000_ICR_INT_ASSERTED 0x80000000 /* If this bit asserted, the driver should claim the interrupt */ 424#define E1000_ICR_INT_ASSERTED 0x80000000 /* If this bit asserted, the driver should claim the interrupt */
417#define E1000_ICR_RXQ0 0x00100000 /* Rx Queue 0 Interrupt */ 425#define E1000_ICR_RXQ0 0x00100000 /* Rx Queue 0 Interrupt */
418#define E1000_ICR_RXQ1 0x00200000 /* Rx Queue 1 Interrupt */ 426#define E1000_ICR_RXQ1 0x00200000 /* Rx Queue 1 Interrupt */
@@ -448,6 +456,7 @@
448#define E1000_IMS_RXSEQ E1000_ICR_RXSEQ /* Rx sequence error */ 456#define E1000_IMS_RXSEQ E1000_ICR_RXSEQ /* Rx sequence error */
449#define E1000_IMS_RXDMT0 E1000_ICR_RXDMT0 /* Rx desc min. threshold */ 457#define E1000_IMS_RXDMT0 E1000_ICR_RXDMT0 /* Rx desc min. threshold */
450#define E1000_IMS_RXT0 E1000_ICR_RXT0 /* Rx timer intr */ 458#define E1000_IMS_RXT0 E1000_ICR_RXT0 /* Rx timer intr */
459#define E1000_IMS_ECCER E1000_ICR_ECCER /* Uncorrectable ECC Error */
451#define E1000_IMS_RXQ0 E1000_ICR_RXQ0 /* Rx Queue 0 Interrupt */ 460#define E1000_IMS_RXQ0 E1000_ICR_RXQ0 /* Rx Queue 0 Interrupt */
452#define E1000_IMS_RXQ1 E1000_ICR_RXQ1 /* Rx Queue 1 Interrupt */ 461#define E1000_IMS_RXQ1 E1000_ICR_RXQ1 /* Rx Queue 1 Interrupt */
453#define E1000_IMS_TXQ0 E1000_ICR_TXQ0 /* Tx Queue 0 Interrupt */ 462#define E1000_IMS_TXQ0 E1000_ICR_TXQ0 /* Tx Queue 0 Interrupt */
diff --git a/drivers/net/ethernet/intel/e1000e/e1000.h b/drivers/net/ethernet/intel/e1000e/e1000.h
index bd5876171376..c96e6fcfdcbc 100644
--- a/drivers/net/ethernet/intel/e1000e/e1000.h
+++ b/drivers/net/ethernet/intel/e1000e/e1000.h
@@ -312,6 +312,8 @@ struct e1000_adapter {
312 312
313 struct napi_struct napi; 313 struct napi_struct napi;
314 314
315 unsigned int uncorr_errors; /* uncorrectable ECC errors */
316 unsigned int corr_errors; /* correctable ECC errors */
315 unsigned int restart_queue; 317 unsigned int restart_queue;
316 u32 txd_cmd; 318 u32 txd_cmd;
317 319
diff --git a/drivers/net/ethernet/intel/e1000e/ethtool.c b/drivers/net/ethernet/intel/e1000e/ethtool.c
index e3855bb10599..124821b49df6 100644
--- a/drivers/net/ethernet/intel/e1000e/ethtool.c
+++ b/drivers/net/ethernet/intel/e1000e/ethtool.c
@@ -109,6 +109,8 @@ static const struct e1000_stats e1000_gstrings_stats[] = {
109 E1000_STAT("rx_dma_failed", rx_dma_failed), 109 E1000_STAT("rx_dma_failed", rx_dma_failed),
110 E1000_STAT("tx_dma_failed", tx_dma_failed), 110 E1000_STAT("tx_dma_failed", tx_dma_failed),
111 E1000_STAT("rx_hwtstamp_cleared", rx_hwtstamp_cleared), 111 E1000_STAT("rx_hwtstamp_cleared", rx_hwtstamp_cleared),
112 E1000_STAT("uncorr_ecc_errors", uncorr_errors),
113 E1000_STAT("corr_ecc_errors", corr_errors),
112}; 114};
113 115
114#define E1000_GLOBAL_STATS_LEN ARRAY_SIZE(e1000_gstrings_stats) 116#define E1000_GLOBAL_STATS_LEN ARRAY_SIZE(e1000_gstrings_stats)
diff --git a/drivers/net/ethernet/intel/e1000e/hw.h b/drivers/net/ethernet/intel/e1000e/hw.h
index 84e6beb78718..4bd49be5915a 100644
--- a/drivers/net/ethernet/intel/e1000e/hw.h
+++ b/drivers/net/ethernet/intel/e1000e/hw.h
@@ -79,6 +79,7 @@ enum e1e_registers {
79#define E1000_POEMB E1000_PHY_CTRL /* PHY OEM Bits */ 79#define E1000_POEMB E1000_PHY_CTRL /* PHY OEM Bits */
80 E1000_PBA = 0x01000, /* Packet Buffer Allocation - RW */ 80 E1000_PBA = 0x01000, /* Packet Buffer Allocation - RW */
81 E1000_PBS = 0x01008, /* Packet Buffer Size */ 81 E1000_PBS = 0x01008, /* Packet Buffer Size */
82 E1000_PBECCSTS = 0x0100C, /* Packet Buffer ECC Status - RW */
82 E1000_EEMNGCTL = 0x01010, /* MNG EEprom Control */ 83 E1000_EEMNGCTL = 0x01010, /* MNG EEprom Control */
83 E1000_EEWR = 0x0102C, /* EEPROM Write Register - RW */ 84 E1000_EEWR = 0x0102C, /* EEPROM Write Register - RW */
84 E1000_FLOP = 0x0103C, /* FLASH Opcode Register */ 85 E1000_FLOP = 0x0103C, /* FLASH Opcode Register */
diff --git a/drivers/net/ethernet/intel/e1000e/ich8lan.c b/drivers/net/ethernet/intel/e1000e/ich8lan.c
index 50935ef48171..56cbfa7981eb 100644
--- a/drivers/net/ethernet/intel/e1000e/ich8lan.c
+++ b/drivers/net/ethernet/intel/e1000e/ich8lan.c
@@ -3704,6 +3704,17 @@ static void e1000_initialize_hw_bits_ich8lan(struct e1000_hw *hw)
3704 if (hw->mac.type == e1000_ich8lan) 3704 if (hw->mac.type == e1000_ich8lan)
3705 reg |= (E1000_RFCTL_IPV6_EX_DIS | E1000_RFCTL_NEW_IPV6_EXT_DIS); 3705 reg |= (E1000_RFCTL_IPV6_EX_DIS | E1000_RFCTL_NEW_IPV6_EXT_DIS);
3706 ew32(RFCTL, reg); 3706 ew32(RFCTL, reg);
3707
3708 /* Enable ECC on Lynxpoint */
3709 if (hw->mac.type == e1000_pch_lpt) {
3710 reg = er32(PBECCSTS);
3711 reg |= E1000_PBECCSTS_ECC_ENABLE;
3712 ew32(PBECCSTS, reg);
3713
3714 reg = er32(CTRL);
3715 reg |= E1000_CTRL_MEHE;
3716 ew32(CTRL, reg);
3717 }
3707} 3718}
3708 3719
3709/** 3720/**
diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c
index 34be756ee1e2..4c7e9fe23458 100644
--- a/drivers/net/ethernet/intel/e1000e/netdev.c
+++ b/drivers/net/ethernet/intel/e1000e/netdev.c
@@ -1780,6 +1780,23 @@ static irqreturn_t e1000_intr_msi(int irq, void *data)
1780 mod_timer(&adapter->watchdog_timer, jiffies + 1); 1780 mod_timer(&adapter->watchdog_timer, jiffies + 1);
1781 } 1781 }
1782 1782
1783 /* Reset on uncorrectable ECC error */
1784 if ((icr & E1000_ICR_ECCER) && (hw->mac.type == e1000_pch_lpt)) {
1785 u32 pbeccsts = er32(PBECCSTS);
1786
1787 adapter->corr_errors +=
1788 pbeccsts & E1000_PBECCSTS_CORR_ERR_CNT_MASK;
1789 adapter->uncorr_errors +=
1790 (pbeccsts & E1000_PBECCSTS_UNCORR_ERR_CNT_MASK) >>
1791 E1000_PBECCSTS_UNCORR_ERR_CNT_SHIFT;
1792
1793 /* Do the reset outside of interrupt context */
1794 schedule_work(&adapter->reset_task);
1795
1796 /* return immediately since reset is imminent */
1797 return IRQ_HANDLED;
1798 }
1799
1783 if (napi_schedule_prep(&adapter->napi)) { 1800 if (napi_schedule_prep(&adapter->napi)) {
1784 adapter->total_tx_bytes = 0; 1801 adapter->total_tx_bytes = 0;
1785 adapter->total_tx_packets = 0; 1802 adapter->total_tx_packets = 0;
@@ -1843,6 +1860,23 @@ static irqreturn_t e1000_intr(int irq, void *data)
1843 mod_timer(&adapter->watchdog_timer, jiffies + 1); 1860 mod_timer(&adapter->watchdog_timer, jiffies + 1);
1844 } 1861 }
1845 1862
1863 /* Reset on uncorrectable ECC error */
1864 if ((icr & E1000_ICR_ECCER) && (hw->mac.type == e1000_pch_lpt)) {
1865 u32 pbeccsts = er32(PBECCSTS);
1866
1867 adapter->corr_errors +=
1868 pbeccsts & E1000_PBECCSTS_CORR_ERR_CNT_MASK;
1869 adapter->uncorr_errors +=
1870 (pbeccsts & E1000_PBECCSTS_UNCORR_ERR_CNT_MASK) >>
1871 E1000_PBECCSTS_UNCORR_ERR_CNT_SHIFT;
1872
1873 /* Do the reset outside of interrupt context */
1874 schedule_work(&adapter->reset_task);
1875
1876 /* return immediately since reset is imminent */
1877 return IRQ_HANDLED;
1878 }
1879
1846 if (napi_schedule_prep(&adapter->napi)) { 1880 if (napi_schedule_prep(&adapter->napi)) {
1847 adapter->total_tx_bytes = 0; 1881 adapter->total_tx_bytes = 0;
1848 adapter->total_tx_packets = 0; 1882 adapter->total_tx_packets = 0;
@@ -2206,6 +2240,8 @@ static void e1000_irq_enable(struct e1000_adapter *adapter)
2206 if (adapter->msix_entries) { 2240 if (adapter->msix_entries) {
2207 ew32(EIAC_82574, adapter->eiac_mask & E1000_EIAC_MASK_82574); 2241 ew32(EIAC_82574, adapter->eiac_mask & E1000_EIAC_MASK_82574);
2208 ew32(IMS, adapter->eiac_mask | E1000_IMS_OTHER | E1000_IMS_LSC); 2242 ew32(IMS, adapter->eiac_mask | E1000_IMS_OTHER | E1000_IMS_LSC);
2243 } else if (hw->mac.type == e1000_pch_lpt) {
2244 ew32(IMS, IMS_ENABLE_MASK | E1000_IMS_ECCER);
2209 } else { 2245 } else {
2210 ew32(IMS, IMS_ENABLE_MASK); 2246 ew32(IMS, IMS_ENABLE_MASK);
2211 } 2247 }
@@ -4619,6 +4655,16 @@ static void e1000e_update_stats(struct e1000_adapter *adapter)
4619 adapter->stats.mgptc += er32(MGTPTC); 4655 adapter->stats.mgptc += er32(MGTPTC);
4620 adapter->stats.mgprc += er32(MGTPRC); 4656 adapter->stats.mgprc += er32(MGTPRC);
4621 adapter->stats.mgpdc += er32(MGTPDC); 4657 adapter->stats.mgpdc += er32(MGTPDC);
4658
4659 /* Correctable ECC Errors */
4660 if (hw->mac.type == e1000_pch_lpt) {
4661 u32 pbeccsts = er32(PBECCSTS);
4662 adapter->corr_errors +=
4663 pbeccsts & E1000_PBECCSTS_CORR_ERR_CNT_MASK;
4664 adapter->uncorr_errors +=
4665 (pbeccsts & E1000_PBECCSTS_UNCORR_ERR_CNT_MASK) >>
4666 E1000_PBECCSTS_UNCORR_ERR_CNT_SHIFT;
4667 }
4622} 4668}
4623 4669
4624/** 4670/**