X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=lib%2Flibrte_eal%2Flinuxapp%2Fkni%2Fethtool%2Figb%2Fe1000_82575.c;fp=lib%2Flibrte_eal%2Flinuxapp%2Fkni%2Fethtool%2Figb%2Fe1000_82575.c;h=b8c9a13f17d8afd356fe5f563aa68fa482388401;hb=b9ee370557f1f9f79c7f4f7eb37d78c562200ad6;hp=6df23ea6246c35f9b567e34e202e98e113e7b54f;hpb=e01d69d51c7913936e98867bc414b71bf1dba989;p=dpdk.git diff --git a/lib/librte_eal/linuxapp/kni/ethtool/igb/e1000_82575.c b/lib/librte_eal/linuxapp/kni/ethtool/igb/e1000_82575.c index 6df23ea624..b8c9a13f17 100644 --- a/lib/librte_eal/linuxapp/kni/ethtool/igb/e1000_82575.c +++ b/lib/librte_eal/linuxapp/kni/ethtool/igb/e1000_82575.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel(R) Gigabit Ethernet Linux driver - Copyright(c) 2007-2012 Intel Corporation. + Copyright(c) 2007-2013 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, @@ -31,9 +31,12 @@ * 82575GB Gigabit Network Connection * 82576 Gigabit Network Connection * 82576 Quad Port Gigabit Mezzanine Adapter + * 82580 Gigabit Network Connection + * I350 Gigabit Network Connection */ #include "e1000_api.h" +#include "e1000_i210.h" static s32 e1000_init_phy_params_82575(struct e1000_hw *hw); static s32 e1000_init_mac_params_82575(struct e1000_hw *hw); @@ -42,6 +45,7 @@ static void e1000_release_phy_82575(struct e1000_hw *hw); static s32 e1000_acquire_nvm_82575(struct e1000_hw *hw); static void e1000_release_nvm_82575(struct e1000_hw *hw); static s32 e1000_check_for_link_82575(struct e1000_hw *hw); +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); @@ -134,6 +138,9 @@ static bool e1000_sgmii_uses_mdio_82575(struct e1000_hw *hw) break; case e1000_82580: case e1000_i350: + case e1000_i354: + case e1000_i210: + case e1000_i211: reg = E1000_READ_REG(hw, E1000_MDICNFG); ext_mdio = !!(reg & E1000_MDICNFG_EXT_MDIO); break; @@ -195,9 +202,15 @@ static s32 e1000_init_phy_params_82575(struct e1000_hw *hw) switch (hw->mac.type) { case e1000_82580: case e1000_i350: + case e1000_i354: phy->ops.read_reg = e1000_read_phy_reg_82580; phy->ops.write_reg = e1000_write_phy_reg_82580; break; + case e1000_i210: + case e1000_i211: + phy->ops.read_reg = e1000_read_phy_reg_gs40g; + phy->ops.write_reg = e1000_write_phy_reg_gs40g; + break; default: phy->ops.read_reg = e1000_read_phy_reg_igp; phy->ops.write_reg = e1000_write_phy_reg_igp; @@ -209,6 +222,7 @@ static s32 e1000_init_phy_params_82575(struct e1000_hw *hw) /* Verify phy id and set remaining function pointers */ switch (phy->id) { + case M88E1543_E_PHY_ID: case I347AT4_E_PHY_ID: case M88E1112_E_PHY_ID: case M88E1340M_E_PHY_ID: @@ -221,9 +235,35 @@ 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 == M88E1543_E_PHY_ID) + phy->ops.get_cable_length = + e1000_get_cable_length_m88_gen2; else phy->ops.get_cable_length = e1000_get_cable_length_m88; phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_m88; + /* Check if this PHY is confgured for media swap. */ + if (phy->id == M88E1112_E_PHY_ID) { + u16 data; + + ret_val = phy->ops.write_reg(hw, + E1000_M88E1112_PAGE_ADDR, + 2); + if (ret_val) + goto out; + + ret_val = phy->ops.read_reg(hw, + E1000_M88E1112_MAC_CTRL_1, + &data); + if (ret_val) + goto out; + + 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; + } break; case IGP03E1000_E_PHY_ID: case IGP04E1000_E_PHY_ID: @@ -246,6 +286,15 @@ static s32 e1000_init_phy_params_82575(struct e1000_hw *hw) phy->ops.set_d0_lplu_state = e1000_set_d0_lplu_state_82580; phy->ops.set_d3_lplu_state = e1000_set_d3_lplu_state_82580; break; + case I210_I_PHY_ID: + phy->type = e1000_phy_i210; + phy->ops.check_polarity = e1000_check_polarity_m88; + phy->ops.get_info = e1000_get_phy_info_m88; + phy->ops.get_cable_length = e1000_get_cable_length_m88_gen2; + phy->ops.set_d0_lplu_state = e1000_set_d0_lplu_state_82580; + phy->ops.set_d3_lplu_state = e1000_set_d3_lplu_state_82580; + phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_m88; + break; default: ret_val = -E1000_ERR_PHY; goto out; @@ -282,27 +331,32 @@ s32 e1000_init_nvm_params_82575(struct e1000_hw *hw) size = 15; nvm->word_size = 1 << size; - nvm->opcode_bits = 8; - nvm->delay_usec = 1; - switch (nvm->override) { - case e1000_nvm_override_spi_large: - nvm->page_size = 32; - nvm->address_bits = 16; - break; - case e1000_nvm_override_spi_small: - nvm->page_size = 8; - nvm->address_bits = 8; - break; - default: - nvm->page_size = eecd & E1000_EECD_ADDR_BITS ? 32 : 8; - nvm->address_bits = eecd & E1000_EECD_ADDR_BITS ? 16 : 8; - break; - } - - nvm->type = e1000_nvm_eeprom_spi; + if (hw->mac.type < e1000_i210) { + nvm->opcode_bits = 8; + nvm->delay_usec = 1; + + switch (nvm->override) { + case e1000_nvm_override_spi_large: + nvm->page_size = 32; + nvm->address_bits = 16; + break; + case e1000_nvm_override_spi_small: + nvm->page_size = 8; + nvm->address_bits = 8; + break; + default: + nvm->page_size = eecd & E1000_EECD_ADDR_BITS ? 32 : 8; + nvm->address_bits = eecd & E1000_EECD_ADDR_BITS ? + 16 : 8; + break; + } + if (nvm->word_size == (1 << 15)) + nvm->page_size = 128; - if (nvm->word_size == (1 << 15)) - nvm->page_size = 128; + nvm->type = e1000_nvm_eeprom_spi; + } else { + nvm->type = e1000_nvm_flash_hw; + } /* Function Pointers */ nvm->ops.acquire = e1000_acquire_nvm_82575; @@ -324,6 +378,7 @@ s32 e1000_init_nvm_params_82575(struct e1000_hw *hw) nvm->ops.update = e1000_update_nvm_checksum_82580; break; case e1000_i350: + //case e1000_i354: nvm->ops.validate = e1000_validate_nvm_checksum_i350; nvm->ops.update = e1000_update_nvm_checksum_i350; break; @@ -357,11 +412,16 @@ static s32 e1000_init_mac_params_82575(struct e1000_hw *hw) mac->rar_entry_count = E1000_RAR_ENTRIES_82576; if (mac->type == e1000_82580) mac->rar_entry_count = E1000_RAR_ENTRIES_82580; - if (mac->type == e1000_i350) { + if (mac->type == e1000_i350 || mac->type == e1000_i354) mac->rar_entry_count = E1000_RAR_ENTRIES_I350; - /* Enable EEE default settings for i350 */ + + /* Enable EEE default settings for EEE supported devices */ + if (mac->type >= e1000_i350) dev_spec->eee_disable = false; - } + + /* Allow a single clear of the SW semaphore on I210 and newer */ + if (mac->type >= e1000_i210) + dev_spec->clear_semaphore_once = true; /* Set if part includes ASF firmware */ mac->asf_firmware_present = true; @@ -394,15 +454,13 @@ static s32 e1000_init_mac_params_82575(struct e1000_hw *hw) mac->ops.power_up_serdes = e1000_power_up_serdes_link_82575; /* check for link */ mac->ops.check_for_link = e1000_check_for_link_82575; - /* receive address register setting */ - mac->ops.rar_set = e1000_rar_set_generic; /* read mac address */ mac->ops.read_mac_addr = e1000_read_mac_addr_82575; /* configure collision distance */ mac->ops.config_collision_dist = e1000_config_collision_dist_82575; /* multicast address update */ mac->ops.update_mc_addr_list = e1000_update_mc_addr_list_generic; - if (hw->mac.type == e1000_i350) { + if (hw->mac.type == e1000_i350 || mac->type == e1000_i354) { /* writing VFTA */ mac->ops.write_vfta = e1000_write_vfta_i350; /* clearing VFTA */ @@ -413,6 +471,9 @@ static s32 e1000_init_mac_params_82575(struct e1000_hw *hw) /* clearing VFTA */ mac->ops.clear_vfta = e1000_clear_vfta_generic; } + if (hw->mac.type >= e1000_82580) + mac->ops.validate_mdi_setting = + e1000_validate_mdi_setting_crossover_generic; /* ID LED init */ mac->ops.id_led_init = e1000_id_led_init_generic; /* blink LED */ @@ -436,6 +497,10 @@ static s32 e1000_init_mac_params_82575(struct e1000_hw *hw) /* acquire SW_FW sync */ mac->ops.acquire_swfw_sync = e1000_acquire_swfw_sync_82575; mac->ops.release_swfw_sync = e1000_release_swfw_sync_82575; + if (mac->type >= e1000_i210) { + mac->ops.acquire_swfw_sync = e1000_acquire_swfw_sync_i210; + mac->ops.release_swfw_sync = e1000_release_swfw_sync_i210; + } /* set lan id for port to determine which phy lock to use */ hw->mac.ops.set_lan_id(hw); @@ -586,6 +651,11 @@ static s32 e1000_get_phy_id_82575(struct e1000_hw *hw) DEBUGFUNC("e1000_get_phy_id_82575"); + /* i354 devices can have a PHY that needs an extra read for 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 @@ -609,6 +679,9 @@ static s32 e1000_get_phy_id_82575(struct e1000_hw *hw) break; case e1000_82580: case e1000_i350: + case e1000_i354: + case e1000_i210: + case e1000_i211: mdic = E1000_READ_REG(hw, E1000_MDICNFG); mdic &= E1000_MDICNFG_PHY_MASK; phy->addr = mdic >> E1000_MDICNFG_PHY_SHIFT; @@ -804,7 +877,7 @@ 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; - u16 data; + u32 data; DEBUGFUNC("e1000_set_d0_lplu_state_82580"); @@ -852,7 +925,7 @@ 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; - u16 data; + u32 data; DEBUGFUNC("e1000_set_d3_lplu_state_82580"); @@ -1060,7 +1133,7 @@ static s32 e1000_get_cfg_done_82575(struct e1000_hw *hw) DEBUGOUT("MNG configuration cycle has not completed.\n"); /* If EEPROM is not marked present, init the PHY manually */ - if (((E1000_READ_REG(hw, E1000_EECD) & E1000_EECD_PRES) == 0) && + if (!(E1000_READ_REG(hw, E1000_EECD) & E1000_EECD_PRES) && (hw->phy.type == e1000_phy_igp_3)) e1000_phy_init_script_igp3(hw); @@ -1118,6 +1191,15 @@ static s32 e1000_check_for_link_82575(struct e1000_hw *hw) */ hw->mac.get_link_status = !hw->mac.serdes_has_link; + /* + * Configure Flow Control now that Auto-Neg has completed. + * First, we need to restore the desired flow control + * settings because we may have had to re-autoneg with a + * different link partner. + */ + ret_val = e1000_config_fc_after_link_up_generic(hw); + if (ret_val) + DEBUGOUT("Error configuring flow control\n"); } else { ret_val = e1000_check_for_copper_link_generic(hw); } @@ -1125,6 +1207,56 @@ static s32 e1000_check_for_link_82575(struct e1000_hw *hw) return ret_val; } +/** + * e1000_check_for_link_media_swap - Check which M88E1112 interface linked + * @hw: pointer to the HW structure + * + * Poll the M88E1112 interfaces to see which interface achieved link. + */ +static s32 e1000_check_for_link_media_swap(struct e1000_hw *hw) +{ + struct e1000_phy_info *phy = &hw->phy; + s32 ret_val; + u16 data; + u8 port = 0; + + DEBUGFUNC("e1000_check_for_link_media_swap"); + + /* Check the copper medium. */ + ret_val = phy->ops.write_reg(hw, E1000_M88E1112_PAGE_ADDR, 0); + if (ret_val) + return ret_val; + + ret_val = phy->ops.read_reg(hw, E1000_M88E1112_STATUS, &data); + if (ret_val) + return ret_val; + + if (data & E1000_M88E1112_STATUS_LINK) + port = E1000_MEDIA_PORT_COPPER; + + /* Check the other medium. */ + ret_val = phy->ops.write_reg(hw, E1000_M88E1112_PAGE_ADDR, 1); + if (ret_val) + return ret_val; + + ret_val = phy->ops.read_reg(hw, E1000_M88E1112_STATUS, &data); + if (ret_val) + return ret_val; + + if (data & E1000_M88E1112_STATUS_LINK) + port = E1000_MEDIA_PORT_OTHER; + + /* Determine if a swap needs to happen. */ + if (port && (hw->dev_spec._82575.media_port != port)) { + hw->dev_spec._82575.media_port = port; + hw->dev_spec._82575.media_changed = true; + } else { + ret_val = e1000_check_for_link_82575(hw); + } + + return E1000_SUCCESS; +} + /** * e1000_power_up_serdes_link_82575 - Power up the serdes link after shutdown * @hw: pointer to the HW structure @@ -1168,14 +1300,10 @@ 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"); - /* Set up defaults for the return values of this function */ - mac->serdes_has_link = false; - *speed = 0; - *duplex = 0; - /* * Read the PCS Status register for link state. For non-copper mode, * the status register is not accurate. The PCS status register is @@ -1202,6 +1330,23 @@ static s32 e1000_get_pcs_speed_and_duplex_82575(struct e1000_hw *hw, *duplex = FULL_DUPLEX; 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; + *duplex = 0; } return E1000_SUCCESS; @@ -1294,7 +1439,7 @@ static s32 e1000_reset_hw_82575(struct e1000_hw *hw) } /* If EEPROM is not present, run manual init scripts */ - if ((E1000_READ_REG(hw, E1000_EECD) & E1000_EECD_PRES) == 0) + if (!(E1000_READ_REG(hw, E1000_EECD) & E1000_EECD_PRES)) e1000_reset_init_script_82575(hw); /* Clear any pending interrupt events. */ @@ -1373,7 +1518,8 @@ static s32 e1000_init_hw_82575(struct e1000_hw *hw) static s32 e1000_setup_copper_link_82575(struct e1000_hw *hw) { u32 ctrl; - s32 ret_val; + s32 ret_val; + u32 phpm_reg; DEBUGFUNC("e1000_setup_copper_link_82575"); @@ -1382,6 +1528,20 @@ 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 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); if (ret_val) goto out; @@ -1397,13 +1557,20 @@ static s32 e1000_setup_copper_link_82575(struct e1000_hw *hw) } } switch (hw->phy.type) { + case e1000_phy_i210: case e1000_phy_m88: - if (hw->phy.id == I347AT4_E_PHY_ID || - hw->phy.id == M88E1112_E_PHY_ID || - hw->phy.id == M88E1340M_E_PHY_ID) + switch (hw->phy.id) { + case I347AT4_E_PHY_ID: + case M88E1112_E_PHY_ID: + case M88E1340M_E_PHY_ID: + case M88E1543_E_PHY_ID: + case I210_I_PHY_ID: ret_val = e1000_copper_link_setup_m88_gen2(hw); - else + break; + default: ret_val = e1000_copper_link_setup_m88(hw); + break; + } break; case e1000_phy_igp_3: ret_val = e1000_copper_link_setup_igp(hw); @@ -1435,7 +1602,7 @@ out: **/ static s32 e1000_setup_serdes_link_82575(struct e1000_hw *hw) { - u32 ctrl_ext, ctrl_reg, reg; + u32 ctrl_ext, ctrl_reg, reg, anadv_reg; bool pcs_autoneg; s32 ret_val = E1000_SUCCESS; u16 data; @@ -1519,26 +1686,47 @@ static s32 e1000_setup_serdes_link_82575(struct e1000_hw *hw) reg &= ~(E1000_PCS_LCTL_AN_ENABLE | E1000_PCS_LCTL_FLV_LINK_UP | E1000_PCS_LCTL_FSD | E1000_PCS_LCTL_FORCE_LINK); - /* - * We force flow control to prevent the CTRL register values from being - * overwritten by the autonegotiated flow control values - */ - reg |= E1000_PCS_LCTL_FORCE_FCTRL; - if (pcs_autoneg) { /* Set PCS register for autoneg */ reg |= E1000_PCS_LCTL_AN_ENABLE | /* Enable Autoneg */ E1000_PCS_LCTL_AN_RESTART; /* Restart autoneg */ + + /* Disable force flow control for autoneg */ + reg &= ~E1000_PCS_LCTL_FORCE_FCTRL; + + /* Configure flow control advertisement for autoneg */ + anadv_reg = E1000_READ_REG(hw, E1000_PCS_ANADV); + anadv_reg &= ~(E1000_TXCW_ASM_DIR | E1000_TXCW_PAUSE); + + switch (hw->fc.requested_mode) { + case e1000_fc_full: + case e1000_fc_rx_pause: + anadv_reg |= E1000_TXCW_ASM_DIR; + anadv_reg |= E1000_TXCW_PAUSE; + break; + case e1000_fc_tx_pause: + anadv_reg |= E1000_TXCW_ASM_DIR; + break; + default: + break; + } + + E1000_WRITE_REG(hw, E1000_PCS_ANADV, anadv_reg); + DEBUGOUT1("Configuring Autoneg:PCS_LCTL=0x%08X\n", reg); } else { /* Set PCS register for forced link */ reg |= E1000_PCS_LCTL_FSD; /* Force Speed */ + + /* Force flow control for forced link */ + reg |= E1000_PCS_LCTL_FORCE_FCTRL; + DEBUGOUT1("Configuring Forced Link:PCS_LCTL=0x%08X\n", reg); } E1000_WRITE_REG(hw, E1000_PCS_LCTL, reg); - if (!e1000_sgmii_active_82575(hw)) + if (!pcs_autoneg && !e1000_sgmii_active_82575(hw)) e1000_force_mac_fc_generic(hw); return ret_val; @@ -1557,140 +1745,70 @@ static s32 e1000_setup_serdes_link_82575(struct e1000_hw *hw) **/ static s32 e1000_get_media_type_82575(struct e1000_hw *hw) { - u32 lan_id = 0; - s32 ret_val = E1000_ERR_CONFIG; struct e1000_dev_spec_82575 *dev_spec = &hw->dev_spec._82575; + s32 ret_val = E1000_SUCCESS; u32 ctrl_ext = 0; - u32 current_link_mode = 0; - u16 init_ctrl_wd_3 = 0; - u8 init_ctrl_wd_3_offset = 0; - u8 init_ctrl_wd_3_bit_offset = 0; + u32 link_mode = 0; /* Set internal phy as default */ dev_spec->sgmii_active = false; dev_spec->module_plugged = false; - /* - * Check if NVM access method is attached already. - * If it is then Init Control Word #3 is considered - * otherwise runtime CSR register content is taken. - */ - /* Get CSR setting */ ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT); - /* Get link mode setting */ - if ((hw->nvm.ops.read) && (hw->nvm.ops.read != e1000_null_read_nvm)) { - /* Take link mode from EEPROM */ - - /* - * Get LAN port ID to derive its - * adequate Init Control Word #3 - */ - lan_id = ((E1000_READ_REG(hw, E1000_STATUS) & - E1000_STATUS_LAN_ID_MASK) >> E1000_STATUS_LAN_ID_OFFSET); - /* - * Derive Init Control Word #3 offset - * and mask to pick up link mode setting. - */ - if (hw->mac.type < e1000_82580) { - init_ctrl_wd_3_offset = lan_id ? - NVM_INIT_CONTROL3_PORT_A : NVM_INIT_CONTROL3_PORT_B; - init_ctrl_wd_3_bit_offset = NVM_WORD24_LNK_MODE_OFFSET; - } else { - init_ctrl_wd_3_offset = - NVM_82580_LAN_FUNC_OFFSET(lan_id) + - NVM_INIT_CONTROL3_PORT_A; - init_ctrl_wd_3_bit_offset = - NVM_WORD24_82580_LNK_MODE_OFFSET; - } - /* Read Init Control Word #3*/ - hw->nvm.ops.read(hw, init_ctrl_wd_3_offset, 1, &init_ctrl_wd_3); - current_link_mode = init_ctrl_wd_3; - /* - * Switch to CSR for all but internal PHY. - */ - if ((init_ctrl_wd_3 << (E1000_CTRL_EXT_LINK_MODE_OFFSET - - init_ctrl_wd_3_bit_offset)) != - E1000_CTRL_EXT_LINK_MODE_GMII) { - current_link_mode = ctrl_ext; - init_ctrl_wd_3_bit_offset = - E1000_CTRL_EXT_LINK_MODE_OFFSET; - } - } else { - /* Take link mode from CSR */ - current_link_mode = ctrl_ext; - init_ctrl_wd_3_bit_offset = E1000_CTRL_EXT_LINK_MODE_OFFSET; - } - - /* - * Align link mode bits to - * their CTRL_EXT location. - */ - current_link_mode <<= (E1000_CTRL_EXT_LINK_MODE_OFFSET - - init_ctrl_wd_3_bit_offset); - current_link_mode &= E1000_CTRL_EXT_LINK_MODE_MASK; - - switch (current_link_mode) { + /* extract link mode setting */ + link_mode = ctrl_ext & E1000_CTRL_EXT_LINK_MODE_MASK; + switch (link_mode) { case E1000_CTRL_EXT_LINK_MODE_1000BASE_KX: hw->phy.media_type = e1000_media_type_internal_serdes; - current_link_mode = E1000_CTRL_EXT_LINK_MODE_1000BASE_KX; break; case E1000_CTRL_EXT_LINK_MODE_GMII: hw->phy.media_type = e1000_media_type_copper; - current_link_mode = E1000_CTRL_EXT_LINK_MODE_GMII; break; case E1000_CTRL_EXT_LINK_MODE_SGMII: - case E1000_CTRL_EXT_LINK_MODE_PCIE_SERDES: /* Get phy control interface type set (MDIO vs. I2C)*/ if (e1000_sgmii_uses_mdio_82575(hw)) { hw->phy.media_type = e1000_media_type_copper; dev_spec->sgmii_active = true; - current_link_mode = E1000_CTRL_EXT_LINK_MODE_SGMII; - } else { - ret_val = e1000_set_sfp_media_type_82575(hw); - if (ret_val != E1000_SUCCESS) - goto out; - if (hw->phy.media_type == - e1000_media_type_internal_serdes) { - current_link_mode = - E1000_CTRL_EXT_LINK_MODE_PCIE_SERDES; - } else if (hw->phy.media_type == - e1000_media_type_copper) { - current_link_mode = - E1000_CTRL_EXT_LINK_MODE_SGMII; + break; + } + /* fall through for I2C based SGMII */ + case E1000_CTRL_EXT_LINK_MODE_PCIE_SERDES: + /* read media type from SFP EEPROM */ + ret_val = e1000_set_sfp_media_type_82575(hw); + if ((ret_val != E1000_SUCCESS) || + (hw->phy.media_type == e1000_media_type_unknown)) { + /* + * If media type was not identified then return media + * type defined by the CTRL_EXT settings. + */ + hw->phy.media_type = e1000_media_type_internal_serdes; + + if (link_mode == E1000_CTRL_EXT_LINK_MODE_SGMII) { + hw->phy.media_type = e1000_media_type_copper; + dev_spec->sgmii_active = true; } + + break; } - break; - default: - DEBUGOUT("Link mode mask doesn't fit bit field size\n"); - goto out; - } - /* - * Do not change current link mode setting - * if media type is fibre or has not been - * recognized. - */ - if ((hw->phy.media_type != e1000_media_type_unknown) && - (hw->phy.media_type != e1000_media_type_fiber)) { - /* Update link mode */ + + /* do not change link mode for 100BaseFX */ + if (dev_spec->eth_flags.e100_base_fx) + break; + + /* change current link mode setting */ ctrl_ext &= ~E1000_CTRL_EXT_LINK_MODE_MASK; - E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext | - current_link_mode); - } - ret_val = E1000_SUCCESS; -out: - /* - * If media type was not identified then return media type - * defined by the CTRL_EXT settings. - */ - if (hw->phy.media_type == e1000_media_type_unknown) { - if (current_link_mode == E1000_CTRL_EXT_LINK_MODE_SGMII) - hw->phy.media_type = e1000_media_type_copper; + if (hw->phy.media_type == e1000_media_type_copper) + ctrl_ext |= E1000_CTRL_EXT_LINK_MODE_SGMII; else - hw->phy.media_type = e1000_media_type_internal_serdes; + ctrl_ext |= E1000_CTRL_EXT_LINK_MODE_PCIE_SERDES; + + E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext); + + break; } return ret_val; @@ -1708,40 +1826,52 @@ static s32 e1000_set_sfp_media_type_82575(struct e1000_hw *hw) s32 ret_val = E1000_ERR_CONFIG; u32 ctrl_ext = 0; struct e1000_dev_spec_82575 *dev_spec = &hw->dev_spec._82575; - struct sfp_e1000_flags eth_flags = {0}; + struct sfp_e1000_flags *eth_flags = &dev_spec->eth_flags; u8 tranceiver_type = 0; + s32 timeout = 3; - /* Turn I2C interface ON */ + /* Turn I2C interface ON and power on sfp cage */ ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT); + ctrl_ext &= ~E1000_CTRL_EXT_SDP3_DATA; E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext | E1000_CTRL_I2C_ENA); + E1000_WRITE_FLUSH(hw); + /* Read SFP module data */ - ret_val = e1000_read_sfp_data_byte(hw, + while (timeout) { + ret_val = e1000_read_sfp_data_byte(hw, E1000_I2CCMD_SFP_DATA_ADDR(E1000_SFF_IDENTIFIER_OFFSET), &tranceiver_type); + if (ret_val == E1000_SUCCESS) + break; + msec_delay(100); + timeout--; + } if (ret_val != E1000_SUCCESS) goto out; + ret_val = e1000_read_sfp_data_byte(hw, E1000_I2CCMD_SFP_DATA_ADDR(E1000_SFF_ETH_FLAGS_OFFSET), - (u8 *)ð_flags); + (u8 *)eth_flags); if (ret_val != E1000_SUCCESS) goto out; - /* - * Check if there is some SFP - * module plugged and powered - */ + + /* Check if there is some SFP module plugged and powered */ if ((tranceiver_type == E1000_SFF_IDENTIFIER_SFP) || (tranceiver_type == E1000_SFF_IDENTIFIER_SFF)) { dev_spec->module_plugged = true; - if (eth_flags.e1000_base_lx || eth_flags.e1000_base_sx) { + if (eth_flags->e1000_base_lx || eth_flags->e1000_base_sx) { + hw->phy.media_type = e1000_media_type_internal_serdes; + } else if (eth_flags->e100_base_fx) { + dev_spec->sgmii_active = true; hw->phy.media_type = e1000_media_type_internal_serdes; - } else if (eth_flags.e1000_base_t) { + } else if (eth_flags->e1000_base_t) { dev_spec->sgmii_active = true; hw->phy.media_type = e1000_media_type_copper; } else { - hw->phy.media_type = e1000_media_type_unknown; - DEBUGOUT("PHY module has not been recognized\n"); - goto out; + hw->phy.media_type = e1000_media_type_unknown; + DEBUGOUT("PHY module has not been recognized\n"); + goto out; } } else { hw->phy.media_type = e1000_media_type_unknown; @@ -2108,42 +2238,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: - 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: + case e1000_i354: + 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); } /** @@ -2167,6 +2288,7 @@ void e1000_vmdq_set_loopback_pf(struct e1000_hw *hw, bool enable) E1000_WRITE_REG(hw, E1000_DTXSWC, dtxswc); break; case e1000_i350: + case e1000_i354: dtxswc = E1000_READ_REG(hw, E1000_TXSWC); if (enable) dtxswc |= E1000_DTXSWC_VMDQ_LOOPBACK_EN; @@ -2312,6 +2434,10 @@ static s32 e1000_reset_hw_82580(struct e1000_hw *hw) hw->dev_spec._82575.global_device_reset = false; + /* 82580 does not reliably do global_device_reset due to hw errata */ + if (hw->mac.type == e1000_82580) + global_device_reset = false; + /* Get current control state. */ ctrl = E1000_READ_REG(hw, E1000_CTRL); @@ -2359,10 +2485,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) == 0) - e1000_reset_init_script_82575(hw); - /* clear global device reset status bit */ E1000_WRITE_REG(hw, E1000_STATUS, E1000_STAT_DEV_RST_SET); @@ -2539,7 +2661,7 @@ static s32 e1000_update_nvm_checksum_82580(struct e1000_hw *hw) goto out; } - if ((nvm_data & NVM_COMPATIBILITY_BIT_MASK) == 0) { + if (!(nvm_data & NVM_COMPATIBILITY_BIT_MASK)) { /* set compatibility bit to validate checksums appropriately */ nvm_data = nvm_data | NVM_COMPATIBILITY_BIT_MASK; ret_val = hw->nvm.ops.write(hw, NVM_COMPATIBILITY_REG_3, 1, @@ -2616,6 +2738,45 @@ out: return ret_val; } +/** + * __e1000_access_emi_reg - Read/write EMI register + * @hw: pointer to the HW structure + * @addr: EMI address to program + * @data: pointer to value to read/write from/to the EMI address + * @read: boolean flag to indicate read or write + **/ +static s32 __e1000_access_emi_reg(struct e1000_hw *hw, u16 address, + u16 *data, bool read) +{ + s32 ret_val = E1000_SUCCESS; + + DEBUGFUNC("__e1000_access_emi_reg"); + + ret_val = hw->phy.ops.write_reg(hw, E1000_EMIADD, address); + if (ret_val) + return ret_val; + + if (read) + ret_val = hw->phy.ops.read_reg(hw, E1000_EMIDATA, data); + else + ret_val = hw->phy.ops.write_reg(hw, E1000_EMIDATA, *data); + + return ret_val; +} + +/** + * e1000_read_emi_reg - Read Extended Management Interface register + * @hw: pointer to the HW structure + * @addr: EMI address to program + * @data: value to be read from the EMI address + **/ +s32 e1000_read_emi_reg(struct e1000_hw *hw, u16 addr, u16 *data) +{ + DEBUGFUNC("e1000_read_emi_reg"); + + return __e1000_access_emi_reg(hw, addr, data, true); +} + /** * e1000_set_eee_i350 - Enable/disable EEE support * @hw: pointer to the HW structure @@ -2638,10 +2799,15 @@ s32 e1000_set_eee_i350(struct e1000_hw *hw) /* enable or disable per user setting */ 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); eeer |= (E1000_EEER_TX_LPI_EN | E1000_EEER_RX_LPI_EN | E1000_EEER_LPI_FC); + /* This bit should not be set in normal operation. */ + if (eee_su & E1000_EEE_SU_LPI_CLK_STP) + DEBUGOUT("LPI Clock Stop Bit should not be set!\n"); } else { ipcnfg &= ~(E1000_IPCNFG_EEE_1G_AN | E1000_IPCNFG_EEE_100M_AN); eeer &= ~(E1000_EEER_TX_LPI_EN | E1000_EEER_RX_LPI_EN | @@ -2656,6 +2822,112 @@ out: return ret_val; } +/** + * e1000_set_eee_i354 - Enable/disable EEE support + * @hw: pointer to the HW structure + * + * Enable/disable EEE legacy mode based on setting in dev_spec structure. + * + **/ +s32 e1000_set_eee_i354(struct e1000_hw *hw) +{ + struct e1000_phy_info *phy = &hw->phy; + s32 ret_val = E1000_SUCCESS; + u16 phy_data; + + DEBUGFUNC("e1000_set_eee_i354"); + + if ((hw->phy.media_type != e1000_media_type_copper) || + ((phy->id != M88E1543_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_M88E1543_PAGE_ADDR, 18); + if (ret_val) + goto out; + + ret_val = phy->ops.read_reg(hw, E1000_M88E1543_EEE_CTRL_1, + &phy_data); + if (ret_val) + goto out; + + 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_M88E1543_PAGE_ADDR, 0); + if (ret_val) + goto out; + + /* Turn on EEE advertisement. */ + ret_val = e1000_read_xmdio_reg(hw, E1000_EEE_ADV_ADDR_I354, + E1000_EEE_ADV_DEV_I354, + &phy_data); + if (ret_val) + goto out; + + phy_data |= E1000_EEE_ADV_100_SUPPORTED | + E1000_EEE_ADV_1000_SUPPORTED; + ret_val = e1000_write_xmdio_reg(hw, E1000_EEE_ADV_ADDR_I354, + E1000_EEE_ADV_DEV_I354, + phy_data); + } else { + /* Turn off EEE advertisement. */ + ret_val = e1000_read_xmdio_reg(hw, E1000_EEE_ADV_ADDR_I354, + E1000_EEE_ADV_DEV_I354, + &phy_data); + if (ret_val) + goto out; + + phy_data &= ~(E1000_EEE_ADV_100_SUPPORTED | + E1000_EEE_ADV_1000_SUPPORTED); + ret_val = e1000_write_xmdio_reg(hw, E1000_EEE_ADV_ADDR_I354, + E1000_EEE_ADV_DEV_I354, + phy_data); + } + +out: + return ret_val; +} + +/** + * e1000_get_eee_status_i354 - Get EEE status + * @hw: pointer to the HW structure + * @status: EEE status + * + * Get EEE status by guessing based on whether Tx or Rx LPI indications have + * been received. + **/ +s32 e1000_get_eee_status_i354(struct e1000_hw *hw, bool *status) +{ + struct e1000_phy_info *phy = &hw->phy; + s32 ret_val = E1000_SUCCESS; + u16 phy_data; + + DEBUGFUNC("e1000_get_eee_status_i354"); + + /* Check if EEE is supported on this device. */ + if ((hw->phy.media_type != e1000_media_type_copper) || + ((phy->id != M88E1543_E_PHY_ID))) + goto out; + + ret_val = e1000_read_xmdio_reg(hw, E1000_PCS_STATUS_ADDR_I354, + E1000_PCS_STATUS_DEV_I354, + &phy_data); + if (ret_val) + goto out; + + *status = phy_data & (E1000_PCS_STATUS_TX_LPI_RCVD | + E1000_PCS_STATUS_RX_LPI_RCVD) ? true : false; + +out: + return ret_val; +} + /* Due to a hw errata, if the host tries to configure the VFTA register * while performing queries from the BMC or DMA, then the VFTA in some * cases won't be written. @@ -2752,7 +3024,7 @@ s32 e1000_read_i2c_byte_generic(struct e1000_hw *hw, u8 byte_offset, u32 retry = 1; u16 swfw_mask = 0; - bool nack = 1; + bool nack = true; DEBUGFUNC("e1000_read_i2c_byte_generic"); @@ -3023,7 +3295,7 @@ static s32 e1000_get_i2c_ack(struct e1000_hw *hw) u32 i = 0; u32 i2cctl = E1000_READ_REG(hw, E1000_I2CPARAMS); u32 timeout = 10; - bool ack = 1; + bool ack = true; DEBUGFUNC("e1000_get_i2c_ack"); @@ -3043,7 +3315,7 @@ static s32 e1000_get_i2c_ack(struct e1000_hw *hw) return E1000_ERR_I2C; ack = e1000_get_i2c_data(&i2cctl); - if (ack == 1) { + if (ack) { DEBUGOUT("I2C ack was not received.\n"); status = E1000_ERR_I2C; }