This delta has a few important items:

PR 122839 is fixed in both em and in igb

Second, the issue on building modules since the static kernel
build changes is now resolved. I was not able to get the fancier
directory hierarchy working, but this works, both em and igb
build as modules now.

Third, there is now support in em for two new NICs, Hartwell
(or 82574) is a low cost PCIE dual port adapter that has MSIX,
for this release it uses 3 vectors only, RX, TX, and LINK. In
the next release I will add a second TX and RX queue. Also, there
is support here for ICH10, the followon to ICH9. Both of these are
early releases, general availability will follow soon.

Fourth: On Hartwell and ICH10 we now have IEEE 1588 PTP support,
I have implemented this in a provisional way so that early adopters
may try and comment on the functionality. The IOCTL structure may
change. This feature is off by default, you need to edit the Makefile
and add the EM_TIMESYNC define to get the code.

Enjoy all!!
This commit is contained in:
jfv 2008-04-25 21:19:41 +00:00
parent 69e5e2aed2
commit b504776a58
26 changed files with 862 additions and 230 deletions

View File

@ -150,6 +150,25 @@ static s32 e1000_init_phy_params_82571(struct e1000_hw *hw)
goto out; goto out;
} }
break; break;
case e1000_82574:
phy->type = e1000_phy_bm;
phy->ops.get_cfg_done = e1000_get_cfg_done_generic;
phy->ops.get_info = e1000_get_phy_info_m88;
phy->ops.commit = e1000_phy_sw_reset_generic;
phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_m88;
phy->ops.get_cable_length = e1000_get_cable_length_m88;
phy->ops.read_reg = e1000_read_phy_reg_bm2;
phy->ops.write_reg = e1000_write_phy_reg_bm2;
/* This uses above function pointers */
ret_val = e1000_get_phy_id_82571(hw);
/* Verify PHY ID */
if (phy->id != BME1000_E_PHY_ID_R2) {
ret_val = -E1000_ERR_PHY;
DEBUGOUT1("PHY ID unknown: type = 0x%08x\n", phy->id);
goto out;
}
break;
default: default:
ret_val = -E1000_ERR_PHY; ret_val = -E1000_ERR_PHY;
goto out; goto out;
@ -193,6 +212,7 @@ static s32 e1000_init_nvm_params_82571(struct e1000_hw *hw)
switch (hw->mac.type) { switch (hw->mac.type) {
case e1000_82573: case e1000_82573:
case e1000_82574:
if (((eecd >> 15) & 0x3) == 0x3) { if (((eecd >> 15) & 0x3) == 0x3) {
nvm->type = e1000_nvm_flash_hw; nvm->type = e1000_nvm_flash_hw;
nvm->word_size = 2048; nvm->word_size = 2048;
@ -374,6 +394,7 @@ static s32 e1000_get_phy_id_82571(struct e1000_hw *hw)
{ {
struct e1000_phy_info *phy = &hw->phy; struct e1000_phy_info *phy = &hw->phy;
s32 ret_val = E1000_SUCCESS; s32 ret_val = E1000_SUCCESS;
u16 phy_id = 0;
DEBUGFUNC("e1000_get_phy_id_82571"); DEBUGFUNC("e1000_get_phy_id_82571");
@ -391,11 +412,26 @@ static s32 e1000_get_phy_id_82571(struct e1000_hw *hw)
case e1000_82573: case e1000_82573:
ret_val = e1000_get_phy_id(hw); ret_val = e1000_get_phy_id(hw);
break; break;
case e1000_82574:
ret_val = phy->ops.read_reg(hw, PHY_ID1, &phy_id);
if (ret_val)
goto out;
phy->id = (u32)(phy_id << 16);
usec_delay(20);
ret_val = phy->ops.read_reg(hw, PHY_ID2, &phy_id);
if (ret_val)
goto out;
phy->id |= (u32)(phy_id);
phy->revision = (u32)(phy_id & ~PHY_REVISION_MASK);
break;
default: default:
ret_val = -E1000_ERR_PHY; ret_val = -E1000_ERR_PHY;
break; break;
} }
out:
return ret_val; return ret_val;
} }
@ -476,7 +512,7 @@ static s32 e1000_acquire_nvm_82571(struct e1000_hw *hw)
if (ret_val) if (ret_val)
goto out; goto out;
if (hw->mac.type != e1000_82573) if (hw->mac.type != e1000_82573 && hw->mac.type != e1000_82574)
ret_val = e1000_acquire_nvm_generic(hw); ret_val = e1000_acquire_nvm_generic(hw);
if (ret_val) if (ret_val)
@ -521,6 +557,7 @@ static s32 e1000_write_nvm_82571(struct e1000_hw *hw, u16 offset, u16 words,
switch (hw->mac.type) { switch (hw->mac.type) {
case e1000_82573: case e1000_82573:
case e1000_82574:
ret_val = e1000_write_nvm_eewr_82571(hw, offset, words, data); ret_val = e1000_write_nvm_eewr_82571(hw, offset, words, data);
break; break;
case e1000_82571: case e1000_82571:
@ -825,7 +862,7 @@ static s32 e1000_reset_hw_82571(struct e1000_hw *hw)
* Must acquire the MDIO ownership before MAC reset. * Must acquire the MDIO ownership before MAC reset.
* Ownership defaults to firmware after a reset. * Ownership defaults to firmware after a reset.
*/ */
if (hw->mac.type == e1000_82573) { if (hw->mac.type == e1000_82573 || hw->mac.type == e1000_82574) {
extcnf_ctrl = E1000_READ_REG(hw, E1000_EXTCNF_CTRL); extcnf_ctrl = E1000_READ_REG(hw, E1000_EXTCNF_CTRL);
extcnf_ctrl |= E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP; extcnf_ctrl |= E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP;
@ -866,7 +903,7 @@ static s32 e1000_reset_hw_82571(struct e1000_hw *hw)
* Need to wait for Phy configuration completion before accessing * Need to wait for Phy configuration completion before accessing
* NVM and Phy. * NVM and Phy.
*/ */
if (hw->mac.type == e1000_82573) if (hw->mac.type == e1000_82573 || hw->mac.type == e1000_82574)
msec_delay(25); msec_delay(25);
/* Clear any pending interrupt events. */ /* Clear any pending interrupt events. */
@ -934,7 +971,7 @@ static s32 e1000_init_hw_82571(struct e1000_hw *hw)
E1000_WRITE_REG(hw, E1000_TXDCTL(0), reg_data); E1000_WRITE_REG(hw, E1000_TXDCTL(0), reg_data);
/* ...for both queues. */ /* ...for both queues. */
if (mac->type != e1000_82573) { if (mac->type != e1000_82573 && mac->type != e1000_82574) {
reg_data = E1000_READ_REG(hw, E1000_TXDCTL(1)); reg_data = E1000_READ_REG(hw, E1000_TXDCTL(1));
reg_data = (reg_data & ~E1000_TXDCTL_WTHRESH) | reg_data = (reg_data & ~E1000_TXDCTL_WTHRESH) |
E1000_TXDCTL_FULL_TX_DESC_WB | E1000_TXDCTL_FULL_TX_DESC_WB |
@ -1014,14 +1051,14 @@ static void e1000_initialize_hw_bits_82571(struct e1000_hw *hw)
} }
/* Device Control */ /* Device Control */
if (hw->mac.type == e1000_82573) { if (hw->mac.type == e1000_82573 || hw->mac.type == e1000_82574) {
reg = E1000_READ_REG(hw, E1000_CTRL); reg = E1000_READ_REG(hw, E1000_CTRL);
reg &= ~(1 << 29); reg &= ~(1 << 29);
E1000_WRITE_REG(hw, E1000_CTRL, reg); E1000_WRITE_REG(hw, E1000_CTRL, reg);
} }
/* Extended Device Control */ /* Extended Device Control */
if (hw->mac.type == e1000_82573) { if (hw->mac.type == e1000_82573 || hw->mac.type == e1000_82574) {
reg = E1000_READ_REG(hw, E1000_CTRL_EXT); reg = E1000_READ_REG(hw, E1000_CTRL_EXT);
reg &= ~(1 << 23); reg &= ~(1 << 23);
reg |= (1 << 22); reg |= (1 << 22);
@ -1048,7 +1085,7 @@ static void e1000_clear_vfta_82571(struct e1000_hw *hw)
DEBUGFUNC("e1000_clear_vfta_82571"); DEBUGFUNC("e1000_clear_vfta_82571");
if (hw->mac.type == e1000_82573) { if (hw->mac.type == e1000_82573 || hw->mac.type == e1000_82574) {
if (hw->mng_cookie.vlan_id != 0) { if (hw->mng_cookie.vlan_id != 0) {
/* /*
* The VFTA is a 4096b bit-field, each identifying * The VFTA is a 4096b bit-field, each identifying
@ -1121,7 +1158,8 @@ static s32 e1000_setup_link_82571(struct e1000_hw *hw)
* the default flow control setting, so we explicitly * the default flow control setting, so we explicitly
* set it to full. * set it to full.
*/ */
if (hw->mac.type == e1000_82573 && hw->fc.type == e1000_fc_default) if ((hw->mac.type == e1000_82573 || hw->mac.type == e1000_82574) &&
hw->fc.type == e1000_fc_default)
hw->fc.type = e1000_fc_full; hw->fc.type = e1000_fc_full;
return e1000_setup_link_generic(hw); return e1000_setup_link_generic(hw);
@ -1224,11 +1262,10 @@ static s32 e1000_valid_led_default_82571(struct e1000_hw *hw, u16 *data)
goto out; goto out;
} }
if (hw->mac.type == e1000_82573 && if ((hw->mac.type == e1000_82573 || hw->mac.type == e1000_82574) &&
*data == ID_LED_RESERVED_F746) *data == ID_LED_RESERVED_F746)
*data = ID_LED_DEFAULT_82573; *data = ID_LED_DEFAULT_82573;
else if (*data == ID_LED_RESERVED_0000 || else if (*data == ID_LED_RESERVED_0000 || *data == ID_LED_RESERVED_FFFF)
*data == ID_LED_RESERVED_FFFF)
*data = ID_LED_DEFAULT; *data = ID_LED_DEFAULT;
out: out:
return ret_val; return ret_val;

View File

@ -43,4 +43,12 @@
#define E1000_GCR_L1_ACT_WITHOUT_L0S_RX 0x08000000 #define E1000_GCR_L1_ACT_WITHOUT_L0S_RX 0x08000000
/* Intr Throttling - RW */
#define E1000_EITR_82574(_n) (0x000E8 + (0x4 * (_n)))
#define E1000_EIAC_82574 0x000DC /* Ext. Interrupt Auto Clear - RW */
#define E1000_EIAC_MASK_82574 0x01500000
#define E1000_RXCFGL 0x0B634 /* TimeSync Rx EtherType & Msg Type Reg - RW */
#endif #endif

View File

@ -216,6 +216,9 @@ s32 e1000_set_mac_type(struct e1000_hw *hw)
case E1000_DEV_ID_82573L: case E1000_DEV_ID_82573L:
mac->type = e1000_82573; mac->type = e1000_82573;
break; break;
case E1000_DEV_ID_82574L:
mac->type = e1000_82574;
break;
case E1000_DEV_ID_80003ES2LAN_COPPER_DPT: case E1000_DEV_ID_80003ES2LAN_COPPER_DPT:
case E1000_DEV_ID_80003ES2LAN_SERDES_DPT: case E1000_DEV_ID_80003ES2LAN_SERDES_DPT:
case E1000_DEV_ID_80003ES2LAN_COPPER_SPT: case E1000_DEV_ID_80003ES2LAN_COPPER_SPT:
@ -238,14 +241,24 @@ s32 e1000_set_mac_type(struct e1000_hw *hw)
case E1000_DEV_ID_ICH9_IGP_M_AMT: case E1000_DEV_ID_ICH9_IGP_M_AMT:
case E1000_DEV_ID_ICH9_IGP_M_V: case E1000_DEV_ID_ICH9_IGP_M_V:
case E1000_DEV_ID_ICH9_IGP_AMT: case E1000_DEV_ID_ICH9_IGP_AMT:
case E1000_DEV_ID_ICH9_BM:
case E1000_DEV_ID_ICH9_IGP_C: case E1000_DEV_ID_ICH9_IGP_C:
case E1000_DEV_ID_ICH10_R_BM_LM:
case E1000_DEV_ID_ICH10_R_BM_LF:
case E1000_DEV_ID_ICH10_R_BM_V:
mac->type = e1000_ich9lan; mac->type = e1000_ich9lan;
break; break;
case E1000_DEV_ID_ICH10_D_BM_LM:
case E1000_DEV_ID_ICH10_D_BM_LF:
mac->type = e1000_ich10lan;
break;
#ifndef NO_82575_SUPPORT
case E1000_DEV_ID_82575EB_COPPER: case E1000_DEV_ID_82575EB_COPPER:
case E1000_DEV_ID_82575EB_FIBER_SERDES: case E1000_DEV_ID_82575EB_FIBER_SERDES:
case E1000_DEV_ID_82575GB_QUAD_COPPER: case E1000_DEV_ID_82575GB_QUAD_COPPER:
mac->type = e1000_82575; mac->type = e1000_82575;
break; break;
#endif
default: default:
/* Should never have loaded on this device */ /* Should never have loaded on this device */
ret_val = -E1000_ERR_MAC_INIT; ret_val = -E1000_ERR_MAC_INIT;
@ -323,6 +336,7 @@ s32 e1000_setup_init_funcs(struct e1000_hw *hw, bool init_device)
case e1000_82571: case e1000_82571:
case e1000_82572: case e1000_82572:
case e1000_82573: case e1000_82573:
case e1000_82574:
e1000_init_function_pointers_82571(hw); e1000_init_function_pointers_82571(hw);
break; break;
case e1000_80003es2lan: case e1000_80003es2lan:
@ -330,11 +344,14 @@ s32 e1000_setup_init_funcs(struct e1000_hw *hw, bool init_device)
break; break;
case e1000_ich8lan: case e1000_ich8lan:
case e1000_ich9lan: case e1000_ich9lan:
case e1000_ich10lan:
e1000_init_function_pointers_ich8lan(hw); e1000_init_function_pointers_ich8lan(hw);
break; break;
#ifndef NO_82575_SUPPORT
case e1000_82575: case e1000_82575:
e1000_init_function_pointers_82575(hw); e1000_init_function_pointers_82575(hw);
break; break;
#endif
default: default:
DEBUGOUT("Hardware not supported\n"); DEBUGOUT("Hardware not supported\n");
ret_val = -E1000_ERR_CONFIG; ret_val = -E1000_ERR_CONFIG;
@ -403,7 +420,7 @@ s32 e1000_get_bus_info(struct e1000_hw *hw)
void e1000_clear_vfta(struct e1000_hw *hw) void e1000_clear_vfta(struct e1000_hw *hw)
{ {
if (hw->mac.ops.clear_vfta) if (hw->mac.ops.clear_vfta)
hw->mac.ops.clear_vfta (hw); hw->mac.ops.clear_vfta(hw);
} }
/** /**

View File

@ -46,7 +46,9 @@ extern void e1000_init_function_pointers_82571(struct e1000_hw *hw);
extern void e1000_init_function_pointers_82541(struct e1000_hw *hw); extern void e1000_init_function_pointers_82541(struct e1000_hw *hw);
extern void e1000_init_function_pointers_80003es2lan(struct e1000_hw *hw); extern void e1000_init_function_pointers_80003es2lan(struct e1000_hw *hw);
extern void e1000_init_function_pointers_ich8lan(struct e1000_hw *hw); extern void e1000_init_function_pointers_ich8lan(struct e1000_hw *hw);
#ifndef NO_82575_SUPPORT
extern void e1000_init_function_pointers_82575(struct e1000_hw *hw); extern void e1000_init_function_pointers_82575(struct e1000_hw *hw);
#endif
s32 e1000_set_mac_type(struct e1000_hw *hw); s32 e1000_set_mac_type(struct e1000_hw *hw);
s32 e1000_setup_init_funcs(struct e1000_hw *hw, bool init_device); s32 e1000_setup_init_funcs(struct e1000_hw *hw, bool init_device);

View File

@ -154,6 +154,7 @@
#define E1000_CTRL_EXT_DF_PAREN 0x02000000 /* descriptor FIFO parity error detection enable */ #define E1000_CTRL_EXT_DF_PAREN 0x02000000 /* descriptor FIFO parity error detection enable */
#define E1000_CTRL_EXT_GHOST_PAREN 0x40000000 #define E1000_CTRL_EXT_GHOST_PAREN 0x40000000
#define E1000_CTRL_EXT_PBA_CLR 0x80000000 /* PBA Clear */ #define E1000_CTRL_EXT_PBA_CLR 0x80000000 /* PBA Clear */
#define E1000_CTRL_EXT_LSECCK 0x00001000
#define E1000_I2CCMD_REG_ADDR_SHIFT 16 #define E1000_I2CCMD_REG_ADDR_SHIFT 16
#define E1000_I2CCMD_REG_ADDR 0x00FF0000 #define E1000_I2CCMD_REG_ADDR 0x00FF0000
#define E1000_I2CCMD_PHY_ADDR_SHIFT 24 #define E1000_I2CCMD_PHY_ADDR_SHIFT 24
@ -202,6 +203,13 @@
#define E1000_RXDEXT_STATERR_IPE 0x40000000 #define E1000_RXDEXT_STATERR_IPE 0x40000000
#define E1000_RXDEXT_STATERR_RXE 0x80000000 #define E1000_RXDEXT_STATERR_RXE 0x80000000
#define E1000_RXDEXT_LSECH 0x01000000
#define E1000_RXDEXT_LSECE_MASK 0x60000000
#define E1000_RXDEXT_LSECE_NO_ERROR 0x00000000
#define E1000_RXDEXT_LSECE_NO_SA_MATCH 0x20000000
#define E1000_RXDEXT_LSECE_REPLAY_DETECT 0x40000000
#define E1000_RXDEXT_LSECE_BAD_SIG 0x60000000
/* mask to determine if packets should be dropped due to frame errors */ /* mask to determine if packets should be dropped due to frame errors */
#define E1000_RXD_ERR_FRAME_ERR_MASK ( \ #define E1000_RXD_ERR_FRAME_ERR_MASK ( \
E1000_RXD_ERR_CE | \ E1000_RXD_ERR_CE | \
@ -397,6 +405,7 @@
#define E1000_CTRL_PHY_RESET4 E1000_CTRL_EXT_SDP4_DATA #define E1000_CTRL_PHY_RESET4 E1000_CTRL_EXT_SDP4_DATA
#define E1000_CONNSW_ENRGSRC 0x4 #define E1000_CONNSW_ENRGSRC 0x4
#define E1000_PCS_CFG_PCS_EN 8
#define E1000_PCS_LCTL_FLV_LINK_UP 1 #define E1000_PCS_LCTL_FLV_LINK_UP 1
#define E1000_PCS_LCTL_FSV_10 0 #define E1000_PCS_LCTL_FSV_10 0
#define E1000_PCS_LCTL_FSV_100 2 #define E1000_PCS_LCTL_FSV_100 2
@ -556,6 +565,8 @@
#define E1000_TXD_CMD_TSE 0x04000000 /* TCP Seg enable */ #define E1000_TXD_CMD_TSE 0x04000000 /* TCP Seg enable */
#define E1000_TXD_STAT_TC 0x00000004 /* Tx Underrun */ #define E1000_TXD_STAT_TC 0x00000004 /* Tx Underrun */
/* Extended desc bits for Linksec and timesync */ /* Extended desc bits for Linksec and timesync */
#define E1000_TXD_CMD_LINKSEC 0x10000000 /* Apply LinkSec on packet */
#define E1000_TXD_EXTCMD_TSTAMP 0x00000010 /* IEEE1588 Timestamp packet */
/* Transmit Control */ /* Transmit Control */
#define E1000_TCTL_RST 0x00000001 /* software reset */ #define E1000_TCTL_RST 0x00000001 /* software reset */
@ -715,6 +726,11 @@
#define E1000_ICR_DSW 0x00000020 /* FW changed the status of DISSW bit in the FWSM */ #define E1000_ICR_DSW 0x00000020 /* FW changed the status of DISSW bit in the FWSM */
#define E1000_ICR_PHYINT 0x00001000 /* LAN connected device generates an interrupt */ #define E1000_ICR_PHYINT 0x00001000 /* LAN connected device generates an interrupt */
#define E1000_ICR_EPRST 0x00100000 /* ME hardware reset occurs */ #define E1000_ICR_EPRST 0x00100000 /* ME hardware reset occurs */
#define E1000_ICR_RXQ0 0x00100000 /* Rx Queue 0 Interrupt */
#define E1000_ICR_RXQ1 0x00200000 /* Rx Queue 1 Interrupt */
#define E1000_ICR_TXQ0 0x00400000 /* Tx Queue 0 Interrupt */
#define E1000_ICR_TXQ1 0x00800000 /* Tx Queue 1 Interrupt */
#define E1000_ICR_OTHER 0x01000000 /* Other Interrupts */
/* Extended Interrupt Cause Read */ /* Extended Interrupt Cause Read */
#define E1000_EICR_RX_QUEUE0 0x00000001 /* Rx Queue 0 Interrupt */ #define E1000_EICR_RX_QUEUE0 0x00000001 /* Rx Queue 0 Interrupt */
@ -787,6 +803,11 @@
#define E1000_IMS_DSW E1000_ICR_DSW #define E1000_IMS_DSW E1000_ICR_DSW
#define E1000_IMS_PHYINT E1000_ICR_PHYINT #define E1000_IMS_PHYINT E1000_ICR_PHYINT
#define E1000_IMS_EPRST E1000_ICR_EPRST #define E1000_IMS_EPRST E1000_ICR_EPRST
#define E1000_IMS_RXQ0 E1000_ICR_RXQ0 /* Rx Queue 0 Interrupt */
#define E1000_IMS_RXQ1 E1000_ICR_RXQ1 /* Rx Queue 1 Interrupt */
#define E1000_IMS_TXQ0 E1000_ICR_TXQ0 /* Tx Queue 0 Interrupt */
#define E1000_IMS_TXQ1 E1000_ICR_TXQ1 /* Tx Queue 1 Interrupt */
#define E1000_IMS_OTHER E1000_ICR_OTHER /* Other Interrupts */
/* Extended Interrupt Mask Set */ /* Extended Interrupt Mask Set */
#define E1000_EIMS_RX_QUEUE0 E1000_EICR_RX_QUEUE0 /* Rx Queue 0 Interrupt */ #define E1000_EIMS_RX_QUEUE0 E1000_EICR_RX_QUEUE0 /* Rx Queue 0 Interrupt */

View File

@ -95,6 +95,7 @@ struct e1000_hw;
#define E1000_DEV_ID_82573E 0x108B #define E1000_DEV_ID_82573E 0x108B
#define E1000_DEV_ID_82573E_IAMT 0x108C #define E1000_DEV_ID_82573E_IAMT 0x108C
#define E1000_DEV_ID_82573L 0x109A #define E1000_DEV_ID_82573L 0x109A
#define E1000_DEV_ID_82574L 0x10D3
#define E1000_DEV_ID_80003ES2LAN_COPPER_DPT 0x1096 #define E1000_DEV_ID_80003ES2LAN_COPPER_DPT 0x1096
#define E1000_DEV_ID_80003ES2LAN_SERDES_DPT 0x1098 #define E1000_DEV_ID_80003ES2LAN_SERDES_DPT 0x1098
#define E1000_DEV_ID_80003ES2LAN_COPPER_SPT 0x10BA #define E1000_DEV_ID_80003ES2LAN_COPPER_SPT 0x10BA
@ -110,10 +111,16 @@ struct e1000_hw;
#define E1000_DEV_ID_ICH9_IGP_M_AMT 0x10F5 #define E1000_DEV_ID_ICH9_IGP_M_AMT 0x10F5
#define E1000_DEV_ID_ICH9_IGP_M_V 0x10CB #define E1000_DEV_ID_ICH9_IGP_M_V 0x10CB
#define E1000_DEV_ID_ICH9_IGP_AMT 0x10BD #define E1000_DEV_ID_ICH9_IGP_AMT 0x10BD
#define E1000_DEV_ID_ICH9_BM 0x10E5
#define E1000_DEV_ID_ICH9_IGP_C 0x294C #define E1000_DEV_ID_ICH9_IGP_C 0x294C
#define E1000_DEV_ID_ICH9_IFE 0x10C0 #define E1000_DEV_ID_ICH9_IFE 0x10C0
#define E1000_DEV_ID_ICH9_IFE_GT 0x10C3 #define E1000_DEV_ID_ICH9_IFE_GT 0x10C3
#define E1000_DEV_ID_ICH9_IFE_G 0x10C2 #define E1000_DEV_ID_ICH9_IFE_G 0x10C2
#define E1000_DEV_ID_ICH10_R_BM_LM 0x10CC
#define E1000_DEV_ID_ICH10_R_BM_LF 0x10CD
#define E1000_DEV_ID_ICH10_R_BM_V 0x10CE
#define E1000_DEV_ID_ICH10_D_BM_LM 0x10DE
#define E1000_DEV_ID_ICH10_D_BM_LF 0x10DF
#define E1000_DEV_ID_82575EB_COPPER 0x10A7 #define E1000_DEV_ID_82575EB_COPPER 0x10A7
#define E1000_DEV_ID_82575EB_FIBER_SERDES 0x10A9 #define E1000_DEV_ID_82575EB_FIBER_SERDES 0x10A9
#define E1000_DEV_ID_82575GB_QUAD_COPPER 0x10D6 #define E1000_DEV_ID_82575GB_QUAD_COPPER 0x10D6
@ -146,9 +153,11 @@ typedef enum {
e1000_82571, e1000_82571,
e1000_82572, e1000_82572,
e1000_82573, e1000_82573,
e1000_82574,
e1000_80003es2lan, e1000_80003es2lan,
e1000_ich8lan, e1000_ich8lan,
e1000_ich9lan, e1000_ich9lan,
e1000_ich10lan,
e1000_82575, e1000_82575,
e1000_num_macs /* List is 1-based, so subtract 1 for TRUE count. */ e1000_num_macs /* List is 1-based, so subtract 1 for TRUE count. */
} e1000_mac_type; } e1000_mac_type;

View File

@ -79,6 +79,8 @@ static s32 e1000_flash_cycle_init_ich8lan(struct e1000_hw *hw);
static s32 e1000_get_phy_info_ife_ich8lan(struct e1000_hw *hw); static s32 e1000_get_phy_info_ife_ich8lan(struct e1000_hw *hw);
static void e1000_initialize_hw_bits_ich8lan(struct e1000_hw *hw); static void e1000_initialize_hw_bits_ich8lan(struct e1000_hw *hw);
static s32 e1000_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw); static s32 e1000_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw);
static s32 e1000_read_flash_byte_ich8lan(struct e1000_hw *hw,
u32 offset, u8* data);
static s32 e1000_read_flash_data_ich8lan(struct e1000_hw *hw, u32 offset, static s32 e1000_read_flash_data_ich8lan(struct e1000_hw *hw, u32 offset,
u8 size, u16* data); u8 size, u16* data);
static s32 e1000_read_flash_word_ich8lan(struct e1000_hw *hw, static s32 e1000_read_flash_word_ich8lan(struct e1000_hw *hw,
@ -1020,10 +1022,46 @@ out:
static s32 e1000_valid_nvm_bank_detect_ich8lan(struct e1000_hw *hw, u32 *bank) static s32 e1000_valid_nvm_bank_detect_ich8lan(struct e1000_hw *hw, u32 *bank)
{ {
s32 ret_val = E1000_SUCCESS; s32 ret_val = E1000_SUCCESS;
if (E1000_READ_REG(hw, E1000_EECD) & E1000_EECD_SEC1VAL) struct e1000_nvm_info *nvm = &hw->nvm;
*bank = 1; /* flash bank size is in words */
else u32 bank1_offset = nvm->flash_bank_size * sizeof(u16);
*bank = 0; u32 act_offset = E1000_ICH_NVM_SIG_WORD * 2 + 1;
u8 bank_high_byte = 0;
if (hw->mac.type != e1000_ich10lan) {
if (E1000_READ_REG(hw, E1000_EECD) & E1000_EECD_SEC1VAL)
*bank = 1;
else
*bank = 0;
} else if (hw->dev_spec != NULL) {
/*
* Make sure the signature for bank 0 is valid,
* if not check for bank1
*/
e1000_read_flash_byte_ich8lan(hw, act_offset, &bank_high_byte);
if ((bank_high_byte & 0xC0) == 0x80) {
*bank = 0;
} else {
/*
* find if segment 1 is valid by verifying
* bit 15:14 = 10b in word 0x13
*/
e1000_read_flash_byte_ich8lan(hw,
act_offset + bank1_offset,
&bank_high_byte);
/* bank1 has a valid signature equivalent to SEC1V */
if ((bank_high_byte & 0xC0) == 0x80) {
*bank = 1;
} else {
DEBUGOUT("ERROR: EEPROM not present\n");
ret_val = -E1000_ERR_NVM;
}
}
} else {
DEBUGOUT("DEV SPEC is NULL\n");
ret_val = -E1000_ERR_NVM;
}
return ret_val; return ret_val;
} }
@ -1240,6 +1278,30 @@ out:
return ret_val; return ret_val;
} }
/**
* e1000_read_flash_byte_ich8lan - Read byte from flash
* @hw: pointer to the HW structure
* @offset: The offset of the byte to read.
* @data: Pointer to a byte to store the value read.
*
* Reads a single byte from the NVM using the flash access registers.
**/
static s32 e1000_read_flash_byte_ich8lan(struct e1000_hw *hw, u32 offset,
u8* data)
{
s32 ret_val = E1000_SUCCESS;
u16 word = 0;
ret_val = e1000_read_flash_data_ich8lan(hw, offset, 1, &word);
if (ret_val)
goto out;
*data = (u8)word;
out:
return ret_val;
}
/** /**
* e1000_read_flash_data_ich8lan - Read byte or word from NVM * e1000_read_flash_data_ich8lan - Read byte or word from NVM
* @hw: pointer to the HW structure * @hw: pointer to the HW structure
@ -2483,13 +2545,14 @@ out:
* 'LPLU Enabled' and 'Gig Disable' to force link speed negotiation * 'LPLU Enabled' and 'Gig Disable' to force link speed negotiation
* to a lower speed. * to a lower speed.
* *
* Should only be called for ICH9. * Should only be called for ICH9 and ICH10 devices.
**/ **/
void e1000_disable_gig_wol_ich8lan(struct e1000_hw *hw) void e1000_disable_gig_wol_ich8lan(struct e1000_hw *hw)
{ {
u32 phy_ctrl; u32 phy_ctrl;
if (hw->mac.type == e1000_ich9lan) { if ((hw->mac.type == e1000_ich10lan) ||
(hw->mac.type == e1000_ich9lan)) {
phy_ctrl = E1000_READ_REG(hw, E1000_PHY_CTRL); phy_ctrl = E1000_READ_REG(hw, E1000_PHY_CTRL);
phy_ctrl |= E1000_PHY_CTRL_D0A_LPLU | phy_ctrl |= E1000_PHY_CTRL_D0A_LPLU |
E1000_PHY_CTRL_GBE_DISABLE; E1000_PHY_CTRL_GBE_DISABLE;
@ -2578,13 +2641,22 @@ static s32 e1000_led_off_ich8lan(struct e1000_hw *hw)
static s32 e1000_get_cfg_done_ich8lan(struct e1000_hw *hw) static s32 e1000_get_cfg_done_ich8lan(struct e1000_hw *hw)
{ {
s32 ret_val = E1000_SUCCESS; s32 ret_val = E1000_SUCCESS;
u32 bank = 0;
e1000_get_cfg_done_generic(hw); e1000_get_cfg_done_generic(hw);
/* If EEPROM is not marked present, init the IGP 3 PHY manually */ /* If EEPROM is not marked present, init the IGP 3 PHY manually */
if (((E1000_READ_REG(hw, E1000_EECD) & E1000_EECD_PRES) == 0) && if (hw->mac.type != e1000_ich10lan) {
(hw->phy.type == e1000_phy_igp_3)) { if (((E1000_READ_REG(hw, E1000_EECD) & E1000_EECD_PRES) == 0) &&
e1000_phy_init_script_igp3(hw); (hw->phy.type == e1000_phy_igp_3)) {
e1000_phy_init_script_igp3(hw);
}
} else {
if (e1000_valid_nvm_bank_detect_ich8lan(hw, &bank)) {
/* Maybe we should do a basic Boazman config */
DEBUGOUT("EEPROM not present\n");
ret_val = -E1000_ERR_CONFIG;
}
} }
return ret_val; return ret_val;

View File

@ -112,4 +112,16 @@
E1000_IMS_PHYINT | \ E1000_IMS_PHYINT | \
E1000_IMS_EPRST) E1000_IMS_EPRST)
/* Additional interrupt register bit definitions */
#define E1000_ICR_LSECPNC 0x00004000 /* PN threshold - client */
#define E1000_IMS_LSECPNC E1000_ICR_LSECPNC /* PN threshold - client */
#define E1000_ICS_LSECPNC E1000_ICR_LSECPNC /* PN threshold - client */
/* Security Processing bit Indication */
#define E1000_RXDEXT_LINKSEC_STATUS_LSECH 0x01000000
#define E1000_RXDEXT_LINKSEC_ERROR_BIT_MASK 0x60000000
#define E1000_RXDEXT_LINKSEC_ERROR_NO_SA_MATCH 0x20000000
#define E1000_RXDEXT_LINKSEC_ERROR_REPLAY_ERROR 0x40000000
#define E1000_RXDEXT_LINKSEC_ERROR_BAD_SIG 0x60000000
#endif #endif

View File

@ -104,8 +104,12 @@ struct e1000_osdep
struct device *dev; struct device *dev;
}; };
#ifdef NO_82542_SUPPORT
#define E1000_REGISTER(hw, reg) reg
#else
#define E1000_REGISTER(hw, reg) (((hw)->mac.type >= e1000_82543) \ #define E1000_REGISTER(hw, reg) (((hw)->mac.type >= e1000_82543) \
? reg : e1000_translate_register_82542(reg)) ? reg : e1000_translate_register_82542(reg))
#endif
#define E1000_WRITE_FLUSH(a) E1000_READ_REG(a, E1000_STATUS) #define E1000_WRITE_FLUSH(a) E1000_READ_REG(a, E1000_STATUS)

View File

@ -614,7 +614,9 @@ s32 e1000_copper_link_setup_m88(struct e1000_hw *hw)
if (ret_val) if (ret_val)
goto out; goto out;
if ((phy->type == e1000_phy_m88) && (phy->revision < E1000_REVISION_4)) { if ((phy->type == e1000_phy_m88) &&
(phy->revision < E1000_REVISION_4) &&
(phy->id != BME1000_E_PHY_ID_R2)) {
/* /*
* Force TX_CLK in the Extended PHY Specific Control Register * Force TX_CLK in the Extended PHY Specific Control Register
* to 25MHz clock. * to 25MHz clock.
@ -2304,6 +2306,105 @@ out:
return ret_val; return ret_val;
} }
/**
* e1000_read_phy_reg_bm2 - Read BM PHY register
* @hw: pointer to the HW structure
* @offset: register offset to be read
* @data: pointer to the read data
*
* Acquires semaphore, if necessary, then reads the PHY register at offset
* and storing the retrieved information in data. Release any acquired
* semaphores before exiting.
**/
s32 e1000_read_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 *data)
{
s32 ret_val;
u16 page = (u16)(offset >> IGP_PAGE_SHIFT);
DEBUGFUNC("e1000_write_phy_reg_bm2");
/* Page 800 works differently than the rest so it has its own func */
if (page == BM_WUC_PAGE) {
ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, data,
TRUE);
goto out;
}
ret_val = hw->phy.ops.acquire(hw);
if (ret_val)
goto out;
hw->phy.addr = 1;
if (offset > MAX_PHY_MULTI_PAGE_REG) {
/* Page is shifted left, PHY expects (page x 32) */
ret_val = e1000_write_phy_reg_mdic(hw, BM_PHY_PAGE_SELECT,
page);
if (ret_val) {
hw->phy.ops.release(hw);
goto out;
}
}
ret_val = e1000_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
data);
hw->phy.ops.release(hw);
out:
return ret_val;
}
/**
* e1000_write_phy_reg_bm2 - Write BM PHY register
* @hw: pointer to the HW structure
* @offset: register offset to write to
* @data: data to write at register offset
*
* Acquires semaphore, if necessary, then writes the data to PHY register
* at the offset. Release any acquired semaphores before exiting.
**/
s32 e1000_write_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 data)
{
s32 ret_val;
u16 page = (u16)(offset >> IGP_PAGE_SHIFT);
DEBUGFUNC("e1000_write_phy_reg_bm2");
/* Page 800 works differently than the rest so it has its own func */
if (page == BM_WUC_PAGE) {
ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, &data,
FALSE);
goto out;
}
ret_val = hw->phy.ops.acquire(hw);
if (ret_val)
goto out;
hw->phy.addr = 1;
if (offset > MAX_PHY_MULTI_PAGE_REG) {
/* Page is shifted left, PHY expects (page x 32) */
ret_val = e1000_write_phy_reg_mdic(hw, BM_PHY_PAGE_SELECT,
page);
if (ret_val) {
hw->phy.ops.release(hw);
goto out;
}
}
ret_val = e1000_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
data);
hw->phy.ops.release(hw);
out:
return ret_val;
}
/** /**
* e1000_access_phy_wakeup_reg_bm - Read BM PHY wakeup register * e1000_access_phy_wakeup_reg_bm - Read BM PHY wakeup register
* @hw: pointer to the HW structure * @hw: pointer to the HW structure

View File

@ -92,6 +92,8 @@ s32 e1000_write_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 data);
s32 e1000_read_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 *data); s32 e1000_read_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 *data);
s32 e1000_access_phy_wakeup_reg_bm(struct e1000_hw *hw, u32 offset, u16 *data, s32 e1000_access_phy_wakeup_reg_bm(struct e1000_hw *hw, u32 offset, u16 *data,
bool read); bool read);
s32 e1000_read_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 *data);
s32 e1000_write_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 data);
void e1000_power_up_phy_copper(struct e1000_hw *hw); void e1000_power_up_phy_copper(struct e1000_hw *hw);
void e1000_power_down_phy_copper(struct e1000_hw *hw); void e1000_power_down_phy_copper(struct e1000_hw *hw);
s32 e1000_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data); s32 e1000_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data);

View File

@ -50,6 +50,10 @@
#include <sys/sockio.h> #include <sys/sockio.h>
#include <sys/sysctl.h> #include <sys/sysctl.h>
#include <sys/taskqueue.h> #include <sys/taskqueue.h>
#ifdef EM_TIMESYNC
#include <sys/ioccom.h>
#include <sys/time.h>
#endif
#include <machine/bus.h> #include <machine/bus.h>
#include <machine/resource.h> #include <machine/resource.h>
@ -76,6 +80,7 @@
#include <dev/pci/pcireg.h> #include <dev/pci/pcireg.h>
#include "e1000_api.h" #include "e1000_api.h"
#include "e1000_82571.h" /* For Hartwell */
#include "if_em.h" #include "if_em.h"
/********************************************************************* /*********************************************************************
@ -86,7 +91,7 @@ int em_display_debug_stats = 0;
/********************************************************************* /*********************************************************************
* Driver version: * Driver version:
*********************************************************************/ *********************************************************************/
char em_driver_version[] = "6.8.8"; char em_driver_version[] = "6.9.0";
/********************************************************************* /*********************************************************************
@ -187,6 +192,9 @@ static em_vendor_info_t em_vendor_info_array[] =
{ 0x8086, E1000_DEV_ID_ICH9_IFE, PCI_ANY_ID, PCI_ANY_ID, 0}, { 0x8086, E1000_DEV_ID_ICH9_IFE, PCI_ANY_ID, PCI_ANY_ID, 0},
{ 0x8086, E1000_DEV_ID_ICH9_IFE_GT, PCI_ANY_ID, PCI_ANY_ID, 0}, { 0x8086, E1000_DEV_ID_ICH9_IFE_GT, PCI_ANY_ID, PCI_ANY_ID, 0},
{ 0x8086, E1000_DEV_ID_ICH9_IFE_G, PCI_ANY_ID, PCI_ANY_ID, 0}, { 0x8086, E1000_DEV_ID_ICH9_IFE_G, PCI_ANY_ID, PCI_ANY_ID, 0},
{ 0x8086, E1000_DEV_ID_82574L, PCI_ANY_ID, PCI_ANY_ID, 0},
{ 0x8086, E1000_DEV_ID_ICH10_D_BM_LM, PCI_ANY_ID, PCI_ANY_ID, 0},
{ 0x8086, E1000_DEV_ID_ICH10_D_BM_LF, PCI_ANY_ID, PCI_ANY_ID, 0},
/* required last entry */ /* required last entry */
{ 0, 0, 0, 0, 0} { 0, 0, 0, 0, 0}
}; };
@ -284,6 +292,11 @@ static void em_get_hw_control(struct adapter *);
static void em_release_hw_control(struct adapter *); static void em_release_hw_control(struct adapter *);
static void em_enable_wakeup(device_t); static void em_enable_wakeup(device_t);
#ifdef EM_TIMESYNC
/* Precision Time sync support */
static int em_tsync_init(struct adapter *);
static void em_tsync_disable(struct adapter *);
#endif
#ifdef EM_LEGACY_IRQ #ifdef EM_LEGACY_IRQ
static void em_intr(void *); static void em_intr(void *);
@ -293,9 +306,10 @@ static void em_irq_fast(void *);
#else #else
static int em_irq_fast(void *); static int em_irq_fast(void *);
#endif #endif
static int em_tx_fast(void *); /* MSIX handlers */
static int em_rx_fast(void *); static void em_msix_tx(void *);
static int em_link_fast(void *); static void em_msix_rx(void *);
static void em_msix_link(void *);
static void em_add_rx_process_limit(struct adapter *, const char *, static void em_add_rx_process_limit(struct adapter *, const char *,
const char *, int *, int); const char *, int *, int);
static void em_handle_rxtx(void *context, int pending); static void em_handle_rxtx(void *context, int pending);
@ -352,6 +366,10 @@ static int em_rx_abs_int_delay_dflt = EM_TICKS_TO_USECS(EM_RADV);
static int em_rxd = EM_DEFAULT_RXD; static int em_rxd = EM_DEFAULT_RXD;
static int em_txd = EM_DEFAULT_TXD; static int em_txd = EM_DEFAULT_TXD;
static int em_smart_pwr_down = FALSE; static int em_smart_pwr_down = FALSE;
/* Controls whether promiscuous also shows bad packets */
static int em_debug_sbp = FALSE;
/* Local switch for MSI/MSIX */
static int em_enable_msi = TRUE;
TUNABLE_INT("hw.em.tx_int_delay", &em_tx_int_delay_dflt); TUNABLE_INT("hw.em.tx_int_delay", &em_tx_int_delay_dflt);
TUNABLE_INT("hw.em.rx_int_delay", &em_rx_int_delay_dflt); TUNABLE_INT("hw.em.rx_int_delay", &em_rx_int_delay_dflt);
@ -360,6 +378,8 @@ TUNABLE_INT("hw.em.rx_abs_int_delay", &em_rx_abs_int_delay_dflt);
TUNABLE_INT("hw.em.rxd", &em_rxd); TUNABLE_INT("hw.em.rxd", &em_rxd);
TUNABLE_INT("hw.em.txd", &em_txd); TUNABLE_INT("hw.em.txd", &em_txd);
TUNABLE_INT("hw.em.smart_pwr_down", &em_smart_pwr_down); TUNABLE_INT("hw.em.smart_pwr_down", &em_smart_pwr_down);
TUNABLE_INT("hw.em.sbp", &em_debug_sbp);
TUNABLE_INT("hw.em.enable_msi", &em_enable_msi);
#ifndef EM_LEGACY_IRQ #ifndef EM_LEGACY_IRQ
/* How many packets rxeof tries to clean at a time */ /* How many packets rxeof tries to clean at a time */
@ -445,6 +465,7 @@ em_attach(device_t dev)
adapter->dev = adapter->osdep.dev = dev; adapter->dev = adapter->osdep.dev = dev;
EM_CORE_LOCK_INIT(adapter, device_get_nameunit(dev)); EM_CORE_LOCK_INIT(adapter, device_get_nameunit(dev));
EM_TX_LOCK_INIT(adapter, device_get_nameunit(dev)); EM_TX_LOCK_INIT(adapter, device_get_nameunit(dev));
EM_RX_LOCK_INIT(adapter, device_get_nameunit(dev));
/* SYSCTL stuff */ /* SYSCTL stuff */
SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
@ -477,6 +498,7 @@ em_attach(device_t dev)
** identified ** identified
*/ */
if ((adapter->hw.mac.type == e1000_ich8lan) || if ((adapter->hw.mac.type == e1000_ich8lan) ||
(adapter->hw.mac.type == e1000_ich10lan) ||
(adapter->hw.mac.type == e1000_ich9lan)) { (adapter->hw.mac.type == e1000_ich9lan)) {
int rid = EM_BAR_TYPE_FLASH; int rid = EM_BAR_TYPE_FLASH;
adapter->flash = bus_alloc_resource_any(dev, adapter->flash = bus_alloc_resource_any(dev,
@ -770,6 +792,7 @@ err_tx_desc:
err_pci: err_pci:
em_free_pci_resources(adapter); em_free_pci_resources(adapter);
EM_TX_LOCK_DESTROY(adapter); EM_TX_LOCK_DESTROY(adapter);
EM_RX_LOCK_DESTROY(adapter);
EM_CORE_LOCK_DESTROY(adapter); EM_CORE_LOCK_DESTROY(adapter);
return (error); return (error);
@ -818,6 +841,7 @@ em_detach(device_t dev)
if (((adapter->hw.mac.type == e1000_82573) || if (((adapter->hw.mac.type == e1000_82573) ||
(adapter->hw.mac.type == e1000_ich8lan) || (adapter->hw.mac.type == e1000_ich8lan) ||
(adapter->hw.mac.type == e1000_ich10lan) ||
(adapter->hw.mac.type == e1000_ich9lan)) && (adapter->hw.mac.type == e1000_ich9lan)) &&
e1000_check_mng_mode(&adapter->hw)) e1000_check_mng_mode(&adapter->hw))
em_release_hw_control(adapter); em_release_hw_control(adapter);
@ -856,6 +880,7 @@ em_detach(device_t dev)
} }
EM_TX_LOCK_DESTROY(adapter); EM_TX_LOCK_DESTROY(adapter);
EM_RX_LOCK_DESTROY(adapter);
EM_CORE_LOCK_DESTROY(adapter); EM_CORE_LOCK_DESTROY(adapter);
return (0); return (0);
@ -891,6 +916,7 @@ em_suspend(device_t dev)
if (((adapter->hw.mac.type == e1000_82573) || if (((adapter->hw.mac.type == e1000_82573) ||
(adapter->hw.mac.type == e1000_ich8lan) || (adapter->hw.mac.type == e1000_ich8lan) ||
(adapter->hw.mac.type == e1000_ich10lan) ||
(adapter->hw.mac.type == e1000_ich9lan)) && (adapter->hw.mac.type == e1000_ich9lan)) &&
e1000_check_mng_mode(&adapter->hw)) e1000_check_mng_mode(&adapter->hw))
em_release_hw_control(adapter); em_release_hw_control(adapter);
@ -915,12 +941,8 @@ em_resume(device_t dev)
EM_CORE_LOCK(adapter); EM_CORE_LOCK(adapter);
em_init_locked(adapter); em_init_locked(adapter);
em_init_manageability(adapter); em_init_manageability(adapter);
if ((ifp->if_flags & IFF_UP) &&
(ifp->if_drv_flags & IFF_DRV_RUNNING))
em_start_locked(ifp);
EM_CORE_UNLOCK(adapter); EM_CORE_UNLOCK(adapter);
em_start(ifp);
return bus_generic_resume(dev); return bus_generic_resume(dev);
} }
@ -1050,6 +1072,8 @@ em_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
case e1000_82571: case e1000_82571:
case e1000_82572: case e1000_82572:
case e1000_ich9lan: case e1000_ich9lan:
case e1000_ich10lan:
case e1000_82574:
case e1000_80003es2lan: /* Limit Jumbo Frame size */ case e1000_80003es2lan: /* Limit Jumbo Frame size */
max_frame_size = 9234; max_frame_size = 9234;
break; break;
@ -1082,7 +1106,7 @@ em_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
if (ifp->if_flags & IFF_UP) { if (ifp->if_flags & IFF_UP) {
if ((ifp->if_drv_flags & IFF_DRV_RUNNING)) { if ((ifp->if_drv_flags & IFF_DRV_RUNNING)) {
if ((ifp->if_flags ^ adapter->if_flags) & if ((ifp->if_flags ^ adapter->if_flags) &
IFF_PROMISC) { (IFF_PROMISC | IFF_ALLMULTI)) {
em_disable_promisc(adapter); em_disable_promisc(adapter);
em_set_promisc(adapter); em_set_promisc(adapter);
} }
@ -1180,6 +1204,69 @@ em_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
break; break;
} }
#ifdef EM_TIMESYNC
/*
** IOCTL support for Precision Time (IEEE 1588) Support
*/
case EM_TIMESYNC_READTS:
{
u32 rx_ctl, tx_ctl;
struct em_tsync_read *tdata;
tdata = (struct em_tsync_read *) ifr->ifr_data;
IOCTL_DEBUGOUT("Reading Timestamp\n");
if (tdata->read_current_time) {
getnanotime(&tdata->system_time);
tdata->network_time = E1000_READ_REG(&adapter->hw, E1000_SYSTIML);
tdata->network_time |=
(u64)E1000_READ_REG(&adapter->hw, E1000_SYSTIMH ) << 32;
}
rx_ctl = E1000_READ_REG(&adapter->hw, E1000_TSYNCRXCTL);
tx_ctl = E1000_READ_REG(&adapter->hw, E1000_TSYNCTXCTL);
IOCTL_DEBUGOUT1("RX_CTL value = %u\n", rx_ctl);
IOCTL_DEBUGOUT1("TX_CTL value = %u\n", tx_ctl);
if (rx_ctl & 0x1) {
IOCTL_DEBUGOUT("RX timestamp is valid\n");
u32 tmp;
unsigned char *tmp_cp;
tdata->rx_valid = 1;
tdata->rx_stamp = E1000_READ_REG(&adapter->hw, E1000_RXSTMPL);
tdata->rx_stamp |= (u64)E1000_READ_REG(&adapter->hw,
E1000_RXSTMPH) << 32;
tmp = E1000_READ_REG(&adapter->hw, E1000_RXSATRL);
tmp_cp = (unsigned char *) &tmp;
tdata->srcid[0] = tmp_cp[0];
tdata->srcid[1] = tmp_cp[1];
tdata->srcid[2] = tmp_cp[2];
tdata->srcid[3] = tmp_cp[3];
tmp = E1000_READ_REG(&adapter->hw, E1000_RXSATRH);
tmp_cp = (unsigned char *) &tmp;
tdata->srcid[4] = tmp_cp[0];
tdata->srcid[5] = tmp_cp[1];
tdata->seqid = tmp >> 16;
tdata->seqid = htons(tdata->seqid);
} else
tdata->rx_valid = 0;
if (tx_ctl & 0x1) {
IOCTL_DEBUGOUT("TX timestamp is valid\n");
tdata->tx_valid = 1;
tdata->tx_stamp = E1000_READ_REG(&adapter->hw, E1000_TXSTMPL);
tdata->tx_stamp |= (u64) E1000_READ_REG(&adapter->hw,
E1000_TXSTMPH) << 32;
} else
tdata->tx_valid = 0;
return (0);
}
#endif /* EM_TIMESYNC */
default: default:
error = ether_ioctl(ifp, command, data); error = ether_ioctl(ifp, command, data);
@ -1294,7 +1381,11 @@ em_init_locked(struct adapter *adapter)
case e1000_82573: /* 82573: Total Packet Buffer is 32K */ case e1000_82573: /* 82573: Total Packet Buffer is 32K */
pba = E1000_PBA_12K; /* 12K for Rx, 20K for Tx */ pba = E1000_PBA_12K; /* 12K for Rx, 20K for Tx */
break; break;
case e1000_82574:
pba = E1000_PBA_20K; /* 20K for Rx, 20K for Tx */
break;
case e1000_ich9lan: case e1000_ich9lan:
case e1000_ich10lan:
#define E1000_PBA_10K 0x000A #define E1000_PBA_10K 0x000A
pba = E1000_PBA_10K; pba = E1000_PBA_10K;
break; break;
@ -1383,6 +1474,21 @@ em_init_locked(struct adapter *adapter)
callout_reset(&adapter->timer, hz, em_local_timer, adapter); callout_reset(&adapter->timer, hz, em_local_timer, adapter);
e1000_clear_hw_cntrs_base_generic(&adapter->hw); e1000_clear_hw_cntrs_base_generic(&adapter->hw);
/* MSI/X configuration for 82574 */
if (adapter->hw.mac.type == e1000_82574) {
int tmp;
tmp = E1000_READ_REG(&adapter->hw, E1000_CTRL_EXT);
tmp |= E1000_CTRL_EXT_PBA_CLR;
E1000_WRITE_REG(&adapter->hw, E1000_CTRL_EXT, tmp);
/*
** Set the IVAR - interrupt vector routing.
** Each nibble represents a vector, high bit
** is enable, other 3 bits are the MSIX table
** entry, we map RXQ0 to 0, TXQ0 to 1, and
** Link (other) to 2, hence the magic number.
*/
E1000_WRITE_REG(&adapter->hw, E1000_IVAR, 0x800A0908);
}
#ifdef DEVICE_POLLING #ifdef DEVICE_POLLING
/* /*
@ -1395,6 +1501,12 @@ em_init_locked(struct adapter *adapter)
#endif /* DEVICE_POLLING */ #endif /* DEVICE_POLLING */
em_enable_intr(adapter); em_enable_intr(adapter);
#ifdef EM_TIMESYNC
/* Initializae IEEE 1588 Precision Time hardware */
if ((adapter->hw.mac.type == e1000_82574) ||
(adapter->hw.mac.type == e1000_ich10lan))
em_tsync_init(adapter);
#endif
/* Don't reset the phy next time init gets called */ /* Don't reset the phy next time init gets called */
adapter->hw.phy.reset_disable = TRUE; adapter->hw.phy.reset_disable = TRUE;
@ -1439,9 +1551,10 @@ em_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
em_local_timer, adapter); em_local_timer, adapter);
} }
} }
em_rxeof(adapter, count);
EM_CORE_UNLOCK(adapter); EM_CORE_UNLOCK(adapter);
em_rxeof(adapter, count);
EM_TX_LOCK(adapter); EM_TX_LOCK(adapter);
em_txeof(adapter); em_txeof(adapter);
@ -1462,17 +1575,14 @@ static void
em_intr(void *arg) em_intr(void *arg)
{ {
struct adapter *adapter = arg; struct adapter *adapter = arg;
struct ifnet *ifp; struct ifnet *ifp = adapter->ifp;
u32 reg_icr; u32 reg_icr;
EM_CORE_LOCK(adapter);
ifp = adapter->ifp;
if (ifp->if_capenable & IFCAP_POLLING) { if (ifp->if_capenable & IFCAP_POLLING)
EM_CORE_UNLOCK(adapter);
return; return;
}
EM_CORE_LOCK(adapter);
for (;;) { for (;;) {
reg_icr = E1000_READ_REG(&adapter->hw, E1000_ICR); reg_icr = E1000_READ_REG(&adapter->hw, E1000_ICR);
@ -1491,12 +1601,14 @@ em_intr(void *arg)
if (reg_icr == 0xffffffff) if (reg_icr == 0xffffffff)
break; break;
EM_CORE_UNLOCK(adapter);
if (ifp->if_drv_flags & IFF_DRV_RUNNING) { if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
em_rxeof(adapter, -1); em_rxeof(adapter, -1);
EM_TX_LOCK(adapter); EM_TX_LOCK(adapter);
em_txeof(adapter); em_txeof(adapter);
EM_TX_UNLOCK(adapter); EM_TX_UNLOCK(adapter);
} }
EM_CORE_LOCK(adapter);
/* Link status change */ /* Link status change */
if (reg_icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) { if (reg_icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) {
@ -1525,9 +1637,7 @@ static void
em_handle_link(void *context, int pending) em_handle_link(void *context, int pending)
{ {
struct adapter *adapter = context; struct adapter *adapter = context;
struct ifnet *ifp; struct ifnet *ifp = adapter->ifp;
ifp = adapter->ifp;
if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) if (!(ifp->if_drv_flags & IFF_DRV_RUNNING))
return; return;
@ -1564,19 +1674,16 @@ em_handle_rxtx(void *context, int pending)
em_enable_intr(adapter); em_enable_intr(adapter);
} }
/* RX deferred handler: used with MSIX */
static void static void
em_handle_rx(void *context, int pending) em_handle_rx(void *context, int pending)
{ {
struct adapter *adapter = context; struct adapter *adapter = context;
struct ifnet *ifp = adapter->ifp; struct ifnet *ifp = adapter->ifp;
++adapter->rx_irq;
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) && if ((ifp->if_drv_flags & IFF_DRV_RUNNING) &&
(em_rxeof(adapter, adapter->rx_process_limit) != 0)) (em_rxeof(adapter, adapter->rx_process_limit) != 0))
taskqueue_enqueue(adapter->tq, &adapter->rx_task); taskqueue_enqueue(adapter->tq, &adapter->rx_task);
em_enable_intr(adapter);
} }
static void static void
@ -1585,17 +1692,13 @@ em_handle_tx(void *context, int pending)
struct adapter *adapter = context; struct adapter *adapter = context;
struct ifnet *ifp = adapter->ifp; struct ifnet *ifp = adapter->ifp;
++adapter->tx_irq;
if (ifp->if_drv_flags & IFF_DRV_RUNNING) { if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
EM_TX_LOCK(adapter); EM_TX_LOCK(adapter);
em_txeof(adapter); em_txeof(adapter);
if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
em_start_locked(ifp); em_start_locked(ifp);
EM_TX_UNLOCK(adapter); EM_TX_UNLOCK(adapter);
} }
em_enable_intr(adapter);
} }
/********************************************************************* /*********************************************************************
@ -1657,52 +1760,50 @@ em_irq_fast(void *arg)
/********************************************************************* /*********************************************************************
* *
* MSIX TX Fast Interrupt Service routine * MSIX Interrupt Service Routines
* *
**********************************************************************/ **********************************************************************/
#define EM_MSIX_TX 0x00040000
#define EM_MSIX_RX 0x00010000
#define EM_MSIX_LINK 0x00100000
static int static void
em_tx_fast(void *arg) em_msix_tx(void *arg)
{ {
struct adapter *adapter = arg; struct adapter *adapter = arg;
u32 reg_icr; struct ifnet *ifp = adapter->ifp;
reg_icr = E1000_READ_REG(&adapter->hw, E1000_ICR); ++adapter->tx_irq;
/* if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
* Mask interrupts until the taskqueue is finished running. This is EM_TX_LOCK(adapter);
* cheap, just assume that it is needed. This also works around the em_txeof(adapter);
* MSI message reordering errata on certain systems. EM_TX_UNLOCK(adapter);
*/ taskqueue_enqueue(adapter->tq, &adapter->tx_task);
em_disable_intr(adapter); }
taskqueue_enqueue(adapter->tq, &adapter->tx_task); /* Reenable this interrupt */
E1000_WRITE_REG(&adapter->hw, E1000_IMS, EM_MSIX_TX);
return FILTER_HANDLED; return;
} }
/********************************************************************* /*********************************************************************
* *
* MSIX RX Fast Interrupt Service routine * MSIX RX Interrupt Service routine
* *
**********************************************************************/ **********************************************************************/
static int static void
em_rx_fast(void *arg) em_msix_rx(void *arg)
{ {
struct adapter *adapter = arg; struct adapter *adapter = arg;
u32 reg_icr; struct ifnet *ifp = adapter->ifp;
reg_icr = E1000_READ_REG(&adapter->hw, E1000_ICR); ++adapter->rx_irq;
/* if ((ifp->if_drv_flags & IFF_DRV_RUNNING) &&
* Mask interrupts until the taskqueue is finished running. This is (em_rxeof(adapter, adapter->rx_process_limit) != 0))
* cheap, just assume that it is needed. This also works around the taskqueue_enqueue(adapter->tq, &adapter->rx_task);
* MSI message reordering errata on certain systems. /* Reenable this interrupt */
*/ E1000_WRITE_REG(&adapter->hw, E1000_IMS, EM_MSIX_RX);
em_disable_intr(adapter); return;
taskqueue_enqueue(adapter->tq, &adapter->rx_task);
if (reg_icr & E1000_ICR_RXO)
adapter->rx_overruns++;
return FILTER_HANDLED;
} }
/********************************************************************* /*********************************************************************
@ -1711,19 +1812,22 @@ em_rx_fast(void *arg)
* *
**********************************************************************/ **********************************************************************/
static int static void
em_link_fast(void *arg) em_msix_link(void *arg)
{ {
struct adapter *adapter = arg; struct adapter *adapter = arg;
u32 reg_eicr; u32 reg_icr;
reg_eicr = E1000_READ_REG(&adapter->hw, E1000_ICR); ++adapter->link_irq;
reg_icr = E1000_READ_REG(&adapter->hw, E1000_ICR);
if (reg_eicr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) if (reg_icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) {
adapter->hw.mac.get_link_status = 1;
taskqueue_enqueue(taskqueue_fast, &adapter->link_task); taskqueue_enqueue(taskqueue_fast, &adapter->link_task);
}
E1000_WRITE_REG(&adapter->hw, E1000_IMS, E1000_IMS_LSC); E1000_WRITE_REG(&adapter->hw, E1000_IMS,
return FILTER_HANDLED; EM_MSIX_LINK | E1000_IMS_LSC);
return;
} }
#endif /* EM_FAST_IRQ */ #endif /* EM_FAST_IRQ */
@ -1988,12 +2092,14 @@ em_xmit(struct adapter *adapter, struct mbuf **m_headp)
tso_desc = TRUE; tso_desc = TRUE;
} else } else
#endif #endif
#ifndef EM_TIMESYNC
/* /*
** Timesync needs to check the packet header ** Timesync needs to check the packet header
** so call checksum code to do so, but don't ** so call checksum code to do so, but don't
** penalize the code if not defined. ** penalize the code if not defined.
*/ */
if (m_head->m_pkthdr.csum_flags & CSUM_OFFLOAD) if (m_head->m_pkthdr.csum_flags & CSUM_OFFLOAD)
#endif
em_transmit_checksum_setup(adapter, m_head, em_transmit_checksum_setup(adapter, m_head,
&txd_upper, &txd_lower); &txd_upper, &txd_lower);
@ -2150,6 +2256,11 @@ em_xmit(struct adapter *adapter, struct mbuf **m_headp)
m_head->m_pkthdr.len); m_head->m_pkthdr.len);
} }
#ifdef EM_TIMESYNC
if (ctxd->upper.data & E1000_TXD_EXTCMD_TSTAMP) {
HW_DEBUGOUT( "@@@ Timestamp bit is set in transmit descriptor\n" );
}
#endif
return (0); return (0);
} }
@ -2280,6 +2391,9 @@ em_set_promisc(struct adapter *adapter)
if (ifp->if_flags & IFF_PROMISC) { if (ifp->if_flags & IFF_PROMISC) {
reg_rctl |= (E1000_RCTL_UPE | E1000_RCTL_MPE); reg_rctl |= (E1000_RCTL_UPE | E1000_RCTL_MPE);
/* Turn this on if you want to see bad packets */
if (em_debug_sbp)
reg_rctl |= E1000_RCTL_SBP;
E1000_WRITE_REG(&adapter->hw, E1000_RCTL, reg_rctl); E1000_WRITE_REG(&adapter->hw, E1000_RCTL, reg_rctl);
} else if (ifp->if_flags & IFF_ALLMULTI) { } else if (ifp->if_flags & IFF_ALLMULTI) {
reg_rctl |= E1000_RCTL_MPE; reg_rctl |= E1000_RCTL_MPE;
@ -2297,6 +2411,7 @@ em_disable_promisc(struct adapter *adapter)
reg_rctl &= (~E1000_RCTL_UPE); reg_rctl &= (~E1000_RCTL_UPE);
reg_rctl &= (~E1000_RCTL_MPE); reg_rctl &= (~E1000_RCTL_MPE);
reg_rctl &= (~E1000_RCTL_SBP);
E1000_WRITE_REG(&adapter->hw, E1000_RCTL, reg_rctl); E1000_WRITE_REG(&adapter->hw, E1000_RCTL, reg_rctl);
} }
@ -2493,6 +2608,12 @@ em_stop(void *arg)
/* Tell the stack that the interface is no longer active */ /* Tell the stack that the interface is no longer active */
ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
#ifdef EM_TIMESYNC
/* Disable IEEE 1588 Time hardware */
if ((adapter->hw.mac.type == e1000_82574) ||
(adapter->hw.mac.type == e1000_ich10lan))
em_tsync_disable(adapter);
#endif
e1000_reset_hw(&adapter->hw); e1000_reset_hw(&adapter->hw);
if (adapter->hw.mac.type >= e1000_82544) if (adapter->hw.mac.type >= e1000_82544)
@ -2603,7 +2724,8 @@ em_allocate_pci_resources(struct adapter *adapter)
/* /*
* Setup MSI/X or MSI if PCI Express * Setup MSI/X or MSI if PCI Express
*/ */
adapter->msi = em_setup_msix(adapter); if (em_enable_msi)
adapter->msi = em_setup_msix(adapter);
adapter->hw.back = &adapter->osdep; adapter->hw.back = &adapter->osdep;
@ -2725,7 +2847,7 @@ em_allocate_msix(struct adapter *adapter)
/* First slot to RX */ /* First slot to RX */
if ((error = bus_setup_intr(dev, adapter->res[0], if ((error = bus_setup_intr(dev, adapter->res[0],
INTR_TYPE_NET, em_rx_fast, NULL, adapter, INTR_TYPE_NET | INTR_MPSAFE, NULL, em_msix_rx, adapter,
&adapter->tag[0])) != 0) { &adapter->tag[0])) != 0) {
device_printf(dev, "Failed to register RX handler"); device_printf(dev, "Failed to register RX handler");
return (error); return (error);
@ -2733,7 +2855,7 @@ em_allocate_msix(struct adapter *adapter)
/* Next TX */ /* Next TX */
if ((error = bus_setup_intr(dev, adapter->res[1], if ((error = bus_setup_intr(dev, adapter->res[1],
INTR_TYPE_NET, em_tx_fast, NULL, adapter, INTR_TYPE_NET | INTR_MPSAFE, NULL, em_msix_tx, adapter,
&adapter->tag[1])) != 0) { &adapter->tag[1])) != 0) {
device_printf(dev, "Failed to register TX handler"); device_printf(dev, "Failed to register TX handler");
return (error); return (error);
@ -2741,7 +2863,7 @@ em_allocate_msix(struct adapter *adapter)
/* And Link */ /* And Link */
if ((error = bus_setup_intr(dev, adapter->res[2], if ((error = bus_setup_intr(dev, adapter->res[2],
INTR_TYPE_NET, em_link_fast, NULL, adapter, INTR_TYPE_NET | INTR_MPSAFE, NULL, em_msix_link, adapter,
&adapter->tag[2])) != 0) { &adapter->tag[2])) != 0) {
device_printf(dev, "Failed to register TX handler"); device_printf(dev, "Failed to register TX handler");
return (error); return (error);
@ -2809,6 +2931,30 @@ em_setup_msix(struct adapter *adapter)
if (adapter->hw.mac.type < e1000_82571) if (adapter->hw.mac.type < e1000_82571)
return (0); return (0);
/* Setup MSI/X for Hartwell */
if (adapter->hw.mac.type == e1000_82574) {
/* Map the MSIX BAR */
int rid = PCIR_BAR(EM_MSIX_BAR);
adapter->msix = bus_alloc_resource_any(dev,
SYS_RES_MEMORY, &rid, RF_ACTIVE);
if (!adapter->msix) {
/* May not be enabled */
device_printf(adapter->dev,
"Unable to map MSIX table \n");
goto msi;
}
val = pci_msix_count(dev);
/*
** 82574 can be configured for 5 but
** we limit use to 3.
*/
if (val > 3) val = 3;
if ((val) && pci_alloc_msix(dev, &val) == 0) {
device_printf(adapter->dev,"Using MSIX interrupts\n");
return (val);
}
}
msi:
val = pci_msi_count(dev); val = pci_msi_count(dev);
if (val == 1 && pci_alloc_msi(dev, &val) == 0) { if (val == 1 && pci_alloc_msi(dev, &val) == 0) {
adapter->msi = 1; adapter->msi = 1;
@ -2838,6 +2984,7 @@ em_hardware_init(struct adapter *adapter)
/* Get control from any management/hw control */ /* Get control from any management/hw control */
if (((adapter->hw.mac.type == e1000_82573) || if (((adapter->hw.mac.type == e1000_82573) ||
(adapter->hw.mac.type == e1000_ich8lan) || (adapter->hw.mac.type == e1000_ich8lan) ||
(adapter->hw.mac.type == e1000_ich10lan) ||
(adapter->hw.mac.type == e1000_ich9lan)) && (adapter->hw.mac.type == e1000_ich9lan)) &&
e1000_check_mng_mode(&adapter->hw)) e1000_check_mng_mode(&adapter->hw))
em_get_hw_control(adapter); em_get_hw_control(adapter);
@ -3463,6 +3610,11 @@ em_transmit_checksum_setup(struct adapter *adapter, struct mbuf *mp,
ipproto = ip6->ip6_nxt; ipproto = ip6->ip6_nxt;
break; break;
#ifdef EM_TIMESYNC
case ETHERTYPE_IEEE1588:
*txd_upper |= E1000_TXD_EXTCMD_TSTAMP;
break;
#endif
default: default:
*txd_upper = 0; *txd_upper = 0;
*txd_lower = 0; *txd_lower = 0;
@ -3488,6 +3640,15 @@ em_transmit_checksum_setup(struct adapter *adapter, struct mbuf *mp,
break; break;
case IPPROTO_UDP: case IPPROTO_UDP:
{ {
#ifdef EM_TIMESYNC
void *hdr = (caddr_t) ip + ip_hlen;
struct udphdr *uh = (struct udphdr *)hdr;
if (uh->uh_dport == htons(TSYNC_PORT)) {
*txd_upper |= E1000_TXD_EXTCMD_TSTAMP;
IOCTL_DEBUGOUT("@@@ Sending Event Packet\n");
}
#endif
if (mp->m_pkthdr.csum_flags & CSUM_UDP) { if (mp->m_pkthdr.csum_flags & CSUM_UDP) {
/* /*
* Start offset for header checksum calculation. * Start offset for header checksum calculation.
@ -3506,6 +3667,15 @@ em_transmit_checksum_setup(struct adapter *adapter, struct mbuf *mp,
break; break;
} }
#ifdef EM_TIMESYNC
/*
** We might be here just for TIMESYNC
** which means we don't need the context
** descriptor.
*/
if (!mp->m_pkthdr.csum_flags & CSUM_OFFLOAD)
return;
#endif
*txd_lower = E1000_TXD_CMD_DEXT | /* Extended descr type */ *txd_lower = E1000_TXD_CMD_DEXT | /* Extended descr type */
E1000_TXD_DTYP_D; /* Data descr */ E1000_TXD_DTYP_D; /* Data descr */
TXD->tcp_seg_setup.data = htole32(0); TXD->tcp_seg_setup.data = htole32(0);
@ -3968,6 +4138,9 @@ em_setup_receive_structures(struct adapter *adapter)
* Enable receive unit. * Enable receive unit.
* *
**********************************************************************/ **********************************************************************/
#define MAX_INTS_PER_SEC 8000
#define DEFAULT_ITR 1000000000/(MAX_INTS_PER_SEC * 256)
static void static void
em_initialize_receive_unit(struct adapter *adapter) em_initialize_receive_unit(struct adapter *adapter)
{ {
@ -3984,18 +4157,30 @@ em_initialize_receive_unit(struct adapter *adapter)
rctl = E1000_READ_REG(&adapter->hw, E1000_RCTL); rctl = E1000_READ_REG(&adapter->hw, E1000_RCTL);
E1000_WRITE_REG(&adapter->hw, E1000_RCTL, rctl & ~E1000_RCTL_EN); E1000_WRITE_REG(&adapter->hw, E1000_RCTL, rctl & ~E1000_RCTL_EN);
if(adapter->hw.mac.type >= e1000_82540) { if (adapter->hw.mac.type >= e1000_82540) {
E1000_WRITE_REG(&adapter->hw, E1000_RADV, E1000_WRITE_REG(&adapter->hw, E1000_RADV,
adapter->rx_abs_int_delay.value); adapter->rx_abs_int_delay.value);
/* /*
* Set the interrupt throttling rate. Value is calculated * Set the interrupt throttling rate. Value is calculated
* as DEFAULT_ITR = 1/(MAX_INTS_PER_SEC * 256ns) * as DEFAULT_ITR = 1/(MAX_INTS_PER_SEC * 256ns)
*/ */
#define MAX_INTS_PER_SEC 8000
#define DEFAULT_ITR 1000000000/(MAX_INTS_PER_SEC * 256)
E1000_WRITE_REG(&adapter->hw, E1000_ITR, DEFAULT_ITR); E1000_WRITE_REG(&adapter->hw, E1000_ITR, DEFAULT_ITR);
} }
/*
** When using MSIX interrupts we need to throttle
** using the EITR register (82574 only)
*/
if (adapter->msix)
for (int i = 0; i < 4; i++)
E1000_WRITE_REG(&adapter->hw,
E1000_EITR_82574(i), DEFAULT_ITR);
/* Disable accelerated ackknowledge */
if (adapter->hw.mac.type == e1000_82574)
E1000_WRITE_REG(&adapter->hw,
E1000_RFCTL, E1000_RFCTL_ACK_DIS);
/* Setup the Base and Length of the Rx Descriptor Ring */ /* Setup the Base and Length of the Rx Descriptor Ring */
bus_addr = adapter->rxdma.dma_paddr; bus_addr = adapter->rxdma.dma_paddr;
E1000_WRITE_REG(&adapter->hw, E1000_RDLEN(0), E1000_WRITE_REG(&adapter->hw, E1000_RDLEN(0),
@ -4138,21 +4323,23 @@ em_free_receive_structures(struct adapter *adapter)
static int static int
em_rxeof(struct adapter *adapter, int count) em_rxeof(struct adapter *adapter, int count)
{ {
struct ifnet *ifp; struct ifnet *ifp = adapter->ifp;;
struct mbuf *mp; struct mbuf *mp;
u8 status, accept_frame = 0, eop = 0; u8 status, accept_frame = 0, eop = 0;
u16 len, desc_len, prev_len_adj; u16 len, desc_len, prev_len_adj;
int i; int i;
struct e1000_rx_desc *current_desc; struct e1000_rx_desc *current_desc;
ifp = adapter->ifp; EM_RX_LOCK(adapter);
i = adapter->next_rx_desc_to_check; i = adapter->next_rx_desc_to_check;
current_desc = &adapter->rx_desc_base[i]; current_desc = &adapter->rx_desc_base[i];
bus_dmamap_sync(adapter->rxdma.dma_tag, adapter->rxdma.dma_map, bus_dmamap_sync(adapter->rxdma.dma_tag, adapter->rxdma.dma_map,
BUS_DMASYNC_POSTREAD); BUS_DMASYNC_POSTREAD);
if (!((current_desc->status) & E1000_RXD_STAT_DD)) if (!((current_desc->status) & E1000_RXD_STAT_DD)) {
EM_RX_UNLOCK(adapter);
return (0); return (0);
}
while ((current_desc->status & E1000_RXD_STAT_DD) && while ((current_desc->status & E1000_RXD_STAT_DD) &&
(count != 0) && (count != 0) &&
@ -4295,14 +4482,10 @@ discard:
i = 0; i = 0;
if (m != NULL) { if (m != NULL) {
adapter->next_rx_desc_to_check = i; adapter->next_rx_desc_to_check = i;
#ifdef EM_LEGACY_IRQ /* Unlock for call into stack */
EM_CORE_UNLOCK(adapter); EM_RX_UNLOCK(adapter);
(*ifp->if_input)(ifp, m); (*ifp->if_input)(ifp, m);
EM_CORE_LOCK(adapter); EM_RX_LOCK(adapter);
#else
/* Already running unlocked */
(*ifp->if_input)(ifp, m);
#endif
i = adapter->next_rx_desc_to_check; i = adapter->next_rx_desc_to_check;
} }
current_desc = &adapter->rx_desc_base[i]; current_desc = &adapter->rx_desc_base[i];
@ -4313,6 +4496,7 @@ discard:
if (--i < 0) if (--i < 0)
i = adapter->num_rx_desc - 1; i = adapter->num_rx_desc - 1;
E1000_WRITE_REG(&adapter->hw, E1000_RDT(0), i); E1000_WRITE_REG(&adapter->hw, E1000_RDT(0), i);
EM_RX_UNLOCK(adapter);
if (!((current_desc->status) & E1000_RXD_STAT_DD)) if (!((current_desc->status) & E1000_RXD_STAT_DD))
return (0); return (0);
@ -4422,28 +4606,26 @@ em_enable_hw_vlans(struct adapter *adapter)
E1000_WRITE_REG(&adapter->hw, E1000_CTRL, ctrl); E1000_WRITE_REG(&adapter->hw, E1000_CTRL, ctrl);
} }
#define QUEUE_MASK 0x01500000
static void static void
em_enable_intr(struct adapter *adapter) em_enable_intr(struct adapter *adapter)
{ {
struct e1000_hw *hw = &adapter->hw;
u32 ims_mask = IMS_ENABLE_MASK; u32 ims_mask = IMS_ENABLE_MASK;
if (adapter->msix) { if (adapter->msix) {
E1000_WRITE_REG(&adapter->hw, E1000_EIMS, QUEUE_MASK); E1000_WRITE_REG(hw, EM_EIAC, EM_MSIX_MASK);
E1000_WRITE_REG(&adapter->hw, E1000_EIAC, QUEUE_MASK); ims_mask |= EM_MSIX_MASK;
ims_mask |= QUEUE_MASK;
} }
E1000_WRITE_REG(&adapter->hw, E1000_IMS, ims_mask); E1000_WRITE_REG(hw, E1000_IMS, ims_mask);
} }
static void static void
em_disable_intr(struct adapter *adapter) em_disable_intr(struct adapter *adapter)
{ {
if (adapter->msix) { struct e1000_hw *hw = &adapter->hw;
E1000_WRITE_REG(&adapter->hw, E1000_EIMC, ~0);
E1000_WRITE_REG(&adapter->hw, E1000_EIAC, 0); if (adapter->msix)
} E1000_WRITE_REG(hw, EM_EIAC, 0);
E1000_WRITE_REG(&adapter->hw, E1000_IMC, 0xffffffff); E1000_WRITE_REG(&adapter->hw, E1000_IMC, 0xffffffff);
} }
@ -4522,6 +4704,7 @@ em_get_hw_control(struct adapter *adapter)
case e1000_80003es2lan: case e1000_80003es2lan:
case e1000_ich8lan: case e1000_ich8lan:
case e1000_ich9lan: case e1000_ich9lan:
case e1000_ich10lan:
ctrl_ext = E1000_READ_REG(&adapter->hw, E1000_CTRL_EXT); ctrl_ext = E1000_READ_REG(&adapter->hw, E1000_CTRL_EXT);
E1000_WRITE_REG(&adapter->hw, E1000_CTRL_EXT, E1000_WRITE_REG(&adapter->hw, E1000_CTRL_EXT,
ctrl_ext | E1000_CTRL_EXT_DRV_LOAD); ctrl_ext | E1000_CTRL_EXT_DRV_LOAD);
@ -4555,6 +4738,7 @@ em_release_hw_control(struct adapter *adapter)
case e1000_80003es2lan: case e1000_80003es2lan:
case e1000_ich8lan: case e1000_ich8lan:
case e1000_ich9lan: case e1000_ich9lan:
case e1000_ich10lan:
ctrl_ext = E1000_READ_REG(&adapter->hw, E1000_CTRL_EXT); ctrl_ext = E1000_READ_REG(&adapter->hw, E1000_CTRL_EXT);
E1000_WRITE_REG(&adapter->hw, E1000_CTRL_EXT, E1000_WRITE_REG(&adapter->hw, E1000_CTRL_EXT,
ctrl_ext & ~E1000_CTRL_EXT_DRV_LOAD); ctrl_ext & ~E1000_CTRL_EXT_DRV_LOAD);
@ -4841,8 +5025,9 @@ em_print_hw_stats(struct adapter *adapter)
device_printf(dev, "RX overruns = %ld\n", adapter->rx_overruns); device_printf(dev, "RX overruns = %ld\n", adapter->rx_overruns);
device_printf(dev, "watchdog timeouts = %ld\n", device_printf(dev, "watchdog timeouts = %ld\n",
adapter->watchdog_events); adapter->watchdog_events);
device_printf(dev, "TX Interrupts = %ld ", adapter->tx_irq); device_printf(dev, "RX MSIX IRQ = %ld TX MSIX IRQ = %ld"
device_printf(dev, "RX Interrupts = %ld\n", adapter->rx_irq); " LINK MSIX IRQ = %ld\n", adapter->rx_irq,
adapter->tx_irq , adapter->link_irq);
device_printf(dev, "XON Rcvd = %lld\n", device_printf(dev, "XON Rcvd = %lld\n",
(long long)adapter->stats.xonrxc); (long long)adapter->stats.xonrxc);
device_printf(dev, "XON Xmtd = %lld\n", device_printf(dev, "XON Xmtd = %lld\n",
@ -5009,3 +5194,100 @@ em_add_rx_process_limit(struct adapter *adapter, const char *name,
} }
#endif #endif
#ifdef EM_TIMESYNC
/*
* Initialize the Time Sync Feature
*/
static int
em_tsync_init(struct adapter *adapter)
{
device_t dev = adapter->dev;
u32 tx_ctl, rx_ctl;
E1000_WRITE_REG(&adapter->hw, E1000_TIMINCA, (1<<24) |
20833/PICOSECS_PER_TICK);
adapter->last_stamp = E1000_READ_REG(&adapter->hw, E1000_SYSTIML);
adapter->last_stamp |= (u64)E1000_READ_REG(&adapter->hw,
E1000_SYSTIMH) << 32ULL;
/* Enable the TX side */
tx_ctl = E1000_READ_REG(&adapter->hw, E1000_TSYNCTXCTL);
tx_ctl |= 0x10;
E1000_WRITE_REG(&adapter->hw, E1000_TSYNCTXCTL, tx_ctl);
E1000_WRITE_FLUSH(&adapter->hw);
tx_ctl = E1000_READ_REG(&adapter->hw, E1000_TSYNCTXCTL);
if ((tx_ctl & 0x10) == 0) {
device_printf(dev, "Failed to enable TX timestamping\n");
return (ENXIO);
}
/* Enable RX */
rx_ctl = E1000_READ_REG(&adapter->hw, E1000_TSYNCRXCTL);
rx_ctl |= 0x10; /* Enable the feature */
rx_ctl |= 0x0a; /* This value turns on Ver 1 and 2 */
E1000_WRITE_REG(&adapter->hw, E1000_TSYNCRXCTL, rx_ctl);
/*
* Ethertype Stamping (Ethertype = 0x88F7)
*/
E1000_WRITE_REG(&adapter->hw, E1000_RXMTRL, htonl(0x440088f7));
/*
* Source Port Queue Filter Setup:
* this is for UDP port filtering
*/
E1000_WRITE_REG(&adapter->hw, E1000_RXUDP, htons(TSYNC_PORT));
/* Protocol = UDP, enable Timestamp, and filter on source/protocol */
E1000_WRITE_FLUSH(&adapter->hw);
rx_ctl = E1000_READ_REG(&adapter->hw, E1000_TSYNCRXCTL);
if ((rx_ctl & 0x10) == 0) {
device_printf(dev, "Failed to enable RX timestamping\n");
return (ENXIO);
}
device_printf(dev, "IEEE 1588 Precision Time Protocol enabled\n");
return (0);
}
/*
* Disable the Time Sync Feature
*/
static void
em_tsync_disable(struct adapter *adapter)
{
u32 tx_ctl, rx_ctl;
tx_ctl = E1000_READ_REG(&adapter->hw, E1000_TSYNCTXCTL);
tx_ctl &= ~0x10;
E1000_WRITE_REG(&adapter->hw, E1000_TSYNCTXCTL, tx_ctl);
E1000_WRITE_FLUSH(&adapter->hw);
/* Invalidate TX Timestamp */
E1000_READ_REG(&adapter->hw, E1000_TXSTMPH);
tx_ctl = E1000_READ_REG(&adapter->hw, E1000_TSYNCTXCTL);
if (tx_ctl & 0x10)
HW_DEBUGOUT("Failed to disable TX timestamping\n");
rx_ctl = E1000_READ_REG(&adapter->hw, E1000_TSYNCRXCTL);
rx_ctl &= ~0x10;
E1000_WRITE_REG(&adapter->hw, E1000_TSYNCRXCTL, rx_ctl);
E1000_WRITE_FLUSH(&adapter->hw);
/* Invalidate RX Timestamp */
E1000_READ_REG(&adapter->hw, E1000_RXSATRH);
rx_ctl = E1000_READ_REG(&adapter->hw, E1000_TSYNCRXCTL);
if (rx_ctl & 0x10)
HW_DEBUGOUT("Failed to disable RX timestamping\n");
return;
}
#endif /* EM_TIMESYNC */

View File

@ -1,36 +1,37 @@
/************************************************************************** /******************************************************************************
Copyright (c) 2001-2008, Intel Corporation Copyright (c) 2001-2008, Intel Corporation
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the Intel Corporation nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
Redistribution and use in source and binary forms, with or without ******************************************************************************/
modification, are permitted provided that the following conditions are met: /*$FreeBSD$*/
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the Intel Corporation nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
***************************************************************************/
/* $FreeBSD$ */
#ifndef _EM_H_DEFINED_ #ifndef _EM_H_DEFINED_
#define _EM_H_DEFINED_ #define _EM_H_DEFINED_
@ -232,10 +233,19 @@ POSSIBILITY OF SUCH DAMAGE.
#define EM_MAX_SCATTER 64 #define EM_MAX_SCATTER 64
#define EM_TSO_SIZE (65535 + sizeof(struct ether_vlan_header)) #define EM_TSO_SIZE (65535 + sizeof(struct ether_vlan_header))
#define EM_TSO_SEG_SIZE 4096 /* Max dma segment size */ #define EM_TSO_SEG_SIZE 4096 /* Max dma segment size */
#define EM_MSIX_MASK 0x01F00000 /* For 82574 use */
#define ETH_ZLEN 60 #define ETH_ZLEN 60
#define ETH_ADDR_LEN 6 #define ETH_ADDR_LEN 6
#define CSUM_OFFLOAD 7 /* Offload bits in mbuf flag */ #define CSUM_OFFLOAD 7 /* Offload bits in mbuf flag */
/*
* 82574 has a nonstandard address for EIAC
* and since its only used in MSIX, and in
* the em driver only 82574 uses MSIX we can
* solve it just using this define.
*/
#define EM_EIAC 0x000DC
/* Used in for 82547 10Mb Half workaround */ /* Used in for 82547 10Mb Half workaround */
#define EM_PBA_BYTES_SHIFT 0xA #define EM_PBA_BYTES_SHIFT 0xA
#define EM_TX_HEAD_ADDR_SHIFT 7 #define EM_TX_HEAD_ADDR_SHIFT 7
@ -243,6 +253,29 @@ POSSIBILITY OF SUCH DAMAGE.
#define EM_FIFO_HDR 0x10 #define EM_FIFO_HDR 0x10
#define EM_82547_PKT_THRESH 0x3e0 #define EM_82547_PKT_THRESH 0x3e0
#ifdef EM_TIMESYNC
/* Precision Time Sync (IEEE 1588) defines */
#define ETHERTYPE_IEEE1588 0x88F7
#define PICOSECS_PER_TICK 20833
#define TSYNC_PORT 319 /* UDP port for the protocol */
/* TIMESYNC IOCTL defines */
#define EM_TIMESYNC_READTS _IOWR('i', 127, struct em_tsync_read)
/* Used in the READTS IOCTL */
struct em_tsync_read {
int read_current_time;
struct timespec system_time;
u64 network_time;
u64 rx_stamp;
u64 tx_stamp;
u16 seqid;
unsigned char srcid[6];
int rx_valid;
int tx_valid;
};
#endif /* EM_TIMESYNC */
struct adapter; struct adapter;
@ -296,6 +329,7 @@ struct adapter {
int min_frame_size; int min_frame_size;
struct mtx core_mtx; struct mtx core_mtx;
struct mtx tx_mtx; struct mtx tx_mtx;
struct mtx rx_mtx;
int em_insert_vlan_header; int em_insert_vlan_header;
/* Task for FAST handling */ /* Task for FAST handling */
@ -376,6 +410,7 @@ struct adapter {
unsigned long rx_overruns; unsigned long rx_overruns;
unsigned long rx_irq; unsigned long rx_irq;
unsigned long tx_irq; unsigned long tx_irq;
unsigned long link_irq;
/* 82547 workaround */ /* 82547 workaround */
uint32_t tx_fifo_size; uint32_t tx_fifo_size;
@ -389,6 +424,11 @@ struct adapter {
boolean_t pcix_82544; boolean_t pcix_82544;
boolean_t in_detach; boolean_t in_detach;
#ifdef EM_TIMESYNC
u64 last_stamp;
u64 last_sec;
u32 last_ns;
#endif
struct e1000_hw_stats stats; struct e1000_hw_stats stats;
}; };
@ -432,12 +472,17 @@ typedef struct _DESCRIPTOR_PAIR
mtx_init(&(_sc)->core_mtx, _name, "EM Core Lock", MTX_DEF) mtx_init(&(_sc)->core_mtx, _name, "EM Core Lock", MTX_DEF)
#define EM_TX_LOCK_INIT(_sc, _name) \ #define EM_TX_LOCK_INIT(_sc, _name) \
mtx_init(&(_sc)->tx_mtx, _name, "EM TX Lock", MTX_DEF) mtx_init(&(_sc)->tx_mtx, _name, "EM TX Lock", MTX_DEF)
#define EM_RX_LOCK_INIT(_sc, _name) \
mtx_init(&(_sc)->rx_mtx, _name, "EM RX Lock", MTX_DEF)
#define EM_CORE_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->core_mtx) #define EM_CORE_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->core_mtx)
#define EM_TX_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->tx_mtx) #define EM_TX_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->tx_mtx)
#define EM_RX_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->rx_mtx)
#define EM_CORE_LOCK(_sc) mtx_lock(&(_sc)->core_mtx) #define EM_CORE_LOCK(_sc) mtx_lock(&(_sc)->core_mtx)
#define EM_TX_LOCK(_sc) mtx_lock(&(_sc)->tx_mtx) #define EM_TX_LOCK(_sc) mtx_lock(&(_sc)->tx_mtx)
#define EM_RX_LOCK(_sc) mtx_lock(&(_sc)->rx_mtx)
#define EM_CORE_UNLOCK(_sc) mtx_unlock(&(_sc)->core_mtx) #define EM_CORE_UNLOCK(_sc) mtx_unlock(&(_sc)->core_mtx)
#define EM_TX_UNLOCK(_sc) mtx_unlock(&(_sc)->tx_mtx) #define EM_TX_UNLOCK(_sc) mtx_unlock(&(_sc)->tx_mtx)
#define EM_RX_UNLOCK(_sc) mtx_unlock(&(_sc)->rx_mtx)
#define EM_CORE_LOCK_ASSERT(_sc) mtx_assert(&(_sc)->core_mtx, MA_OWNED) #define EM_CORE_LOCK_ASSERT(_sc) mtx_assert(&(_sc)->core_mtx, MA_OWNED)
#define EM_TX_LOCK_ASSERT(_sc) mtx_assert(&(_sc)->tx_mtx, MA_OWNED) #define EM_TX_LOCK_ASSERT(_sc) mtx_assert(&(_sc)->tx_mtx, MA_OWNED)

View File

@ -37,7 +37,6 @@
*/ */
#include "e1000_api.h" #include "e1000_api.h"
#include "e1000_82575.h"
static s32 e1000_init_phy_params_82575(struct e1000_hw *hw); static s32 e1000_init_phy_params_82575(struct e1000_hw *hw);
static s32 e1000_init_nvm_params_82575(struct e1000_hw *hw); static s32 e1000_init_nvm_params_82575(struct e1000_hw *hw);
@ -554,7 +553,7 @@ static s32 e1000_phy_hw_reset_sgmii_82575(struct e1000_hw *hw)
DEBUGFUNC("e1000_phy_hw_reset_sgmii_82575"); DEBUGFUNC("e1000_phy_hw_reset_sgmii_82575");
/* /*
* This isn't a true "hard" reset, but is the only reset * This isn't a TRUE "hard" reset, but is the only reset
* available to us at this time. * available to us at this time.
*/ */
@ -1303,25 +1302,25 @@ static s32 e1000_reset_init_script_82575(struct e1000_hw* hw)
if (hw->mac.type == e1000_82575) { if (hw->mac.type == e1000_82575) {
DEBUGOUT("Running reset init script for 82575\n"); DEBUGOUT("Running reset init script for 82575\n");
/* SerDes configuration via SERDESCTRL */ /* SerDes configuration via SERDESCTRL */
e1000_write_8bit_ctrl_reg(hw, E1000_SCTL, 0x00, 0x0C); e1000_write_8bit_ctrl_reg_generic(hw, E1000_SCTL, 0x00, 0x0C);
e1000_write_8bit_ctrl_reg(hw, E1000_SCTL, 0x01, 0x78); e1000_write_8bit_ctrl_reg_generic(hw, E1000_SCTL, 0x01, 0x78);
e1000_write_8bit_ctrl_reg(hw, E1000_SCTL, 0x1B, 0x23); e1000_write_8bit_ctrl_reg_generic(hw, E1000_SCTL, 0x1B, 0x23);
e1000_write_8bit_ctrl_reg(hw, E1000_SCTL, 0x23, 0x15); e1000_write_8bit_ctrl_reg_generic(hw, E1000_SCTL, 0x23, 0x15);
/* CCM configuration via CCMCTL register */ /* CCM configuration via CCMCTL register */
e1000_write_8bit_ctrl_reg(hw, E1000_CCMCTL, 0x14, 0x00); e1000_write_8bit_ctrl_reg_generic(hw, E1000_CCMCTL, 0x14, 0x00);
e1000_write_8bit_ctrl_reg(hw, E1000_CCMCTL, 0x10, 0x00); e1000_write_8bit_ctrl_reg_generic(hw, E1000_CCMCTL, 0x10, 0x00);
/* PCIe lanes configuration */ /* PCIe lanes configuration */
e1000_write_8bit_ctrl_reg(hw, E1000_GIOCTL, 0x00, 0xEC); e1000_write_8bit_ctrl_reg_generic(hw, E1000_GIOCTL, 0x00, 0xEC);
e1000_write_8bit_ctrl_reg(hw, E1000_GIOCTL, 0x61, 0xDF); e1000_write_8bit_ctrl_reg_generic(hw, E1000_GIOCTL, 0x61, 0xDF);
e1000_write_8bit_ctrl_reg(hw, E1000_GIOCTL, 0x34, 0x05); e1000_write_8bit_ctrl_reg_generic(hw, E1000_GIOCTL, 0x34, 0x05);
e1000_write_8bit_ctrl_reg(hw, E1000_GIOCTL, 0x2F, 0x81); e1000_write_8bit_ctrl_reg_generic(hw, E1000_GIOCTL, 0x2F, 0x81);
/* PCIe PLL Configuration */ /* PCIe PLL Configuration */
e1000_write_8bit_ctrl_reg(hw, E1000_SCCTL, 0x02, 0x47); e1000_write_8bit_ctrl_reg_generic(hw, E1000_SCCTL, 0x02, 0x47);
e1000_write_8bit_ctrl_reg(hw, E1000_SCCTL, 0x14, 0x00); e1000_write_8bit_ctrl_reg_generic(hw, E1000_SCCTL, 0x14, 0x00);
e1000_write_8bit_ctrl_reg(hw, E1000_SCCTL, 0x10, 0x00); e1000_write_8bit_ctrl_reg_generic(hw, E1000_SCCTL, 0x10, 0x00);
} }
return E1000_SUCCESS; return E1000_SUCCESS;

View File

@ -33,9 +33,6 @@
/*$FreeBSD$*/ /*$FreeBSD$*/
#include "e1000_api.h" #include "e1000_api.h"
#include "e1000_mac.h"
#include "e1000_nvm.h"
#include "e1000_phy.h"
/** /**
* e1000_init_mac_params - Initialize MAC function pointers * e1000_init_mac_params - Initialize MAC function pointers
@ -260,7 +257,7 @@ s32 e1000_get_bus_info(struct e1000_hw *hw)
void e1000_clear_vfta(struct e1000_hw *hw) void e1000_clear_vfta(struct e1000_hw *hw)
{ {
if (hw->mac.ops.clear_vfta) if (hw->mac.ops.clear_vfta)
hw->mac.ops.clear_vfta (hw); hw->mac.ops.clear_vfta(hw);
} }
/** /**
@ -871,7 +868,7 @@ s32 e1000_phy_commit(struct e1000_hw *hw)
* Success returns 0, Failure returns 1 * Success returns 0, Failure returns 1
* *
* The low power link up (lplu) state is set to the power management level D0 * The low power link up (lplu) state is set to the power management level D0
* and SmartSpeed is disabled when active is true, else clear lplu for D0 * and SmartSpeed is disabled when active is TRUE, else clear lplu for D0
* and enable Smartspeed. LPLU and Smartspeed are mutually exclusive. LPLU * and enable Smartspeed. LPLU and Smartspeed are mutually exclusive. LPLU
* is used during Dx states where the power conservation is most important. * is used during Dx states where the power conservation is most important.
* During driver activity, SmartSpeed should be enabled so performance is * During driver activity, SmartSpeed should be enabled so performance is
@ -893,7 +890,7 @@ s32 e1000_set_d0_lplu_state(struct e1000_hw *hw, bool active)
* Success returns 0, Failure returns 1 * Success returns 0, Failure returns 1
* *
* The low power link up (lplu) state is set to the power management level D3 * The low power link up (lplu) state is set to the power management level D3
* and SmartSpeed is disabled when active is true, else clear lplu for D3 * and SmartSpeed is disabled when active is TRUE, else clear lplu for D3
* and enable Smartspeed. LPLU and Smartspeed are mutually exclusive. LPLU * and enable Smartspeed. LPLU and Smartspeed are mutually exclusive. LPLU
* is used during Dx states where the power conservation is most important. * is used during Dx states where the power conservation is most important.
* During driver activity, SmartSpeed should be enabled so performance is * During driver activity, SmartSpeed should be enabled so performance is

View File

@ -98,7 +98,6 @@ s32 e1000_wait_autoneg(struct e1000_hw *hw);
s32 e1000_set_d3_lplu_state(struct e1000_hw *hw, bool active); s32 e1000_set_d3_lplu_state(struct e1000_hw *hw, bool active);
s32 e1000_set_d0_lplu_state(struct e1000_hw *hw, bool active); s32 e1000_set_d0_lplu_state(struct e1000_hw *hw, bool active);
bool e1000_check_mng_mode(struct e1000_hw *hw); bool e1000_check_mng_mode(struct e1000_hw *hw);
bool e1000_enable_mng_pass_thru(struct e1000_hw *hw);
bool e1000_enable_tx_pkt_filtering(struct e1000_hw *hw); bool e1000_enable_tx_pkt_filtering(struct e1000_hw *hw);
s32 e1000_mng_enable_host_if(struct e1000_hw *hw); s32 e1000_mng_enable_host_if(struct e1000_hw *hw);
s32 e1000_mng_host_if_write(struct e1000_hw *hw, s32 e1000_mng_host_if_write(struct e1000_hw *hw,
@ -108,7 +107,6 @@ s32 e1000_mng_write_cmd_header(struct e1000_hw *hw,
s32 e1000_mng_write_dhcp_info(struct e1000_hw * hw, s32 e1000_mng_write_dhcp_info(struct e1000_hw * hw,
u8 *buffer, u16 length); u8 *buffer, u16 length);
/* /*
* TBI_ACCEPT macro definition: * TBI_ACCEPT macro definition:
* *

View File

@ -384,6 +384,7 @@
#define E1000_CTRL_PHY_RESET4 E1000_CTRL_EXT_SDP4_DATA #define E1000_CTRL_PHY_RESET4 E1000_CTRL_EXT_SDP4_DATA
#define E1000_CONNSW_ENRGSRC 0x4 #define E1000_CONNSW_ENRGSRC 0x4
#define E1000_PCS_CFG_PCS_EN 8
#define E1000_PCS_LCTL_FLV_LINK_UP 1 #define E1000_PCS_LCTL_FLV_LINK_UP 1
#define E1000_PCS_LCTL_FSV_10 0 #define E1000_PCS_LCTL_FSV_10 0
#define E1000_PCS_LCTL_FSV_100 2 #define E1000_PCS_LCTL_FSV_100 2

View File

@ -57,7 +57,7 @@ struct e1000_hw;
typedef enum { typedef enum {
e1000_undefined = 0, e1000_undefined = 0,
e1000_82575, e1000_82575,
e1000_num_macs /* List is 1-based, so subtract 1 for true count. */ e1000_num_macs /* List is 1-based, so subtract 1 for TRUE count. */
} e1000_mac_type; } e1000_mac_type;
typedef enum { typedef enum {
@ -615,9 +615,9 @@ struct e1000_hw {
u8 revision_id; u8 revision_id;
}; };
#include "e1000_82575.h"
/* These functions must be implemented by drivers */ /* These functions must be implemented by drivers */
void e1000_pci_clear_mwi(struct e1000_hw *hw);
void e1000_pci_set_mwi(struct e1000_hw *hw);
s32 e1000_alloc_zeroed_dev_spec_struct(struct e1000_hw *hw, u32 size); s32 e1000_alloc_zeroed_dev_spec_struct(struct e1000_hw *hw, u32 size);
s32 e1000_read_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value); s32 e1000_read_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value);
void e1000_free_dev_spec_struct(struct e1000_hw *hw); void e1000_free_dev_spec_struct(struct e1000_hw *hw);

View File

@ -33,7 +33,6 @@
/*$FreeBSD$*/ /*$FreeBSD$*/
#include "e1000_api.h" #include "e1000_api.h"
#include "e1000_mac.h"
/** /**
* e1000_init_mac_ops_generic - Initialize MAC function pointers * e1000_init_mac_ops_generic - Initialize MAC function pointers
@ -526,7 +525,7 @@ void e1000_update_mc_addr_list_generic(struct e1000_hw *hw,
/* Load any remaining multicast addresses into the hash table. */ /* Load any remaining multicast addresses into the hash table. */
for (; mc_addr_count > 0; mc_addr_count--) { for (; mc_addr_count > 0; mc_addr_count--) {
hash_value = e1000_hash_mc_addr(hw, mc_addr_list); hash_value = e1000_hash_mc_addr_generic(hw, mc_addr_list);
DEBUGOUT1("Hash value = 0x%03X\n", hash_value); DEBUGOUT1("Hash value = 0x%03X\n", hash_value);
hw->mac.ops.mta_set(hw, hash_value); hw->mac.ops.mta_set(hw, hash_value);
mc_addr_list += ETH_ADDR_LEN; mc_addr_list += ETH_ADDR_LEN;

View File

@ -44,6 +44,7 @@ s32 e1000_mng_write_cmd_header_generic(struct e1000_hw *hw,
struct e1000_host_mng_command_header *hdr); struct e1000_host_mng_command_header *hdr);
s32 e1000_mng_write_dhcp_info_generic(struct e1000_hw *hw, s32 e1000_mng_write_dhcp_info_generic(struct e1000_hw *hw,
u8 *buffer, u16 length); u8 *buffer, u16 length);
bool e1000_enable_mng_pass_thru(struct e1000_hw *hw);
typedef enum { typedef enum {
e1000_mng_mode_none = 0, e1000_mng_mode_none = 0,

View File

@ -52,20 +52,6 @@ e1000_read_pci_cfg(struct e1000_hw *hw, uint32_t reg, uint16_t *value)
*value = pci_read_config(((struct e1000_osdep *)hw->back)->dev, reg, 2); *value = pci_read_config(((struct e1000_osdep *)hw->back)->dev, reg, 2);
} }
void
e1000_pci_set_mwi(struct e1000_hw *hw)
{
pci_write_config(((struct e1000_osdep *)hw->back)->dev, PCIR_COMMAND,
(hw->bus.pci_cmd_word | CMD_MEM_WRT_INVALIDATE), 2);
}
void
e1000_pci_clear_mwi(struct e1000_hw *hw)
{
pci_write_config(((struct e1000_osdep *)hw->back)->dev, PCIR_COMMAND,
(hw->bus.pci_cmd_word & ~CMD_MEM_WRT_INVALIDATE), 2);
}
/* /*
* Read the PCI Express capabilities * Read the PCI Express capabilities
*/ */

View File

@ -71,11 +71,13 @@
#define DEBUGOUT3(S,A,B,C) #define DEBUGOUT3(S,A,B,C)
#define DEBUGOUT7(S,A,B,C,D,E,F,G) #define DEBUGOUT7(S,A,B,C,D,E,F,G)
#define STATIC static #define STATIC static
#define FALSE 0 #define FALSE 0
#define TRUE 1 #define false FALSE /* shared code stupidity */
#define CMD_MEM_WRT_INVALIDATE 0x0010 /* BIT_4 */ #define TRUE 1
#define PCI_COMMAND_REGISTER PCIR_COMMAND #define true TRUE
#define CMD_MEM_WRT_INVALIDATE 0x0010 /* BIT_4 */
#define PCI_COMMAND_REGISTER PCIR_COMMAND
/* /*
** These typedefs are necessary due to the new ** These typedefs are necessary due to the new

View File

@ -33,7 +33,6 @@
/*$FreeBSD$*/ /*$FreeBSD$*/
#include "e1000_api.h" #include "e1000_api.h"
#include "e1000_phy.h"
/* Cable length tables */ /* Cable length tables */
static const u16 e1000_m88_cable_length_table[] = static const u16 e1000_m88_cable_length_table[] =
@ -670,7 +669,7 @@ s32 e1000_copper_link_setup_igp(struct e1000_hw *hw)
goto out; goto out;
} }
ret_val = e1000_phy_hw_reset(hw); ret_val = hw->phy.ops.reset(hw);
if (ret_val) { if (ret_val) {
DEBUGOUT("Error resetting the PHY.\n"); DEBUGOUT("Error resetting the PHY.\n");
goto out; goto out;
@ -688,7 +687,7 @@ s32 e1000_copper_link_setup_igp(struct e1000_hw *hw)
*/ */
if (phy->type == e1000_phy_igp) { if (phy->type == e1000_phy_igp) {
/* disable lplu d3 during driver init */ /* disable lplu d3 during driver init */
ret_val = e1000_set_d3_lplu_state(hw, FALSE); ret_val = hw->phy.ops.set_d3_lplu_state(hw, FALSE);
if (ret_val) { if (ret_val) {
DEBUGOUT("Error Disabling LPLU D3\n"); DEBUGOUT("Error Disabling LPLU D3\n");
goto out; goto out;
@ -696,7 +695,7 @@ s32 e1000_copper_link_setup_igp(struct e1000_hw *hw)
} }
/* disable lplu d0 during driver init */ /* disable lplu d0 during driver init */
ret_val = e1000_set_d0_lplu_state(hw, FALSE); ret_val = hw->phy.ops.set_d0_lplu_state(hw, FALSE);
if (ret_val) { if (ret_val) {
DEBUGOUT("Error Disabling LPLU D0\n"); DEBUGOUT("Error Disabling LPLU D0\n");
goto out; goto out;
@ -846,7 +845,7 @@ s32 e1000_copper_link_autoneg(struct e1000_hw *hw)
* check at a later time (for example, callback routine). * check at a later time (for example, callback routine).
*/ */
if (phy->autoneg_wait_to_complete) { if (phy->autoneg_wait_to_complete) {
ret_val = e1000_wait_autoneg(hw); ret_val = hw->mac.ops.wait_autoneg(hw);
if (ret_val) { if (ret_val) {
DEBUGOUT("Error while waiting for " DEBUGOUT("Error while waiting for "
"autoneg to complete\n"); "autoneg to complete\n");
@ -1343,7 +1342,7 @@ void e1000_phy_force_speed_duplex_setup(struct e1000_hw *hw, u16 *phy_ctrl)
* Success returns 0, Failure returns 1 * Success returns 0, Failure returns 1
* *
* The low power link up (lplu) state is set to the power management level D3 * The low power link up (lplu) state is set to the power management level D3
* and SmartSpeed is disabled when active is true, else clear lplu for D3 * and SmartSpeed is disabled when active is TRUE, else clear lplu for D3
* and enable Smartspeed. LPLU and Smartspeed are mutually exclusive. LPLU * and enable Smartspeed. LPLU and Smartspeed are mutually exclusive. LPLU
* is used during Dx states where the power conservation is most important. * is used during Dx states where the power conservation is most important.
* During driver activity, SmartSpeed should be enabled so performance is * During driver activity, SmartSpeed should be enabled so performance is
@ -1798,7 +1797,7 @@ s32 e1000_get_phy_info_m88(struct e1000_hw *hw)
phy->is_mdix = (phy_data & M88E1000_PSSR_MDIX) ? TRUE : FALSE; phy->is_mdix = (phy_data & M88E1000_PSSR_MDIX) ? TRUE : FALSE;
if ((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_1000MBS) { if ((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_1000MBS) {
ret_val = e1000_get_cable_length(hw); ret_val = hw->phy.ops.get_cable_length(hw);
if (ret_val) if (ret_val)
goto out; goto out;
@ -1866,7 +1865,7 @@ s32 e1000_get_phy_info_igp(struct e1000_hw *hw)
if ((data & IGP01E1000_PSSR_SPEED_MASK) == if ((data & IGP01E1000_PSSR_SPEED_MASK) ==
IGP01E1000_PSSR_SPEED_1000MBPS) { IGP01E1000_PSSR_SPEED_1000MBPS) {
ret_val = e1000_get_cable_length(hw); ret_val = hw->phy.ops.get_cable_length(hw);
if (ret_val) if (ret_val)
goto out; goto out;

View File

@ -88,7 +88,7 @@ int igb_display_debug_stats = 0;
/********************************************************************* /*********************************************************************
* Driver version: * Driver version:
*********************************************************************/ *********************************************************************/
char igb_driver_version[] = "version - 1.1.6"; char igb_driver_version[] = "version - 1.1.9";
/********************************************************************* /*********************************************************************
@ -271,13 +271,18 @@ TUNABLE_INT("hw.igb.rxd", &igb_rxd);
TUNABLE_INT("hw.igb.txd", &igb_txd); TUNABLE_INT("hw.igb.txd", &igb_txd);
TUNABLE_INT("hw.igb.smart_pwr_down", &igb_smart_pwr_down); TUNABLE_INT("hw.igb.smart_pwr_down", &igb_smart_pwr_down);
/* These auto configure if set to 0, based on number of cpus */ /*
extern int mp_ncpus; ** IF YOU CHANGE THESE: be sure and change IGB_MSIX_VEC in
** if_igb.h to match. These can be autoconfigured if set to
** 0, it will then be based on number of cpus.
*/
static int igb_tx_queues = 1; static int igb_tx_queues = 1;
static int igb_rx_queues = 1; static int igb_rx_queues = 1;
TUNABLE_INT("hw.igb.tx_queues", &igb_tx_queues); TUNABLE_INT("hw.igb.tx_queues", &igb_tx_queues);
TUNABLE_INT("hw.igb.rx_queues", &igb_rx_queues); TUNABLE_INT("hw.igb.rx_queues", &igb_rx_queues);
extern int mp_ncpus;
/* How many packets rxeof tries to clean at a time */ /* How many packets rxeof tries to clean at a time */
static int igb_rx_process_limit = 100; static int igb_rx_process_limit = 100;
TUNABLE_INT("hw.igb.rx_process_limit", &igb_rx_process_limit); TUNABLE_INT("hw.igb.rx_process_limit", &igb_rx_process_limit);
@ -605,11 +610,11 @@ igb_detach(device_t dev)
callout_drain(&adapter->timer); callout_drain(&adapter->timer);
e1000_remove_device(&adapter->hw);
igb_free_pci_resources(adapter); igb_free_pci_resources(adapter);
bus_generic_detach(dev); bus_generic_detach(dev);
if_free(ifp); if_free(ifp);
e1000_remove_device(&adapter->hw);
igb_free_transmit_structures(adapter); igb_free_transmit_structures(adapter);
igb_free_receive_structures(adapter); igb_free_receive_structures(adapter);
@ -819,7 +824,7 @@ igb_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
if (ifp->if_flags & IFF_UP) { if (ifp->if_flags & IFF_UP) {
if ((ifp->if_drv_flags & IFF_DRV_RUNNING)) { if ((ifp->if_drv_flags & IFF_DRV_RUNNING)) {
if ((ifp->if_flags ^ adapter->if_flags) & if ((ifp->if_flags ^ adapter->if_flags) &
IFF_PROMISC) { (IFF_PROMISC | IFF_ALLMULTI)) {
igb_disable_promisc(adapter); igb_disable_promisc(adapter);
igb_set_promisc(adapter); igb_set_promisc(adapter);
} }
@ -1090,8 +1095,10 @@ igb_init_locked(struct adapter *adapter)
else else
#endif /* DEVICE_POLLING */ #endif /* DEVICE_POLLING */
{ {
/* this clears any pending interrupts */
E1000_READ_REG(&adapter->hw, E1000_ICR); E1000_READ_REG(&adapter->hw, E1000_ICR);
igb_enable_intr(adapter); igb_enable_intr(adapter);
E1000_WRITE_REG(&adapter->hw, E1000_ICS, E1000_ICS_LSC);
} }
@ -1268,7 +1275,7 @@ igb_irq_fast(void *arg)
/* Link status change */ /* Link status change */
if (reg_icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) { if (reg_icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) {
adapter->hw.mac.get_link_status = 1; adapter->hw.mac.get_link_status = 1;
taskqueue_enqueue(taskqueue_fast, &adapter->link_task); taskqueue_enqueue(adapter->tq, &adapter->link_task);
} }
if (reg_icr & E1000_ICR_RXO) if (reg_icr & E1000_ICR_RXO)
@ -1341,11 +1348,12 @@ igb_msix_link(void *arg)
if (!(icr & E1000_ICR_LSC)) if (!(icr & E1000_ICR_LSC))
goto spurious; goto spurious;
adapter->hw.mac.get_link_status = 1; adapter->hw.mac.get_link_status = 1;
taskqueue_enqueue(taskqueue_fast, &adapter->link_task); taskqueue_enqueue(adapter->tq, &adapter->link_task);
spurious: spurious:
/* Rearm */
E1000_WRITE_REG(&adapter->hw, E1000_IMS, E1000_IMS_LSC); E1000_WRITE_REG(&adapter->hw, E1000_IMS, E1000_IMS_LSC);
E1000_WRITE_REG(&adapter->hw, E1000_EIMS, E1000_EIMS_OTHER); E1000_WRITE_REG(&adapter->hw, E1000_EIMS, adapter->link_mask);
return; return;
} }
@ -2094,7 +2102,7 @@ igb_configure_queues(struct adapter *adapter)
E1000_WRITE_REG(hw, E1000_CTRL_EXT, tmp); E1000_WRITE_REG(hw, E1000_CTRL_EXT, tmp);
/* Set the interrupt throttling rate. */ /* Set the interrupt throttling rate. */
for (int i = 0; i < 10; i++) for (int i = 0; i < IGB_MSIX_VEC; i++)
E1000_WRITE_REG(&adapter->hw, E1000_WRITE_REG(&adapter->hw,
E1000_EITR(i), DEFAULT_ITR); E1000_EITR(i), DEFAULT_ITR);
@ -2117,7 +2125,8 @@ igb_configure_queues(struct adapter *adapter)
/* Link */ /* Link */
E1000_WRITE_REG(hw, E1000_MSIXBM(adapter->linkvec), E1000_WRITE_REG(hw, E1000_MSIXBM(adapter->linkvec),
E1000_EIMS_OTHER); E1000_EIMS_OTHER);
adapter->eims_mask |= E1000_EIMS_OTHER; adapter->link_mask |= E1000_EIMS_OTHER;
adapter->eims_mask |= adapter->link_mask;
} }
return; return;
} }
@ -2191,6 +2200,10 @@ igb_setup_msix(struct adapter *adapter)
goto msi; goto msi;
} }
/* Limit by the number set in header */
if (msgs > IGB_MSIX_VEC)
msgs = IGB_MSIX_VEC;
/* Figure out a reasonable auto config value */ /* Figure out a reasonable auto config value */
queues = (mp_ncpus > ((msgs-1)/2)) ? (msgs-1)/2 : mp_ncpus; queues = (mp_ncpus > ((msgs-1)/2)) ? (msgs-1)/2 : mp_ncpus;
@ -2204,7 +2217,7 @@ igb_setup_msix(struct adapter *adapter)
else { else {
device_printf(adapter->dev, device_printf(adapter->dev,
"MSIX Configuration Problem, " "MSIX Configuration Problem, "
"%d vectors but %d queues wanted!\n", "%d vectors configured, but %d queues wanted!\n",
msgs, want); msgs, want);
return (ENXIO); return (ENXIO);
} }
@ -2860,7 +2873,6 @@ igb_tso_setup(struct tx_ring *txr, struct mbuf *mp, u32 *hdrlen)
ip = (struct ip *)(mp->m_data + ehdrlen); ip = (struct ip *)(mp->m_data + ehdrlen);
if (ip->ip_p != IPPROTO_TCP) if (ip->ip_p != IPPROTO_TCP)
return FALSE; /* 0 */ return FALSE; /* 0 */
ip->ip_len = 0;
ip->ip_sum = 0; ip->ip_sum = 0;
ip_hlen = ip->ip_hl << 2; ip_hlen = ip->ip_hl << 2;
th = (struct tcphdr *)((caddr_t)ip + ip_hlen); th = (struct tcphdr *)((caddr_t)ip + ip_hlen);
@ -3813,7 +3825,7 @@ igb_fixup_rx(struct rx_ring *rxr)
rxr->fmp = n; rxr->fmp = n;
} else { } else {
adapter->dropped_pkts++; adapter->dropped_pkts++;
m_freem(rxr->fmp); m_freem(adapter->fmp);
rxr->fmp = NULL; rxr->fmp = NULL;
error = ENOMEM; error = ENOMEM;
} }
@ -3885,6 +3897,8 @@ igb_enable_intr(struct adapter *adapter)
if (adapter->msix_mem) { if (adapter->msix_mem) {
E1000_WRITE_REG(&adapter->hw, E1000_EIAC, E1000_WRITE_REG(&adapter->hw, E1000_EIAC,
adapter->eims_mask); adapter->eims_mask);
E1000_WRITE_REG(&adapter->hw, E1000_EIAM,
adapter->eims_mask);
E1000_WRITE_REG(&adapter->hw, E1000_EIMS, E1000_WRITE_REG(&adapter->hw, E1000_EIMS,
adapter->eims_mask); adapter->eims_mask);
E1000_WRITE_REG(&adapter->hw, E1000_IMS, E1000_WRITE_REG(&adapter->hw, E1000_IMS,
@ -3905,7 +3919,7 @@ igb_disable_intr(struct adapter *adapter)
E1000_WRITE_REG(&adapter->hw, E1000_EIMC, ~0); E1000_WRITE_REG(&adapter->hw, E1000_EIMC, ~0);
E1000_WRITE_REG(&adapter->hw, E1000_EIAC, 0); E1000_WRITE_REG(&adapter->hw, E1000_EIAC, 0);
} }
E1000_WRITE_REG(&adapter->hw, E1000_IMC, ~0); E1000_WRITE_REG(&adapter->hw, E1000_IMC, ~0);
E1000_WRITE_FLUSH(&adapter->hw); E1000_WRITE_FLUSH(&adapter->hw);
return; return;
} }
@ -4143,9 +4157,18 @@ igb_print_debug_info(struct adapter *adapter)
device_printf(dev, "CTRL = 0x%x RCTL = 0x%x \n", device_printf(dev, "CTRL = 0x%x RCTL = 0x%x \n",
E1000_READ_REG(&adapter->hw, E1000_CTRL), E1000_READ_REG(&adapter->hw, E1000_CTRL),
E1000_READ_REG(&adapter->hw, E1000_RCTL)); E1000_READ_REG(&adapter->hw, E1000_RCTL));
#if (DEBUG_HW > 0) /* Dont output these errors normally */
device_printf(dev, "IMS = 0x%x EIMS = 0x%x \n", device_printf(dev, "IMS = 0x%x EIMS = 0x%x \n",
E1000_READ_REG(&adapter->hw, E1000_IMS), E1000_READ_REG(&adapter->hw, E1000_IMS),
E1000_READ_REG(&adapter->hw, E1000_EIMS)); E1000_READ_REG(&adapter->hw, E1000_EIMS));
/* Kawela only */
device_printf(dev, "IVAR0 = 0x%x IVAR1 = 0x%x IVAR_MISC = 0x%x\n",
E1000_READ_REG_ARRAY(&adapter->hw, E1000_IVAR0, 0),
E1000_READ_REG_ARRAY(&adapter->hw, E1000_IVAR0, 1),
E1000_READ_REG(&adapter->hw, E1000_IVAR_MISC));
#endif
device_printf(dev, "Packet buffer = Tx=%dk Rx=%dk \n", device_printf(dev, "Packet buffer = Tx=%dk Rx=%dk \n",
((E1000_READ_REG(&adapter->hw, E1000_PBA) & 0xffff0000) >> 16),\ ((E1000_READ_REG(&adapter->hw, E1000_PBA) & 0xffff0000) >> 16),\
(E1000_READ_REG(&adapter->hw, E1000_PBA) & 0xffff) ); (E1000_READ_REG(&adapter->hw, E1000_PBA) & 0xffff) );
@ -4163,24 +4186,24 @@ igb_print_debug_info(struct adapter *adapter)
device_printf(dev, "Queue(%d) tdh = %d, tdt = %d\n", i, device_printf(dev, "Queue(%d) tdh = %d, tdt = %d\n", i,
E1000_READ_REG(&adapter->hw, E1000_TDH(i)), E1000_READ_REG(&adapter->hw, E1000_TDH(i)),
E1000_READ_REG(&adapter->hw, E1000_TDT(i))); E1000_READ_REG(&adapter->hw, E1000_TDT(i)));
device_printf(dev, "no descriptors avail event = %lld\n", device_printf(dev, "no descriptors avail event = %lu\n",
(long long)txr->no_desc_avail); txr->no_desc_avail);
device_printf(dev, "TX(%d) MSIX IRQ Handled = %lld\n", txr->me, device_printf(dev, "TX(%d) MSIX IRQ Handled = %lu\n", txr->me,
(long long)txr->tx_irq); txr->tx_irq);
device_printf(dev, "TX(%d) Packets sent = %lld\n", txr->me, device_printf(dev, "TX(%d) Packets sent = %lu\n", txr->me,
(long long)txr->tx_packets); txr->tx_packets);
} }
for (int i = 0; i < adapter->num_rx_queues; i++, rxr++) { for (int i = 0; i < adapter->num_rx_queues; i++, rxr++) {
device_printf(dev, "Queue(%d) rdh = %d, rdt = %d\n", i, device_printf(dev, "Queue(%d) rdh = %d, rdt = %d\n", i,
E1000_READ_REG(&adapter->hw, E1000_RDH(i)), E1000_READ_REG(&adapter->hw, E1000_RDH(i)),
E1000_READ_REG(&adapter->hw, E1000_RDT(i))); E1000_READ_REG(&adapter->hw, E1000_RDT(i)));
device_printf(dev, "RX(%d) Packets received = %lld\n", rxr->me, device_printf(dev, "RX(%d) Packets received = %lu\n", rxr->me,
(long long)rxr->rx_packets); rxr->rx_packets);
device_printf(dev, "RX(%d) Byte count = %lld\n", rxr->me, device_printf(dev, "RX(%d) Byte count = %lu\n", rxr->me,
(long long)rxr->rx_bytes); rxr->rx_bytes);
device_printf(dev, "RX(%d) MSIX IRQ Handled = %lld\n", rxr->me, device_printf(dev, "RX(%d) MSIX IRQ Handled = %lu\n", rxr->me,
(long long)rxr->rx_irq); rxr->rx_irq);
} }
device_printf(dev, "LINK MSIX IRQ Handled = %u\n", adapter->link_irq); device_printf(dev, "LINK MSIX IRQ Handled = %u\n", adapter->link_irq);

View File

@ -203,7 +203,14 @@
/* PCI Config defines */ /* PCI Config defines */
#define IGB_MSIX_BAR 3 #define IGB_MSIX_BAR 3
#define IGB_MSIX_VEC 10 /* Max vectors supported */
/*
** This is the total number of MSIX vectors you wish
** to use, it also controls the size of resources.
** The 82575 has a total of 10, 82576 has 25. Set this
** to the real amount you need to streamline data storage.
*/
#define IGB_MSIX_VEC 5 /* MSIX vectors configured */
/* Defines for printing debug information */ /* Defines for printing debug information */
#define DEBUG_INIT 0 #define DEBUG_INIT 0
@ -318,6 +325,7 @@ struct adapter {
u32 eims_mask; u32 eims_mask;
int linkvec; int linkvec;
int link_mask;
int link_irq; int link_irq;
struct ifmedia media; struct ifmedia media;

View File

@ -7,9 +7,16 @@ SHARED_SRCS = e1000_api.c e1000_phy.c e1000_nvm.c e1000_mac.c e1000_manage.c
SHARED_SRCS += e1000_80003es2lan.c e1000_82542.c e1000_82541.c e1000_82543.c SHARED_SRCS += e1000_80003es2lan.c e1000_82542.c e1000_82541.c e1000_82543.c
SHARED_SRCS += e1000_82540.c e1000_ich8lan.c e1000_82571.c e1000_osdep.c SHARED_SRCS += e1000_82540.c e1000_ich8lan.c e1000_82571.c e1000_osdep.c
CFLAGS+= -I${.CURDIR}/../../dev/em CFLAGS+= -DNO_82575_SUPPORT -I${.CURDIR}/../../dev/em
# DEVICE_POLLING gives you Legacy interrupt handling # Uncomment this to disable Fast interrupt handling.
# and enable legacy interrupt handling
#CFLAGS += -DEM_LEGACY_IRQ
# This option enables IEEE 1588 Precision Time Protocol
#CFLAGS += -DEM_TIMESYNC
# DEVICE_POLLING for a non-interrupt-driven method
#CFLAGS += -DDEVICE_POLLING #CFLAGS += -DDEVICE_POLLING
clean: clean: