From 54037505a5278ce85df66531f384109ad94947e3 Mon Sep 17 00:00:00 2001 From: Don Skidmore Date: Sat, 21 Feb 2009 15:42:56 -0800 Subject: [PATCH] ixgbe: fix for 82598 Si errata causing buffer overflow The failure happens when an interrupt occurs and the driver is reading EICR. This read will cause a clear-by-read which leads to two TLP being inserted in the PCIe retry buffer leading to an overflow of the buffer and corruption of TLPs. The solution is different depending where the reading of EICR takes place. For ixgbe_msix_lsc() since we are in MSIX mode and know OCD is enabled a clear-by-write is done instead of the normal clear-by-read. For ixgbe_intr() 0xffffffff is written to EIMC before the read, masking the interrupts. Signed-off-by: Don Skidmore Acked-by: Peter P Waskiewicz Jr Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe_main.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 8c32c18f569c..e0d736cc245b 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -936,7 +936,16 @@ static irqreturn_t ixgbe_msix_lsc(int irq, void *data) struct net_device *netdev = data; struct ixgbe_adapter *adapter = netdev_priv(netdev); struct ixgbe_hw *hw = &adapter->hw; - u32 eicr = IXGBE_READ_REG(hw, IXGBE_EICR); + u32 eicr; + + /* + * Workaround for Silicon errata. Use clear-by-write instead + * of clear-by-read. Reading with EICS will return the + * interrupt causes without clearing, which later be done + * with the write to EICR. + */ + eicr = IXGBE_READ_REG(hw, IXGBE_EICS); + IXGBE_WRITE_REG(hw, IXGBE_EICR, eicr); if (eicr & IXGBE_EICR_LSC) ixgbe_check_lsc(adapter); @@ -1355,6 +1364,12 @@ static irqreturn_t ixgbe_intr(int irq, void *data) struct ixgbe_hw *hw = &adapter->hw; u32 eicr; + /* + * Workaround for silicon errata. Mask the interrupts + * before the read of EICR. + */ + IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_IRQ_CLEAR_MASK); + /* for NAPI, using EIAM to auto-mask tx/rx interrupt bits on read * therefore no explict interrupt disable is necessary */ eicr = IXGBE_READ_REG(hw, IXGBE_EICR); -- 2.30.2