Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 263214
b: refs/heads/master
c: c6e7f51
h: refs/heads/master
v: v3
  • Loading branch information
Bruce Allan authored and Jeff Kirsher committed Aug 13, 2011
1 parent dd1b3f1 commit 08b7ee5
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 5 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 0ed013e28fe853244f4972cf18d8e2bd62eeb8fc
refs/heads/master: c6e7f51e73c1bc6044bce989ec503ef2e4758d55
4 changes: 4 additions & 0 deletions trunk/drivers/net/e1000e/e1000.h
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,9 @@ struct e1000_info;
#define HV_M_STATUS_SPEED_1000 0x0200
#define HV_M_STATUS_LINK_UP 0x0040

#define E1000_ICH_FWSM_PCIM2PCI 0x01000000 /* ME PCIm-to-PCI active */
#define E1000_ICH_FWSM_PCIM2PCI_COUNT 2000

/* Time to wait before putting the device into D3 if there's no link (in ms). */
#define LINK_TIMEOUT 100

Expand Down Expand Up @@ -454,6 +457,7 @@ struct e1000_info {
#define FLAG2_DISABLE_AIM (1 << 8)
#define FLAG2_CHECK_PHY_HANG (1 << 9)
#define FLAG2_NO_DISABLE_RX (1 << 10)
#define FLAG2_PCIM2PCI_ARBITER_WA (1 << 11)

#define E1000_RX_DESC_PS(R, i) \
(&(((union e1000_rx_desc_packet_split *)((R).desc))[i]))
Expand Down
5 changes: 5 additions & 0 deletions trunk/drivers/net/e1000e/ich8lan.c
Original file line number Diff line number Diff line change
Expand Up @@ -814,6 +814,11 @@ static s32 e1000_get_variants_ich8lan(struct e1000_adapter *adapter)
(adapter->hw.phy.type == e1000_phy_igp_3))
adapter->flags |= FLAG_LSC_GIG_SPEED_DROP;

/* Enable workaround for 82579 w/ ME enabled */
if ((adapter->hw.mac.type == e1000_pch2lan) &&
(er32(FWSM) & E1000_ICH_FWSM_FW_VALID))
adapter->flags2 |= FLAG2_PCIM2PCI_ARBITER_WA;

/* Disable EEE by default until IEEE802.3az spec is finalized */
if (adapter->flags2 & FLAG2_HAS_EEE)
adapter->hw.dev_spec.ich8lan.eee_disable = true;
Expand Down
80 changes: 76 additions & 4 deletions trunk/drivers/net/e1000e/netdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -518,6 +518,63 @@ static void e1000_rx_checksum(struct e1000_adapter *adapter, u32 status_err,
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, u8 __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_adapter *adapter, unsigned int i)
{
u8 __iomem *tail = (adapter->hw.hw_addr + adapter->rx_ring->tail);
struct e1000_hw *hw = &adapter->hw;

if (e1000e_update_tail_wa(hw, tail, i)) {
u32 rctl = er32(RCTL);
ew32(RCTL, rctl & ~E1000_RCTL_EN);
e_err("ME firmware caused invalid RDT - resetting\n");
schedule_work(&adapter->reset_task);
}
}

static void e1000e_update_tdt_wa(struct e1000_adapter *adapter, unsigned int i)
{
u8 __iomem *tail = (adapter->hw.hw_addr + adapter->tx_ring->tail);
struct e1000_hw *hw = &adapter->hw;

if (e1000e_update_tail_wa(hw, tail, i)) {
u32 tctl = er32(TCTL);
ew32(TCTL, tctl & ~E1000_TCTL_EN);
e_err("ME firmware caused invalid TDT - resetting\n");
schedule_work(&adapter->reset_task);
}
}

/**
* e1000_alloc_rx_buffers - Replace used receive buffers; legacy & extended
* @adapter: address of board private structure
Expand Down Expand Up @@ -573,7 +630,10 @@ static void e1000_alloc_rx_buffers(struct e1000_adapter *adapter,
* such as IA-64).
*/
wmb();
writel(i, adapter->hw.hw_addr + rx_ring->tail);
if (adapter->flags2 & FLAG2_PCIM2PCI_ARBITER_WA)
e1000e_update_rdt_wa(adapter, i);
else
writel(i, adapter->hw.hw_addr + rx_ring->tail);
}
i++;
if (i == rx_ring->count)
Expand Down Expand Up @@ -673,7 +733,11 @@ static void e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter,
* such as IA-64).
*/
wmb();
writel(i << 1, adapter->hw.hw_addr + rx_ring->tail);
if (adapter->flags2 & FLAG2_PCIM2PCI_ARBITER_WA)
e1000e_update_rdt_wa(adapter, i << 1);
else
writel(i << 1,
adapter->hw.hw_addr + rx_ring->tail);
}

i++;
Expand Down Expand Up @@ -756,7 +820,10 @@ static void e1000_alloc_jumbo_rx_buffers(struct e1000_adapter *adapter,
* applicable for weak-ordered memory model archs,
* such as IA-64). */
wmb();
writel(i, adapter->hw.hw_addr + rx_ring->tail);
if (adapter->flags2 & FLAG2_PCIM2PCI_ARBITER_WA)
e1000e_update_rdt_wa(adapter, i);
else
writel(i, adapter->hw.hw_addr + rx_ring->tail);
}
}

Expand Down Expand Up @@ -4689,7 +4756,12 @@ static void e1000_tx_queue(struct e1000_adapter *adapter,
wmb();

tx_ring->next_to_use = i;
writel(i, adapter->hw.hw_addr + tx_ring->tail);

if (adapter->flags2 & FLAG2_PCIM2PCI_ARBITER_WA)
e1000e_update_tdt_wa(adapter, i);
else
writel(i, adapter->hw.hw_addr + tx_ring->tail);

/*
* we need this if more than one processor can write to our tail
* at a time, it synchronizes IO on IA64/Altix systems
Expand Down

0 comments on commit 08b7ee5

Please sign in to comment.