e1000e: 82579 potential system hang on stress when ME enabled
Previously, a workaround was added to address a hardware bug in the PCIm2PCI arbiter where a write by the driver of the Transmit/Receive Descriptor Tail register could happen concurrently with a write of any MAC CSR register by the Manageability Engine (ME) which could cause the Tail register to have an incorrect value. The arbiter is supposed to prevent the concurrent writes but there is a bug that can cause the Host (driver) access to be acknowledged later than it should. After further investigation, it was discovered that a driver write access of any MAC CSR register after being idle for some time can be lost when ME is accessing a MAC CSR register. When this happens, no further target access is claimed by the MAC which could hang the system. The workaround to check bit 24 in the FWSM register (set only when ME is accessing a MAC CSR register) and delay for a limited amount of time until it is cleared is now done for all driver writes of MAC CSR registers on 82579 with ME enabled. In the rare case when the driver is writing the Tail register and ME is accessing any MAC CSR register for a duration longer than the maximum delay, write the register and verify it has the correct value before continuing, otherwise reset the device. This patch also moves some pre-existing macros from the hardware-specific header file to the more appropriate generic driver header file. 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
36ceeb43ce
commit
bdc125f73f
@@ -735,9 +735,46 @@ static inline u32 __er32(struct e1000_hw *hw, unsigned long reg)
|
||||
return readl(hw->hw_addr + reg);
|
||||
}
|
||||
|
||||
#define er32(reg) __er32(hw, E1000_##reg)
|
||||
|
||||
/**
|
||||
* __ew32_prepare - prepare to write to MAC CSR register on certain parts
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* When updating the MAC CSR registers, the Manageability Engine (ME) could
|
||||
* be accessing the registers at the same time. Normally, this is handled in
|
||||
* h/w by an arbiter but on some parts there is a bug that acknowledges Host
|
||||
* accesses later than it should which could result in the register to have
|
||||
* an incorrect value. Workaround this by checking the FWSM register which
|
||||
* has bit 24 set while ME is accessing MAC CSR registers, wait if it is set
|
||||
* and try again a number of times.
|
||||
**/
|
||||
static inline s32 __ew32_prepare(struct e1000_hw *hw)
|
||||
{
|
||||
s32 i = E1000_ICH_FWSM_PCIM2PCI_COUNT;
|
||||
|
||||
while ((er32(FWSM) & E1000_ICH_FWSM_PCIM2PCI) && --i)
|
||||
udelay(50);
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
static inline void __ew32(struct e1000_hw *hw, unsigned long reg, u32 val)
|
||||
{
|
||||
if (hw->adapter->flags2 & FLAG2_PCIM2PCI_ARBITER_WA)
|
||||
__ew32_prepare(hw);
|
||||
|
||||
writel(val, hw->hw_addr + reg);
|
||||
}
|
||||
|
||||
#define ew32(reg, val) __ew32(hw, E1000_##reg, (val))
|
||||
|
||||
#define e1e_flush() er32(STATUS)
|
||||
|
||||
#define E1000_WRITE_REG_ARRAY(a, reg, offset, value) \
|
||||
(__ew32((a), (reg + ((offset) << 2)), (value)))
|
||||
|
||||
#define E1000_READ_REG_ARRAY(a, reg, offset) \
|
||||
(readl((a)->hw_addr + reg + ((offset) << 2)))
|
||||
|
||||
#endif /* _E1000_H_ */
|
||||
|
Reference in New Issue
Block a user