From: Sepherosa Ziehau Date: Sat, 19 Dec 2015 01:50:30 +0000 (+0800) Subject: ig_hal/igb: Merge Intel igb-2.4.3 X-Git-Tag: v4.6.0rc~1151 X-Git-Url: https://gitweb.dragonflybsd.org/~tuxillo/dragonfly.git/commitdiff_plain/ba0123e048ee8fc054e24e0c0cef5568095e6e6e ig_hal/igb: Merge Intel igb-2.4.3 - Add one more device - Fix settings for i354 Tested-by: dillon@ (I354, I217[emx]) me (I350, 82580, 82576, 82575) --- diff --git a/share/man/man4/igb.4 b/share/man/man4/igb.4 index 252d5de2cf..d8f4824870 100644 --- a/share/man/man4/igb.4 +++ b/share/man/man4/igb.4 @@ -31,7 +31,7 @@ .\" .\" $FreeBSD: src/share/man/man4/igb.4,v 1.2 2010/05/14 20:11:30 marius Exp $ .\" -.Dd November 26, 2015 +.Dd December 19, 2015 .Dt IGB 4 .Os .Sh NAME @@ -235,43 +235,55 @@ controller chips: .Pp .Bl -bullet -compact .It -Intel 82575EB Gigabit Ethernet Controller +Intel 82576EB Gigabit Ethernet Controller .It -Intel 82576 Gigabit Ethernet Controller +Intel 82576NS Gigabit Ethernet Controller .It Intel 82580EB Gigabit Ethernet Controller .It -Intel Ethernet Controller I210 Series +Intel Ethernet Server Adapter I340-F4 .It -Intel Ethernet Controller I211 Series +Intel Ethernet Server Adapter I340-T4 .It -Intel Ethernet Controller I350 +Intel Gigabit ET2 Quad Port Server Adapter .It -Intel Ethernet Controller I354 +Intel Gigabit VT Quad Port Server Adapter .It -Intel Ethernet Server Adapter I210-T1 +Intel 82575EB Gigabit Ethernet Controller .It -Intel Ethernet Server Adapter I340-F4 +Intel Gigabit EF Dual Port Server Adapter .It -Intel Ethernet Server Adapter I340-T4 +Intel Gigabit ET Dual Port Server Adapter .It -Intel Ethernet Server Adapter I350-F2 +Intel Gigabit ET Quad Port Server Adapter .It -Intel Ethernet Server Adapter I350-F4 +Intel Ethernet Controller I350-AM4 +.It +Intel Ethernet Controller I350-BT2 +.It +Intel Ethernet Controller I350-AM2 .It Intel Ethernet Server Adapter I350-T2 .It Intel Ethernet Server Adapter I350-T4 .It -Intel Gigabit EF Dual Port Server Adapter +Intel Ethernet Server Adapter I350-F2 .It -Intel Gigabit ET Dual Port Server Adapter +Intel Ethernet Server Adapter I350-F4 .It -Intel Gigabit ET Quad Port Server Adapter +Intel Ethernet Controller I210-AT .It -Intel Gigabit ET2 Quad Port Server Adapter +Intel Ethernet Controller I210-IS .It -Intel Gigabit VT Quad Port Server Adapter +Intel Ethernet Controller I210-IT +.It +Intel Ethernet Controller I211-AT +.It +Intel Ethernet Server Adapter I210-T1 +.It +Intel Ethernet Controller I210-AS +.It +Intel Ethernet Controller I210-CS .El .Sh TUNABLES Tunables can be set at the diff --git a/sys/dev/netif/ig_hal/e1000_82575.c b/sys/dev/netif/ig_hal/e1000_82575.c index 2cb2bddb0e..c0473847f2 100644 --- a/sys/dev/netif/ig_hal/e1000_82575.c +++ b/sys/dev/netif/ig_hal/e1000_82575.c @@ -1,6 +1,6 @@ /****************************************************************************** - Copyright (c) 2001-2011, Intel Corporation + Copyright (c) 2001-2013, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without @@ -56,7 +56,6 @@ static s32 e1000_check_for_link_media_swap(struct e1000_hw *hw); static s32 e1000_get_cfg_done_82575(struct e1000_hw *hw); static s32 e1000_get_link_up_info_82575(struct e1000_hw *hw, u16 *speed, u16 *duplex); -static s32 e1000_init_hw_82575(struct e1000_hw *hw); static s32 e1000_phy_hw_reset_sgmii_82575(struct e1000_hw *hw); static s32 e1000_read_phy_reg_sgmii_82575(struct e1000_hw *hw, u32 offset, u16 *data); @@ -120,7 +119,8 @@ static bool e1000_get_i2c_data(u32 *i2cctl); static const u16 e1000_82580_rxpbs_table[] = { 36, 72, 144, 1, 2, 4, 8, 16, 35, 70, 140 }; #define E1000_82580_RXPBS_TABLE_SIZE \ - (sizeof(e1000_82580_rxpbs_table)/sizeof(u16)) + (sizeof(e1000_82580_rxpbs_table) / \ + sizeof(e1000_82580_rxpbs_table[0])) /** @@ -229,7 +229,8 @@ static s32 e1000_init_phy_params_82575(struct e1000_hw *hw) /* Verify phy id and set remaining function pointers */ switch (phy->id) { - case M88E1545_E_PHY_ID: + case M88E1543_E_PHY_ID: + case M88E1512_E_PHY_ID: case I347AT4_E_PHY_ID: case M88E1112_E_PHY_ID: case M88E1340M_E_PHY_ID: @@ -242,7 +243,8 @@ static s32 e1000_init_phy_params_82575(struct e1000_hw *hw) phy->id == M88E1340M_E_PHY_ID) phy->ops.get_cable_length = e1000_get_cable_length_m88_gen2; - else if (phy->id == M88E1545_E_PHY_ID) + else if (phy->id == M88E1543_E_PHY_ID || + phy->id == M88E1512_E_PHY_ID) phy->ops.get_cable_length = e1000_get_cable_length_m88_gen2; else @@ -264,11 +266,18 @@ static s32 e1000_init_phy_params_82575(struct e1000_hw *hw) if (ret_val) goto out; - if (data == E1000_M88E1112_AUTO_A || - data == E1000_M88E1112_AUTO_B) + data = (data & E1000_M88E1112_MAC_CTRL_1_MODE_MASK) >> + E1000_M88E1112_MAC_CTRL_1_MODE_SHIFT; + if (data == E1000_M88E1112_AUTO_COPPER_SGMII || + data == E1000_M88E1112_AUTO_COPPER_BASEX) hw->mac.ops.check_for_link = e1000_check_for_link_media_swap; } + if (phy->id == M88E1512_E_PHY_ID) { + ret_val = e1000_initialize_M88E1512_phy(hw); + if (ret_val) + goto out; + } break; case IGP03E1000_E_PHY_ID: case IGP04E1000_E_PHY_ID: @@ -446,6 +455,9 @@ static s32 e1000_init_mac_params_82575(struct e1000_hw *hw) else mac->ops.reset_hw = e1000_reset_hw_82575; /* hw initialization */ + if ((mac->type == e1000_i210) || (mac->type == e1000_i211)) + mac->ops.init_hw = e1000_init_hw_i210; + else mac->ops.init_hw = e1000_init_hw_82575; /* link setup */ mac->ops.setup_link = e1000_setup_link_generic; @@ -651,6 +663,10 @@ static s32 e1000_get_phy_id_82575(struct e1000_hw *hw) DEBUGFUNC("e1000_get_phy_id_82575"); + /* some i354 devices need an extra read for phy id */ + if (hw->mac.type == e1000_i354) + e1000_get_phy_id(hw); + /* * For SGMII PHYs, we try the list of possible addresses until * we find one that works. For non-SGMII PHYs @@ -742,6 +758,7 @@ out: static s32 e1000_phy_hw_reset_sgmii_82575(struct e1000_hw *hw) { s32 ret_val = E1000_SUCCESS; + struct e1000_phy_info *phy = &hw->phy; DEBUGFUNC("e1000_phy_hw_reset_sgmii_82575"); @@ -764,7 +781,11 @@ static s32 e1000_phy_hw_reset_sgmii_82575(struct e1000_hw *hw) goto out; ret_val = hw->phy.ops.commit(hw); + if (ret_val) + goto out; + if (phy->id == M88E1512_E_PHY_ID) + ret_val = e1000_initialize_M88E1512_phy(hw); out: return ret_val; } @@ -871,7 +892,6 @@ out: static s32 e1000_set_d0_lplu_state_82580(struct e1000_hw *hw, bool active) { struct e1000_phy_info *phy = &hw->phy; - s32 ret_val = E1000_SUCCESS; u32 data; DEBUGFUNC("e1000_set_d0_lplu_state_82580"); @@ -899,7 +919,7 @@ static s32 e1000_set_d0_lplu_state_82580(struct e1000_hw *hw, bool active) } E1000_WRITE_REG(hw, E1000_82580_PHY_POWER_MGMT, data); - return ret_val; + return E1000_SUCCESS; } /** @@ -919,7 +939,6 @@ static s32 e1000_set_d0_lplu_state_82580(struct e1000_hw *hw, bool active) s32 e1000_set_d3_lplu_state_82580(struct e1000_hw *hw, bool active) { struct e1000_phy_info *phy = &hw->phy; - s32 ret_val = E1000_SUCCESS; u32 data; DEBUGFUNC("e1000_set_d3_lplu_state_82580"); @@ -947,7 +966,7 @@ s32 e1000_set_d3_lplu_state_82580(struct e1000_hw *hw, bool active) } E1000_WRITE_REG(hw, E1000_82580_PHY_POWER_MGMT, data); - return ret_val; + return E1000_SUCCESS; } /** @@ -961,7 +980,7 @@ s32 e1000_set_d3_lplu_state_82580(struct e1000_hw *hw, bool active) **/ static s32 e1000_acquire_nvm_82575(struct e1000_hw *hw) { - s32 ret_val; + s32 ret_val = E1000_SUCCESS; DEBUGFUNC("e1000_acquire_nvm_82575"); @@ -983,6 +1002,7 @@ static s32 e1000_acquire_nvm_82575(struct e1000_hw *hw) DEBUGOUT("Nvm bit banging access error detected and cleared.\n"); } } + if (hw->mac.type == e1000_82580) { u32 eecd = E1000_READ_REG(hw, E1000_EECD); if (eecd & E1000_EECD_BLOCKED) { @@ -993,7 +1013,6 @@ static s32 e1000_acquire_nvm_82575(struct e1000_hw *hw) } } - ret_val = e1000_acquire_nvm_generic(hw); if (ret_val) e1000_release_swfw_sync_82575(hw, E1000_SWFW_EEP_SM); @@ -1032,7 +1051,7 @@ static s32 e1000_acquire_swfw_sync_82575(struct e1000_hw *hw, u16 mask) u32 swmask = mask; u32 fwmask = mask << 16; s32 ret_val = E1000_SUCCESS; - s32 i = 0, timeout = 200; /* FIXME: find real value to use here */ + s32 i = 0, timeout = 200; DEBUGFUNC("e1000_acquire_swfw_sync_82575"); @@ -1107,7 +1126,6 @@ static void e1000_release_swfw_sync_82575(struct e1000_hw *hw, u16 mask) static s32 e1000_get_cfg_done_82575(struct e1000_hw *hw) { s32 timeout = PHY_CFG_TIMEOUT; - s32 ret_val = E1000_SUCCESS; u32 mask = E1000_NVM_CFG_DONE_PORT_0; DEBUGFUNC("e1000_get_cfg_done_82575"); @@ -1132,7 +1150,7 @@ static s32 e1000_get_cfg_done_82575(struct e1000_hw *hw) (hw->phy.type == e1000_phy_igp_3)) e1000_phy_init_script_igp3(hw); - return ret_val; + return E1000_SUCCESS; } /** @@ -1217,7 +1235,7 @@ static s32 e1000_check_for_link_media_swap(struct e1000_hw *hw) DEBUGFUNC("e1000_check_for_link_media_swap"); - /* Check the copper medium. */ + /* Check for copper. */ ret_val = phy->ops.write_reg(hw, E1000_M88E1112_PAGE_ADDR, 0); if (ret_val) return ret_val; @@ -1229,7 +1247,7 @@ static s32 e1000_check_for_link_media_swap(struct e1000_hw *hw) if (data & E1000_M88E1112_STATUS_LINK) port = E1000_MEDIA_PORT_COPPER; - /* Check the other medium. */ + /* Check for other. */ ret_val = phy->ops.write_reg(hw, E1000_M88E1112_PAGE_ADDR, 1); if (ret_val) return ret_val; @@ -1245,8 +1263,20 @@ static s32 e1000_check_for_link_media_swap(struct e1000_hw *hw) if (port && (hw->dev_spec._82575.media_port != port)) { hw->dev_spec._82575.media_port = port; hw->dev_spec._82575.media_changed = TRUE; + } + + if (port == E1000_MEDIA_PORT_COPPER) { + /* reset page to 0 */ + ret_val = phy->ops.write_reg(hw, E1000_M88E1112_PAGE_ADDR, 0); + if (ret_val) + return ret_val; + e1000_check_for_link_82575(hw); } else { - ret_val = e1000_check_for_link_82575(hw); + e1000_check_for_link_82575(hw); + /* reset page to 0 */ + ret_val = phy->ops.write_reg(hw, E1000_M88E1112_PAGE_ADDR, 0); + if (ret_val) + return ret_val; } return E1000_SUCCESS; @@ -1295,6 +1325,7 @@ static s32 e1000_get_pcs_speed_and_duplex_82575(struct e1000_hw *hw, { struct e1000_mac_info *mac = &hw->mac; u32 pcs; + u32 status; DEBUGFUNC("e1000_get_pcs_speed_and_duplex_82575"); @@ -1325,6 +1356,18 @@ static s32 e1000_get_pcs_speed_and_duplex_82575(struct e1000_hw *hw, else *duplex = HALF_DUPLEX; + /* Check if it is an I354 2.5Gb backplane connection. */ + if (mac->type == e1000_i354) { + status = E1000_READ_REG(hw, E1000_STATUS); + if ((status & E1000_STATUS_2P5_SKU) && + !(status & E1000_STATUS_2P5_SKU_OVER)) { + *speed = SPEED_2500; + *duplex = FULL_DUPLEX; + DEBUGOUT("2500 Mbs, "); + DEBUGOUT("Full Duplex\n"); + } + } + } else { mac->serdes_has_link = FALSE; *speed = 0; @@ -1440,7 +1483,7 @@ static s32 e1000_reset_hw_82575(struct e1000_hw *hw) * * This inits the hardware readying it for operation. **/ -static s32 e1000_init_hw_82575(struct e1000_hw *hw) +s32 e1000_init_hw_82575(struct e1000_hw *hw) { struct e1000_mac_info *mac = &hw->mac; s32 ret_val; @@ -1510,11 +1553,18 @@ static s32 e1000_setup_copper_link_82575(struct e1000_hw *hw) ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX); E1000_WRITE_REG(hw, E1000_CTRL, ctrl); - /* Clear Go Link Disconnect bit */ - if (hw->mac.type >= e1000_82580) { + /* Clear Go Link Disconnect bit on supported devices */ + switch (hw->mac.type) { + case e1000_82580: + case e1000_i350: + case e1000_i210: + case e1000_i211: phpm_reg = E1000_READ_REG(hw, E1000_82580_PHY_POWER_MGMT); phpm_reg &= ~E1000_82580_PM_GO_LINKD; E1000_WRITE_REG(hw, E1000_82580_PHY_POWER_MGMT, phpm_reg); + break; + default: + break; } ret_val = e1000_setup_serdes_link_82575(hw); @@ -1538,7 +1588,8 @@ static s32 e1000_setup_copper_link_82575(struct e1000_hw *hw) case I347AT4_E_PHY_ID: case M88E1112_E_PHY_ID: case M88E1340M_E_PHY_ID: - case M88E1545_E_PHY_ID: + case M88E1543_E_PHY_ID: + case M88E1512_E_PHY_ID: case I210_I_PHY_ID: ret_val = e1000_copper_link_setup_m88_gen2(hw); break; @@ -1951,7 +2002,7 @@ static s32 e1000_reset_init_script_82575(struct e1000_hw *hw) **/ static s32 e1000_read_mac_addr_82575(struct e1000_hw *hw) { - s32 ret_val = E1000_SUCCESS; + s32 ret_val; DEBUGFUNC("e1000_read_mac_addr_82575"); @@ -2082,7 +2133,7 @@ static void e1000_clear_hw_cntrs_82575(struct e1000_hw *hw) * e1000_rx_fifo_flush_82575 - Clean rx fifo after Rx enable * @hw: pointer to the HW structure * - * After rx enable if managability is enabled then there is likely some + * After Rx enable, if manageability is enabled then there is likely some * bad data at the start of the fifo and possibly in the DMA fifo. This * function clears the fifos and flushes any packets that came in as rx was * being enabled. @@ -2092,7 +2143,13 @@ void e1000_rx_fifo_flush_82575(struct e1000_hw *hw) u32 rctl, rlpml, rxdctl[4], rfctl, temp_rctl, rx_enabled; int i, ms_wait; - DEBUGFUNC("e1000_rx_fifo_workaround_82575"); + DEBUGFUNC("e1000_rx_fifo_flush_82575"); + + /* disable IPv6 options as per hardware errata */ + rfctl = E1000_READ_REG(hw, E1000_RFCTL); + rfctl |= E1000_RFCTL_IPV6_EX_DIS; + E1000_WRITE_REG(hw, E1000_RFCTL, rfctl); + if (hw->mac.type != e1000_82575 || !(E1000_READ_REG(hw, E1000_MANC) & E1000_MANC_RCV_TCO_EN)) return; @@ -2120,7 +2177,6 @@ void e1000_rx_fifo_flush_82575(struct e1000_hw *hw) * incoming packets are rejected. Set enable and wait 2ms so that * any packet that was coming in as RCTL.EN was set is flushed */ - rfctl = E1000_READ_REG(hw, E1000_RFCTL); E1000_WRITE_REG(hw, E1000_RFCTL, rfctl & ~E1000_RFCTL_LEF); rlpml = E1000_READ_REG(hw, E1000_RLPML); @@ -2213,43 +2269,33 @@ out: **/ void e1000_vmdq_set_anti_spoofing_pf(struct e1000_hw *hw, bool enable, int pf) { - u32 dtxswc; + u32 reg_val, reg_offset; switch (hw->mac.type) { case e1000_82576: - dtxswc = E1000_READ_REG(hw, E1000_DTXSWC); - if (enable) { - dtxswc |= (E1000_DTXSWC_MAC_SPOOF_MASK | - E1000_DTXSWC_VLAN_SPOOF_MASK); - /* The PF can spoof - it has to in order to - * support emulation mode NICs */ - dtxswc ^= (1 << pf | 1 << (pf + - E1000_DTXSWC_VLAN_SPOOF_SHIFT)); - } else { - dtxswc &= ~(E1000_DTXSWC_MAC_SPOOF_MASK | - E1000_DTXSWC_VLAN_SPOOF_MASK); - } - E1000_WRITE_REG(hw, E1000_DTXSWC, dtxswc); + reg_offset = E1000_DTXSWC; break; case e1000_i350: case e1000_i354: - dtxswc = E1000_READ_REG(hw, E1000_TXSWC); - if (enable) { - dtxswc |= (E1000_DTXSWC_MAC_SPOOF_MASK | - E1000_DTXSWC_VLAN_SPOOF_MASK); - /* The PF can spoof - it has to in order to - * support emulation mode NICs - */ - dtxswc ^= (1 << pf | 1 << (pf + - E1000_DTXSWC_VLAN_SPOOF_SHIFT)); - } else { - dtxswc &= ~(E1000_DTXSWC_MAC_SPOOF_MASK | - E1000_DTXSWC_VLAN_SPOOF_MASK); - } - E1000_WRITE_REG(hw, E1000_TXSWC, dtxswc); - default: + reg_offset = E1000_TXSWC; break; + default: + return; } + + reg_val = E1000_READ_REG(hw, reg_offset); + if (enable) { + reg_val |= (E1000_DTXSWC_MAC_SPOOF_MASK | + E1000_DTXSWC_VLAN_SPOOF_MASK); + /* The PF can spoof - it has to in order to + * support emulation mode NICs + */ + reg_val ^= (1 << pf | 1 << (pf + MAX_NUM_VFS)); + } else { + reg_val &= ~(E1000_DTXSWC_MAC_SPOOF_MASK | + E1000_DTXSWC_VLAN_SPOOF_MASK); + } + E1000_WRITE_REG(hw, reg_offset, reg_val); } /** @@ -2454,11 +2500,17 @@ static s32 e1000_reset_hw_82580(struct e1000_hw *hw) ctrl |= E1000_CTRL_RST; E1000_WRITE_REG(hw, E1000_CTRL, ctrl); - E1000_WRITE_FLUSH(hw); - /* Add delay to insure DEV_RST has time to complete */ - if (global_device_reset) - msec_delay(5); + switch (hw->device_id) { + case E1000_DEV_ID_DH89XXCC_SGMII: + break; + default: + E1000_WRITE_FLUSH(hw); + break; + } + + /* Add delay to insure DEV_RST or RST has time to complete */ + msec_delay(5); ret_val = e1000_get_auto_rd_done_generic(hw); if (ret_val) { @@ -2470,10 +2522,6 @@ static s32 e1000_reset_hw_82580(struct e1000_hw *hw) DEBUGOUT("Auto Read Done did not complete\n"); } - /* If EEPROM is not present, run manual init scripts */ - if (!(E1000_READ_REG(hw, E1000_EECD) & E1000_EECD_PRES)) - e1000_reset_init_script_82575(hw); - /* clear global device reset status bit */ E1000_WRITE_REG(hw, E1000_STATUS, E1000_STAT_DEV_RST_SET); @@ -2597,7 +2645,7 @@ out: **/ static s32 e1000_validate_nvm_checksum_82580(struct e1000_hw *hw) { - s32 ret_val = E1000_SUCCESS; + s32 ret_val; u16 eeprom_regions_count = 1; u16 j, nvm_data; u16 nvm_offset; @@ -2737,7 +2785,7 @@ out: static s32 __e1000_access_emi_reg(struct e1000_hw *hw, u16 address, u16 *data, bool read) { - s32 ret_val = E1000_SUCCESS; + s32 ret_val; DEBUGFUNC("__e1000_access_emi_reg"); @@ -2766,16 +2814,106 @@ s32 e1000_read_emi_reg(struct e1000_hw *hw, u16 addr, u16 *data) return __e1000_access_emi_reg(hw, addr, data, TRUE); } +/** + * e1000_initialize_M88E1512_phy - Initialize M88E1512 PHY + * @hw: pointer to the HW structure + * + * Initialize Marverl 1512 to work correctly with Avoton. + **/ +s32 e1000_initialize_M88E1512_phy(struct e1000_hw *hw) +{ + struct e1000_phy_info *phy = &hw->phy; + s32 ret_val = E1000_SUCCESS; + + DEBUGFUNC("e1000_initialize_M88E1512_phy"); + + /* Check if this is correct PHY. */ + if (phy->id != M88E1512_E_PHY_ID) + goto out; + + /* Switch to PHY page 0xFF. */ + ret_val = phy->ops.write_reg(hw, E1000_M88E1543_PAGE_ADDR, 0x00FF); + if (ret_val) + goto out; + + ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_2, 0x214B); + if (ret_val) + goto out; + + ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_1, 0x2144); + if (ret_val) + goto out; + + ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_2, 0x0C28); + if (ret_val) + goto out; + + ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_1, 0x2146); + if (ret_val) + goto out; + + ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_2, 0xB233); + if (ret_val) + goto out; + + ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_1, 0x214D); + if (ret_val) + goto out; + + ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_2, 0xCC0C); + if (ret_val) + goto out; + + ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_1, 0x2159); + if (ret_val) + goto out; + + /* Switch to PHY page 0xFB. */ + ret_val = phy->ops.write_reg(hw, E1000_M88E1543_PAGE_ADDR, 0x00FB); + if (ret_val) + goto out; + + ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_3, 0x000D); + if (ret_val) + goto out; + + /* Switch to PHY page 0x12. */ + ret_val = phy->ops.write_reg(hw, E1000_M88E1543_PAGE_ADDR, 0x12); + if (ret_val) + goto out; + + /* Change mode to SGMII-to-Copper */ + ret_val = phy->ops.write_reg(hw, E1000_M88E1512_MODE, 0x8001); + if (ret_val) + goto out; + + /* Return the PHY to page 0. */ + ret_val = phy->ops.write_reg(hw, E1000_M88E1543_PAGE_ADDR, 0); + if (ret_val) + goto out; + + ret_val = phy->ops.commit(hw); + if (ret_val) { + DEBUGOUT("Error committing the PHY changes\n"); + return ret_val; + } + + msec_delay(1000); +out: + return ret_val; +} + /** * e1000_set_eee_i350 - Enable/disable EEE support * @hw: pointer to the HW structure + * @adv1g: boolean flag enabling 1G EEE advertisement + * @adv100m: boolean flag enabling 100M EEE advertisement * * Enable/disable EEE based on setting in dev_spec structure. * **/ -s32 e1000_set_eee_i350(struct e1000_hw *hw) +s32 e1000_set_eee_i350(struct e1000_hw *hw, bool adv1G, bool adv100M) { - s32 ret_val = E1000_SUCCESS; u32 ipcnfg, eeer; DEBUGFUNC("e1000_set_eee_i350"); @@ -2790,7 +2928,16 @@ s32 e1000_set_eee_i350(struct e1000_hw *hw) if (!(hw->dev_spec._82575.eee_disable)) { u32 eee_su = E1000_READ_REG(hw, E1000_EEE_SU); - ipcnfg |= (E1000_IPCNFG_EEE_1G_AN | E1000_IPCNFG_EEE_100M_AN); + if (adv100M) + ipcnfg |= E1000_IPCNFG_EEE_100M_AN; + else + ipcnfg &= ~E1000_IPCNFG_EEE_100M_AN; + + if (adv1G) + ipcnfg |= E1000_IPCNFG_EEE_1G_AN; + else + ipcnfg &= ~E1000_IPCNFG_EEE_1G_AN; + eeer |= (E1000_EEER_TX_LPI_EN | E1000_EEER_RX_LPI_EN | E1000_EEER_LPI_FC); @@ -2808,17 +2955,19 @@ s32 e1000_set_eee_i350(struct e1000_hw *hw) E1000_READ_REG(hw, E1000_EEER); out: - return ret_val; + return E1000_SUCCESS; } /** * e1000_set_eee_i354 - Enable/disable EEE support * @hw: pointer to the HW structure + * @adv1g: boolean flag enabling 1G EEE advertisement + * @adv100m: boolean flag enabling 100M EEE advertisement * * Enable/disable EEE legacy mode based on setting in dev_spec structure. * **/ -s32 e1000_set_eee_i354(struct e1000_hw *hw) +s32 e1000_set_eee_i354(struct e1000_hw *hw, bool adv1G, bool adv100M) { struct e1000_phy_info *phy = &hw->phy; s32 ret_val = E1000_SUCCESS; @@ -2827,28 +2976,29 @@ s32 e1000_set_eee_i354(struct e1000_hw *hw) DEBUGFUNC("e1000_set_eee_i354"); if ((hw->phy.media_type != e1000_media_type_copper) || - (phy->id != M88E1545_E_PHY_ID)) + ((phy->id != M88E1543_E_PHY_ID) && + (phy->id != M88E1512_E_PHY_ID))) goto out; if (!hw->dev_spec._82575.eee_disable) { /* Switch to PHY page 18. */ - ret_val = phy->ops.write_reg(hw, E1000_M88E1545_PAGE_ADDR, 18); + ret_val = phy->ops.write_reg(hw, E1000_M88E1543_PAGE_ADDR, 18); if (ret_val) goto out; - ret_val = phy->ops.read_reg(hw, E1000_M88E1545_EEE_CTRL_1, + ret_val = phy->ops.read_reg(hw, E1000_M88E1543_EEE_CTRL_1, &phy_data); if (ret_val) goto out; - phy_data |= E1000_M88E1545_EEE_CTRL_1_MS; - ret_val = phy->ops.write_reg(hw, E1000_M88E1545_EEE_CTRL_1, + phy_data |= E1000_M88E1543_EEE_CTRL_1_MS; + ret_val = phy->ops.write_reg(hw, E1000_M88E1543_EEE_CTRL_1, phy_data); if (ret_val) goto out; /* Return the PHY to page 0. */ - ret_val = phy->ops.write_reg(hw, E1000_M88E1545_PAGE_ADDR, 0); + ret_val = phy->ops.write_reg(hw, E1000_M88E1543_PAGE_ADDR, 0); if (ret_val) goto out; @@ -2859,8 +3009,16 @@ s32 e1000_set_eee_i354(struct e1000_hw *hw) if (ret_val) goto out; - phy_data |= E1000_EEE_ADV_100_SUPPORTED | - E1000_EEE_ADV_1000_SUPPORTED; + if (adv100M) + phy_data |= E1000_EEE_ADV_100_SUPPORTED; + else + phy_data &= ~E1000_EEE_ADV_100_SUPPORTED; + + if (adv1G) + phy_data |= E1000_EEE_ADV_1000_SUPPORTED; + else + phy_data &= ~E1000_EEE_ADV_1000_SUPPORTED; + ret_val = e1000_write_xmdio_reg(hw, E1000_EEE_ADV_ADDR_I354, E1000_EEE_ADV_DEV_I354, phy_data); @@ -2901,7 +3059,8 @@ s32 e1000_get_eee_status_i354(struct e1000_hw *hw, bool *status) /* Check if EEE is supported on this device. */ if ((hw->phy.media_type != e1000_media_type_copper) || - (phy->id != M88E1545_E_PHY_ID)) + ((phy->id != M88E1543_E_PHY_ID) && + (phy->id != M88E1512_E_PHY_ID))) goto out; ret_val = e1000_read_xmdio_reg(hw, E1000_PCS_STATUS_ADDR_I354, diff --git a/sys/dev/netif/ig_hal/e1000_82575.h b/sys/dev/netif/ig_hal/e1000_82575.h index ffef28c654..00ad915e89 100644 --- a/sys/dev/netif/ig_hal/e1000_82575.h +++ b/sys/dev/netif/ig_hal/e1000_82575.h @@ -1,6 +1,6 @@ /****************************************************************************** - Copyright (c) 2001-2011, Intel Corporation + Copyright (c) 2001-2013, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without @@ -245,6 +245,8 @@ union e1000_adv_rx_desc { #define E1000_RXDADV_RSSTYPE_IPV6_UDP_EX 0x00000009 /* RSS Packet Types as indicated in the receive descriptor */ +#define E1000_RXDADV_PKTTYPE_ILMASK 0x000000F0 +#define E1000_RXDADV_PKTTYPE_TLMASK 0x00000F00 #define E1000_RXDADV_PKTTYPE_NONE 0x00000000 #define E1000_RXDADV_PKTTYPE_IPV4 0x00000010 /* IPV4 hdr present */ #define E1000_RXDADV_PKTTYPE_IPV4_EX 0x00000020 /* IPV4 hdr + extensions */ @@ -478,6 +480,7 @@ void e1000_vmdq_set_loopback_pf(struct e1000_hw *hw, bool enable); void e1000_vmdq_set_anti_spoofing_pf(struct e1000_hw *hw, bool enable, int pf); void e1000_vmdq_set_replication_pf(struct e1000_hw *hw, bool enable); s32 e1000_init_nvm_params_82575(struct e1000_hw *hw); +s32 e1000_init_hw_82575(struct e1000_hw *hw); enum e1000_promisc_type { e1000_promisc_disabled = 0, /* all promisc modes disabled */ @@ -492,9 +495,10 @@ void e1000_rlpml_set_vf(struct e1000_hw *, u16); s32 e1000_promisc_set_vf(struct e1000_hw *, enum e1000_promisc_type type); u16 e1000_rxpbs_adjust_82580(u32 data); s32 e1000_read_emi_reg(struct e1000_hw *hw, u16 addr, u16 *data); -s32 e1000_set_eee_i350(struct e1000_hw *); -s32 e1000_set_eee_i354(struct e1000_hw *); +s32 e1000_set_eee_i350(struct e1000_hw *hw, bool adv1G, bool adv100M); +s32 e1000_set_eee_i354(struct e1000_hw *hw, bool adv1G, bool adv100M); s32 e1000_get_eee_status_i354(struct e1000_hw *, bool *); +s32 e1000_initialize_M88E1512_phy(struct e1000_hw *hw); /* I2C SDA and SCL timing parameters for standard mode */ #define E1000_I2C_T_HD_STA 4 diff --git a/sys/dev/netif/ig_hal/e1000_api.c b/sys/dev/netif/ig_hal/e1000_api.c index f5d1e739ee..2bac61ac41 100644 --- a/sys/dev/netif/ig_hal/e1000_api.c +++ b/sys/dev/netif/ig_hal/e1000_api.c @@ -360,6 +360,7 @@ s32 e1000_set_mac_type(struct e1000_hw *hw) case E1000_DEV_ID_I354_BACKPLANE_1GBPS: case E1000_DEV_ID_I354_SGMII: + case E1000_DEV_ID_I354_BACKPLANE_2_5GBPS: mac->type = e1000_i354; break; default: diff --git a/sys/dev/netif/ig_hal/e1000_api.h b/sys/dev/netif/ig_hal/e1000_api.h index a8945ed75b..e8d64103f3 100644 --- a/sys/dev/netif/ig_hal/e1000_api.h +++ b/sys/dev/netif/ig_hal/e1000_api.h @@ -129,14 +129,14 @@ u32 e1000_translate_register_82542(u32 reg); * TBI_ACCEPT macro definition: * * This macro requires: - * adapter = a pointer to struct e1000_hw + * a = a pointer to struct e1000_hw * status = the 8 bit status field of the Rx descriptor with EOP set - * error = the 8 bit error field of the Rx descriptor with EOP set + * errors = the 8 bit error field of the Rx descriptor with EOP set * length = the sum of all the length fields of the Rx descriptors that * make up the current frame * last_byte = the last byte of the frame DMAed by the hardware - * max_frame_length = the maximum frame length we want to accept. - * min_frame_length = the minimum frame length we want to accept. + * min_frame_size = the minimum frame length we want to accept. + * max_frame_size = the maximum frame length we want to accept. * * This macro is a conditional that should be used in the interrupt * handler's Rx processing routine when RxErrors have been detected. @@ -162,10 +162,10 @@ u32 e1000_translate_register_82542(u32 reg); (((errors) & E1000_RXD_ERR_FRAME_ERR_MASK) == E1000_RXD_ERR_CE) && \ ((last_byte) == CARRIER_EXTENSION) && \ (((status) & E1000_RXD_STAT_VP) ? \ - (((length) > (min_frame_size - VLAN_TAG_SIZE)) && \ - ((length) <= (max_frame_size + 1))) : \ - (((length) > min_frame_size) && \ - ((length) <= (max_frame_size + VLAN_TAG_SIZE + 1))))) + (((length) > ((min_frame_size) - VLAN_TAG_SIZE)) && \ + ((length) <= ((max_frame_size) + 1))) : \ + (((length) > (min_frame_size)) && \ + ((length) <= ((max_frame_size) + VLAN_TAG_SIZE + 1))))) #define E1000_MAX(a, b) ((a) > (b) ? (a) : (b)) #define E1000_DIVIDE_ROUND_UP(a, b) (((a) + (b) - 1) / (b)) /* ceil(a/b) */ diff --git a/sys/dev/netif/ig_hal/e1000_defines.h b/sys/dev/netif/ig_hal/e1000_defines.h index 5d31c27dd3..e433dab7a2 100644 --- a/sys/dev/netif/ig_hal/e1000_defines.h +++ b/sys/dev/netif/ig_hal/e1000_defines.h @@ -175,6 +175,7 @@ #define E1000_CTRL_EXT_IPS 0x00004000 /* Invert Power State */ /* Physical Func Reset Done Indication */ #define E1000_CTRL_EXT_PFRSTD 0x00004000 +#define E1000_CTRL_EXT_SDLPE 0X00040000 /* SerDes Low Power Enable */ #define E1000_CTRL_EXT_SPD_BYPS 0x00008000 /* Speed Select Bypass */ #define E1000_CTRL_EXT_RO_DIS 0x00020000 /* Relaxed Ordering disable */ #define E1000_CTRL_EXT_DMA_DYN_CLK_EN 0x00080000 /* DMA Dynamic Clk Gating */ @@ -365,6 +366,7 @@ #define E1000_RCTL_RDMTS_HALF 0x00000000 /* Rx desc min thresh size */ #define E1000_RCTL_RDMTS_QUAT 0x00000100 /* Rx desc min thresh size */ #define E1000_RCTL_RDMTS_EIGTH 0x00000200 /* Rx desc min thresh size */ +#define E1000_RCTL_RDMTS_HEX 0x00010000 #define E1000_RCTL_MO_SHIFT 12 /* multicast offset shift */ #define E1000_RCTL_MO_0 0x00000000 /* multicast offset 11:0 */ #define E1000_RCTL_MO_1 0x00001000 /* multicast offset 12:1 */ @@ -490,7 +492,10 @@ #define E1000_CONNSW_ENRGSRC 0x4 #define E1000_CONNSW_PHYSD 0x400 +#define E1000_CONNSW_PHY_PDN 0x800 #define E1000_CONNSW_SERDESD 0x200 +#define E1000_CONNSW_AUTOSENSE_CONF 0x2 +#define E1000_CONNSW_AUTOSENSE_EN 0x1 #define E1000_PCS_CFG_PCS_EN 8 #define E1000_PCS_LCTL_FLV_LINK_UP 1 #define E1000_PCS_LCTL_FSV_10 0 @@ -545,6 +550,8 @@ #define E1000_STATUS_MTXCKOK 0x00000400 /* MTX clock running OK */ #define E1000_STATUS_PCI66 0x00000800 /* In 66Mhz slot */ #define E1000_STATUS_BUS64 0x00001000 /* In 64 bit slot */ +#define E1000_STATUS_2P5_SKU 0x00001000 /* Val of 2.5GBE SKU strap */ +#define E1000_STATUS_2P5_SKU_OVER 0x00002000 /* Val of 2.5GBE SKU Over */ #define E1000_STATUS_PCIX_MODE 0x00002000 /* PCI-X mode */ #define E1000_STATUS_PCIX_SPEED 0x0000C000 /* PCI-X bus speed */ #define E1000_STATUS_BMC_SKU_0 0x00100000 /* BMC USB redirect disbld */ @@ -567,6 +574,7 @@ #define SPEED_10 10 #define SPEED_100 100 #define SPEED_1000 1000 +#define SPEED_2500 2500 #define HALF_DUPLEX 1 #define FULL_DUPLEX 2 @@ -836,6 +844,7 @@ #define E1000_ICR_ACK 0x00020000 /* Receive Ack frame */ #define E1000_ICR_MNG 0x00040000 /* Manageability event */ #define E1000_ICR_DOCK 0x00080000 /* Dock/Undock */ +#define E1000_ICR_ECCER 0x00400000 /* Uncorrectable ECC Error */ #define E1000_ICR_TS 0x00080000 /* Time Sync Interrupt */ #define E1000_ICR_DRSTA 0x40000000 /* Device Reset Asserted */ #define E1000_ICR_ECCER 0x00400000 /* Uncorrectable ECC Error */ @@ -936,6 +945,7 @@ #define E1000_IMS_ACK E1000_ICR_ACK /* Receive Ack frame */ #define E1000_IMS_MNG E1000_ICR_MNG /* Manageability event */ #define E1000_IMS_DOCK E1000_ICR_DOCK /* Dock/Undock */ +#define E1000_IMS_ECCER E1000_ICR_ECCER /* Uncorrectable ECC Error */ #define E1000_IMS_TS E1000_ICR_TS /* Time Sync Interrupt */ #define E1000_IMS_DRSTA E1000_ICR_DRSTA /* Device Reset Asserted */ /* Q0 Rx desc FIFO parity error */ @@ -1028,6 +1038,7 @@ #define E1000_EITR_ITR_INT_MASK 0x0000FFFF /* E1000_EITR_CNT_IGNR is only for 82576 and newer */ #define E1000_EITR_CNT_IGNR 0x80000000 /* Don't reset counters on write */ +#define E1000_EITR_INTERVAL 0x00007FFC /* Transmit Descriptor Control */ #define E1000_TXDCTL_PTHRESH 0x0000003F /* TXDCTL Prefetch Threshold */ @@ -1194,14 +1205,17 @@ #define E1000_MDICNFG_COM_MDIO 0x40000000 /* MDI shared w/ lan 0 */ #define E1000_MDICNFG_PHY_MASK 0x03E00000 #define E1000_MDICNFG_PHY_SHIFT 21 -#define E1000_MEDIA_PORT_COPPER 1 -#define E1000_MEDIA_PORT_OTHER 2 -#define E1000_M88E1112_AUTO_A 0x010 /* Auto Copper/SGMII Mode */ -#define E1000_M88E1112_AUTO_B 0x011 /* Auto Copper/1000 Base X Mode */ -#define E1000_M88E1112_STATUS_LINK 0x0004 /* Interface Link Bit */ -#define E1000_M88E1112_MAC_CTRL_1 0x10 /* MAC Specific Control 1 */ -#define E1000_M88E1112_PAGE_ADDR 0x16 -#define E1000_M88E1112_STATUS 0x01 + +#define E1000_MEDIA_PORT_COPPER 1 +#define E1000_MEDIA_PORT_OTHER 2 +#define E1000_M88E1112_AUTO_COPPER_SGMII 0x2 +#define E1000_M88E1112_AUTO_COPPER_BASEX 0x3 +#define E1000_M88E1112_STATUS_LINK 0x0004 /* Interface Link Bit */ +#define E1000_M88E1112_MAC_CTRL_1 0x10 +#define E1000_M88E1112_MAC_CTRL_1_MODE_MASK 0x0380 /* Mode Select */ +#define E1000_M88E1112_MAC_CTRL_1_MODE_SHIFT 7 +#define E1000_M88E1112_PAGE_ADDR 0x16 +#define E1000_M88E1112_STATUS 0x01 #define E1000_THSTAT_LOW_EVENT 0x20000000 /* Low thermal threshold */ #define E1000_THSTAT_MID_EVENT 0x00200000 /* Mid thermal threshold */ @@ -1220,9 +1234,9 @@ #define E1000_EEER_RX_LPI_STATUS 0x40000000 /* Rx in LPI state */ #define E1000_EEER_TX_LPI_STATUS 0x80000000 /* Tx in LPI state */ #define E1000_EEE_LP_ADV_ADDR_I350 0x040F /* EEE LP Advertisement */ -#define E1000_M88E1545_PAGE_ADDR 0x16 /* Page Offset Register */ -#define E1000_M88E1545_EEE_CTRL_1 0x0 -#define E1000_M88E1545_EEE_CTRL_1_MS 0x0001 /* EEE Master/Slave */ +#define E1000_M88E1543_PAGE_ADDR 0x16 /* Page Offset Register */ +#define E1000_M88E1543_EEE_CTRL_1 0x0 +#define E1000_M88E1543_EEE_CTRL_1_MS 0x0001 /* EEE Master/Slave */ #define E1000_EEE_ADV_DEV_I354 7 #define E1000_EEE_ADV_ADDR_I354 60 #define E1000_EEE_ADV_100_SUPPORTED (1 << 1) /* 100BaseTx EEE Supported */ @@ -1232,6 +1246,10 @@ #define E1000_PCS_STATUS_TX_LPI_IND 0x0200 /* Tx in LPI state */ #define E1000_PCS_STATUS_RX_LPI_RCVD 0x0400 #define E1000_PCS_STATUS_TX_LPI_RCVD 0x0800 +#define E1000_M88E1512_CFG_REG_1 0x0010 +#define E1000_M88E1512_CFG_REG_2 0x0011 +#define E1000_M88E1512_CFG_REG_3 0x0007 +#define E1000_M88E1512_MODE 0x0014 #define E1000_EEE_SU_LPI_CLK_STP 0x00800000 /* EEE LPI Clock Stop */ #define E1000_EEE_LP_ADV_DEV_I210 7 /* EEE LP Adv Device */ #define E1000_EEE_LP_ADV_ADDR_I210 61 /* EEE LP Adv Register */ @@ -1643,7 +1661,8 @@ #define IGP01E1000_I_PHY_ID 0x02A80380 #define M88E1011_I_REV_4 0x04 #define M88E1111_I_PHY_ID 0x01410CC0 -#define M88E1545_E_PHY_ID 0x01410EA0 +#define M88E1543_E_PHY_ID 0x01410EA0 +#define M88E1512_E_PHY_ID 0x01410DD0 #define M88E1112_E_PHY_ID 0x01410C90 #define I347AT4_E_PHY_ID 0x01410DC0 #define M88E1340M_E_PHY_ID 0x01410DF0 @@ -1944,6 +1963,9 @@ #define E1000_RXPBS_CFG_TS_EN 0x80000000 /* Timestamp in Rx buffer */ #define E1000_RXPBS_SIZE_I210_MASK 0x0000003F /* Rx packet buffer size */ #define E1000_TXPB0S_SIZE_I210_MASK 0x0000003F /* Tx packet buffer 0 size */ +#define I210_RXPBSIZE_DEFAULT 0x000000A2 /* RXPBSIZE default */ +#define I210_TXPBSIZE_DEFAULT 0x04000014 /* TXPBSIZE default */ + /* Proxy Filter Control */ #define E1000_PROXYFC_D0 0x00000001 /* Enable offload in D0 */ @@ -1967,6 +1989,10 @@ /* Lan ID bit field offset in status register */ #define E1000_STATUS_LAN_ID_OFFSET 2 #define E1000_VFTA_ENTRIES 128 +#ifndef E1000_UNUSEDARG #define E1000_UNUSEDARG +#endif /* E1000_UNUSEDARG */ +#ifndef ERROR_REPORT #define ERROR_REPORT(fmt) do { } while (0) +#endif /* ERROR_REPORT */ #endif /* _E1000_DEFINES_H_ */ diff --git a/sys/dev/netif/ig_hal/e1000_hw.h b/sys/dev/netif/ig_hal/e1000_hw.h index 62f5d3ac18..b27ca9181c 100644 --- a/sys/dev/netif/ig_hal/e1000_hw.h +++ b/sys/dev/netif/ig_hal/e1000_hw.h @@ -180,6 +180,7 @@ struct e1000_hw; #define E1000_DEV_ID_I211_COPPER 0x1539 #define E1000_DEV_ID_I354_BACKPLANE_1GBPS 0x1F40 #define E1000_DEV_ID_I354_SGMII 0x1F41 +#define E1000_DEV_ID_I354_BACKPLANE_2_5GBPS 0x1F45 #define E1000_DEV_ID_DH89XXCC_SGMII 0x0438 #define E1000_DEV_ID_DH89XXCC_SERDES 0x043A #define E1000_DEV_ID_DH89XXCC_BACKPLANE 0x043C @@ -794,7 +795,7 @@ struct e1000_mac_info { u16 uta_reg_count; /* Maximum size of the MTA register table in all supported adapters */ - #define MAX_MTA_REG 128 +#define MAX_MTA_REG 128 u32 mta_shadow[MAX_MTA_REG]; u16 rar_entry_count; diff --git a/sys/dev/netif/ig_hal/e1000_i210.c b/sys/dev/netif/ig_hal/e1000_i210.c index 44d73fd4f8..d55b6a4547 100644 --- a/sys/dev/netif/ig_hal/e1000_i210.c +++ b/sys/dev/netif/ig_hal/e1000_i210.c @@ -1,6 +1,6 @@ /****************************************************************************** - Copyright (c) 2001-2011, Intel Corporation + Copyright (c) 2001-2013, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without @@ -635,7 +635,7 @@ s32 e1000_validate_nvm_checksum_i210(struct e1000_hw *hw) **/ s32 e1000_update_nvm_checksum_i210(struct e1000_hw *hw) { - s32 ret_val = E1000_SUCCESS; + s32 ret_val; u16 checksum = 0; u16 i, nvm_data; @@ -714,7 +714,7 @@ bool e1000_get_flash_presence_i210(struct e1000_hw *hw) **/ s32 e1000_update_flash_i210(struct e1000_hw *hw) { - s32 ret_val = E1000_SUCCESS; + s32 ret_val; u32 flup; DEBUGFUNC("e1000_update_flash_i210"); @@ -770,7 +770,7 @@ s32 e1000_pool_flash_update_done_i210(struct e1000_hw *hw) **/ static s32 e1000_init_nvm_params_i210(struct e1000_hw *hw) { - s32 ret_val = E1000_SUCCESS; + s32 ret_val; struct e1000_nvm_info *nvm = &hw->nvm; DEBUGFUNC("e1000_init_nvm_params_i210"); @@ -855,7 +855,7 @@ out: static s32 __e1000_access_xmdio_reg(struct e1000_hw *hw, u16 address, u8 dev_addr, u16 *data, bool read) { - s32 ret_val = E1000_SUCCESS; + s32 ret_val; DEBUGFUNC("__e1000_access_xmdio_reg"); @@ -914,3 +914,90 @@ s32 e1000_write_xmdio_reg(struct e1000_hw *hw, u16 addr, u8 dev_addr, u16 data) return __e1000_access_xmdio_reg(hw, addr, dev_addr, &data, FALSE); } + +/** + * e1000_pll_workaround_i210 + * @hw: pointer to the HW structure + * + * Works around an errata in the PLL circuit where it occasionally + * provides the wrong clock frequency after power up. + **/ +static s32 e1000_pll_workaround_i210(struct e1000_hw *hw) +{ + s32 ret_val; + u32 wuc, mdicnfg, ctrl, ctrl_ext, reg_val; + u16 nvm_word, phy_word, pci_word, tmp_nvm; + int i; + + /* Get and set needed register values */ + wuc = E1000_READ_REG(hw, E1000_WUC); + mdicnfg = E1000_READ_REG(hw, E1000_MDICNFG); + reg_val = mdicnfg & ~E1000_MDICNFG_EXT_MDIO; + E1000_WRITE_REG(hw, E1000_MDICNFG, reg_val); + + /* Get data from NVM, or set default */ + ret_val = e1000_read_invm_word_i210(hw, E1000_INVM_AUTOLOAD, + &nvm_word); + if (ret_val != E1000_SUCCESS) + nvm_word = E1000_INVM_DEFAULT_AL; + tmp_nvm = nvm_word | E1000_INVM_PLL_WO_VAL; + for (i = 0; i < E1000_MAX_PLL_TRIES; i++) { + /* check current state directly from internal PHY */ + e1000_read_phy_reg_gs40g(hw, (E1000_PHY_PLL_FREQ_PAGE | + E1000_PHY_PLL_FREQ_REG), &phy_word); + if ((phy_word & E1000_PHY_PLL_UNCONF) + != E1000_PHY_PLL_UNCONF) { + ret_val = E1000_SUCCESS; + break; + } else { + ret_val = -E1000_ERR_PHY; + } + /* directly reset the internal PHY */ + ctrl = E1000_READ_REG(hw, E1000_CTRL); + E1000_WRITE_REG(hw, E1000_CTRL, ctrl|E1000_CTRL_PHY_RST); + + ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT); + ctrl_ext |= (E1000_CTRL_EXT_PHYPDEN | E1000_CTRL_EXT_SDLPE); + E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext); + + E1000_WRITE_REG(hw, E1000_WUC, 0); + reg_val = (E1000_INVM_AUTOLOAD << 4) | (tmp_nvm << 16); + E1000_WRITE_REG(hw, E1000_EEARBC_I210, reg_val); + + e1000_read_pci_cfg(hw, E1000_PCI_PMCSR, &pci_word); + pci_word |= E1000_PCI_PMCSR_D3; + e1000_write_pci_cfg(hw, E1000_PCI_PMCSR, &pci_word); + msec_delay(1); + pci_word &= ~E1000_PCI_PMCSR_D3; + e1000_write_pci_cfg(hw, E1000_PCI_PMCSR, &pci_word); + reg_val = (E1000_INVM_AUTOLOAD << 4) | (nvm_word << 16); + E1000_WRITE_REG(hw, E1000_EEARBC_I210, reg_val); + + /* restore WUC register */ + E1000_WRITE_REG(hw, E1000_WUC, wuc); + } + /* restore MDICNFG setting */ + E1000_WRITE_REG(hw, E1000_MDICNFG, mdicnfg); + return ret_val; +} + +/** + * e1000_init_hw_i210 - Init hw for I210/I211 + * @hw: pointer to the HW structure + * + * Called to initialize hw for i210 hw family. + **/ +s32 e1000_init_hw_i210(struct e1000_hw *hw) +{ + s32 ret_val; + + DEBUGFUNC("e1000_init_hw_i210"); + if ((hw->mac.type >= e1000_i210) && + !(e1000_get_flash_presence_i210(hw))) { + ret_val = e1000_pll_workaround_i210(hw); + if (ret_val != E1000_SUCCESS) + return ret_val; + } + ret_val = e1000_init_hw_82575(hw); + return ret_val; +} diff --git a/sys/dev/netif/ig_hal/e1000_i210.h b/sys/dev/netif/ig_hal/e1000_i210.h index ae4c8c9cd8..fab7284035 100644 --- a/sys/dev/netif/ig_hal/e1000_i210.h +++ b/sys/dev/netif/ig_hal/e1000_i210.h @@ -1,6 +1,6 @@ /****************************************************************************** - Copyright (c) 2001-2011, Intel Corporation + Copyright (c) 2001-2013, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without @@ -51,6 +51,7 @@ s32 e1000_read_xmdio_reg(struct e1000_hw *hw, u16 addr, u8 dev_addr, u16 *data); s32 e1000_write_xmdio_reg(struct e1000_hw *hw, u16 addr, u8 dev_addr, u16 data); +s32 e1000_init_hw_i210(struct e1000_hw *hw); #define E1000_STM_OPCODE 0xDB00 #define E1000_EEPROM_FLASH_SIZE_WORD 0x11 @@ -88,11 +89,23 @@ enum E1000_INVM_STRUCTURE_TYPE { (ID_LED_OFF1_OFF2)) #define ID_LED_DEFAULT_I210_SERDES ((ID_LED_DEF1_DEF2 << 8) | \ (ID_LED_DEF1_DEF2 << 4) | \ - (ID_LED_DEF1_DEF2)) + (ID_LED_OFF1_ON2)) /* NVM offset defaults for I211 devices */ #define NVM_INIT_CTRL_2_DEFAULT_I211 0X7243 #define NVM_INIT_CTRL_4_DEFAULT_I211 0x00C1 #define NVM_LED_1_CFG_DEFAULT_I211 0x0184 #define NVM_LED_0_2_CFG_DEFAULT_I211 0x200C + +/* PLL Defines */ +#define E1000_PCI_PMCSR 0x44 +#define E1000_PCI_PMCSR_D3 0x03 +#define E1000_MAX_PLL_TRIES 5 +#define E1000_PHY_PLL_UNCONF 0xFF +#define E1000_PHY_PLL_FREQ_PAGE 0xFC0000 +#define E1000_PHY_PLL_FREQ_REG 0x000E +#define E1000_INVM_DEFAULT_AL 0x202F +#define E1000_INVM_AUTOLOAD 0x0A +#define E1000_INVM_PLL_WO_VAL 0x0010 + #endif diff --git a/sys/dev/netif/ig_hal/e1000_mac.c b/sys/dev/netif/ig_hal/e1000_mac.c index 43984d23bf..7be02eff28 100644 --- a/sys/dev/netif/ig_hal/e1000_mac.c +++ b/sys/dev/netif/ig_hal/e1000_mac.c @@ -952,6 +952,7 @@ s32 e1000_set_default_fc_generic(struct e1000_hw *hw) { s32 ret_val; u16 nvm_data; + u16 nvm_offset = 0; DEBUGFUNC("e1000_set_default_fc_generic"); @@ -963,7 +964,18 @@ s32 e1000_set_default_fc_generic(struct e1000_hw *hw) * control setting, then the variable hw->fc will * be initialized based on a value in the EEPROM. */ - ret_val = hw->nvm.ops.read(hw, NVM_INIT_CONTROL2_REG, 1, &nvm_data); + if (hw->mac.type == e1000_i350) { + nvm_offset = NVM_82580_LAN_FUNC_OFFSET(hw->bus.func); + ret_val = hw->nvm.ops.read(hw, + NVM_INIT_CONTROL2_REG + + nvm_offset, + 1, &nvm_data); + } else { + ret_val = hw->nvm.ops.read(hw, + NVM_INIT_CONTROL2_REG, + 1, &nvm_data); + } + if (ret_val) { DEBUGOUT("NVM Read Error\n"); @@ -2090,7 +2102,8 @@ s32 e1000_disable_pcie_master_generic(struct e1000_hw *hw) while (timeout) { if (!(E1000_READ_REG(hw, E1000_STATUS) & - E1000_STATUS_GIO_MASTER_ENABLE)) + E1000_STATUS_GIO_MASTER_ENABLE) || + E1000_REMOVED(hw->hw_addr)) break; usec_delay(100); timeout--; diff --git a/sys/dev/netif/ig_hal/e1000_mac.h b/sys/dev/netif/ig_hal/e1000_mac.h index 99ffd66293..a52086d429 100644 --- a/sys/dev/netif/ig_hal/e1000_mac.h +++ b/sys/dev/netif/ig_hal/e1000_mac.h @@ -36,6 +36,9 @@ #define _E1000_MAC_H_ void e1000_init_mac_ops_generic(struct e1000_hw *hw); +#ifndef E1000_REMOVED +#define E1000_REMOVED(a) (0) +#endif /* E1000_REMOVED */ void e1000_null_mac_generic(struct e1000_hw *hw); s32 e1000_null_ops_generic(struct e1000_hw *hw); s32 e1000_null_link_info(struct e1000_hw *hw, u16 *s, u16 *d); diff --git a/sys/dev/netif/ig_hal/e1000_mbx.c b/sys/dev/netif/ig_hal/e1000_mbx.c index f84df49115..7a1d44ccd8 100644 --- a/sys/dev/netif/ig_hal/e1000_mbx.c +++ b/sys/dev/netif/ig_hal/e1000_mbx.c @@ -1,6 +1,6 @@ /****************************************************************************** - Copyright (c) 2001-2011, Intel Corporation + Copyright (c) 2001-2013, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/sys/dev/netif/ig_hal/e1000_mbx.h b/sys/dev/netif/ig_hal/e1000_mbx.h index 5c506ee44b..efd284777c 100644 --- a/sys/dev/netif/ig_hal/e1000_mbx.h +++ b/sys/dev/netif/ig_hal/e1000_mbx.h @@ -1,6 +1,6 @@ /****************************************************************************** - Copyright (c) 2001-2011, Intel Corporation + Copyright (c) 2001-2013, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/sys/dev/netif/ig_hal/e1000_nvm.c b/sys/dev/netif/ig_hal/e1000_nvm.c index ba4b97dd5e..ab7164d70a 100644 --- a/sys/dev/netif/ig_hal/e1000_nvm.c +++ b/sys/dev/netif/ig_hal/e1000_nvm.c @@ -779,6 +779,12 @@ s32 e1000_read_pba_string_generic(struct e1000_hw *hw, u8 *pba_num, DEBUGFUNC("e1000_read_pba_string_generic"); + if ((hw->mac.type >= e1000_i210) && + !e1000_get_flash_presence_i210(hw)) { + DEBUGOUT("Flashless no PBA string\n"); + return -E1000_ERR_NVM_PBA_SECTION; + } + if (pba_num == NULL) { DEBUGOUT("PBA string buffer was null\n"); return -E1000_ERR_INVALID_ARGUMENT; @@ -1282,7 +1288,6 @@ void e1000_get_fw_version(struct e1000_hw *hw, struct e1000_fw_version *fw_vers) /* basic eeprom version numbers, bits used vary by part and by tool * used to create the nvm images */ /* Check which data format we have */ - hw->nvm.ops.read(hw, NVM_ETRACK_HIWORD, 1, &etrack_test); switch (hw->mac.type) { case e1000_i211: e1000_read_invm_version(hw, fw_vers); @@ -1290,6 +1295,7 @@ void e1000_get_fw_version(struct e1000_hw *hw, struct e1000_fw_version *fw_vers) case e1000_82575: case e1000_82576: case e1000_82580: + hw->nvm.ops.read(hw, NVM_ETRACK_HIWORD, 1, &etrack_test); /* Use this format, unless EETRACK ID exists, * then use alternate format */ @@ -1304,7 +1310,13 @@ void e1000_get_fw_version(struct e1000_hw *hw, struct e1000_fw_version *fw_vers) } break; case e1000_i210: + if (!(e1000_get_flash_presence_i210(hw))) { + e1000_read_invm_version(hw, fw_vers); + return; + } + /* fall through */ case e1000_i350: + hw->nvm.ops.read(hw, NVM_ETRACK_HIWORD, 1, &etrack_test); /* find combo image version */ hw->nvm.ops.read(hw, NVM_COMB_VER_PTR, 1, &comb_offset); if ((comb_offset != 0x0) && @@ -1332,6 +1344,7 @@ void e1000_get_fw_version(struct e1000_hw *hw, struct e1000_fw_version *fw_vers) } break; default: + hw->nvm.ops.read(hw, NVM_ETRACK_HIWORD, 1, &etrack_test); return; } hw->nvm.ops.read(hw, NVM_VERSION, 1, &fw_version); @@ -1360,8 +1373,12 @@ etrack_id: hw->nvm.ops.read(hw, (NVM_ETRACK_WORD + 1), 1, &eeprom_verh); fw_vers->etrack_id = (eeprom_verh << NVM_ETRACK_SHIFT) | eeprom_verl; + } else if ((etrack_test & NVM_ETRACK_VALID) == 0) { + hw->nvm.ops.read(hw, NVM_ETRACK_WORD, 1, &eeprom_verh); + hw->nvm.ops.read(hw, (NVM_ETRACK_WORD + 1), 1, &eeprom_verl); + fw_vers->etrack_id = (eeprom_verh << NVM_ETRACK_SHIFT) | + eeprom_verl; } - return; } diff --git a/sys/dev/netif/ig_hal/e1000_phy.c b/sys/dev/netif/ig_hal/e1000_phy.c index 5aa1b5a2a3..6856d79d15 100644 --- a/sys/dev/netif/ig_hal/e1000_phy.c +++ b/sys/dev/netif/ig_hal/e1000_phy.c @@ -1251,12 +1251,6 @@ s32 e1000_copper_link_setup_m88(struct e1000_hw *hw) return ret_val; } - if (phy->type == e1000_phy_i210) { - ret_val = e1000_set_master_slave_mode(hw); - if (ret_val) - return ret_val; - } - return E1000_SUCCESS; } @@ -1320,6 +1314,20 @@ s32 e1000_copper_link_setup_m88_gen2(struct e1000_hw *hw) phy_data |= M88E1000_PSCR_POLARITY_REVERSAL; /* Enable downshift and setting it to X6 */ + if (phy->id == M88E1543_E_PHY_ID) { + phy_data &= ~I347AT4_PSCR_DOWNSHIFT_ENABLE; + ret_val = + phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data); + if (ret_val) + return ret_val; + + ret_val = phy->ops.commit(hw); + if (ret_val) { + DEBUGOUT("Error committing the PHY changes\n"); + return ret_val; + } + } + phy_data &= ~I347AT4_PSCR_DOWNSHIFT_MASK; phy_data |= I347AT4_PSCR_DOWNSHIFT_6X; phy_data |= I347AT4_PSCR_DOWNSHIFT_ENABLE; @@ -1853,7 +1861,8 @@ s32 e1000_phy_force_speed_duplex_m88(struct e1000_hw *hw) case I347AT4_E_PHY_ID: case M88E1340M_E_PHY_ID: case M88E1112_E_PHY_ID: - case M88E1545_E_PHY_ID: + case M88E1543_E_PHY_ID: + case M88E1512_E_PHY_ID: case I210_I_PHY_ID: reset_dsp = FALSE; break; @@ -1896,7 +1905,8 @@ s32 e1000_phy_force_speed_duplex_m88(struct e1000_hw *hw) return E1000_SUCCESS; if (hw->phy.id == I210_I_PHY_ID) return E1000_SUCCESS; - if (hw->phy.id == M88E1545_E_PHY_ID) + if ((hw->phy.id == M88E1543_E_PHY_ID) || + (hw->phy.id == M88E1512_E_PHY_ID)) return E1000_SUCCESS; ret_val = phy->ops.read_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_data); if (ret_val) @@ -2450,7 +2460,8 @@ s32 e1000_get_cable_length_m88_gen2(struct e1000_hw *hw) phy->max_cable_length = phy_data / (is_cm ? 100 : 1); phy->cable_length = phy_data / (is_cm ? 100 : 1); break; - case M88E1545_E_PHY_ID: + case M88E1543_E_PHY_ID: + case M88E1512_E_PHY_ID: case M88E1340M_E_PHY_ID: case I347AT4_E_PHY_ID: /* Remember the original page select and set it to 7 */ @@ -2984,7 +2995,8 @@ enum e1000_phy_type e1000_get_phy_type_from_id(u32 phy_id) case M88E1000_E_PHY_ID: case M88E1111_I_PHY_ID: case M88E1011_I_PHY_ID: - case M88E1545_E_PHY_ID: + case M88E1543_E_PHY_ID: + case M88E1512_E_PHY_ID: case I347AT4_E_PHY_ID: case M88E1112_E_PHY_ID: case M88E1340M_E_PHY_ID: @@ -3480,16 +3492,10 @@ static s32 e1000_access_phy_wakeup_reg_bm(struct e1000_hw *hw, u32 offset, void e1000_power_up_phy_copper(struct e1000_hw *hw) { u16 mii_reg = 0; - u16 power_reg = 0; /* The PHY will retain its settings across a power down/up cycle */ hw->phy.ops.read_reg(hw, PHY_CONTROL, &mii_reg); mii_reg &= ~MII_CR_POWER_DOWN; - if (hw->phy.type == e1000_phy_i210) { - hw->phy.ops.read_reg(hw, GS40G_COPPER_SPEC, &power_reg); - power_reg &= ~GS40G_CS_POWER_DOWN; - hw->phy.ops.write_reg(hw, GS40G_COPPER_SPEC, power_reg); - } hw->phy.ops.write_reg(hw, PHY_CONTROL, mii_reg); } @@ -3504,17 +3510,10 @@ void e1000_power_up_phy_copper(struct e1000_hw *hw) void e1000_power_down_phy_copper(struct e1000_hw *hw) { u16 mii_reg = 0; - u16 power_reg = 0; /* The PHY will retain its settings across a power down/up cycle */ hw->phy.ops.read_reg(hw, PHY_CONTROL, &mii_reg); mii_reg |= MII_CR_POWER_DOWN; - /* i210 Phy requires an additional bit for power up/down */ - if (hw->phy.type == e1000_phy_i210) { - hw->phy.ops.read_reg(hw, GS40G_COPPER_SPEC, &power_reg); - power_reg |= GS40G_CS_POWER_DOWN; - hw->phy.ops.write_reg(hw, GS40G_COPPER_SPEC, power_reg); - } hw->phy.ops.write_reg(hw, PHY_CONTROL, mii_reg); msec_delay(1); } @@ -4112,7 +4111,7 @@ s32 e1000_read_phy_reg_mphy(struct e1000_hw *hw, u32 address, u32 *data) { u32 mphy_ctrl = 0; bool locked = FALSE; - bool ready = FALSE; + bool ready; DEBUGFUNC("e1000_read_phy_reg_mphy"); @@ -4136,7 +4135,11 @@ s32 e1000_read_phy_reg_mphy(struct e1000_hw *hw, u32 address, u32 *data) ready = e1000_is_mphy_ready(hw); if (!ready) return -E1000_ERR_PHY; - mphy_ctrl |= (address & E1000_MPHY_ADDRESS_MASK); + + /* We mask address, because we want to use only current lane */ + mphy_ctrl = (mphy_ctrl & ~E1000_MPHY_ADDRESS_MASK & + ~E1000_MPHY_ADDRESS_FNC_OVERRIDE) | + (address & E1000_MPHY_ADDRESS_MASK); E1000_WRITE_REG(hw, E1000_MPHY_ADDR_CTRL, mphy_ctrl); /* Read data from the address */ @@ -4162,14 +4165,16 @@ s32 e1000_read_phy_reg_mphy(struct e1000_hw *hw, u32 address, u32 *data) * @hw: pointer to the HW structure * @address: address to write to * @data: data to write to register at offset + * @line_override: used when we want to use different line than default one * * Writes data to mPHY control register. **/ -s32 e1000_write_phy_reg_mphy(struct e1000_hw *hw, u32 address, u32 data) +s32 e1000_write_phy_reg_mphy(struct e1000_hw *hw, u32 address, u32 data, + bool line_override) { u32 mphy_ctrl = 0; bool locked = FALSE; - bool ready = FALSE; + bool ready; DEBUGFUNC("e1000_write_phy_reg_mphy"); @@ -4193,7 +4198,14 @@ s32 e1000_write_phy_reg_mphy(struct e1000_hw *hw, u32 address, u32 data) ready = e1000_is_mphy_ready(hw); if (!ready) return -E1000_ERR_PHY; - mphy_ctrl |= (address & E1000_MPHY_ADDRESS_MASK); + + /* We mask address, because we want to use only current lane */ + if (line_override) + mphy_ctrl |= E1000_MPHY_ADDRESS_FNC_OVERRIDE; + else + mphy_ctrl &= ~E1000_MPHY_ADDRESS_FNC_OVERRIDE; + mphy_ctrl = (mphy_ctrl & ~E1000_MPHY_ADDRESS_MASK) | + (address & E1000_MPHY_ADDRESS_MASK); E1000_WRITE_REG(hw, E1000_MPHY_ADDR_CTRL, mphy_ctrl); /* Read data from the address */ diff --git a/sys/dev/netif/ig_hal/e1000_phy.h b/sys/dev/netif/ig_hal/e1000_phy.h index f60a4f0c88..d54f227e31 100644 --- a/sys/dev/netif/ig_hal/e1000_phy.h +++ b/sys/dev/netif/ig_hal/e1000_phy.h @@ -117,7 +117,8 @@ s32 e1000_get_cable_length_82577(struct e1000_hw *hw); s32 e1000_write_phy_reg_gs40g(struct e1000_hw *hw, u32 offset, u16 data); s32 e1000_read_phy_reg_gs40g(struct e1000_hw *hw, u32 offset, u16 *data); s32 e1000_read_phy_reg_mphy(struct e1000_hw *hw, u32 address, u32 *data); -s32 e1000_write_phy_reg_mphy(struct e1000_hw *hw, u32 address, u32 data); +s32 e1000_write_phy_reg_mphy(struct e1000_hw *hw, u32 address, u32 data, + bool line_override); bool e1000_is_mphy_ready(struct e1000_hw *hw); #define E1000_MAX_PHY_ADDR 8 @@ -223,10 +224,11 @@ bool e1000_is_mphy_ready(struct e1000_hw *hw); #define E1000_82580_PM_GO_LINKD 0x0020 /* Go Link Disconnect */ -#define E1000_MPHY_DIS_ACCESS 0x80000000 /* disable_access bit */ -#define E1000_MPHY_ENA_ACCESS 0x40000000 /* enable_access bit */ -#define E1000_MPHY_BUSY 0x00010000 /* busy bit */ -#define E1000_MPHY_ADDRESS_MASK 0x0000FFFF /* address bit mask */ +#define E1000_MPHY_DIS_ACCESS 0x80000000 /* disable_access bit */ +#define E1000_MPHY_ENA_ACCESS 0x40000000 /* enable_access bit */ +#define E1000_MPHY_BUSY 0x00010000 /* busy bit */ +#define E1000_MPHY_ADDRESS_FNC_OVERRIDE 0x20000000 /* fnc_override bit */ +#define E1000_MPHY_ADDRESS_MASK 0x0000FFFF /* address mask */ #define IGP01E1000_PHY_PCS_INIT_REG 0x00B4 #define IGP01E1000_PHY_POLARITY_MASK 0x0078 @@ -275,6 +277,17 @@ bool e1000_is_mphy_ready(struct e1000_hw *hw); #define E1000_KMRNCTRLSTA_K1_CONFIG 0x7 #define E1000_KMRNCTRLSTA_K1_ENABLE 0x0002 /* enable K1 */ #define E1000_KMRNCTRLSTA_HD_CTRL 0x10 /* Kumeran HD Control */ +#if !defined(EXTERNAL_RELEASE) || defined(ULP_IN_D0_SUPPORT) +#define E1000_KMRNCTRLSTA_K0S_CTRL 0x1E /* Kumeran K0s Control */ +#define E1000_KMRNCTRLSTA_K0S_CTRL_ENTRY_LTNCY_SHIFT 0 +#define E1000_KMRNCTRLSTA_K0S_CTRL_MIN_TIME_SHIFT 4 +#define E1000_KMRNCTRLSTA_K0S_CTRL_ENTRY_LTNCY_MASK \ + (3 << E1000_KMRNCTRLSTA_K0S_CTRL_ENTRY_LTNCY_SHIFT) +#define E1000_KMRNCTRLSTA_K0S_CTRL_MIN_TIME_MASK \ + (7 << E1000_KMRNCTRLSTA_K0S_CTRL_MIN_TIME_SHIFT) +#define E1000_KMRNCTRLSTA_OP_MODES 0x1F /* Kumeran Modes of Operation */ +#define E1000_KMRNCTRLSTA_OP_MODES_LSC2CSC 0x0002 /* change LSC to CSC */ +#endif /* !EXTERNAL_RELEASE || ULP_IN_D0_SUPPORT */ #define IFE_PHY_EXTENDED_STATUS_CONTROL 0x10 #define IFE_PHY_SPECIAL_CONTROL 0x11 /* 100BaseTx PHY Special Ctrl */ diff --git a/sys/dev/netif/ig_hal/e1000_regs.h b/sys/dev/netif/ig_hal/e1000_regs.h index 964aa182d5..d688f4ecbd 100644 --- a/sys/dev/netif/ig_hal/e1000_regs.h +++ b/sys/dev/netif/ig_hal/e1000_regs.h @@ -110,6 +110,7 @@ #define E1000_EEMNGCTL 0x01010 /* MNG EEprom Control */ #define E1000_EEARBC 0x01024 /* EEPROM Auto Read Bus Control */ #define E1000_FLASHT 0x01028 /* FLASH Timer Register */ +#define E1000_EEARBC_I210 0x12024 /* EEPROM Auto Read Bus Control */ #define E1000_EEWR 0x0102C /* EEPROM Write Register - RW */ #define E1000_FLSWCTL 0x01030 /* FLASH control register */ #define E1000_FLSWDATA 0x01034 /* FLASH data register */ @@ -201,7 +202,7 @@ /* Queues fetch arbitration priority control register */ #define E1000_I210_TQAVARBCTRL 0x3574 /* Queues priority masks where _n and _p can be 0-3. */ -#define E1000_TQAVARBCTRL_QUEUE_PRI(_n, _p) ((_p) << (2 * _n)) +#define E1000_TQAVARBCTRL_QUEUE_PRI(_n, _p) ((_p) << (2 * (_n))) /* QAV Tx mode control registers where _n can be 0 or 1. */ #define E1000_I210_TQAVCC(_n) (0x3004 + 0x40 * (_n)) @@ -214,7 +215,7 @@ #define E1000_PQGPTC(_n) (0x010014 + (0x100 * (_n))) /* Queues packet buffer size masks where _n can be 0-3 and _s 0-63 [kB] */ -#define E1000_I210_TXPBS_SIZE(_n, _s) ((_s) << (6 * _n)) +#define E1000_I210_TXPBS_SIZE(_n, _s) ((_s) << (6 * (_n))) #define E1000_MMDAC 13 /* MMD Access Control */ #define E1000_MMDAAD 14 /* MMD Access Address/Data */ diff --git a/sys/dev/netif/ig_hal/e1000_vf.c b/sys/dev/netif/ig_hal/e1000_vf.c index 1edad6a110..7646f8b754 100644 --- a/sys/dev/netif/ig_hal/e1000_vf.c +++ b/sys/dev/netif/ig_hal/e1000_vf.c @@ -1,6 +1,6 @@ /****************************************************************************** - Copyright (c) 2001-2011, Intel Corporation + Copyright (c) 2001-2013, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without @@ -49,7 +49,7 @@ static s32 e1000_get_link_up_info_vf(struct e1000_hw *hw, u16 *speed, static s32 e1000_init_hw_vf(struct e1000_hw *hw); static s32 e1000_reset_hw_vf(struct e1000_hw *hw); static void e1000_update_mc_addr_list_vf(struct e1000_hw *hw, u8 *, u32); -static int e1000_rar_set_vf(struct e1000_hw *, u8 *, u32); +static int e1000_rar_set_vf(struct e1000_hw *, u8 *, u32); static s32 e1000_read_mac_addr_vf(struct e1000_hw *); /** @@ -321,7 +321,7 @@ static s32 e1000_init_hw_vf(struct e1000_hw *hw) * @index receive address array register **/ static int e1000_rar_set_vf(struct e1000_hw *hw, u8 *addr, - u32 E1000_UNUSEDARG index) + u32 E1000_UNUSEDARG index) { struct e1000_mbx_info *mbx = &hw->mbx; u32 msgbuf[3]; diff --git a/sys/dev/netif/ig_hal/e1000_vf.h b/sys/dev/netif/ig_hal/e1000_vf.h index 63850927d7..0865fa7f8e 100644 --- a/sys/dev/netif/ig_hal/e1000_vf.h +++ b/sys/dev/netif/ig_hal/e1000_vf.h @@ -1,6 +1,6 @@ /****************************************************************************** - Copyright (c) 2001-2011, Intel Corporation + Copyright (c) 2001-2013, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without @@ -208,7 +208,7 @@ struct e1000_mac_operations { s32 (*init_hw)(struct e1000_hw *); s32 (*setup_link)(struct e1000_hw *); void (*write_vfta)(struct e1000_hw *, u32, u32); - void (*rar_set)(struct e1000_hw *, u8*, u32); + int (*rar_set)(struct e1000_hw *, u8*, u32); s32 (*read_mac_addr)(struct e1000_hw *); }; diff --git a/sys/dev/netif/igb/if_igb.c b/sys/dev/netif/igb/if_igb.c index 5847e7e76c..d3a25fdaf4 100644 --- a/sys/dev/netif/igb/if_igb.c +++ b/sys/dev/netif/igb/if_igb.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001-2011, Intel Corporation + * Copyright (c) 2001-2013, Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -130,6 +130,7 @@ static struct igb_device { IGB_DEVICE(I210_SGMII), IGB_DEVICE(I211_COPPER), IGB_DEVICE(I354_BACKPLANE_1GBPS), + IGB_DEVICE(I354_BACKPLANE_2_5GBPS), IGB_DEVICE(I354_SGMII), /* required last entry */ @@ -165,12 +166,13 @@ static int igb_sysctl_npoll_txoff(SYSCTL_HANDLER_ARGS); #endif static void igb_vf_init_stats(struct igb_softc *); -static void igb_reset(struct igb_softc *); +static void igb_reset(struct igb_softc *, boolean_t); static void igb_update_stats_counters(struct igb_softc *); static void igb_update_vf_stats_counters(struct igb_softc *); static void igb_update_link_status(struct igb_softc *); static void igb_init_tx_unit(struct igb_softc *); static void igb_init_rx_unit(struct igb_softc *); +static void igb_init_dmac(struct igb_softc *, uint32_t); static void igb_set_vlan(struct igb_softc *); static void igb_set_multi(struct igb_softc *); @@ -398,6 +400,9 @@ igb_attach(device_t dev) device_get_unit(dev)); sc->dev = sc->osdep.dev = dev; + /* Enable bus mastering */ + pci_enable_busmaster(dev); + /* * Determine hardware and mac type */ @@ -473,9 +478,6 @@ igb_attach(device_t dev) igb_flowctrl); sc->ifm_flowctrl = ifmedia_str2ethfc(flowctrl); - /* Enable bus mastering */ - pci_enable_busmaster(dev); - /* * Allocate IO memory */ @@ -598,9 +600,9 @@ igb_attach(device_t dev) #endif if (sc->hw.phy.media_type == e1000_media_type_copper) { if (sc->hw.mac.type == e1000_i354) - e1000_set_eee_i354(&sc->hw); + e1000_set_eee_i354(&sc->hw, TRUE, TRUE); else - e1000_set_eee_i350(&sc->hw); + e1000_set_eee_i350(&sc->hw, TRUE, TRUE); } } @@ -646,7 +648,7 @@ igb_attach(device_t dev) igb_add_sysctl(sc); /* Now get a good starting state */ - igb_reset(sc); + igb_reset(sc, FALSE); /* Initialize statistics */ igb_update_stats_counters(sc); @@ -939,7 +941,7 @@ igb_init(void *xsc) /* Put the address into the Receive Address Array */ e1000_rar_set(&sc->hw, sc->hw.mac.addr, 0); - igb_reset(sc); + igb_reset(sc, FALSE); igb_update_link_status(sc); E1000_WRITE_REG(&sc->hw, E1000_VET, ETHERTYPE_VLAN); @@ -1028,9 +1030,9 @@ igb_init(void *xsc) /* Set Energy Efficient Ethernet */ if (sc->hw.phy.media_type == e1000_media_type_copper) { if (sc->hw.mac.type == e1000_i354) - e1000_set_eee_i354(&sc->hw); + e1000_set_eee_i354(&sc->hw, TRUE, TRUE); else - e1000_set_eee_i350(&sc->hw); + e1000_set_eee_i350(&sc->hw, TRUE, TRUE); } } @@ -1084,6 +1086,10 @@ igb_media_status(struct ifnet *ifp, struct ifmediareq *ifmr) else ifmr->ifm_active |= IFM_1000_T; break; + + case 2500: + ifmr->ifm_active |= IFM_2500_SX; + break; } if (sc->link_duplex == FULL_DUPLEX) @@ -1349,6 +1355,14 @@ igb_update_link_status(struct igb_softc *sc) hw->mac.type == e1000_i211) && hw->phy.id == I210_I_PHY_ID) msec_delay(IGB_I210_LINK_DELAY); + /* + * Reset if the media type changed. + * Support AutoMediaDetect for Marvell M88 PHY in i354. + */ + if (hw->dev_spec._82575.media_changed) { + hw->dev_spec._82575.media_changed = FALSE; + igb_reset(sc, TRUE); + } /* This can sleep */ ifp->if_link_state = LINK_STATE_UP; if_link_state_change(ifp); @@ -1399,7 +1413,7 @@ igb_stop(struct igb_softc *sc) } static void -igb_reset(struct igb_softc *sc) +igb_reset(struct igb_softc *sc, boolean_t media_reset) { struct ifnet *ifp = &sc->arpcom.ac_if; struct e1000_hw *hw = &sc->hw; @@ -1497,73 +1511,18 @@ igb_reset(struct igb_softc *sc) e1000_reset_hw(hw); E1000_WRITE_REG(hw, E1000_WUC, 0); + /* Reset for AutoMediaDetect */ + if (media_reset) { + e1000_setup_init_funcs(hw, TRUE); + e1000_get_bus_info(hw); + } + if (e1000_init_hw(hw) < 0) if_printf(ifp, "Hardware Initialization Failed\n"); /* Setup DMA Coalescing */ - if (hw->mac.type > e1000_82580 && hw->mac.type != e1000_i211) { - uint32_t dmac; - uint32_t reg; + igb_init_dmac(sc, pba); - if (sc->dma_coalesce == 0) { - /* - * Disabled - */ - reg = E1000_READ_REG(hw, E1000_DMACR); - reg &= ~E1000_DMACR_DMAC_EN; - E1000_WRITE_REG(hw, E1000_DMACR, reg); - goto reset_out; - } - - /* Set starting thresholds */ - E1000_WRITE_REG(hw, E1000_DMCTXTH, 0); - E1000_WRITE_REG(hw, E1000_DMCRTRH, 0); - - hwm = 64 * pba - sc->max_frame_size / 16; - if (hwm < 64 * (pba - 6)) - hwm = 64 * (pba - 6); - reg = E1000_READ_REG(hw, E1000_FCRTC); - reg &= ~E1000_FCRTC_RTH_COAL_MASK; - reg |= ((hwm << E1000_FCRTC_RTH_COAL_SHIFT) - & E1000_FCRTC_RTH_COAL_MASK); - E1000_WRITE_REG(hw, E1000_FCRTC, reg); - - dmac = pba - sc->max_frame_size / 512; - if (dmac < pba - 10) - dmac = pba - 10; - reg = E1000_READ_REG(hw, E1000_DMACR); - reg &= ~E1000_DMACR_DMACTHR_MASK; - reg |= ((dmac << E1000_DMACR_DMACTHR_SHIFT) - & E1000_DMACR_DMACTHR_MASK); - /* Transition to L0x or L1 if available.. */ - reg |= (E1000_DMACR_DMAC_EN | E1000_DMACR_DMAC_LX_MASK); - /* timer = value in sc->dma_coalesce in 32usec intervals */ - reg |= (sc->dma_coalesce >> 5); - E1000_WRITE_REG(hw, E1000_DMACR, reg); - - /* Set the interval before transition */ - reg = E1000_READ_REG(hw, E1000_DMCTLX); - reg |= 0x80000004; - E1000_WRITE_REG(hw, E1000_DMCTLX, reg); - - /* Free space in tx packet buffer to wake from DMA coal */ - E1000_WRITE_REG(hw, E1000_DMCTXTH, - (20480 - (2 * sc->max_frame_size)) >> 6); - - /* Make low power state decision controlled by DMA coal */ - reg = E1000_READ_REG(hw, E1000_PCIEMISC); - reg &= ~E1000_PCIEMISC_LX_DECISION; - E1000_WRITE_REG(hw, E1000_PCIEMISC, reg); - if_printf(ifp, "DMA Coalescing enabled\n"); - } else if (hw->mac.type == e1000_82580) { - uint32_t reg = E1000_READ_REG(hw, E1000_PCIEMISC); - - E1000_WRITE_REG(hw, E1000_DMACR, 0); - E1000_WRITE_REG(hw, E1000_PCIEMISC, - reg & ~E1000_PCIEMISC_LX_DECISION); - } - -reset_out: E1000_WRITE_REG(&sc->hw, E1000_VET, ETHERTYPE_VLAN); e1000_get_phy_info(hw); e1000_check_for_link(hw); @@ -4901,3 +4860,108 @@ igb_set_timer_cpuid(struct igb_softc *sc, boolean_t polling) else sc->timer_cpuid = rman_get_cpuid(sc->intr_data[0].intr_res); } + +static void +igb_init_dmac(struct igb_softc *sc, uint32_t pba) +{ + struct e1000_hw *hw = &sc->hw; + uint32_t reg; + + if (hw->mac.type == e1000_i211) + return; + + if (hw->mac.type > e1000_82580) { + uint32_t dmac; + uint16_t hwm; + + if (sc->dma_coalesce == 0) { /* Disabling it */ + reg = ~E1000_DMACR_DMAC_EN; + E1000_WRITE_REG(hw, E1000_DMACR, reg); + return; + } else { + if_printf(&sc->arpcom.ac_if, + "DMA Coalescing enabled\n"); + } + + /* Set starting threshold */ + E1000_WRITE_REG(hw, E1000_DMCTXTH, 0); + + hwm = 64 * pba - sc->max_frame_size / 16; + if (hwm < 64 * (pba - 6)) + hwm = 64 * (pba - 6); + reg = E1000_READ_REG(hw, E1000_FCRTC); + reg &= ~E1000_FCRTC_RTH_COAL_MASK; + reg |= ((hwm << E1000_FCRTC_RTH_COAL_SHIFT) + & E1000_FCRTC_RTH_COAL_MASK); + E1000_WRITE_REG(hw, E1000_FCRTC, reg); + + dmac = pba - sc->max_frame_size / 512; + if (dmac < pba - 10) + dmac = pba - 10; + reg = E1000_READ_REG(hw, E1000_DMACR); + reg &= ~E1000_DMACR_DMACTHR_MASK; + reg |= ((dmac << E1000_DMACR_DMACTHR_SHIFT) + & E1000_DMACR_DMACTHR_MASK); + + /* transition to L0x or L1 if available..*/ + reg |= (E1000_DMACR_DMAC_EN | E1000_DMACR_DMAC_LX_MASK); + + /* + * Check if status is 2.5Gb backplane connection + * before configuration of watchdog timer, which + * is in msec values in 12.8usec intervals watchdog + * timer = msec values in 32usec intervals for non + * 2.5Gb connection. + */ + if (hw->mac.type == e1000_i354) { + int status = E1000_READ_REG(hw, E1000_STATUS); + + if ((status & E1000_STATUS_2P5_SKU) && + !(status & E1000_STATUS_2P5_SKU_OVER)) + reg |= ((sc->dma_coalesce * 5) >> 6); + else + reg |= (sc->dma_coalesce >> 5); + } else { + reg |= (sc->dma_coalesce >> 5); + } + + E1000_WRITE_REG(hw, E1000_DMACR, reg); + + E1000_WRITE_REG(hw, E1000_DMCRTRH, 0); + + /* Set the interval before transition */ + reg = E1000_READ_REG(hw, E1000_DMCTLX); + if (hw->mac.type == e1000_i350) + reg |= IGB_DMCTLX_DCFLUSH_DIS; + /* + * In 2.5Gb connection, TTLX unit is 0.4 usec, which + * is 0x4*2 = 0xA. But delay is still 4 usec. + */ + if (hw->mac.type == e1000_i354) { + int status = E1000_READ_REG(hw, E1000_STATUS); + + if ((status & E1000_STATUS_2P5_SKU) && + !(status & E1000_STATUS_2P5_SKU_OVER)) + reg |= 0xA; + else + reg |= 0x4; + } else { + reg |= 0x4; + } + E1000_WRITE_REG(hw, E1000_DMCTLX, reg); + + /* Free space in tx packet buffer to wake from DMA coal */ + E1000_WRITE_REG(hw, E1000_DMCTXTH, + (IGB_TXPBSIZE - (2 * sc->max_frame_size)) >> 6); + + /* Make low power state decision controlled by DMA coal */ + reg = E1000_READ_REG(hw, E1000_PCIEMISC); + reg &= ~E1000_PCIEMISC_LX_DECISION; + E1000_WRITE_REG(hw, E1000_PCIEMISC, reg); + } else if (hw->mac.type == e1000_82580) { + reg = E1000_READ_REG(hw, E1000_PCIEMISC); + E1000_WRITE_REG(hw, E1000_PCIEMISC, + reg & ~E1000_PCIEMISC_LX_DECISION); + E1000_WRITE_REG(hw, E1000_DMACR, 0); + } +} diff --git a/sys/dev/netif/igb/if_igb.h b/sys/dev/netif/igb/if_igb.h index 6bf7abcdb9..8afb6f0f34 100644 --- a/sys/dev/netif/igb/if_igb.h +++ b/sys/dev/netif/igb/if_igb.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001-2011, Intel Corporation + * Copyright (c) 2001-2013, Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -152,11 +152,13 @@ #define IGB_SMARTSPEED_MAX 15 #define IGB_MAX_LOOP 10 -#define IGB_RX_PTHRESH (hw->mac.type <= e1000_82576 ? 16 : 8) +#define IGB_RX_PTHRESH ((hw->mac.type == e1000_i354) ? 12 : \ + ((hw->mac.type <= e1000_82576) ? 16 : 8)) #define IGB_RX_HTHRESH 8 -#define IGB_RX_WTHRESH 1 +#define IGB_RX_WTHRESH ((hw->mac.type == e1000_82576 && \ + sc->msix_mem_res) ? 1 : 4) -#define IGB_TX_PTHRESH 8 +#define IGB_TX_PTHRESH ((hw->mac.type == e1000_i354) ? 20 : 8) #define IGB_TX_HTHRESH 1 #define IGB_TX_WTHRESH 16 @@ -182,6 +184,7 @@ #define IGB_TSO_SIZE (IP_MAXPACKET + \ sizeof(struct ether_vlan_header)) #define IGB_HDR_BUF 128 +#define IGB_TXPBSIZE 20408 #define IGB_PKTTYPE_MASK 0x0000FFF0 #define IGB_CSUM_FEATURES (CSUM_IP | CSUM_TCP | CSUM_UDP) @@ -207,6 +210,9 @@ #define IGB_EITR_INTVL_MASK 0x7ffc #define IGB_EITR_INTVL_SHIFT 2 +/* Disable DMA Coalesce Flush */ +#define IGB_DMCTLX_DCFLUSH_DIS 0x80000000 + struct igb_softc; /*