diff --git a/sys/dev/em/e1000_82571.c b/sys/dev/em/e1000_82571.c index 7a2e2093bdb8..b4edaaedb572 100644 --- a/sys/dev/em/e1000_82571.c +++ b/sys/dev/em/e1000_82571.c @@ -150,6 +150,25 @@ static s32 e1000_init_phy_params_82571(struct e1000_hw *hw) goto out; } 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: ret_val = -E1000_ERR_PHY; goto out; @@ -193,6 +212,7 @@ static s32 e1000_init_nvm_params_82571(struct e1000_hw *hw) switch (hw->mac.type) { case e1000_82573: + case e1000_82574: if (((eecd >> 15) & 0x3) == 0x3) { nvm->type = e1000_nvm_flash_hw; 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; s32 ret_val = E1000_SUCCESS; + u16 phy_id = 0; DEBUGFUNC("e1000_get_phy_id_82571"); @@ -391,11 +412,26 @@ static s32 e1000_get_phy_id_82571(struct e1000_hw *hw) case e1000_82573: ret_val = e1000_get_phy_id(hw); 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: ret_val = -E1000_ERR_PHY; break; } +out: return ret_val; } @@ -476,7 +512,7 @@ static s32 e1000_acquire_nvm_82571(struct e1000_hw *hw) if (ret_val) 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); 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) { case e1000_82573: + case e1000_82574: ret_val = e1000_write_nvm_eewr_82571(hw, offset, words, data); break; 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. * 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_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 * NVM and Phy. */ - if (hw->mac.type == e1000_82573) + if (hw->mac.type == e1000_82573 || hw->mac.type == e1000_82574) msec_delay(25); /* 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); /* ...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 = (reg_data & ~E1000_TXDCTL_WTHRESH) | E1000_TXDCTL_FULL_TX_DESC_WB | @@ -1014,14 +1051,14 @@ static void e1000_initialize_hw_bits_82571(struct e1000_hw *hw) } /* 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 &= ~(1 << 29); E1000_WRITE_REG(hw, E1000_CTRL, reg); } /* 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 &= ~(1 << 23); reg |= (1 << 22); @@ -1048,7 +1085,7 @@ static void e1000_clear_vfta_82571(struct e1000_hw *hw) 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) { /* * 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 * 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; 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; } - 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_DEFAULT_82573; - else if (*data == ID_LED_RESERVED_0000 || - *data == ID_LED_RESERVED_FFFF) + else if (*data == ID_LED_RESERVED_0000 || *data == ID_LED_RESERVED_FFFF) *data = ID_LED_DEFAULT; out: return ret_val; diff --git a/sys/dev/em/e1000_82571.h b/sys/dev/em/e1000_82571.h index e6469ea57603..ceb0ab05e1ed 100644 --- a/sys/dev/em/e1000_82571.h +++ b/sys/dev/em/e1000_82571.h @@ -43,4 +43,12 @@ #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 diff --git a/sys/dev/em/e1000_api.c b/sys/dev/em/e1000_api.c index ead54d6f7143..fee0e4e2d3fe 100644 --- a/sys/dev/em/e1000_api.c +++ b/sys/dev/em/e1000_api.c @@ -216,6 +216,9 @@ s32 e1000_set_mac_type(struct e1000_hw *hw) case E1000_DEV_ID_82573L: mac->type = e1000_82573; break; + case E1000_DEV_ID_82574L: + mac->type = e1000_82574; + break; case E1000_DEV_ID_80003ES2LAN_COPPER_DPT: case E1000_DEV_ID_80003ES2LAN_SERDES_DPT: 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_V: case E1000_DEV_ID_ICH9_IGP_AMT: + case E1000_DEV_ID_ICH9_BM: 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; 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_FIBER_SERDES: case E1000_DEV_ID_82575GB_QUAD_COPPER: mac->type = e1000_82575; break; +#endif default: /* Should never have loaded on this device */ 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_82572: case e1000_82573: + case e1000_82574: e1000_init_function_pointers_82571(hw); break; case e1000_80003es2lan: @@ -330,11 +344,14 @@ s32 e1000_setup_init_funcs(struct e1000_hw *hw, bool init_device) break; case e1000_ich8lan: case e1000_ich9lan: + case e1000_ich10lan: e1000_init_function_pointers_ich8lan(hw); break; +#ifndef NO_82575_SUPPORT case e1000_82575: e1000_init_function_pointers_82575(hw); break; +#endif default: DEBUGOUT("Hardware not supported\n"); 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) { if (hw->mac.ops.clear_vfta) - hw->mac.ops.clear_vfta (hw); + hw->mac.ops.clear_vfta(hw); } /** diff --git a/sys/dev/em/e1000_api.h b/sys/dev/em/e1000_api.h index 921b194a595b..84f261b6210b 100644 --- a/sys/dev/em/e1000_api.h +++ b/sys/dev/em/e1000_api.h @@ -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_80003es2lan(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); +#endif s32 e1000_set_mac_type(struct e1000_hw *hw); s32 e1000_setup_init_funcs(struct e1000_hw *hw, bool init_device); diff --git a/sys/dev/em/e1000_defines.h b/sys/dev/em/e1000_defines.h index 516db57dfe50..72aa978c4e02 100644 --- a/sys/dev/em/e1000_defines.h +++ b/sys/dev/em/e1000_defines.h @@ -154,6 +154,7 @@ #define E1000_CTRL_EXT_DF_PAREN 0x02000000 /* descriptor FIFO parity error detection enable */ #define E1000_CTRL_EXT_GHOST_PAREN 0x40000000 #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 0x00FF0000 #define E1000_I2CCMD_PHY_ADDR_SHIFT 24 @@ -202,6 +203,13 @@ #define E1000_RXDEXT_STATERR_IPE 0x40000000 #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 */ #define E1000_RXD_ERR_FRAME_ERR_MASK ( \ E1000_RXD_ERR_CE | \ @@ -397,6 +405,7 @@ #define E1000_CTRL_PHY_RESET4 E1000_CTRL_EXT_SDP4_DATA #define E1000_CONNSW_ENRGSRC 0x4 +#define E1000_PCS_CFG_PCS_EN 8 #define E1000_PCS_LCTL_FLV_LINK_UP 1 #define E1000_PCS_LCTL_FSV_10 0 #define E1000_PCS_LCTL_FSV_100 2 @@ -556,6 +565,8 @@ #define E1000_TXD_CMD_TSE 0x04000000 /* TCP Seg enable */ #define E1000_TXD_STAT_TC 0x00000004 /* Tx Underrun */ /* 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 */ #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_PHYINT 0x00001000 /* LAN connected device generates an interrupt */ #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 */ #define E1000_EICR_RX_QUEUE0 0x00000001 /* Rx Queue 0 Interrupt */ @@ -787,6 +803,11 @@ #define E1000_IMS_DSW E1000_ICR_DSW #define E1000_IMS_PHYINT E1000_ICR_PHYINT #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 */ #define E1000_EIMS_RX_QUEUE0 E1000_EICR_RX_QUEUE0 /* Rx Queue 0 Interrupt */ diff --git a/sys/dev/em/e1000_hw.h b/sys/dev/em/e1000_hw.h index ebc20bf53296..ea32a0559f83 100644 --- a/sys/dev/em/e1000_hw.h +++ b/sys/dev/em/e1000_hw.h @@ -95,6 +95,7 @@ struct e1000_hw; #define E1000_DEV_ID_82573E 0x108B #define E1000_DEV_ID_82573E_IAMT 0x108C #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_SERDES_DPT 0x1098 #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_V 0x10CB #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_IFE 0x10C0 #define E1000_DEV_ID_ICH9_IFE_GT 0x10C3 #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_FIBER_SERDES 0x10A9 #define E1000_DEV_ID_82575GB_QUAD_COPPER 0x10D6 @@ -146,9 +153,11 @@ typedef enum { e1000_82571, e1000_82572, e1000_82573, + e1000_82574, e1000_80003es2lan, e1000_ich8lan, e1000_ich9lan, + e1000_ich10lan, e1000_82575, e1000_num_macs /* List is 1-based, so subtract 1 for TRUE count. */ } e1000_mac_type; diff --git a/sys/dev/em/e1000_ich8lan.c b/sys/dev/em/e1000_ich8lan.c index 149d66b051d5..d8c9e5005800 100644 --- a/sys/dev/em/e1000_ich8lan.c +++ b/sys/dev/em/e1000_ich8lan.c @@ -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 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_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, u8 size, u16* data); 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) { s32 ret_val = E1000_SUCCESS; - if (E1000_READ_REG(hw, E1000_EECD) & E1000_EECD_SEC1VAL) - *bank = 1; - else - *bank = 0; + struct e1000_nvm_info *nvm = &hw->nvm; + /* flash bank size is in words */ + u32 bank1_offset = nvm->flash_bank_size * sizeof(u16); + 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; } @@ -1240,6 +1278,30 @@ out: 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 * @hw: pointer to the HW structure @@ -2483,13 +2545,14 @@ out: * 'LPLU Enabled' and 'Gig Disable' to force link speed negotiation * 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) { 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_PHY_CTRL_D0A_LPLU | 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) { s32 ret_val = E1000_SUCCESS; + u32 bank = 0; e1000_get_cfg_done_generic(hw); /* If EEPROM is not marked present, init the IGP 3 PHY manually */ - if (((E1000_READ_REG(hw, E1000_EECD) & E1000_EECD_PRES) == 0) && - (hw->phy.type == e1000_phy_igp_3)) { - e1000_phy_init_script_igp3(hw); + if (hw->mac.type != e1000_ich10lan) { + if (((E1000_READ_REG(hw, E1000_EECD) & E1000_EECD_PRES) == 0) && + (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; diff --git a/sys/dev/em/e1000_ich8lan.h b/sys/dev/em/e1000_ich8lan.h index caa23a091d6f..8de854ac24f9 100644 --- a/sys/dev/em/e1000_ich8lan.h +++ b/sys/dev/em/e1000_ich8lan.h @@ -112,4 +112,16 @@ E1000_IMS_PHYINT | \ 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 diff --git a/sys/dev/em/e1000_osdep.h b/sys/dev/em/e1000_osdep.h index 8a63950ac875..a4be0cdaa1cb 100644 --- a/sys/dev/em/e1000_osdep.h +++ b/sys/dev/em/e1000_osdep.h @@ -104,8 +104,12 @@ struct e1000_osdep struct device *dev; }; +#ifdef NO_82542_SUPPORT +#define E1000_REGISTER(hw, reg) reg +#else #define E1000_REGISTER(hw, reg) (((hw)->mac.type >= e1000_82543) \ ? reg : e1000_translate_register_82542(reg)) +#endif #define E1000_WRITE_FLUSH(a) E1000_READ_REG(a, E1000_STATUS) diff --git a/sys/dev/em/e1000_phy.c b/sys/dev/em/e1000_phy.c index af0f663a88d4..713ba3aa7702 100644 --- a/sys/dev/em/e1000_phy.c +++ b/sys/dev/em/e1000_phy.c @@ -614,7 +614,9 @@ s32 e1000_copper_link_setup_m88(struct e1000_hw *hw) if (ret_val) 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 * to 25MHz clock. @@ -2304,6 +2306,105 @@ out: 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 * @hw: pointer to the HW structure diff --git a/sys/dev/em/e1000_phy.h b/sys/dev/em/e1000_phy.h index 16d3d70b981a..4473730c7c56 100644 --- a/sys/dev/em/e1000_phy.h +++ b/sys/dev/em/e1000_phy.h @@ -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_access_phy_wakeup_reg_bm(struct e1000_hw *hw, u32 offset, u16 *data, 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_down_phy_copper(struct e1000_hw *hw); s32 e1000_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data); diff --git a/sys/dev/em/if_em.c b/sys/dev/em/if_em.c index 584b4be9e53d..506d2de7f386 100644 --- a/sys/dev/em/if_em.c +++ b/sys/dev/em/if_em.c @@ -50,6 +50,10 @@ #include #include #include +#ifdef EM_TIMESYNC +#include +#include +#endif #include #include @@ -76,6 +80,7 @@ #include #include "e1000_api.h" +#include "e1000_82571.h" /* For Hartwell */ #include "if_em.h" /********************************************************************* @@ -86,7 +91,7 @@ int em_display_debug_stats = 0; /********************************************************************* * 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_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_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 */ { 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_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 static void em_intr(void *); @@ -293,9 +306,10 @@ static void em_irq_fast(void *); #else static int em_irq_fast(void *); #endif -static int em_tx_fast(void *); -static int em_rx_fast(void *); -static int em_link_fast(void *); +/* MSIX handlers */ +static void em_msix_tx(void *); +static void em_msix_rx(void *); +static void em_msix_link(void *); static void em_add_rx_process_limit(struct adapter *, const char *, const char *, int *, int); 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_txd = EM_DEFAULT_TXD; 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.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.txd", &em_txd); 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 /* 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; EM_CORE_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_ADD_PROC(device_get_sysctl_ctx(dev), @@ -477,6 +498,7 @@ em_attach(device_t dev) ** identified */ if ((adapter->hw.mac.type == e1000_ich8lan) || + (adapter->hw.mac.type == e1000_ich10lan) || (adapter->hw.mac.type == e1000_ich9lan)) { int rid = EM_BAR_TYPE_FLASH; adapter->flash = bus_alloc_resource_any(dev, @@ -770,6 +792,7 @@ err_tx_desc: err_pci: em_free_pci_resources(adapter); EM_TX_LOCK_DESTROY(adapter); + EM_RX_LOCK_DESTROY(adapter); EM_CORE_LOCK_DESTROY(adapter); return (error); @@ -818,6 +841,7 @@ em_detach(device_t dev) if (((adapter->hw.mac.type == e1000_82573) || (adapter->hw.mac.type == e1000_ich8lan) || + (adapter->hw.mac.type == e1000_ich10lan) || (adapter->hw.mac.type == e1000_ich9lan)) && e1000_check_mng_mode(&adapter->hw)) em_release_hw_control(adapter); @@ -856,6 +880,7 @@ em_detach(device_t dev) } EM_TX_LOCK_DESTROY(adapter); + EM_RX_LOCK_DESTROY(adapter); EM_CORE_LOCK_DESTROY(adapter); return (0); @@ -891,6 +916,7 @@ em_suspend(device_t dev) if (((adapter->hw.mac.type == e1000_82573) || (adapter->hw.mac.type == e1000_ich8lan) || + (adapter->hw.mac.type == e1000_ich10lan) || (adapter->hw.mac.type == e1000_ich9lan)) && e1000_check_mng_mode(&adapter->hw)) em_release_hw_control(adapter); @@ -915,12 +941,8 @@ em_resume(device_t dev) EM_CORE_LOCK(adapter); em_init_locked(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_start(ifp); 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_82572: case e1000_ich9lan: + case e1000_ich10lan: + case e1000_82574: case e1000_80003es2lan: /* Limit Jumbo Frame size */ max_frame_size = 9234; 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_drv_flags & IFF_DRV_RUNNING)) { if ((ifp->if_flags ^ adapter->if_flags) & - IFF_PROMISC) { + (IFF_PROMISC | IFF_ALLMULTI)) { em_disable_promisc(adapter); em_set_promisc(adapter); } @@ -1180,6 +1204,69 @@ em_ioctl(struct ifnet *ifp, u_long command, caddr_t data) 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: 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 */ pba = E1000_PBA_12K; /* 12K for Rx, 20K for Tx */ break; + case e1000_82574: + pba = E1000_PBA_20K; /* 20K for Rx, 20K for Tx */ + break; case e1000_ich9lan: + case e1000_ich10lan: #define E1000_PBA_10K 0x000A pba = E1000_PBA_10K; break; @@ -1383,6 +1474,21 @@ em_init_locked(struct adapter *adapter) callout_reset(&adapter->timer, hz, em_local_timer, adapter); 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 /* @@ -1395,6 +1501,12 @@ em_init_locked(struct adapter *adapter) #endif /* DEVICE_POLLING */ 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 */ 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_rxeof(adapter, count); EM_CORE_UNLOCK(adapter); + em_rxeof(adapter, count); + EM_TX_LOCK(adapter); em_txeof(adapter); @@ -1462,17 +1575,14 @@ static void em_intr(void *arg) { struct adapter *adapter = arg; - struct ifnet *ifp; + struct ifnet *ifp = adapter->ifp; u32 reg_icr; - EM_CORE_LOCK(adapter); - ifp = adapter->ifp; - if (ifp->if_capenable & IFCAP_POLLING) { - EM_CORE_UNLOCK(adapter); + if (ifp->if_capenable & IFCAP_POLLING) return; - } + EM_CORE_LOCK(adapter); for (;;) { reg_icr = E1000_READ_REG(&adapter->hw, E1000_ICR); @@ -1491,12 +1601,14 @@ em_intr(void *arg) if (reg_icr == 0xffffffff) break; + EM_CORE_UNLOCK(adapter); if (ifp->if_drv_flags & IFF_DRV_RUNNING) { em_rxeof(adapter, -1); EM_TX_LOCK(adapter); em_txeof(adapter); EM_TX_UNLOCK(adapter); } + EM_CORE_LOCK(adapter); /* Link status change */ if (reg_icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) { @@ -1525,9 +1637,7 @@ static void em_handle_link(void *context, int pending) { struct adapter *adapter = context; - struct ifnet *ifp; - - ifp = adapter->ifp; + struct ifnet *ifp = adapter->ifp; if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) return; @@ -1564,19 +1674,16 @@ em_handle_rxtx(void *context, int pending) em_enable_intr(adapter); } -/* RX deferred handler: used with MSIX */ static void em_handle_rx(void *context, int pending) { struct adapter *adapter = context; struct ifnet *ifp = adapter->ifp; - ++adapter->rx_irq; if ((ifp->if_drv_flags & IFF_DRV_RUNNING) && (em_rxeof(adapter, adapter->rx_process_limit) != 0)) taskqueue_enqueue(adapter->tq, &adapter->rx_task); - em_enable_intr(adapter); } static void @@ -1585,17 +1692,13 @@ em_handle_tx(void *context, int pending) struct adapter *adapter = context; struct ifnet *ifp = adapter->ifp; - ++adapter->tx_irq; if (ifp->if_drv_flags & IFF_DRV_RUNNING) { EM_TX_LOCK(adapter); em_txeof(adapter); - if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) em_start_locked(ifp); 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 -em_tx_fast(void *arg) +static void +em_msix_tx(void *arg) { struct adapter *adapter = arg; - u32 reg_icr; + struct ifnet *ifp = adapter->ifp; - reg_icr = E1000_READ_REG(&adapter->hw, E1000_ICR); - /* - * Mask interrupts until the taskqueue is finished running. This is - * cheap, just assume that it is needed. This also works around the - * MSI message reordering errata on certain systems. - */ - em_disable_intr(adapter); - taskqueue_enqueue(adapter->tq, &adapter->tx_task); - - return FILTER_HANDLED; + ++adapter->tx_irq; + if (ifp->if_drv_flags & IFF_DRV_RUNNING) { + EM_TX_LOCK(adapter); + em_txeof(adapter); + EM_TX_UNLOCK(adapter); + taskqueue_enqueue(adapter->tq, &adapter->tx_task); + } + /* Reenable this interrupt */ + E1000_WRITE_REG(&adapter->hw, E1000_IMS, EM_MSIX_TX); + return; } /********************************************************************* * - * MSIX RX Fast Interrupt Service routine + * MSIX RX Interrupt Service routine * **********************************************************************/ -static int -em_rx_fast(void *arg) +static void +em_msix_rx(void *arg) { struct adapter *adapter = arg; - u32 reg_icr; + struct ifnet *ifp = adapter->ifp; - reg_icr = E1000_READ_REG(&adapter->hw, E1000_ICR); - /* - * Mask interrupts until the taskqueue is finished running. This is - * cheap, just assume that it is needed. This also works around the - * MSI message reordering errata on certain systems. - */ - em_disable_intr(adapter); - taskqueue_enqueue(adapter->tq, &adapter->rx_task); - if (reg_icr & E1000_ICR_RXO) - adapter->rx_overruns++; - - return FILTER_HANDLED; + ++adapter->rx_irq; + if ((ifp->if_drv_flags & IFF_DRV_RUNNING) && + (em_rxeof(adapter, adapter->rx_process_limit) != 0)) + taskqueue_enqueue(adapter->tq, &adapter->rx_task); + /* Reenable this interrupt */ + E1000_WRITE_REG(&adapter->hw, E1000_IMS, EM_MSIX_RX); + return; } /********************************************************************* @@ -1711,19 +1812,22 @@ em_rx_fast(void *arg) * **********************************************************************/ -static int -em_link_fast(void *arg) +static void +em_msix_link(void *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); - - E1000_WRITE_REG(&adapter->hw, E1000_IMS, E1000_IMS_LSC); - return FILTER_HANDLED; + } + E1000_WRITE_REG(&adapter->hw, E1000_IMS, + EM_MSIX_LINK | E1000_IMS_LSC); + return; } #endif /* EM_FAST_IRQ */ @@ -1988,12 +2092,14 @@ em_xmit(struct adapter *adapter, struct mbuf **m_headp) tso_desc = TRUE; } else #endif +#ifndef EM_TIMESYNC /* ** Timesync needs to check the packet header ** so call checksum code to do so, but don't ** penalize the code if not defined. */ if (m_head->m_pkthdr.csum_flags & CSUM_OFFLOAD) +#endif em_transmit_checksum_setup(adapter, m_head, &txd_upper, &txd_lower); @@ -2150,6 +2256,11 @@ em_xmit(struct adapter *adapter, struct mbuf **m_headp) 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); } @@ -2280,6 +2391,9 @@ em_set_promisc(struct adapter *adapter) if (ifp->if_flags & IFF_PROMISC) { 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); } else if (ifp->if_flags & IFF_ALLMULTI) { reg_rctl |= E1000_RCTL_MPE; @@ -2297,6 +2411,7 @@ em_disable_promisc(struct adapter *adapter) reg_rctl &= (~E1000_RCTL_UPE); reg_rctl &= (~E1000_RCTL_MPE); + reg_rctl &= (~E1000_RCTL_SBP); 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 */ 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); 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 */ - adapter->msi = em_setup_msix(adapter); + if (em_enable_msi) + adapter->msi = em_setup_msix(adapter); adapter->hw.back = &adapter->osdep; @@ -2725,7 +2847,7 @@ em_allocate_msix(struct adapter *adapter) /* First slot to RX */ 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) { device_printf(dev, "Failed to register RX handler"); return (error); @@ -2733,7 +2855,7 @@ em_allocate_msix(struct adapter *adapter) /* Next TX */ 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) { device_printf(dev, "Failed to register TX handler"); return (error); @@ -2741,7 +2863,7 @@ em_allocate_msix(struct adapter *adapter) /* And Link */ 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) { device_printf(dev, "Failed to register TX handler"); return (error); @@ -2809,6 +2931,30 @@ em_setup_msix(struct adapter *adapter) if (adapter->hw.mac.type < e1000_82571) 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); if (val == 1 && pci_alloc_msi(dev, &val) == 0) { adapter->msi = 1; @@ -2838,6 +2984,7 @@ em_hardware_init(struct adapter *adapter) /* Get control from any management/hw control */ if (((adapter->hw.mac.type == e1000_82573) || (adapter->hw.mac.type == e1000_ich8lan) || + (adapter->hw.mac.type == e1000_ich10lan) || (adapter->hw.mac.type == e1000_ich9lan)) && e1000_check_mng_mode(&adapter->hw)) em_get_hw_control(adapter); @@ -3463,6 +3610,11 @@ em_transmit_checksum_setup(struct adapter *adapter, struct mbuf *mp, ipproto = ip6->ip6_nxt; break; +#ifdef EM_TIMESYNC + case ETHERTYPE_IEEE1588: + *txd_upper |= E1000_TXD_EXTCMD_TSTAMP; + break; +#endif default: *txd_upper = 0; *txd_lower = 0; @@ -3488,6 +3640,15 @@ em_transmit_checksum_setup(struct adapter *adapter, struct mbuf *mp, break; 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) { /* * Start offset for header checksum calculation. @@ -3506,6 +3667,15 @@ em_transmit_checksum_setup(struct adapter *adapter, struct mbuf *mp, 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 */ E1000_TXD_DTYP_D; /* Data descr */ TXD->tcp_seg_setup.data = htole32(0); @@ -3968,6 +4138,9 @@ em_setup_receive_structures(struct adapter *adapter) * Enable receive unit. * **********************************************************************/ +#define MAX_INTS_PER_SEC 8000 +#define DEFAULT_ITR 1000000000/(MAX_INTS_PER_SEC * 256) + static void 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); 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, adapter->rx_abs_int_delay.value); /* * Set the interrupt throttling rate. Value is calculated * 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); } + /* + ** 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 */ bus_addr = adapter->rxdma.dma_paddr; E1000_WRITE_REG(&adapter->hw, E1000_RDLEN(0), @@ -4138,21 +4323,23 @@ em_free_receive_structures(struct adapter *adapter) static int em_rxeof(struct adapter *adapter, int count) { - struct ifnet *ifp; + struct ifnet *ifp = adapter->ifp;; struct mbuf *mp; u8 status, accept_frame = 0, eop = 0; u16 len, desc_len, prev_len_adj; int i; struct e1000_rx_desc *current_desc; - ifp = adapter->ifp; + EM_RX_LOCK(adapter); i = adapter->next_rx_desc_to_check; current_desc = &adapter->rx_desc_base[i]; bus_dmamap_sync(adapter->rxdma.dma_tag, adapter->rxdma.dma_map, 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); + } while ((current_desc->status & E1000_RXD_STAT_DD) && (count != 0) && @@ -4295,14 +4482,10 @@ discard: i = 0; if (m != NULL) { adapter->next_rx_desc_to_check = i; -#ifdef EM_LEGACY_IRQ - EM_CORE_UNLOCK(adapter); + /* Unlock for call into stack */ + EM_RX_UNLOCK(adapter); (*ifp->if_input)(ifp, m); - EM_CORE_LOCK(adapter); -#else - /* Already running unlocked */ - (*ifp->if_input)(ifp, m); -#endif + EM_RX_LOCK(adapter); i = adapter->next_rx_desc_to_check; } current_desc = &adapter->rx_desc_base[i]; @@ -4313,6 +4496,7 @@ discard: if (--i < 0) i = adapter->num_rx_desc - 1; E1000_WRITE_REG(&adapter->hw, E1000_RDT(0), i); + EM_RX_UNLOCK(adapter); if (!((current_desc->status) & E1000_RXD_STAT_DD)) return (0); @@ -4422,28 +4606,26 @@ em_enable_hw_vlans(struct adapter *adapter) E1000_WRITE_REG(&adapter->hw, E1000_CTRL, ctrl); } -#define QUEUE_MASK 0x01500000 - static void em_enable_intr(struct adapter *adapter) { + struct e1000_hw *hw = &adapter->hw; u32 ims_mask = IMS_ENABLE_MASK; if (adapter->msix) { - E1000_WRITE_REG(&adapter->hw, E1000_EIMS, QUEUE_MASK); - E1000_WRITE_REG(&adapter->hw, E1000_EIAC, QUEUE_MASK); - ims_mask |= QUEUE_MASK; + E1000_WRITE_REG(hw, EM_EIAC, EM_MSIX_MASK); + ims_mask |= EM_MSIX_MASK; } - E1000_WRITE_REG(&adapter->hw, E1000_IMS, ims_mask); + E1000_WRITE_REG(hw, E1000_IMS, ims_mask); } static void em_disable_intr(struct adapter *adapter) { - if (adapter->msix) { - E1000_WRITE_REG(&adapter->hw, E1000_EIMC, ~0); - E1000_WRITE_REG(&adapter->hw, E1000_EIAC, 0); - } + struct e1000_hw *hw = &adapter->hw; + + if (adapter->msix) + E1000_WRITE_REG(hw, EM_EIAC, 0); E1000_WRITE_REG(&adapter->hw, E1000_IMC, 0xffffffff); } @@ -4522,6 +4704,7 @@ em_get_hw_control(struct adapter *adapter) case e1000_80003es2lan: case e1000_ich8lan: case e1000_ich9lan: + case e1000_ich10lan: ctrl_ext = E1000_READ_REG(&adapter->hw, E1000_CTRL_EXT); E1000_WRITE_REG(&adapter->hw, E1000_CTRL_EXT, ctrl_ext | E1000_CTRL_EXT_DRV_LOAD); @@ -4555,6 +4738,7 @@ em_release_hw_control(struct adapter *adapter) case e1000_80003es2lan: case e1000_ich8lan: case e1000_ich9lan: + case e1000_ich10lan: ctrl_ext = E1000_READ_REG(&adapter->hw, E1000_CTRL_EXT); E1000_WRITE_REG(&adapter->hw, E1000_CTRL_EXT, 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, "watchdog timeouts = %ld\n", adapter->watchdog_events); - device_printf(dev, "TX Interrupts = %ld ", adapter->tx_irq); - device_printf(dev, "RX Interrupts = %ld\n", adapter->rx_irq); + device_printf(dev, "RX MSIX IRQ = %ld TX MSIX IRQ = %ld" + " LINK MSIX IRQ = %ld\n", adapter->rx_irq, + adapter->tx_irq , adapter->link_irq); device_printf(dev, "XON Rcvd = %lld\n", (long long)adapter->stats.xonrxc); device_printf(dev, "XON Xmtd = %lld\n", @@ -5009,3 +5194,100 @@ em_add_rx_process_limit(struct adapter *adapter, const char *name, } #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 */ diff --git a/sys/dev/em/if_em.h b/sys/dev/em/if_em.h index 9a3b0b4bd872..8fa2a43887e3 100644 --- a/sys/dev/em/if_em.h +++ b/sys/dev/em/if_em.h @@ -1,36 +1,37 @@ -/************************************************************************** +/****************************************************************************** -Copyright (c) 2001-2008, Intel Corporation -All rights reserved. + Copyright (c) 2001-2008, Intel Corporation + 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_ #define _EM_H_DEFINED_ @@ -232,10 +233,19 @@ POSSIBILITY OF SUCH DAMAGE. #define EM_MAX_SCATTER 64 #define EM_TSO_SIZE (65535 + sizeof(struct ether_vlan_header)) #define EM_TSO_SEG_SIZE 4096 /* Max dma segment size */ +#define EM_MSIX_MASK 0x01F00000 /* For 82574 use */ #define ETH_ZLEN 60 #define ETH_ADDR_LEN 6 #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 */ #define EM_PBA_BYTES_SHIFT 0xA #define EM_TX_HEAD_ADDR_SHIFT 7 @@ -243,6 +253,29 @@ POSSIBILITY OF SUCH DAMAGE. #define EM_FIFO_HDR 0x10 #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; @@ -296,6 +329,7 @@ struct adapter { int min_frame_size; struct mtx core_mtx; struct mtx tx_mtx; + struct mtx rx_mtx; int em_insert_vlan_header; /* Task for FAST handling */ @@ -376,6 +410,7 @@ struct adapter { unsigned long rx_overruns; unsigned long rx_irq; unsigned long tx_irq; + unsigned long link_irq; /* 82547 workaround */ uint32_t tx_fifo_size; @@ -389,6 +424,11 @@ struct adapter { boolean_t pcix_82544; boolean_t in_detach; +#ifdef EM_TIMESYNC + u64 last_stamp; + u64 last_sec; + u32 last_ns; +#endif struct e1000_hw_stats stats; }; @@ -432,12 +472,17 @@ typedef struct _DESCRIPTOR_PAIR mtx_init(&(_sc)->core_mtx, _name, "EM Core Lock", MTX_DEF) #define EM_TX_LOCK_INIT(_sc, _name) \ 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_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_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_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_TX_LOCK_ASSERT(_sc) mtx_assert(&(_sc)->tx_mtx, MA_OWNED) diff --git a/sys/dev/igb/e1000_82575.c b/sys/dev/igb/e1000_82575.c index eb99282351c4..9b6a28be6030 100644 --- a/sys/dev/igb/e1000_82575.c +++ b/sys/dev/igb/e1000_82575.c @@ -37,7 +37,6 @@ */ #include "e1000_api.h" -#include "e1000_82575.h" static s32 e1000_init_phy_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"); /* - * 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. */ @@ -1303,25 +1302,25 @@ static s32 e1000_reset_init_script_82575(struct e1000_hw* hw) if (hw->mac.type == e1000_82575) { DEBUGOUT("Running reset init script for 82575\n"); /* SerDes configuration via SERDESCTRL */ - e1000_write_8bit_ctrl_reg(hw, E1000_SCTL, 0x00, 0x0C); - e1000_write_8bit_ctrl_reg(hw, E1000_SCTL, 0x01, 0x78); - e1000_write_8bit_ctrl_reg(hw, E1000_SCTL, 0x1B, 0x23); - e1000_write_8bit_ctrl_reg(hw, E1000_SCTL, 0x23, 0x15); + e1000_write_8bit_ctrl_reg_generic(hw, E1000_SCTL, 0x00, 0x0C); + e1000_write_8bit_ctrl_reg_generic(hw, E1000_SCTL, 0x01, 0x78); + e1000_write_8bit_ctrl_reg_generic(hw, E1000_SCTL, 0x1B, 0x23); + e1000_write_8bit_ctrl_reg_generic(hw, E1000_SCTL, 0x23, 0x15); /* CCM configuration via CCMCTL register */ - e1000_write_8bit_ctrl_reg(hw, E1000_CCMCTL, 0x14, 0x00); - e1000_write_8bit_ctrl_reg(hw, E1000_CCMCTL, 0x10, 0x00); + e1000_write_8bit_ctrl_reg_generic(hw, E1000_CCMCTL, 0x14, 0x00); + e1000_write_8bit_ctrl_reg_generic(hw, E1000_CCMCTL, 0x10, 0x00); /* PCIe lanes configuration */ - e1000_write_8bit_ctrl_reg(hw, E1000_GIOCTL, 0x00, 0xEC); - e1000_write_8bit_ctrl_reg(hw, E1000_GIOCTL, 0x61, 0xDF); - e1000_write_8bit_ctrl_reg(hw, E1000_GIOCTL, 0x34, 0x05); - e1000_write_8bit_ctrl_reg(hw, E1000_GIOCTL, 0x2F, 0x81); + e1000_write_8bit_ctrl_reg_generic(hw, E1000_GIOCTL, 0x00, 0xEC); + e1000_write_8bit_ctrl_reg_generic(hw, E1000_GIOCTL, 0x61, 0xDF); + e1000_write_8bit_ctrl_reg_generic(hw, E1000_GIOCTL, 0x34, 0x05); + e1000_write_8bit_ctrl_reg_generic(hw, E1000_GIOCTL, 0x2F, 0x81); /* PCIe PLL Configuration */ - e1000_write_8bit_ctrl_reg(hw, E1000_SCCTL, 0x02, 0x47); - e1000_write_8bit_ctrl_reg(hw, E1000_SCCTL, 0x14, 0x00); - e1000_write_8bit_ctrl_reg(hw, E1000_SCCTL, 0x10, 0x00); + e1000_write_8bit_ctrl_reg_generic(hw, E1000_SCCTL, 0x02, 0x47); + e1000_write_8bit_ctrl_reg_generic(hw, E1000_SCCTL, 0x14, 0x00); + e1000_write_8bit_ctrl_reg_generic(hw, E1000_SCCTL, 0x10, 0x00); } return E1000_SUCCESS; diff --git a/sys/dev/igb/e1000_api.c b/sys/dev/igb/e1000_api.c index 2438b3f826d7..b8298f8c14d2 100644 --- a/sys/dev/igb/e1000_api.c +++ b/sys/dev/igb/e1000_api.c @@ -33,9 +33,6 @@ /*$FreeBSD$*/ #include "e1000_api.h" -#include "e1000_mac.h" -#include "e1000_nvm.h" -#include "e1000_phy.h" /** * 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) { 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 * * 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 * is used during Dx states where the power conservation is most important. * 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 * * 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 * is used during Dx states where the power conservation is most important. * During driver activity, SmartSpeed should be enabled so performance is diff --git a/sys/dev/igb/e1000_api.h b/sys/dev/igb/e1000_api.h index 93e49f0f8bfc..728588ac2f95 100644 --- a/sys/dev/igb/e1000_api.h +++ b/sys/dev/igb/e1000_api.h @@ -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_d0_lplu_state(struct e1000_hw *hw, bool active); 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); s32 e1000_mng_enable_host_if(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, u8 *buffer, u16 length); - /* * TBI_ACCEPT macro definition: * diff --git a/sys/dev/igb/e1000_defines.h b/sys/dev/igb/e1000_defines.h index 7fd69234332b..6f23fc370913 100644 --- a/sys/dev/igb/e1000_defines.h +++ b/sys/dev/igb/e1000_defines.h @@ -384,6 +384,7 @@ #define E1000_CTRL_PHY_RESET4 E1000_CTRL_EXT_SDP4_DATA #define E1000_CONNSW_ENRGSRC 0x4 +#define E1000_PCS_CFG_PCS_EN 8 #define E1000_PCS_LCTL_FLV_LINK_UP 1 #define E1000_PCS_LCTL_FSV_10 0 #define E1000_PCS_LCTL_FSV_100 2 diff --git a/sys/dev/igb/e1000_hw.h b/sys/dev/igb/e1000_hw.h index f3b339b245a7..9b46b371c556 100644 --- a/sys/dev/igb/e1000_hw.h +++ b/sys/dev/igb/e1000_hw.h @@ -57,7 +57,7 @@ struct e1000_hw; typedef enum { e1000_undefined = 0, 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; typedef enum { @@ -615,9 +615,9 @@ struct e1000_hw { u8 revision_id; }; +#include "e1000_82575.h" + /* 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_read_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value); void e1000_free_dev_spec_struct(struct e1000_hw *hw); diff --git a/sys/dev/igb/e1000_mac.c b/sys/dev/igb/e1000_mac.c index fa50d81125af..df56ddcca988 100644 --- a/sys/dev/igb/e1000_mac.c +++ b/sys/dev/igb/e1000_mac.c @@ -33,7 +33,6 @@ /*$FreeBSD$*/ #include "e1000_api.h" -#include "e1000_mac.h" /** * 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. */ 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); hw->mac.ops.mta_set(hw, hash_value); mc_addr_list += ETH_ADDR_LEN; diff --git a/sys/dev/igb/e1000_manage.h b/sys/dev/igb/e1000_manage.h index 97b5188af8e2..32aee301b400 100644 --- a/sys/dev/igb/e1000_manage.h +++ b/sys/dev/igb/e1000_manage.h @@ -44,6 +44,7 @@ s32 e1000_mng_write_cmd_header_generic(struct e1000_hw *hw, struct e1000_host_mng_command_header *hdr); s32 e1000_mng_write_dhcp_info_generic(struct e1000_hw *hw, u8 *buffer, u16 length); +bool e1000_enable_mng_pass_thru(struct e1000_hw *hw); typedef enum { e1000_mng_mode_none = 0, diff --git a/sys/dev/igb/e1000_osdep.c b/sys/dev/igb/e1000_osdep.c index 60be8674e1a3..daa6781a6afc 100644 --- a/sys/dev/igb/e1000_osdep.c +++ b/sys/dev/igb/e1000_osdep.c @@ -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); } -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 */ diff --git a/sys/dev/igb/e1000_osdep.h b/sys/dev/igb/e1000_osdep.h index 0d3d9a8c0c0c..432863e051aa 100644 --- a/sys/dev/igb/e1000_osdep.h +++ b/sys/dev/igb/e1000_osdep.h @@ -71,11 +71,13 @@ #define DEBUGOUT3(S,A,B,C) #define DEBUGOUT7(S,A,B,C,D,E,F,G) -#define STATIC static -#define FALSE 0 -#define TRUE 1 -#define CMD_MEM_WRT_INVALIDATE 0x0010 /* BIT_4 */ -#define PCI_COMMAND_REGISTER PCIR_COMMAND +#define STATIC static +#define FALSE 0 +#define false FALSE /* shared code stupidity */ +#define TRUE 1 +#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 diff --git a/sys/dev/igb/e1000_phy.c b/sys/dev/igb/e1000_phy.c index d55a4e4df433..c0b33de90e51 100644 --- a/sys/dev/igb/e1000_phy.c +++ b/sys/dev/igb/e1000_phy.c @@ -33,7 +33,6 @@ /*$FreeBSD$*/ #include "e1000_api.h" -#include "e1000_phy.h" /* Cable length tables */ static const u16 e1000_m88_cable_length_table[] = @@ -670,7 +669,7 @@ s32 e1000_copper_link_setup_igp(struct e1000_hw *hw) goto out; } - ret_val = e1000_phy_hw_reset(hw); + ret_val = hw->phy.ops.reset(hw); if (ret_val) { DEBUGOUT("Error resetting the PHY.\n"); goto out; @@ -688,7 +687,7 @@ s32 e1000_copper_link_setup_igp(struct e1000_hw *hw) */ if (phy->type == e1000_phy_igp) { /* 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) { DEBUGOUT("Error Disabling LPLU D3\n"); goto out; @@ -696,7 +695,7 @@ s32 e1000_copper_link_setup_igp(struct e1000_hw *hw) } /* 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) { DEBUGOUT("Error Disabling LPLU D0\n"); goto out; @@ -846,7 +845,7 @@ s32 e1000_copper_link_autoneg(struct e1000_hw *hw) * check at a later time (for example, callback routine). */ if (phy->autoneg_wait_to_complete) { - ret_val = e1000_wait_autoneg(hw); + ret_val = hw->mac.ops.wait_autoneg(hw); if (ret_val) { DEBUGOUT("Error while waiting for " "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 * * 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 * is used during Dx states where the power conservation is most important. * 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; 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) goto out; @@ -1866,7 +1865,7 @@ s32 e1000_get_phy_info_igp(struct e1000_hw *hw) if ((data & IGP01E1000_PSSR_SPEED_MASK) == IGP01E1000_PSSR_SPEED_1000MBPS) { - ret_val = e1000_get_cable_length(hw); + ret_val = hw->phy.ops.get_cable_length(hw); if (ret_val) goto out; diff --git a/sys/dev/igb/if_igb.c b/sys/dev/igb/if_igb.c index 2d32255e6315..946e43cd4865 100644 --- a/sys/dev/igb/if_igb.c +++ b/sys/dev/igb/if_igb.c @@ -88,7 +88,7 @@ int igb_display_debug_stats = 0; /********************************************************************* * 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.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_rx_queues = 1; TUNABLE_INT("hw.igb.tx_queues", &igb_tx_queues); TUNABLE_INT("hw.igb.rx_queues", &igb_rx_queues); +extern int mp_ncpus; + /* How many packets rxeof tries to clean at a time */ static int igb_rx_process_limit = 100; TUNABLE_INT("hw.igb.rx_process_limit", &igb_rx_process_limit); @@ -605,11 +610,11 @@ igb_detach(device_t dev) callout_drain(&adapter->timer); + e1000_remove_device(&adapter->hw); igb_free_pci_resources(adapter); bus_generic_detach(dev); if_free(ifp); - e1000_remove_device(&adapter->hw); igb_free_transmit_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_drv_flags & IFF_DRV_RUNNING)) { if ((ifp->if_flags ^ adapter->if_flags) & - IFF_PROMISC) { + (IFF_PROMISC | IFF_ALLMULTI)) { igb_disable_promisc(adapter); igb_set_promisc(adapter); } @@ -1090,8 +1095,10 @@ igb_init_locked(struct adapter *adapter) else #endif /* DEVICE_POLLING */ { + /* this clears any pending interrupts */ E1000_READ_REG(&adapter->hw, E1000_ICR); 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 */ 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(adapter->tq, &adapter->link_task); } if (reg_icr & E1000_ICR_RXO) @@ -1341,11 +1348,12 @@ igb_msix_link(void *arg) if (!(icr & E1000_ICR_LSC)) goto spurious; adapter->hw.mac.get_link_status = 1; - taskqueue_enqueue(taskqueue_fast, &adapter->link_task); + taskqueue_enqueue(adapter->tq, &adapter->link_task); spurious: + /* Rearm */ 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; } @@ -2094,7 +2102,7 @@ igb_configure_queues(struct adapter *adapter) E1000_WRITE_REG(hw, E1000_CTRL_EXT, tmp); /* 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_EITR(i), DEFAULT_ITR); @@ -2117,7 +2125,8 @@ igb_configure_queues(struct adapter *adapter) /* Link */ E1000_WRITE_REG(hw, E1000_MSIXBM(adapter->linkvec), E1000_EIMS_OTHER); - adapter->eims_mask |= E1000_EIMS_OTHER; + adapter->link_mask |= E1000_EIMS_OTHER; + adapter->eims_mask |= adapter->link_mask; } return; } @@ -2191,6 +2200,10 @@ igb_setup_msix(struct adapter *adapter) 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 */ queues = (mp_ncpus > ((msgs-1)/2)) ? (msgs-1)/2 : mp_ncpus; @@ -2204,7 +2217,7 @@ igb_setup_msix(struct adapter *adapter) else { device_printf(adapter->dev, "MSIX Configuration Problem, " - "%d vectors but %d queues wanted!\n", + "%d vectors configured, but %d queues wanted!\n", msgs, want); 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); if (ip->ip_p != IPPROTO_TCP) return FALSE; /* 0 */ - ip->ip_len = 0; ip->ip_sum = 0; ip_hlen = ip->ip_hl << 2; th = (struct tcphdr *)((caddr_t)ip + ip_hlen); @@ -3813,7 +3825,7 @@ igb_fixup_rx(struct rx_ring *rxr) rxr->fmp = n; } else { adapter->dropped_pkts++; - m_freem(rxr->fmp); + m_freem(adapter->fmp); rxr->fmp = NULL; error = ENOMEM; } @@ -3885,6 +3897,8 @@ igb_enable_intr(struct adapter *adapter) if (adapter->msix_mem) { E1000_WRITE_REG(&adapter->hw, E1000_EIAC, adapter->eims_mask); + E1000_WRITE_REG(&adapter->hw, E1000_EIAM, + adapter->eims_mask); E1000_WRITE_REG(&adapter->hw, E1000_EIMS, adapter->eims_mask); 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_EIAC, 0); } - E1000_WRITE_REG(&adapter->hw, E1000_IMC, ~0); + E1000_WRITE_REG(&adapter->hw, E1000_IMC, ~0); E1000_WRITE_FLUSH(&adapter->hw); return; } @@ -4143,9 +4157,18 @@ igb_print_debug_info(struct adapter *adapter) device_printf(dev, "CTRL = 0x%x RCTL = 0x%x \n", E1000_READ_REG(&adapter->hw, E1000_CTRL), 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", E1000_READ_REG(&adapter->hw, E1000_IMS), 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", ((E1000_READ_REG(&adapter->hw, E1000_PBA) & 0xffff0000) >> 16),\ (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, E1000_READ_REG(&adapter->hw, E1000_TDH(i)), E1000_READ_REG(&adapter->hw, E1000_TDT(i))); - device_printf(dev, "no descriptors avail event = %lld\n", - (long long)txr->no_desc_avail); - device_printf(dev, "TX(%d) MSIX IRQ Handled = %lld\n", txr->me, - (long long)txr->tx_irq); - device_printf(dev, "TX(%d) Packets sent = %lld\n", txr->me, - (long long)txr->tx_packets); + device_printf(dev, "no descriptors avail event = %lu\n", + txr->no_desc_avail); + device_printf(dev, "TX(%d) MSIX IRQ Handled = %lu\n", txr->me, + txr->tx_irq); + device_printf(dev, "TX(%d) Packets sent = %lu\n", txr->me, + txr->tx_packets); } for (int i = 0; i < adapter->num_rx_queues; i++, rxr++) { 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_RDT(i))); - device_printf(dev, "RX(%d) Packets received = %lld\n", rxr->me, - (long long)rxr->rx_packets); - device_printf(dev, "RX(%d) Byte count = %lld\n", rxr->me, - (long long)rxr->rx_bytes); - device_printf(dev, "RX(%d) MSIX IRQ Handled = %lld\n", rxr->me, - (long long)rxr->rx_irq); + device_printf(dev, "RX(%d) Packets received = %lu\n", rxr->me, + rxr->rx_packets); + device_printf(dev, "RX(%d) Byte count = %lu\n", rxr->me, + rxr->rx_bytes); + device_printf(dev, "RX(%d) MSIX IRQ Handled = %lu\n", rxr->me, + rxr->rx_irq); } device_printf(dev, "LINK MSIX IRQ Handled = %u\n", adapter->link_irq); diff --git a/sys/dev/igb/if_igb.h b/sys/dev/igb/if_igb.h index 134eff145b4e..03699dcfb1a9 100644 --- a/sys/dev/igb/if_igb.h +++ b/sys/dev/igb/if_igb.h @@ -203,7 +203,14 @@ /* PCI Config defines */ #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 */ #define DEBUG_INIT 0 @@ -318,6 +325,7 @@ struct adapter { u32 eims_mask; int linkvec; + int link_mask; int link_irq; struct ifmedia media; diff --git a/sys/modules/em/Makefile b/sys/modules/em/Makefile index 6fe050bff709..8a2dbdd4587f 100644 --- a/sys/modules/em/Makefile +++ b/sys/modules/em/Makefile @@ -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_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 clean: