igb: fix init on 82575 with MNG enabled

This patch resolves an issue seen on 82575 adapters with managability
pass-thru enabled, which could cause the system to panic.

Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
This commit is contained in:
Alexander Duyck 2008-06-27 11:00:29 -07:00 committed by Jeff Garzik
parent 652fff3214
commit 662d7205b3
4 changed files with 79 additions and 0 deletions

View file

@ -1227,6 +1227,79 @@ static void igb_clear_hw_cntrs_82575(struct e1000_hw *hw)
temp = rd32(E1000_SCVPC);
}
/**
* igb_rx_fifo_flush_82575 - Clean rx fifo after RX enable
* @hw: pointer to the HW structure
*
* After rx enable if managability is enabled then there is likely some
* bad data at the start of the fifo and possibly in the DMA fifo. This
* function clears the fifos and flushes any packets that came in as rx was
* being enabled.
**/
void igb_rx_fifo_flush_82575(struct e1000_hw *hw)
{
u32 rctl, rlpml, rxdctl[4], rfctl, temp_rctl, rx_enabled;
int i, ms_wait;
if (hw->mac.type != e1000_82575 ||
!(rd32(E1000_MANC) & E1000_MANC_RCV_TCO_EN))
return;
/* Disable all RX queues */
for (i = 0; i < 4; i++) {
rxdctl[i] = rd32(E1000_RXDCTL(i));
wr32(E1000_RXDCTL(i),
rxdctl[i] & ~E1000_RXDCTL_QUEUE_ENABLE);
}
/* Poll all queues to verify they have shut down */
for (ms_wait = 0; ms_wait < 10; ms_wait++) {
msleep(1);
rx_enabled = 0;
for (i = 0; i < 4; i++)
rx_enabled |= rd32(E1000_RXDCTL(i));
if (!(rx_enabled & E1000_RXDCTL_QUEUE_ENABLE))
break;
}
if (ms_wait == 10)
hw_dbg("Queue disable timed out after 10ms\n");
/* Clear RLPML, RCTL.SBP, RFCTL.LEF, and set RCTL.LPE so that all
* incoming packets are rejected. Set enable and wait 2ms so that
* any packet that was coming in as RCTL.EN was set is flushed
*/
rfctl = rd32(E1000_RFCTL);
wr32(E1000_RFCTL, rfctl & ~E1000_RFCTL_LEF);
rlpml = rd32(E1000_RLPML);
wr32(E1000_RLPML, 0);
rctl = rd32(E1000_RCTL);
temp_rctl = rctl & ~(E1000_RCTL_EN | E1000_RCTL_SBP);
temp_rctl |= E1000_RCTL_LPE;
wr32(E1000_RCTL, temp_rctl);
wr32(E1000_RCTL, temp_rctl | E1000_RCTL_EN);
wrfl();
msleep(2);
/* Enable RX queues that were previously enabled and restore our
* previous state
*/
for (i = 0; i < 4; i++)
wr32(E1000_RXDCTL(i), rxdctl[i]);
wr32(E1000_RCTL, rctl);
wrfl();
wr32(E1000_RLPML, rlpml);
wr32(E1000_RFCTL, rfctl);
/* Flush receive errors generated by workaround */
rd32(E1000_ROC);
rd32(E1000_RNBC);
rd32(E1000_MPC);
}
static struct e1000_mac_operations e1000_mac_ops_82575 = {
.reset_hw = igb_reset_hw_82575,
.init_hw = igb_init_hw_82575,

View file

@ -28,6 +28,8 @@
#ifndef _E1000_82575_H_
#define _E1000_82575_H_
extern void igb_rx_fifo_flush_82575(struct e1000_hw *hw);
#define E1000_RAR_ENTRIES_82575 16
/* SRRCTL bit definitions */

View file

@ -340,6 +340,7 @@
#define E1000_RXCSUM_PCSD 0x00002000 /* packet checksum disabled */
/* Header split receive */
#define E1000_RFCTL_LEF 0x00040000
/* Collision related configuration parameters */
#define E1000_COLLISION_THRESHOLD 15

View file

@ -630,6 +630,9 @@ static void igb_configure(struct igb_adapter *adapter)
igb_configure_tx(adapter);
igb_setup_rctl(adapter);
igb_configure_rx(adapter);
igb_rx_fifo_flush_82575(&adapter->hw);
/* call IGB_DESC_UNUSED which always leaves
* at least 1 descriptor unused to make sure
* next_to_use != next_to_clean */