|
@@ -538,43 +538,15 @@ static void e1000_rx_checksum(struct e1000_adapter *adapter, u32 status_err,
|
|
adapter->hw_csum_good++;
|
|
adapter->hw_csum_good++;
|
|
}
|
|
}
|
|
|
|
|
|
-/**
|
|
|
|
- * e1000e_update_tail_wa - helper function for e1000e_update_[rt]dt_wa()
|
|
|
|
- * @hw: pointer to the HW structure
|
|
|
|
- * @tail: address of tail descriptor register
|
|
|
|
- * @i: value to write to tail descriptor register
|
|
|
|
- *
|
|
|
|
- * When updating the tail register, the ME could be accessing Host CSR
|
|
|
|
- * 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 descriptor register to
|
|
|
|
- * have an incorrect value. Workaround this by checking the FWSM register
|
|
|
|
- * which has bit 24 set while ME is accessing Host CSR registers, wait
|
|
|
|
- * if it is set and try again a number of times.
|
|
|
|
- **/
|
|
|
|
-static inline s32 e1000e_update_tail_wa(struct e1000_hw *hw, void __iomem *tail,
|
|
|
|
- unsigned int i)
|
|
|
|
-{
|
|
|
|
- unsigned int j = 0;
|
|
|
|
-
|
|
|
|
- while ((j++ < E1000_ICH_FWSM_PCIM2PCI_COUNT) &&
|
|
|
|
- (er32(FWSM) & E1000_ICH_FWSM_PCIM2PCI))
|
|
|
|
- udelay(50);
|
|
|
|
-
|
|
|
|
- writel(i, tail);
|
|
|
|
-
|
|
|
|
- if ((j == E1000_ICH_FWSM_PCIM2PCI_COUNT) && (i != readl(tail)))
|
|
|
|
- return E1000_ERR_SWFW_SYNC;
|
|
|
|
-
|
|
|
|
- return 0;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
static void e1000e_update_rdt_wa(struct e1000_ring *rx_ring, unsigned int i)
|
|
static void e1000e_update_rdt_wa(struct e1000_ring *rx_ring, unsigned int i)
|
|
{
|
|
{
|
|
struct e1000_adapter *adapter = rx_ring->adapter;
|
|
struct e1000_adapter *adapter = rx_ring->adapter;
|
|
struct e1000_hw *hw = &adapter->hw;
|
|
struct e1000_hw *hw = &adapter->hw;
|
|
|
|
+ s32 ret_val = __ew32_prepare(hw);
|
|
|
|
+
|
|
|
|
+ writel(i, rx_ring->tail);
|
|
|
|
|
|
- if (e1000e_update_tail_wa(hw, rx_ring->tail, i)) {
|
|
|
|
|
|
+ if (unlikely(!ret_val && (i != readl(rx_ring->tail)))) {
|
|
u32 rctl = er32(RCTL);
|
|
u32 rctl = er32(RCTL);
|
|
ew32(RCTL, rctl & ~E1000_RCTL_EN);
|
|
ew32(RCTL, rctl & ~E1000_RCTL_EN);
|
|
e_err("ME firmware caused invalid RDT - resetting\n");
|
|
e_err("ME firmware caused invalid RDT - resetting\n");
|
|
@@ -586,8 +558,11 @@ static void e1000e_update_tdt_wa(struct e1000_ring *tx_ring, unsigned int i)
|
|
{
|
|
{
|
|
struct e1000_adapter *adapter = tx_ring->adapter;
|
|
struct e1000_adapter *adapter = tx_ring->adapter;
|
|
struct e1000_hw *hw = &adapter->hw;
|
|
struct e1000_hw *hw = &adapter->hw;
|
|
|
|
+ s32 ret_val = __ew32_prepare(hw);
|
|
|
|
|
|
- if (e1000e_update_tail_wa(hw, tx_ring->tail, i)) {
|
|
|
|
|
|
+ writel(i, tx_ring->tail);
|
|
|
|
+
|
|
|
|
+ if (unlikely(!ret_val && (i != readl(tx_ring->tail)))) {
|
|
u32 tctl = er32(TCTL);
|
|
u32 tctl = er32(TCTL);
|
|
ew32(TCTL, tctl & ~E1000_TCTL_EN);
|
|
ew32(TCTL, tctl & ~E1000_TCTL_EN);
|
|
e_err("ME firmware caused invalid TDT - resetting\n");
|
|
e_err("ME firmware caused invalid TDT - resetting\n");
|
|
@@ -1646,7 +1621,10 @@ static void e1000_clean_rx_ring(struct e1000_ring *rx_ring)
|
|
adapter->flags2 &= ~FLAG2_IS_DISCARDING;
|
|
adapter->flags2 &= ~FLAG2_IS_DISCARDING;
|
|
|
|
|
|
writel(0, rx_ring->head);
|
|
writel(0, rx_ring->head);
|
|
- writel(0, rx_ring->tail);
|
|
|
|
|
|
+ if (rx_ring->adapter->flags2 & FLAG2_PCIM2PCI_ARBITER_WA)
|
|
|
|
+ e1000e_update_rdt_wa(rx_ring, 0);
|
|
|
|
+ else
|
|
|
|
+ writel(0, rx_ring->tail);
|
|
}
|
|
}
|
|
|
|
|
|
static void e1000e_downshift_workaround(struct work_struct *work)
|
|
static void e1000e_downshift_workaround(struct work_struct *work)
|
|
@@ -2319,7 +2297,10 @@ static void e1000_clean_tx_ring(struct e1000_ring *tx_ring)
|
|
tx_ring->next_to_clean = 0;
|
|
tx_ring->next_to_clean = 0;
|
|
|
|
|
|
writel(0, tx_ring->head);
|
|
writel(0, tx_ring->head);
|
|
- writel(0, tx_ring->tail);
|
|
|
|
|
|
+ if (tx_ring->adapter->flags2 & FLAG2_PCIM2PCI_ARBITER_WA)
|
|
|
|
+ e1000e_update_tdt_wa(tx_ring, 0);
|
|
|
|
+ else
|
|
|
|
+ writel(0, tx_ring->tail);
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|