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>
This commit is contained in:

committed by
Jeff Kirsher

parent
d89777bf0e
commit
94fb848bf4
@@ -1780,6 +1780,23 @@ static irqreturn_t e1000_intr_msi(int irq, void *data)
|
||||
mod_timer(&adapter->watchdog_timer, jiffies + 1);
|
||||
}
|
||||
|
||||
/* Reset on uncorrectable ECC error */
|
||||
if ((icr & E1000_ICR_ECCER) && (hw->mac.type == e1000_pch_lpt)) {
|
||||
u32 pbeccsts = er32(PBECCSTS);
|
||||
|
||||
adapter->corr_errors +=
|
||||
pbeccsts & E1000_PBECCSTS_CORR_ERR_CNT_MASK;
|
||||
adapter->uncorr_errors +=
|
||||
(pbeccsts & E1000_PBECCSTS_UNCORR_ERR_CNT_MASK) >>
|
||||
E1000_PBECCSTS_UNCORR_ERR_CNT_SHIFT;
|
||||
|
||||
/* Do the reset outside of interrupt context */
|
||||
schedule_work(&adapter->reset_task);
|
||||
|
||||
/* return immediately since reset is imminent */
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
if (napi_schedule_prep(&adapter->napi)) {
|
||||
adapter->total_tx_bytes = 0;
|
||||
adapter->total_tx_packets = 0;
|
||||
@@ -1843,6 +1860,23 @@ static irqreturn_t e1000_intr(int irq, void *data)
|
||||
mod_timer(&adapter->watchdog_timer, jiffies + 1);
|
||||
}
|
||||
|
||||
/* Reset on uncorrectable ECC error */
|
||||
if ((icr & E1000_ICR_ECCER) && (hw->mac.type == e1000_pch_lpt)) {
|
||||
u32 pbeccsts = er32(PBECCSTS);
|
||||
|
||||
adapter->corr_errors +=
|
||||
pbeccsts & E1000_PBECCSTS_CORR_ERR_CNT_MASK;
|
||||
adapter->uncorr_errors +=
|
||||
(pbeccsts & E1000_PBECCSTS_UNCORR_ERR_CNT_MASK) >>
|
||||
E1000_PBECCSTS_UNCORR_ERR_CNT_SHIFT;
|
||||
|
||||
/* Do the reset outside of interrupt context */
|
||||
schedule_work(&adapter->reset_task);
|
||||
|
||||
/* return immediately since reset is imminent */
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
if (napi_schedule_prep(&adapter->napi)) {
|
||||
adapter->total_tx_bytes = 0;
|
||||
adapter->total_tx_packets = 0;
|
||||
@@ -2206,6 +2240,8 @@ static void e1000_irq_enable(struct e1000_adapter *adapter)
|
||||
if (adapter->msix_entries) {
|
||||
ew32(EIAC_82574, adapter->eiac_mask & E1000_EIAC_MASK_82574);
|
||||
ew32(IMS, adapter->eiac_mask | E1000_IMS_OTHER | E1000_IMS_LSC);
|
||||
} else if (hw->mac.type == e1000_pch_lpt) {
|
||||
ew32(IMS, IMS_ENABLE_MASK | E1000_IMS_ECCER);
|
||||
} else {
|
||||
ew32(IMS, IMS_ENABLE_MASK);
|
||||
}
|
||||
@@ -4619,6 +4655,16 @@ static void e1000e_update_stats(struct e1000_adapter *adapter)
|
||||
adapter->stats.mgptc += er32(MGTPTC);
|
||||
adapter->stats.mgprc += er32(MGTPRC);
|
||||
adapter->stats.mgpdc += er32(MGTPDC);
|
||||
|
||||
/* Correctable ECC Errors */
|
||||
if (hw->mac.type == e1000_pch_lpt) {
|
||||
u32 pbeccsts = er32(PBECCSTS);
|
||||
adapter->corr_errors +=
|
||||
pbeccsts & E1000_PBECCSTS_CORR_ERR_CNT_MASK;
|
||||
adapter->uncorr_errors +=
|
||||
(pbeccsts & E1000_PBECCSTS_UNCORR_ERR_CNT_MASK) >>
|
||||
E1000_PBECCSTS_UNCORR_ERR_CNT_SHIFT;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
Reference in New Issue
Block a user