162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* Copyright(c) 1999 - 2018 Intel Corporation. */ 362306a36Sopenharmony_ci 462306a36Sopenharmony_ci#include <linux/pci.h> 562306a36Sopenharmony_ci#include <linux/delay.h> 662306a36Sopenharmony_ci#include <linux/sched.h> 762306a36Sopenharmony_ci#include <linux/netdevice.h> 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci#include "ixgbe.h" 1062306a36Sopenharmony_ci#include "ixgbe_common.h" 1162306a36Sopenharmony_ci#include "ixgbe_phy.h" 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_cistatic s32 ixgbe_acquire_eeprom(struct ixgbe_hw *hw); 1462306a36Sopenharmony_cistatic s32 ixgbe_get_eeprom_semaphore(struct ixgbe_hw *hw); 1562306a36Sopenharmony_cistatic void ixgbe_release_eeprom_semaphore(struct ixgbe_hw *hw); 1662306a36Sopenharmony_cistatic s32 ixgbe_ready_eeprom(struct ixgbe_hw *hw); 1762306a36Sopenharmony_cistatic void ixgbe_standby_eeprom(struct ixgbe_hw *hw); 1862306a36Sopenharmony_cistatic void ixgbe_shift_out_eeprom_bits(struct ixgbe_hw *hw, u16 data, 1962306a36Sopenharmony_ci u16 count); 2062306a36Sopenharmony_cistatic u16 ixgbe_shift_in_eeprom_bits(struct ixgbe_hw *hw, u16 count); 2162306a36Sopenharmony_cistatic void ixgbe_raise_eeprom_clk(struct ixgbe_hw *hw, u32 *eec); 2262306a36Sopenharmony_cistatic void ixgbe_lower_eeprom_clk(struct ixgbe_hw *hw, u32 *eec); 2362306a36Sopenharmony_cistatic void ixgbe_release_eeprom(struct ixgbe_hw *hw); 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_cistatic s32 ixgbe_mta_vector(struct ixgbe_hw *hw, u8 *mc_addr); 2662306a36Sopenharmony_cistatic s32 ixgbe_poll_eerd_eewr_done(struct ixgbe_hw *hw, u32 ee_reg); 2762306a36Sopenharmony_cistatic s32 ixgbe_read_eeprom_buffer_bit_bang(struct ixgbe_hw *hw, u16 offset, 2862306a36Sopenharmony_ci u16 words, u16 *data); 2962306a36Sopenharmony_cistatic s32 ixgbe_write_eeprom_buffer_bit_bang(struct ixgbe_hw *hw, u16 offset, 3062306a36Sopenharmony_ci u16 words, u16 *data); 3162306a36Sopenharmony_cistatic s32 ixgbe_detect_eeprom_page_size_generic(struct ixgbe_hw *hw, 3262306a36Sopenharmony_ci u16 offset); 3362306a36Sopenharmony_cistatic s32 ixgbe_disable_pcie_primary(struct ixgbe_hw *hw); 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci/* Base table for registers values that change by MAC */ 3662306a36Sopenharmony_ciconst u32 ixgbe_mvals_8259X[IXGBE_MVALS_IDX_LIMIT] = { 3762306a36Sopenharmony_ci IXGBE_MVALS_INIT(8259X) 3862306a36Sopenharmony_ci}; 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci/** 4162306a36Sopenharmony_ci * ixgbe_device_supports_autoneg_fc - Check if phy supports autoneg flow 4262306a36Sopenharmony_ci * control 4362306a36Sopenharmony_ci * @hw: pointer to hardware structure 4462306a36Sopenharmony_ci * 4562306a36Sopenharmony_ci * There are several phys that do not support autoneg flow control. This 4662306a36Sopenharmony_ci * function check the device id to see if the associated phy supports 4762306a36Sopenharmony_ci * autoneg flow control. 4862306a36Sopenharmony_ci **/ 4962306a36Sopenharmony_cibool ixgbe_device_supports_autoneg_fc(struct ixgbe_hw *hw) 5062306a36Sopenharmony_ci{ 5162306a36Sopenharmony_ci bool supported = false; 5262306a36Sopenharmony_ci ixgbe_link_speed speed; 5362306a36Sopenharmony_ci bool link_up; 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci switch (hw->phy.media_type) { 5662306a36Sopenharmony_ci case ixgbe_media_type_fiber: 5762306a36Sopenharmony_ci /* flow control autoneg black list */ 5862306a36Sopenharmony_ci switch (hw->device_id) { 5962306a36Sopenharmony_ci case IXGBE_DEV_ID_X550EM_A_SFP: 6062306a36Sopenharmony_ci case IXGBE_DEV_ID_X550EM_A_SFP_N: 6162306a36Sopenharmony_ci supported = false; 6262306a36Sopenharmony_ci break; 6362306a36Sopenharmony_ci default: 6462306a36Sopenharmony_ci hw->mac.ops.check_link(hw, &speed, &link_up, false); 6562306a36Sopenharmony_ci /* if link is down, assume supported */ 6662306a36Sopenharmony_ci if (link_up) 6762306a36Sopenharmony_ci supported = speed == IXGBE_LINK_SPEED_1GB_FULL; 6862306a36Sopenharmony_ci else 6962306a36Sopenharmony_ci supported = true; 7062306a36Sopenharmony_ci } 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ci break; 7362306a36Sopenharmony_ci case ixgbe_media_type_backplane: 7462306a36Sopenharmony_ci if (hw->device_id == IXGBE_DEV_ID_X550EM_X_XFI) 7562306a36Sopenharmony_ci supported = false; 7662306a36Sopenharmony_ci else 7762306a36Sopenharmony_ci supported = true; 7862306a36Sopenharmony_ci break; 7962306a36Sopenharmony_ci case ixgbe_media_type_copper: 8062306a36Sopenharmony_ci /* only some copper devices support flow control autoneg */ 8162306a36Sopenharmony_ci switch (hw->device_id) { 8262306a36Sopenharmony_ci case IXGBE_DEV_ID_82599_T3_LOM: 8362306a36Sopenharmony_ci case IXGBE_DEV_ID_X540T: 8462306a36Sopenharmony_ci case IXGBE_DEV_ID_X540T1: 8562306a36Sopenharmony_ci case IXGBE_DEV_ID_X550T: 8662306a36Sopenharmony_ci case IXGBE_DEV_ID_X550T1: 8762306a36Sopenharmony_ci case IXGBE_DEV_ID_X550EM_X_10G_T: 8862306a36Sopenharmony_ci case IXGBE_DEV_ID_X550EM_A_10G_T: 8962306a36Sopenharmony_ci case IXGBE_DEV_ID_X550EM_A_1G_T: 9062306a36Sopenharmony_ci case IXGBE_DEV_ID_X550EM_A_1G_T_L: 9162306a36Sopenharmony_ci supported = true; 9262306a36Sopenharmony_ci break; 9362306a36Sopenharmony_ci default: 9462306a36Sopenharmony_ci break; 9562306a36Sopenharmony_ci } 9662306a36Sopenharmony_ci break; 9762306a36Sopenharmony_ci default: 9862306a36Sopenharmony_ci break; 9962306a36Sopenharmony_ci } 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ci if (!supported) 10262306a36Sopenharmony_ci hw_dbg(hw, "Device %x does not support flow control autoneg\n", 10362306a36Sopenharmony_ci hw->device_id); 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_ci return supported; 10662306a36Sopenharmony_ci} 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_ci/** 10962306a36Sopenharmony_ci * ixgbe_setup_fc_generic - Set up flow control 11062306a36Sopenharmony_ci * @hw: pointer to hardware structure 11162306a36Sopenharmony_ci * 11262306a36Sopenharmony_ci * Called at init time to set up flow control. 11362306a36Sopenharmony_ci **/ 11462306a36Sopenharmony_cis32 ixgbe_setup_fc_generic(struct ixgbe_hw *hw) 11562306a36Sopenharmony_ci{ 11662306a36Sopenharmony_ci s32 ret_val = 0; 11762306a36Sopenharmony_ci u32 reg = 0, reg_bp = 0; 11862306a36Sopenharmony_ci u16 reg_cu = 0; 11962306a36Sopenharmony_ci bool locked = false; 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_ci /* 12262306a36Sopenharmony_ci * Validate the requested mode. Strict IEEE mode does not allow 12362306a36Sopenharmony_ci * ixgbe_fc_rx_pause because it will cause us to fail at UNH. 12462306a36Sopenharmony_ci */ 12562306a36Sopenharmony_ci if (hw->fc.strict_ieee && hw->fc.requested_mode == ixgbe_fc_rx_pause) { 12662306a36Sopenharmony_ci hw_dbg(hw, "ixgbe_fc_rx_pause not valid in strict IEEE mode\n"); 12762306a36Sopenharmony_ci return -EINVAL; 12862306a36Sopenharmony_ci } 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ci /* 13162306a36Sopenharmony_ci * 10gig parts do not have a word in the EEPROM to determine the 13262306a36Sopenharmony_ci * default flow control setting, so we explicitly set it to full. 13362306a36Sopenharmony_ci */ 13462306a36Sopenharmony_ci if (hw->fc.requested_mode == ixgbe_fc_default) 13562306a36Sopenharmony_ci hw->fc.requested_mode = ixgbe_fc_full; 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ci /* 13862306a36Sopenharmony_ci * Set up the 1G and 10G flow control advertisement registers so the 13962306a36Sopenharmony_ci * HW will be able to do fc autoneg once the cable is plugged in. If 14062306a36Sopenharmony_ci * we link at 10G, the 1G advertisement is harmless and vice versa. 14162306a36Sopenharmony_ci */ 14262306a36Sopenharmony_ci switch (hw->phy.media_type) { 14362306a36Sopenharmony_ci case ixgbe_media_type_backplane: 14462306a36Sopenharmony_ci /* some MAC's need RMW protection on AUTOC */ 14562306a36Sopenharmony_ci ret_val = hw->mac.ops.prot_autoc_read(hw, &locked, ®_bp); 14662306a36Sopenharmony_ci if (ret_val) 14762306a36Sopenharmony_ci return ret_val; 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_ci fallthrough; /* only backplane uses autoc */ 15062306a36Sopenharmony_ci case ixgbe_media_type_fiber: 15162306a36Sopenharmony_ci reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANA); 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ci break; 15462306a36Sopenharmony_ci case ixgbe_media_type_copper: 15562306a36Sopenharmony_ci hw->phy.ops.read_reg(hw, MDIO_AN_ADVERTISE, 15662306a36Sopenharmony_ci MDIO_MMD_AN, ®_cu); 15762306a36Sopenharmony_ci break; 15862306a36Sopenharmony_ci default: 15962306a36Sopenharmony_ci break; 16062306a36Sopenharmony_ci } 16162306a36Sopenharmony_ci 16262306a36Sopenharmony_ci /* 16362306a36Sopenharmony_ci * The possible values of fc.requested_mode are: 16462306a36Sopenharmony_ci * 0: Flow control is completely disabled 16562306a36Sopenharmony_ci * 1: Rx flow control is enabled (we can receive pause frames, 16662306a36Sopenharmony_ci * but not send pause frames). 16762306a36Sopenharmony_ci * 2: Tx flow control is enabled (we can send pause frames but 16862306a36Sopenharmony_ci * we do not support receiving pause frames). 16962306a36Sopenharmony_ci * 3: Both Rx and Tx flow control (symmetric) are enabled. 17062306a36Sopenharmony_ci * other: Invalid. 17162306a36Sopenharmony_ci */ 17262306a36Sopenharmony_ci switch (hw->fc.requested_mode) { 17362306a36Sopenharmony_ci case ixgbe_fc_none: 17462306a36Sopenharmony_ci /* Flow control completely disabled by software override. */ 17562306a36Sopenharmony_ci reg &= ~(IXGBE_PCS1GANA_SYM_PAUSE | IXGBE_PCS1GANA_ASM_PAUSE); 17662306a36Sopenharmony_ci if (hw->phy.media_type == ixgbe_media_type_backplane) 17762306a36Sopenharmony_ci reg_bp &= ~(IXGBE_AUTOC_SYM_PAUSE | 17862306a36Sopenharmony_ci IXGBE_AUTOC_ASM_PAUSE); 17962306a36Sopenharmony_ci else if (hw->phy.media_type == ixgbe_media_type_copper) 18062306a36Sopenharmony_ci reg_cu &= ~(IXGBE_TAF_SYM_PAUSE | IXGBE_TAF_ASM_PAUSE); 18162306a36Sopenharmony_ci break; 18262306a36Sopenharmony_ci case ixgbe_fc_tx_pause: 18362306a36Sopenharmony_ci /* 18462306a36Sopenharmony_ci * Tx Flow control is enabled, and Rx Flow control is 18562306a36Sopenharmony_ci * disabled by software override. 18662306a36Sopenharmony_ci */ 18762306a36Sopenharmony_ci reg |= IXGBE_PCS1GANA_ASM_PAUSE; 18862306a36Sopenharmony_ci reg &= ~IXGBE_PCS1GANA_SYM_PAUSE; 18962306a36Sopenharmony_ci if (hw->phy.media_type == ixgbe_media_type_backplane) { 19062306a36Sopenharmony_ci reg_bp |= IXGBE_AUTOC_ASM_PAUSE; 19162306a36Sopenharmony_ci reg_bp &= ~IXGBE_AUTOC_SYM_PAUSE; 19262306a36Sopenharmony_ci } else if (hw->phy.media_type == ixgbe_media_type_copper) { 19362306a36Sopenharmony_ci reg_cu |= IXGBE_TAF_ASM_PAUSE; 19462306a36Sopenharmony_ci reg_cu &= ~IXGBE_TAF_SYM_PAUSE; 19562306a36Sopenharmony_ci } 19662306a36Sopenharmony_ci break; 19762306a36Sopenharmony_ci case ixgbe_fc_rx_pause: 19862306a36Sopenharmony_ci /* 19962306a36Sopenharmony_ci * Rx Flow control is enabled and Tx Flow control is 20062306a36Sopenharmony_ci * disabled by software override. Since there really 20162306a36Sopenharmony_ci * isn't a way to advertise that we are capable of RX 20262306a36Sopenharmony_ci * Pause ONLY, we will advertise that we support both 20362306a36Sopenharmony_ci * symmetric and asymmetric Rx PAUSE, as such we fall 20462306a36Sopenharmony_ci * through to the fc_full statement. Later, we will 20562306a36Sopenharmony_ci * disable the adapter's ability to send PAUSE frames. 20662306a36Sopenharmony_ci */ 20762306a36Sopenharmony_ci case ixgbe_fc_full: 20862306a36Sopenharmony_ci /* Flow control (both Rx and Tx) is enabled by SW override. */ 20962306a36Sopenharmony_ci reg |= IXGBE_PCS1GANA_SYM_PAUSE | IXGBE_PCS1GANA_ASM_PAUSE; 21062306a36Sopenharmony_ci if (hw->phy.media_type == ixgbe_media_type_backplane) 21162306a36Sopenharmony_ci reg_bp |= IXGBE_AUTOC_SYM_PAUSE | 21262306a36Sopenharmony_ci IXGBE_AUTOC_ASM_PAUSE; 21362306a36Sopenharmony_ci else if (hw->phy.media_type == ixgbe_media_type_copper) 21462306a36Sopenharmony_ci reg_cu |= IXGBE_TAF_SYM_PAUSE | IXGBE_TAF_ASM_PAUSE; 21562306a36Sopenharmony_ci break; 21662306a36Sopenharmony_ci default: 21762306a36Sopenharmony_ci hw_dbg(hw, "Flow control param set incorrectly\n"); 21862306a36Sopenharmony_ci return -EIO; 21962306a36Sopenharmony_ci } 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_ci if (hw->mac.type != ixgbe_mac_X540) { 22262306a36Sopenharmony_ci /* 22362306a36Sopenharmony_ci * Enable auto-negotiation between the MAC & PHY; 22462306a36Sopenharmony_ci * the MAC will advertise clause 37 flow control. 22562306a36Sopenharmony_ci */ 22662306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_PCS1GANA, reg); 22762306a36Sopenharmony_ci reg = IXGBE_READ_REG(hw, IXGBE_PCS1GLCTL); 22862306a36Sopenharmony_ci 22962306a36Sopenharmony_ci /* Disable AN timeout */ 23062306a36Sopenharmony_ci if (hw->fc.strict_ieee) 23162306a36Sopenharmony_ci reg &= ~IXGBE_PCS1GLCTL_AN_1G_TIMEOUT_EN; 23262306a36Sopenharmony_ci 23362306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_PCS1GLCTL, reg); 23462306a36Sopenharmony_ci hw_dbg(hw, "Set up FC; PCS1GLCTL = 0x%08X\n", reg); 23562306a36Sopenharmony_ci } 23662306a36Sopenharmony_ci 23762306a36Sopenharmony_ci /* 23862306a36Sopenharmony_ci * AUTOC restart handles negotiation of 1G and 10G on backplane 23962306a36Sopenharmony_ci * and copper. There is no need to set the PCS1GCTL register. 24062306a36Sopenharmony_ci * 24162306a36Sopenharmony_ci */ 24262306a36Sopenharmony_ci if (hw->phy.media_type == ixgbe_media_type_backplane) { 24362306a36Sopenharmony_ci /* Need the SW/FW semaphore around AUTOC writes if 82599 and 24462306a36Sopenharmony_ci * LESM is on, likewise reset_pipeline requries the lock as 24562306a36Sopenharmony_ci * it also writes AUTOC. 24662306a36Sopenharmony_ci */ 24762306a36Sopenharmony_ci ret_val = hw->mac.ops.prot_autoc_write(hw, reg_bp, locked); 24862306a36Sopenharmony_ci if (ret_val) 24962306a36Sopenharmony_ci return ret_val; 25062306a36Sopenharmony_ci 25162306a36Sopenharmony_ci } else if ((hw->phy.media_type == ixgbe_media_type_copper) && 25262306a36Sopenharmony_ci ixgbe_device_supports_autoneg_fc(hw)) { 25362306a36Sopenharmony_ci hw->phy.ops.write_reg(hw, MDIO_AN_ADVERTISE, 25462306a36Sopenharmony_ci MDIO_MMD_AN, reg_cu); 25562306a36Sopenharmony_ci } 25662306a36Sopenharmony_ci 25762306a36Sopenharmony_ci hw_dbg(hw, "Set up FC; IXGBE_AUTOC = 0x%08X\n", reg); 25862306a36Sopenharmony_ci return ret_val; 25962306a36Sopenharmony_ci} 26062306a36Sopenharmony_ci 26162306a36Sopenharmony_ci/** 26262306a36Sopenharmony_ci * ixgbe_start_hw_generic - Prepare hardware for Tx/Rx 26362306a36Sopenharmony_ci * @hw: pointer to hardware structure 26462306a36Sopenharmony_ci * 26562306a36Sopenharmony_ci * Starts the hardware by filling the bus info structure and media type, clears 26662306a36Sopenharmony_ci * all on chip counters, initializes receive address registers, multicast 26762306a36Sopenharmony_ci * table, VLAN filter table, calls routine to set up link and flow control 26862306a36Sopenharmony_ci * settings, and leaves transmit and receive units disabled and uninitialized 26962306a36Sopenharmony_ci **/ 27062306a36Sopenharmony_cis32 ixgbe_start_hw_generic(struct ixgbe_hw *hw) 27162306a36Sopenharmony_ci{ 27262306a36Sopenharmony_ci s32 ret_val; 27362306a36Sopenharmony_ci u32 ctrl_ext; 27462306a36Sopenharmony_ci u16 device_caps; 27562306a36Sopenharmony_ci 27662306a36Sopenharmony_ci /* Set the media type */ 27762306a36Sopenharmony_ci hw->phy.media_type = hw->mac.ops.get_media_type(hw); 27862306a36Sopenharmony_ci 27962306a36Sopenharmony_ci /* Identify the PHY */ 28062306a36Sopenharmony_ci hw->phy.ops.identify(hw); 28162306a36Sopenharmony_ci 28262306a36Sopenharmony_ci /* Clear the VLAN filter table */ 28362306a36Sopenharmony_ci hw->mac.ops.clear_vfta(hw); 28462306a36Sopenharmony_ci 28562306a36Sopenharmony_ci /* Clear statistics registers */ 28662306a36Sopenharmony_ci hw->mac.ops.clear_hw_cntrs(hw); 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_ci /* Set No Snoop Disable */ 28962306a36Sopenharmony_ci ctrl_ext = IXGBE_READ_REG(hw, IXGBE_CTRL_EXT); 29062306a36Sopenharmony_ci ctrl_ext |= IXGBE_CTRL_EXT_NS_DIS; 29162306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_CTRL_EXT, ctrl_ext); 29262306a36Sopenharmony_ci IXGBE_WRITE_FLUSH(hw); 29362306a36Sopenharmony_ci 29462306a36Sopenharmony_ci /* Setup flow control if method for doing so */ 29562306a36Sopenharmony_ci if (hw->mac.ops.setup_fc) { 29662306a36Sopenharmony_ci ret_val = hw->mac.ops.setup_fc(hw); 29762306a36Sopenharmony_ci if (ret_val) 29862306a36Sopenharmony_ci return ret_val; 29962306a36Sopenharmony_ci } 30062306a36Sopenharmony_ci 30162306a36Sopenharmony_ci /* Cashe bit indicating need for crosstalk fix */ 30262306a36Sopenharmony_ci switch (hw->mac.type) { 30362306a36Sopenharmony_ci case ixgbe_mac_82599EB: 30462306a36Sopenharmony_ci case ixgbe_mac_X550EM_x: 30562306a36Sopenharmony_ci case ixgbe_mac_x550em_a: 30662306a36Sopenharmony_ci hw->mac.ops.get_device_caps(hw, &device_caps); 30762306a36Sopenharmony_ci if (device_caps & IXGBE_DEVICE_CAPS_NO_CROSSTALK_WR) 30862306a36Sopenharmony_ci hw->need_crosstalk_fix = false; 30962306a36Sopenharmony_ci else 31062306a36Sopenharmony_ci hw->need_crosstalk_fix = true; 31162306a36Sopenharmony_ci break; 31262306a36Sopenharmony_ci default: 31362306a36Sopenharmony_ci hw->need_crosstalk_fix = false; 31462306a36Sopenharmony_ci break; 31562306a36Sopenharmony_ci } 31662306a36Sopenharmony_ci 31762306a36Sopenharmony_ci /* Clear adapter stopped flag */ 31862306a36Sopenharmony_ci hw->adapter_stopped = false; 31962306a36Sopenharmony_ci 32062306a36Sopenharmony_ci return 0; 32162306a36Sopenharmony_ci} 32262306a36Sopenharmony_ci 32362306a36Sopenharmony_ci/** 32462306a36Sopenharmony_ci * ixgbe_start_hw_gen2 - Init sequence for common device family 32562306a36Sopenharmony_ci * @hw: pointer to hw structure 32662306a36Sopenharmony_ci * 32762306a36Sopenharmony_ci * Performs the init sequence common to the second generation 32862306a36Sopenharmony_ci * of 10 GbE devices. 32962306a36Sopenharmony_ci * Devices in the second generation: 33062306a36Sopenharmony_ci * 82599 33162306a36Sopenharmony_ci * X540 33262306a36Sopenharmony_ci **/ 33362306a36Sopenharmony_cis32 ixgbe_start_hw_gen2(struct ixgbe_hw *hw) 33462306a36Sopenharmony_ci{ 33562306a36Sopenharmony_ci u32 i; 33662306a36Sopenharmony_ci 33762306a36Sopenharmony_ci /* Clear the rate limiters */ 33862306a36Sopenharmony_ci for (i = 0; i < hw->mac.max_tx_queues; i++) { 33962306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_RTTDQSEL, i); 34062306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_RTTBCNRC, 0); 34162306a36Sopenharmony_ci } 34262306a36Sopenharmony_ci IXGBE_WRITE_FLUSH(hw); 34362306a36Sopenharmony_ci 34462306a36Sopenharmony_ci return 0; 34562306a36Sopenharmony_ci} 34662306a36Sopenharmony_ci 34762306a36Sopenharmony_ci/** 34862306a36Sopenharmony_ci * ixgbe_init_hw_generic - Generic hardware initialization 34962306a36Sopenharmony_ci * @hw: pointer to hardware structure 35062306a36Sopenharmony_ci * 35162306a36Sopenharmony_ci * Initialize the hardware by resetting the hardware, filling the bus info 35262306a36Sopenharmony_ci * structure and media type, clears all on chip counters, initializes receive 35362306a36Sopenharmony_ci * address registers, multicast table, VLAN filter table, calls routine to set 35462306a36Sopenharmony_ci * up link and flow control settings, and leaves transmit and receive units 35562306a36Sopenharmony_ci * disabled and uninitialized 35662306a36Sopenharmony_ci **/ 35762306a36Sopenharmony_cis32 ixgbe_init_hw_generic(struct ixgbe_hw *hw) 35862306a36Sopenharmony_ci{ 35962306a36Sopenharmony_ci s32 status; 36062306a36Sopenharmony_ci 36162306a36Sopenharmony_ci /* Reset the hardware */ 36262306a36Sopenharmony_ci status = hw->mac.ops.reset_hw(hw); 36362306a36Sopenharmony_ci 36462306a36Sopenharmony_ci if (status == 0) { 36562306a36Sopenharmony_ci /* Start the HW */ 36662306a36Sopenharmony_ci status = hw->mac.ops.start_hw(hw); 36762306a36Sopenharmony_ci } 36862306a36Sopenharmony_ci 36962306a36Sopenharmony_ci /* Initialize the LED link active for LED blink support */ 37062306a36Sopenharmony_ci if (hw->mac.ops.init_led_link_act) 37162306a36Sopenharmony_ci hw->mac.ops.init_led_link_act(hw); 37262306a36Sopenharmony_ci 37362306a36Sopenharmony_ci return status; 37462306a36Sopenharmony_ci} 37562306a36Sopenharmony_ci 37662306a36Sopenharmony_ci/** 37762306a36Sopenharmony_ci * ixgbe_clear_hw_cntrs_generic - Generic clear hardware counters 37862306a36Sopenharmony_ci * @hw: pointer to hardware structure 37962306a36Sopenharmony_ci * 38062306a36Sopenharmony_ci * Clears all hardware statistics counters by reading them from the hardware 38162306a36Sopenharmony_ci * Statistics counters are clear on read. 38262306a36Sopenharmony_ci **/ 38362306a36Sopenharmony_cis32 ixgbe_clear_hw_cntrs_generic(struct ixgbe_hw *hw) 38462306a36Sopenharmony_ci{ 38562306a36Sopenharmony_ci u16 i = 0; 38662306a36Sopenharmony_ci 38762306a36Sopenharmony_ci IXGBE_READ_REG(hw, IXGBE_CRCERRS); 38862306a36Sopenharmony_ci IXGBE_READ_REG(hw, IXGBE_ILLERRC); 38962306a36Sopenharmony_ci IXGBE_READ_REG(hw, IXGBE_ERRBC); 39062306a36Sopenharmony_ci IXGBE_READ_REG(hw, IXGBE_MSPDC); 39162306a36Sopenharmony_ci for (i = 0; i < 8; i++) 39262306a36Sopenharmony_ci IXGBE_READ_REG(hw, IXGBE_MPC(i)); 39362306a36Sopenharmony_ci 39462306a36Sopenharmony_ci IXGBE_READ_REG(hw, IXGBE_MLFC); 39562306a36Sopenharmony_ci IXGBE_READ_REG(hw, IXGBE_MRFC); 39662306a36Sopenharmony_ci IXGBE_READ_REG(hw, IXGBE_RLEC); 39762306a36Sopenharmony_ci IXGBE_READ_REG(hw, IXGBE_LXONTXC); 39862306a36Sopenharmony_ci IXGBE_READ_REG(hw, IXGBE_LXOFFTXC); 39962306a36Sopenharmony_ci if (hw->mac.type >= ixgbe_mac_82599EB) { 40062306a36Sopenharmony_ci IXGBE_READ_REG(hw, IXGBE_LXONRXCNT); 40162306a36Sopenharmony_ci IXGBE_READ_REG(hw, IXGBE_LXOFFRXCNT); 40262306a36Sopenharmony_ci } else { 40362306a36Sopenharmony_ci IXGBE_READ_REG(hw, IXGBE_LXONRXC); 40462306a36Sopenharmony_ci IXGBE_READ_REG(hw, IXGBE_LXOFFRXC); 40562306a36Sopenharmony_ci } 40662306a36Sopenharmony_ci 40762306a36Sopenharmony_ci for (i = 0; i < 8; i++) { 40862306a36Sopenharmony_ci IXGBE_READ_REG(hw, IXGBE_PXONTXC(i)); 40962306a36Sopenharmony_ci IXGBE_READ_REG(hw, IXGBE_PXOFFTXC(i)); 41062306a36Sopenharmony_ci if (hw->mac.type >= ixgbe_mac_82599EB) { 41162306a36Sopenharmony_ci IXGBE_READ_REG(hw, IXGBE_PXONRXCNT(i)); 41262306a36Sopenharmony_ci IXGBE_READ_REG(hw, IXGBE_PXOFFRXCNT(i)); 41362306a36Sopenharmony_ci } else { 41462306a36Sopenharmony_ci IXGBE_READ_REG(hw, IXGBE_PXONRXC(i)); 41562306a36Sopenharmony_ci IXGBE_READ_REG(hw, IXGBE_PXOFFRXC(i)); 41662306a36Sopenharmony_ci } 41762306a36Sopenharmony_ci } 41862306a36Sopenharmony_ci if (hw->mac.type >= ixgbe_mac_82599EB) 41962306a36Sopenharmony_ci for (i = 0; i < 8; i++) 42062306a36Sopenharmony_ci IXGBE_READ_REG(hw, IXGBE_PXON2OFFCNT(i)); 42162306a36Sopenharmony_ci IXGBE_READ_REG(hw, IXGBE_PRC64); 42262306a36Sopenharmony_ci IXGBE_READ_REG(hw, IXGBE_PRC127); 42362306a36Sopenharmony_ci IXGBE_READ_REG(hw, IXGBE_PRC255); 42462306a36Sopenharmony_ci IXGBE_READ_REG(hw, IXGBE_PRC511); 42562306a36Sopenharmony_ci IXGBE_READ_REG(hw, IXGBE_PRC1023); 42662306a36Sopenharmony_ci IXGBE_READ_REG(hw, IXGBE_PRC1522); 42762306a36Sopenharmony_ci IXGBE_READ_REG(hw, IXGBE_GPRC); 42862306a36Sopenharmony_ci IXGBE_READ_REG(hw, IXGBE_BPRC); 42962306a36Sopenharmony_ci IXGBE_READ_REG(hw, IXGBE_MPRC); 43062306a36Sopenharmony_ci IXGBE_READ_REG(hw, IXGBE_GPTC); 43162306a36Sopenharmony_ci IXGBE_READ_REG(hw, IXGBE_GORCL); 43262306a36Sopenharmony_ci IXGBE_READ_REG(hw, IXGBE_GORCH); 43362306a36Sopenharmony_ci IXGBE_READ_REG(hw, IXGBE_GOTCL); 43462306a36Sopenharmony_ci IXGBE_READ_REG(hw, IXGBE_GOTCH); 43562306a36Sopenharmony_ci if (hw->mac.type == ixgbe_mac_82598EB) 43662306a36Sopenharmony_ci for (i = 0; i < 8; i++) 43762306a36Sopenharmony_ci IXGBE_READ_REG(hw, IXGBE_RNBC(i)); 43862306a36Sopenharmony_ci IXGBE_READ_REG(hw, IXGBE_RUC); 43962306a36Sopenharmony_ci IXGBE_READ_REG(hw, IXGBE_RFC); 44062306a36Sopenharmony_ci IXGBE_READ_REG(hw, IXGBE_ROC); 44162306a36Sopenharmony_ci IXGBE_READ_REG(hw, IXGBE_RJC); 44262306a36Sopenharmony_ci IXGBE_READ_REG(hw, IXGBE_MNGPRC); 44362306a36Sopenharmony_ci IXGBE_READ_REG(hw, IXGBE_MNGPDC); 44462306a36Sopenharmony_ci IXGBE_READ_REG(hw, IXGBE_MNGPTC); 44562306a36Sopenharmony_ci IXGBE_READ_REG(hw, IXGBE_TORL); 44662306a36Sopenharmony_ci IXGBE_READ_REG(hw, IXGBE_TORH); 44762306a36Sopenharmony_ci IXGBE_READ_REG(hw, IXGBE_TPR); 44862306a36Sopenharmony_ci IXGBE_READ_REG(hw, IXGBE_TPT); 44962306a36Sopenharmony_ci IXGBE_READ_REG(hw, IXGBE_PTC64); 45062306a36Sopenharmony_ci IXGBE_READ_REG(hw, IXGBE_PTC127); 45162306a36Sopenharmony_ci IXGBE_READ_REG(hw, IXGBE_PTC255); 45262306a36Sopenharmony_ci IXGBE_READ_REG(hw, IXGBE_PTC511); 45362306a36Sopenharmony_ci IXGBE_READ_REG(hw, IXGBE_PTC1023); 45462306a36Sopenharmony_ci IXGBE_READ_REG(hw, IXGBE_PTC1522); 45562306a36Sopenharmony_ci IXGBE_READ_REG(hw, IXGBE_MPTC); 45662306a36Sopenharmony_ci IXGBE_READ_REG(hw, IXGBE_BPTC); 45762306a36Sopenharmony_ci for (i = 0; i < 16; i++) { 45862306a36Sopenharmony_ci IXGBE_READ_REG(hw, IXGBE_QPRC(i)); 45962306a36Sopenharmony_ci IXGBE_READ_REG(hw, IXGBE_QPTC(i)); 46062306a36Sopenharmony_ci if (hw->mac.type >= ixgbe_mac_82599EB) { 46162306a36Sopenharmony_ci IXGBE_READ_REG(hw, IXGBE_QBRC_L(i)); 46262306a36Sopenharmony_ci IXGBE_READ_REG(hw, IXGBE_QBRC_H(i)); 46362306a36Sopenharmony_ci IXGBE_READ_REG(hw, IXGBE_QBTC_L(i)); 46462306a36Sopenharmony_ci IXGBE_READ_REG(hw, IXGBE_QBTC_H(i)); 46562306a36Sopenharmony_ci IXGBE_READ_REG(hw, IXGBE_QPRDC(i)); 46662306a36Sopenharmony_ci } else { 46762306a36Sopenharmony_ci IXGBE_READ_REG(hw, IXGBE_QBRC(i)); 46862306a36Sopenharmony_ci IXGBE_READ_REG(hw, IXGBE_QBTC(i)); 46962306a36Sopenharmony_ci } 47062306a36Sopenharmony_ci } 47162306a36Sopenharmony_ci 47262306a36Sopenharmony_ci if (hw->mac.type == ixgbe_mac_X550 || hw->mac.type == ixgbe_mac_X540) { 47362306a36Sopenharmony_ci if (hw->phy.id == 0) 47462306a36Sopenharmony_ci hw->phy.ops.identify(hw); 47562306a36Sopenharmony_ci hw->phy.ops.read_reg(hw, IXGBE_PCRC8ECL, MDIO_MMD_PCS, &i); 47662306a36Sopenharmony_ci hw->phy.ops.read_reg(hw, IXGBE_PCRC8ECH, MDIO_MMD_PCS, &i); 47762306a36Sopenharmony_ci hw->phy.ops.read_reg(hw, IXGBE_LDPCECL, MDIO_MMD_PCS, &i); 47862306a36Sopenharmony_ci hw->phy.ops.read_reg(hw, IXGBE_LDPCECH, MDIO_MMD_PCS, &i); 47962306a36Sopenharmony_ci } 48062306a36Sopenharmony_ci 48162306a36Sopenharmony_ci return 0; 48262306a36Sopenharmony_ci} 48362306a36Sopenharmony_ci 48462306a36Sopenharmony_ci/** 48562306a36Sopenharmony_ci * ixgbe_read_pba_string_generic - Reads part number string from EEPROM 48662306a36Sopenharmony_ci * @hw: pointer to hardware structure 48762306a36Sopenharmony_ci * @pba_num: stores the part number string from the EEPROM 48862306a36Sopenharmony_ci * @pba_num_size: part number string buffer length 48962306a36Sopenharmony_ci * 49062306a36Sopenharmony_ci * Reads the part number string from the EEPROM. 49162306a36Sopenharmony_ci **/ 49262306a36Sopenharmony_cis32 ixgbe_read_pba_string_generic(struct ixgbe_hw *hw, u8 *pba_num, 49362306a36Sopenharmony_ci u32 pba_num_size) 49462306a36Sopenharmony_ci{ 49562306a36Sopenharmony_ci s32 ret_val; 49662306a36Sopenharmony_ci u16 data; 49762306a36Sopenharmony_ci u16 pba_ptr; 49862306a36Sopenharmony_ci u16 offset; 49962306a36Sopenharmony_ci u16 length; 50062306a36Sopenharmony_ci 50162306a36Sopenharmony_ci if (pba_num == NULL) { 50262306a36Sopenharmony_ci hw_dbg(hw, "PBA string buffer was null\n"); 50362306a36Sopenharmony_ci return -EINVAL; 50462306a36Sopenharmony_ci } 50562306a36Sopenharmony_ci 50662306a36Sopenharmony_ci ret_val = hw->eeprom.ops.read(hw, IXGBE_PBANUM0_PTR, &data); 50762306a36Sopenharmony_ci if (ret_val) { 50862306a36Sopenharmony_ci hw_dbg(hw, "NVM Read Error\n"); 50962306a36Sopenharmony_ci return ret_val; 51062306a36Sopenharmony_ci } 51162306a36Sopenharmony_ci 51262306a36Sopenharmony_ci ret_val = hw->eeprom.ops.read(hw, IXGBE_PBANUM1_PTR, &pba_ptr); 51362306a36Sopenharmony_ci if (ret_val) { 51462306a36Sopenharmony_ci hw_dbg(hw, "NVM Read Error\n"); 51562306a36Sopenharmony_ci return ret_val; 51662306a36Sopenharmony_ci } 51762306a36Sopenharmony_ci 51862306a36Sopenharmony_ci /* 51962306a36Sopenharmony_ci * if data is not ptr guard the PBA must be in legacy format which 52062306a36Sopenharmony_ci * means pba_ptr is actually our second data word for the PBA number 52162306a36Sopenharmony_ci * and we can decode it into an ascii string 52262306a36Sopenharmony_ci */ 52362306a36Sopenharmony_ci if (data != IXGBE_PBANUM_PTR_GUARD) { 52462306a36Sopenharmony_ci hw_dbg(hw, "NVM PBA number is not stored as string\n"); 52562306a36Sopenharmony_ci 52662306a36Sopenharmony_ci /* we will need 11 characters to store the PBA */ 52762306a36Sopenharmony_ci if (pba_num_size < 11) { 52862306a36Sopenharmony_ci hw_dbg(hw, "PBA string buffer too small\n"); 52962306a36Sopenharmony_ci return -ENOSPC; 53062306a36Sopenharmony_ci } 53162306a36Sopenharmony_ci 53262306a36Sopenharmony_ci /* extract hex string from data and pba_ptr */ 53362306a36Sopenharmony_ci pba_num[0] = (data >> 12) & 0xF; 53462306a36Sopenharmony_ci pba_num[1] = (data >> 8) & 0xF; 53562306a36Sopenharmony_ci pba_num[2] = (data >> 4) & 0xF; 53662306a36Sopenharmony_ci pba_num[3] = data & 0xF; 53762306a36Sopenharmony_ci pba_num[4] = (pba_ptr >> 12) & 0xF; 53862306a36Sopenharmony_ci pba_num[5] = (pba_ptr >> 8) & 0xF; 53962306a36Sopenharmony_ci pba_num[6] = '-'; 54062306a36Sopenharmony_ci pba_num[7] = 0; 54162306a36Sopenharmony_ci pba_num[8] = (pba_ptr >> 4) & 0xF; 54262306a36Sopenharmony_ci pba_num[9] = pba_ptr & 0xF; 54362306a36Sopenharmony_ci 54462306a36Sopenharmony_ci /* put a null character on the end of our string */ 54562306a36Sopenharmony_ci pba_num[10] = '\0'; 54662306a36Sopenharmony_ci 54762306a36Sopenharmony_ci /* switch all the data but the '-' to hex char */ 54862306a36Sopenharmony_ci for (offset = 0; offset < 10; offset++) { 54962306a36Sopenharmony_ci if (pba_num[offset] < 0xA) 55062306a36Sopenharmony_ci pba_num[offset] += '0'; 55162306a36Sopenharmony_ci else if (pba_num[offset] < 0x10) 55262306a36Sopenharmony_ci pba_num[offset] += 'A' - 0xA; 55362306a36Sopenharmony_ci } 55462306a36Sopenharmony_ci 55562306a36Sopenharmony_ci return 0; 55662306a36Sopenharmony_ci } 55762306a36Sopenharmony_ci 55862306a36Sopenharmony_ci ret_val = hw->eeprom.ops.read(hw, pba_ptr, &length); 55962306a36Sopenharmony_ci if (ret_val) { 56062306a36Sopenharmony_ci hw_dbg(hw, "NVM Read Error\n"); 56162306a36Sopenharmony_ci return ret_val; 56262306a36Sopenharmony_ci } 56362306a36Sopenharmony_ci 56462306a36Sopenharmony_ci if (length == 0xFFFF || length == 0) { 56562306a36Sopenharmony_ci hw_dbg(hw, "NVM PBA number section invalid length\n"); 56662306a36Sopenharmony_ci return -EIO; 56762306a36Sopenharmony_ci } 56862306a36Sopenharmony_ci 56962306a36Sopenharmony_ci /* check if pba_num buffer is big enough */ 57062306a36Sopenharmony_ci if (pba_num_size < (((u32)length * 2) - 1)) { 57162306a36Sopenharmony_ci hw_dbg(hw, "PBA string buffer too small\n"); 57262306a36Sopenharmony_ci return -ENOSPC; 57362306a36Sopenharmony_ci } 57462306a36Sopenharmony_ci 57562306a36Sopenharmony_ci /* trim pba length from start of string */ 57662306a36Sopenharmony_ci pba_ptr++; 57762306a36Sopenharmony_ci length--; 57862306a36Sopenharmony_ci 57962306a36Sopenharmony_ci for (offset = 0; offset < length; offset++) { 58062306a36Sopenharmony_ci ret_val = hw->eeprom.ops.read(hw, pba_ptr + offset, &data); 58162306a36Sopenharmony_ci if (ret_val) { 58262306a36Sopenharmony_ci hw_dbg(hw, "NVM Read Error\n"); 58362306a36Sopenharmony_ci return ret_val; 58462306a36Sopenharmony_ci } 58562306a36Sopenharmony_ci pba_num[offset * 2] = (u8)(data >> 8); 58662306a36Sopenharmony_ci pba_num[(offset * 2) + 1] = (u8)(data & 0xFF); 58762306a36Sopenharmony_ci } 58862306a36Sopenharmony_ci pba_num[offset * 2] = '\0'; 58962306a36Sopenharmony_ci 59062306a36Sopenharmony_ci return 0; 59162306a36Sopenharmony_ci} 59262306a36Sopenharmony_ci 59362306a36Sopenharmony_ci/** 59462306a36Sopenharmony_ci * ixgbe_get_mac_addr_generic - Generic get MAC address 59562306a36Sopenharmony_ci * @hw: pointer to hardware structure 59662306a36Sopenharmony_ci * @mac_addr: Adapter MAC address 59762306a36Sopenharmony_ci * 59862306a36Sopenharmony_ci * Reads the adapter's MAC address from first Receive Address Register (RAR0) 59962306a36Sopenharmony_ci * A reset of the adapter must be performed prior to calling this function 60062306a36Sopenharmony_ci * in order for the MAC address to have been loaded from the EEPROM into RAR0 60162306a36Sopenharmony_ci **/ 60262306a36Sopenharmony_cis32 ixgbe_get_mac_addr_generic(struct ixgbe_hw *hw, u8 *mac_addr) 60362306a36Sopenharmony_ci{ 60462306a36Sopenharmony_ci u32 rar_high; 60562306a36Sopenharmony_ci u32 rar_low; 60662306a36Sopenharmony_ci u16 i; 60762306a36Sopenharmony_ci 60862306a36Sopenharmony_ci rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(0)); 60962306a36Sopenharmony_ci rar_low = IXGBE_READ_REG(hw, IXGBE_RAL(0)); 61062306a36Sopenharmony_ci 61162306a36Sopenharmony_ci for (i = 0; i < 4; i++) 61262306a36Sopenharmony_ci mac_addr[i] = (u8)(rar_low >> (i*8)); 61362306a36Sopenharmony_ci 61462306a36Sopenharmony_ci for (i = 0; i < 2; i++) 61562306a36Sopenharmony_ci mac_addr[i+4] = (u8)(rar_high >> (i*8)); 61662306a36Sopenharmony_ci 61762306a36Sopenharmony_ci return 0; 61862306a36Sopenharmony_ci} 61962306a36Sopenharmony_ci 62062306a36Sopenharmony_cienum ixgbe_bus_width ixgbe_convert_bus_width(u16 link_status) 62162306a36Sopenharmony_ci{ 62262306a36Sopenharmony_ci switch (link_status & IXGBE_PCI_LINK_WIDTH) { 62362306a36Sopenharmony_ci case IXGBE_PCI_LINK_WIDTH_1: 62462306a36Sopenharmony_ci return ixgbe_bus_width_pcie_x1; 62562306a36Sopenharmony_ci case IXGBE_PCI_LINK_WIDTH_2: 62662306a36Sopenharmony_ci return ixgbe_bus_width_pcie_x2; 62762306a36Sopenharmony_ci case IXGBE_PCI_LINK_WIDTH_4: 62862306a36Sopenharmony_ci return ixgbe_bus_width_pcie_x4; 62962306a36Sopenharmony_ci case IXGBE_PCI_LINK_WIDTH_8: 63062306a36Sopenharmony_ci return ixgbe_bus_width_pcie_x8; 63162306a36Sopenharmony_ci default: 63262306a36Sopenharmony_ci return ixgbe_bus_width_unknown; 63362306a36Sopenharmony_ci } 63462306a36Sopenharmony_ci} 63562306a36Sopenharmony_ci 63662306a36Sopenharmony_cienum ixgbe_bus_speed ixgbe_convert_bus_speed(u16 link_status) 63762306a36Sopenharmony_ci{ 63862306a36Sopenharmony_ci switch (link_status & IXGBE_PCI_LINK_SPEED) { 63962306a36Sopenharmony_ci case IXGBE_PCI_LINK_SPEED_2500: 64062306a36Sopenharmony_ci return ixgbe_bus_speed_2500; 64162306a36Sopenharmony_ci case IXGBE_PCI_LINK_SPEED_5000: 64262306a36Sopenharmony_ci return ixgbe_bus_speed_5000; 64362306a36Sopenharmony_ci case IXGBE_PCI_LINK_SPEED_8000: 64462306a36Sopenharmony_ci return ixgbe_bus_speed_8000; 64562306a36Sopenharmony_ci default: 64662306a36Sopenharmony_ci return ixgbe_bus_speed_unknown; 64762306a36Sopenharmony_ci } 64862306a36Sopenharmony_ci} 64962306a36Sopenharmony_ci 65062306a36Sopenharmony_ci/** 65162306a36Sopenharmony_ci * ixgbe_get_bus_info_generic - Generic set PCI bus info 65262306a36Sopenharmony_ci * @hw: pointer to hardware structure 65362306a36Sopenharmony_ci * 65462306a36Sopenharmony_ci * Sets the PCI bus info (speed, width, type) within the ixgbe_hw structure 65562306a36Sopenharmony_ci **/ 65662306a36Sopenharmony_cis32 ixgbe_get_bus_info_generic(struct ixgbe_hw *hw) 65762306a36Sopenharmony_ci{ 65862306a36Sopenharmony_ci u16 link_status; 65962306a36Sopenharmony_ci 66062306a36Sopenharmony_ci hw->bus.type = ixgbe_bus_type_pci_express; 66162306a36Sopenharmony_ci 66262306a36Sopenharmony_ci /* Get the negotiated link width and speed from PCI config space */ 66362306a36Sopenharmony_ci link_status = ixgbe_read_pci_cfg_word(hw, IXGBE_PCI_LINK_STATUS); 66462306a36Sopenharmony_ci 66562306a36Sopenharmony_ci hw->bus.width = ixgbe_convert_bus_width(link_status); 66662306a36Sopenharmony_ci hw->bus.speed = ixgbe_convert_bus_speed(link_status); 66762306a36Sopenharmony_ci 66862306a36Sopenharmony_ci hw->mac.ops.set_lan_id(hw); 66962306a36Sopenharmony_ci 67062306a36Sopenharmony_ci return 0; 67162306a36Sopenharmony_ci} 67262306a36Sopenharmony_ci 67362306a36Sopenharmony_ci/** 67462306a36Sopenharmony_ci * ixgbe_set_lan_id_multi_port_pcie - Set LAN id for PCIe multiple port devices 67562306a36Sopenharmony_ci * @hw: pointer to the HW structure 67662306a36Sopenharmony_ci * 67762306a36Sopenharmony_ci * Determines the LAN function id by reading memory-mapped registers 67862306a36Sopenharmony_ci * and swaps the port value if requested. 67962306a36Sopenharmony_ci **/ 68062306a36Sopenharmony_civoid ixgbe_set_lan_id_multi_port_pcie(struct ixgbe_hw *hw) 68162306a36Sopenharmony_ci{ 68262306a36Sopenharmony_ci struct ixgbe_bus_info *bus = &hw->bus; 68362306a36Sopenharmony_ci u16 ee_ctrl_4; 68462306a36Sopenharmony_ci u32 reg; 68562306a36Sopenharmony_ci 68662306a36Sopenharmony_ci reg = IXGBE_READ_REG(hw, IXGBE_STATUS); 68762306a36Sopenharmony_ci bus->func = (reg & IXGBE_STATUS_LAN_ID) >> IXGBE_STATUS_LAN_ID_SHIFT; 68862306a36Sopenharmony_ci bus->lan_id = bus->func; 68962306a36Sopenharmony_ci 69062306a36Sopenharmony_ci /* check for a port swap */ 69162306a36Sopenharmony_ci reg = IXGBE_READ_REG(hw, IXGBE_FACTPS(hw)); 69262306a36Sopenharmony_ci if (reg & IXGBE_FACTPS_LFS) 69362306a36Sopenharmony_ci bus->func ^= 0x1; 69462306a36Sopenharmony_ci 69562306a36Sopenharmony_ci /* Get MAC instance from EEPROM for configuring CS4227 */ 69662306a36Sopenharmony_ci if (hw->device_id == IXGBE_DEV_ID_X550EM_A_SFP) { 69762306a36Sopenharmony_ci hw->eeprom.ops.read(hw, IXGBE_EEPROM_CTRL_4, &ee_ctrl_4); 69862306a36Sopenharmony_ci bus->instance_id = (ee_ctrl_4 & IXGBE_EE_CTRL_4_INST_ID) >> 69962306a36Sopenharmony_ci IXGBE_EE_CTRL_4_INST_ID_SHIFT; 70062306a36Sopenharmony_ci } 70162306a36Sopenharmony_ci} 70262306a36Sopenharmony_ci 70362306a36Sopenharmony_ci/** 70462306a36Sopenharmony_ci * ixgbe_stop_adapter_generic - Generic stop Tx/Rx units 70562306a36Sopenharmony_ci * @hw: pointer to hardware structure 70662306a36Sopenharmony_ci * 70762306a36Sopenharmony_ci * Sets the adapter_stopped flag within ixgbe_hw struct. Clears interrupts, 70862306a36Sopenharmony_ci * disables transmit and receive units. The adapter_stopped flag is used by 70962306a36Sopenharmony_ci * the shared code and drivers to determine if the adapter is in a stopped 71062306a36Sopenharmony_ci * state and should not touch the hardware. 71162306a36Sopenharmony_ci **/ 71262306a36Sopenharmony_cis32 ixgbe_stop_adapter_generic(struct ixgbe_hw *hw) 71362306a36Sopenharmony_ci{ 71462306a36Sopenharmony_ci u32 reg_val; 71562306a36Sopenharmony_ci u16 i; 71662306a36Sopenharmony_ci 71762306a36Sopenharmony_ci /* 71862306a36Sopenharmony_ci * Set the adapter_stopped flag so other driver functions stop touching 71962306a36Sopenharmony_ci * the hardware 72062306a36Sopenharmony_ci */ 72162306a36Sopenharmony_ci hw->adapter_stopped = true; 72262306a36Sopenharmony_ci 72362306a36Sopenharmony_ci /* Disable the receive unit */ 72462306a36Sopenharmony_ci hw->mac.ops.disable_rx(hw); 72562306a36Sopenharmony_ci 72662306a36Sopenharmony_ci /* Clear interrupt mask to stop interrupts from being generated */ 72762306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_IRQ_CLEAR_MASK); 72862306a36Sopenharmony_ci 72962306a36Sopenharmony_ci /* Clear any pending interrupts, flush previous writes */ 73062306a36Sopenharmony_ci IXGBE_READ_REG(hw, IXGBE_EICR); 73162306a36Sopenharmony_ci 73262306a36Sopenharmony_ci /* Disable the transmit unit. Each queue must be disabled. */ 73362306a36Sopenharmony_ci for (i = 0; i < hw->mac.max_tx_queues; i++) 73462306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(i), IXGBE_TXDCTL_SWFLSH); 73562306a36Sopenharmony_ci 73662306a36Sopenharmony_ci /* Disable the receive unit by stopping each queue */ 73762306a36Sopenharmony_ci for (i = 0; i < hw->mac.max_rx_queues; i++) { 73862306a36Sopenharmony_ci reg_val = IXGBE_READ_REG(hw, IXGBE_RXDCTL(i)); 73962306a36Sopenharmony_ci reg_val &= ~IXGBE_RXDCTL_ENABLE; 74062306a36Sopenharmony_ci reg_val |= IXGBE_RXDCTL_SWFLSH; 74162306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(i), reg_val); 74262306a36Sopenharmony_ci } 74362306a36Sopenharmony_ci 74462306a36Sopenharmony_ci /* flush all queues disables */ 74562306a36Sopenharmony_ci IXGBE_WRITE_FLUSH(hw); 74662306a36Sopenharmony_ci usleep_range(1000, 2000); 74762306a36Sopenharmony_ci 74862306a36Sopenharmony_ci /* 74962306a36Sopenharmony_ci * Prevent the PCI-E bus from hanging by disabling PCI-E primary 75062306a36Sopenharmony_ci * access and verify no pending requests 75162306a36Sopenharmony_ci */ 75262306a36Sopenharmony_ci return ixgbe_disable_pcie_primary(hw); 75362306a36Sopenharmony_ci} 75462306a36Sopenharmony_ci 75562306a36Sopenharmony_ci/** 75662306a36Sopenharmony_ci * ixgbe_init_led_link_act_generic - Store the LED index link/activity. 75762306a36Sopenharmony_ci * @hw: pointer to hardware structure 75862306a36Sopenharmony_ci * 75962306a36Sopenharmony_ci * Store the index for the link active LED. This will be used to support 76062306a36Sopenharmony_ci * blinking the LED. 76162306a36Sopenharmony_ci **/ 76262306a36Sopenharmony_cis32 ixgbe_init_led_link_act_generic(struct ixgbe_hw *hw) 76362306a36Sopenharmony_ci{ 76462306a36Sopenharmony_ci struct ixgbe_mac_info *mac = &hw->mac; 76562306a36Sopenharmony_ci u32 led_reg, led_mode; 76662306a36Sopenharmony_ci u16 i; 76762306a36Sopenharmony_ci 76862306a36Sopenharmony_ci led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL); 76962306a36Sopenharmony_ci 77062306a36Sopenharmony_ci /* Get LED link active from the LEDCTL register */ 77162306a36Sopenharmony_ci for (i = 0; i < 4; i++) { 77262306a36Sopenharmony_ci led_mode = led_reg >> IXGBE_LED_MODE_SHIFT(i); 77362306a36Sopenharmony_ci 77462306a36Sopenharmony_ci if ((led_mode & IXGBE_LED_MODE_MASK_BASE) == 77562306a36Sopenharmony_ci IXGBE_LED_LINK_ACTIVE) { 77662306a36Sopenharmony_ci mac->led_link_act = i; 77762306a36Sopenharmony_ci return 0; 77862306a36Sopenharmony_ci } 77962306a36Sopenharmony_ci } 78062306a36Sopenharmony_ci 78162306a36Sopenharmony_ci /* If LEDCTL register does not have the LED link active set, then use 78262306a36Sopenharmony_ci * known MAC defaults. 78362306a36Sopenharmony_ci */ 78462306a36Sopenharmony_ci switch (hw->mac.type) { 78562306a36Sopenharmony_ci case ixgbe_mac_x550em_a: 78662306a36Sopenharmony_ci mac->led_link_act = 0; 78762306a36Sopenharmony_ci break; 78862306a36Sopenharmony_ci case ixgbe_mac_X550EM_x: 78962306a36Sopenharmony_ci mac->led_link_act = 1; 79062306a36Sopenharmony_ci break; 79162306a36Sopenharmony_ci default: 79262306a36Sopenharmony_ci mac->led_link_act = 2; 79362306a36Sopenharmony_ci } 79462306a36Sopenharmony_ci 79562306a36Sopenharmony_ci return 0; 79662306a36Sopenharmony_ci} 79762306a36Sopenharmony_ci 79862306a36Sopenharmony_ci/** 79962306a36Sopenharmony_ci * ixgbe_led_on_generic - Turns on the software controllable LEDs. 80062306a36Sopenharmony_ci * @hw: pointer to hardware structure 80162306a36Sopenharmony_ci * @index: led number to turn on 80262306a36Sopenharmony_ci **/ 80362306a36Sopenharmony_cis32 ixgbe_led_on_generic(struct ixgbe_hw *hw, u32 index) 80462306a36Sopenharmony_ci{ 80562306a36Sopenharmony_ci u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL); 80662306a36Sopenharmony_ci 80762306a36Sopenharmony_ci if (index > 3) 80862306a36Sopenharmony_ci return -EINVAL; 80962306a36Sopenharmony_ci 81062306a36Sopenharmony_ci /* To turn on the LED, set mode to ON. */ 81162306a36Sopenharmony_ci led_reg &= ~IXGBE_LED_MODE_MASK(index); 81262306a36Sopenharmony_ci led_reg |= IXGBE_LED_ON << IXGBE_LED_MODE_SHIFT(index); 81362306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg); 81462306a36Sopenharmony_ci IXGBE_WRITE_FLUSH(hw); 81562306a36Sopenharmony_ci 81662306a36Sopenharmony_ci return 0; 81762306a36Sopenharmony_ci} 81862306a36Sopenharmony_ci 81962306a36Sopenharmony_ci/** 82062306a36Sopenharmony_ci * ixgbe_led_off_generic - Turns off the software controllable LEDs. 82162306a36Sopenharmony_ci * @hw: pointer to hardware structure 82262306a36Sopenharmony_ci * @index: led number to turn off 82362306a36Sopenharmony_ci **/ 82462306a36Sopenharmony_cis32 ixgbe_led_off_generic(struct ixgbe_hw *hw, u32 index) 82562306a36Sopenharmony_ci{ 82662306a36Sopenharmony_ci u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL); 82762306a36Sopenharmony_ci 82862306a36Sopenharmony_ci if (index > 3) 82962306a36Sopenharmony_ci return -EINVAL; 83062306a36Sopenharmony_ci 83162306a36Sopenharmony_ci /* To turn off the LED, set mode to OFF. */ 83262306a36Sopenharmony_ci led_reg &= ~IXGBE_LED_MODE_MASK(index); 83362306a36Sopenharmony_ci led_reg |= IXGBE_LED_OFF << IXGBE_LED_MODE_SHIFT(index); 83462306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg); 83562306a36Sopenharmony_ci IXGBE_WRITE_FLUSH(hw); 83662306a36Sopenharmony_ci 83762306a36Sopenharmony_ci return 0; 83862306a36Sopenharmony_ci} 83962306a36Sopenharmony_ci 84062306a36Sopenharmony_ci/** 84162306a36Sopenharmony_ci * ixgbe_init_eeprom_params_generic - Initialize EEPROM params 84262306a36Sopenharmony_ci * @hw: pointer to hardware structure 84362306a36Sopenharmony_ci * 84462306a36Sopenharmony_ci * Initializes the EEPROM parameters ixgbe_eeprom_info within the 84562306a36Sopenharmony_ci * ixgbe_hw struct in order to set up EEPROM access. 84662306a36Sopenharmony_ci **/ 84762306a36Sopenharmony_cis32 ixgbe_init_eeprom_params_generic(struct ixgbe_hw *hw) 84862306a36Sopenharmony_ci{ 84962306a36Sopenharmony_ci struct ixgbe_eeprom_info *eeprom = &hw->eeprom; 85062306a36Sopenharmony_ci u32 eec; 85162306a36Sopenharmony_ci u16 eeprom_size; 85262306a36Sopenharmony_ci 85362306a36Sopenharmony_ci if (eeprom->type == ixgbe_eeprom_uninitialized) { 85462306a36Sopenharmony_ci eeprom->type = ixgbe_eeprom_none; 85562306a36Sopenharmony_ci /* Set default semaphore delay to 10ms which is a well 85662306a36Sopenharmony_ci * tested value */ 85762306a36Sopenharmony_ci eeprom->semaphore_delay = 10; 85862306a36Sopenharmony_ci /* Clear EEPROM page size, it will be initialized as needed */ 85962306a36Sopenharmony_ci eeprom->word_page_size = 0; 86062306a36Sopenharmony_ci 86162306a36Sopenharmony_ci /* 86262306a36Sopenharmony_ci * Check for EEPROM present first. 86362306a36Sopenharmony_ci * If not present leave as none 86462306a36Sopenharmony_ci */ 86562306a36Sopenharmony_ci eec = IXGBE_READ_REG(hw, IXGBE_EEC(hw)); 86662306a36Sopenharmony_ci if (eec & IXGBE_EEC_PRES) { 86762306a36Sopenharmony_ci eeprom->type = ixgbe_eeprom_spi; 86862306a36Sopenharmony_ci 86962306a36Sopenharmony_ci /* 87062306a36Sopenharmony_ci * SPI EEPROM is assumed here. This code would need to 87162306a36Sopenharmony_ci * change if a future EEPROM is not SPI. 87262306a36Sopenharmony_ci */ 87362306a36Sopenharmony_ci eeprom_size = (u16)((eec & IXGBE_EEC_SIZE) >> 87462306a36Sopenharmony_ci IXGBE_EEC_SIZE_SHIFT); 87562306a36Sopenharmony_ci eeprom->word_size = BIT(eeprom_size + 87662306a36Sopenharmony_ci IXGBE_EEPROM_WORD_SIZE_SHIFT); 87762306a36Sopenharmony_ci } 87862306a36Sopenharmony_ci 87962306a36Sopenharmony_ci if (eec & IXGBE_EEC_ADDR_SIZE) 88062306a36Sopenharmony_ci eeprom->address_bits = 16; 88162306a36Sopenharmony_ci else 88262306a36Sopenharmony_ci eeprom->address_bits = 8; 88362306a36Sopenharmony_ci hw_dbg(hw, "Eeprom params: type = %d, size = %d, address bits: %d\n", 88462306a36Sopenharmony_ci eeprom->type, eeprom->word_size, eeprom->address_bits); 88562306a36Sopenharmony_ci } 88662306a36Sopenharmony_ci 88762306a36Sopenharmony_ci return 0; 88862306a36Sopenharmony_ci} 88962306a36Sopenharmony_ci 89062306a36Sopenharmony_ci/** 89162306a36Sopenharmony_ci * ixgbe_write_eeprom_buffer_bit_bang_generic - Write EEPROM using bit-bang 89262306a36Sopenharmony_ci * @hw: pointer to hardware structure 89362306a36Sopenharmony_ci * @offset: offset within the EEPROM to write 89462306a36Sopenharmony_ci * @words: number of words 89562306a36Sopenharmony_ci * @data: 16 bit word(s) to write to EEPROM 89662306a36Sopenharmony_ci * 89762306a36Sopenharmony_ci * Reads 16 bit word(s) from EEPROM through bit-bang method 89862306a36Sopenharmony_ci **/ 89962306a36Sopenharmony_cis32 ixgbe_write_eeprom_buffer_bit_bang_generic(struct ixgbe_hw *hw, u16 offset, 90062306a36Sopenharmony_ci u16 words, u16 *data) 90162306a36Sopenharmony_ci{ 90262306a36Sopenharmony_ci s32 status; 90362306a36Sopenharmony_ci u16 i, count; 90462306a36Sopenharmony_ci 90562306a36Sopenharmony_ci hw->eeprom.ops.init_params(hw); 90662306a36Sopenharmony_ci 90762306a36Sopenharmony_ci if (words == 0 || (offset + words > hw->eeprom.word_size)) 90862306a36Sopenharmony_ci return -EINVAL; 90962306a36Sopenharmony_ci 91062306a36Sopenharmony_ci /* 91162306a36Sopenharmony_ci * The EEPROM page size cannot be queried from the chip. We do lazy 91262306a36Sopenharmony_ci * initialization. It is worth to do that when we write large buffer. 91362306a36Sopenharmony_ci */ 91462306a36Sopenharmony_ci if ((hw->eeprom.word_page_size == 0) && 91562306a36Sopenharmony_ci (words > IXGBE_EEPROM_PAGE_SIZE_MAX)) 91662306a36Sopenharmony_ci ixgbe_detect_eeprom_page_size_generic(hw, offset); 91762306a36Sopenharmony_ci 91862306a36Sopenharmony_ci /* 91962306a36Sopenharmony_ci * We cannot hold synchronization semaphores for too long 92062306a36Sopenharmony_ci * to avoid other entity starvation. However it is more efficient 92162306a36Sopenharmony_ci * to read in bursts than synchronizing access for each word. 92262306a36Sopenharmony_ci */ 92362306a36Sopenharmony_ci for (i = 0; i < words; i += IXGBE_EEPROM_RD_BUFFER_MAX_COUNT) { 92462306a36Sopenharmony_ci count = (words - i) / IXGBE_EEPROM_RD_BUFFER_MAX_COUNT > 0 ? 92562306a36Sopenharmony_ci IXGBE_EEPROM_RD_BUFFER_MAX_COUNT : (words - i); 92662306a36Sopenharmony_ci status = ixgbe_write_eeprom_buffer_bit_bang(hw, offset + i, 92762306a36Sopenharmony_ci count, &data[i]); 92862306a36Sopenharmony_ci 92962306a36Sopenharmony_ci if (status != 0) 93062306a36Sopenharmony_ci break; 93162306a36Sopenharmony_ci } 93262306a36Sopenharmony_ci 93362306a36Sopenharmony_ci return status; 93462306a36Sopenharmony_ci} 93562306a36Sopenharmony_ci 93662306a36Sopenharmony_ci/** 93762306a36Sopenharmony_ci * ixgbe_write_eeprom_buffer_bit_bang - Writes 16 bit word(s) to EEPROM 93862306a36Sopenharmony_ci * @hw: pointer to hardware structure 93962306a36Sopenharmony_ci * @offset: offset within the EEPROM to be written to 94062306a36Sopenharmony_ci * @words: number of word(s) 94162306a36Sopenharmony_ci * @data: 16 bit word(s) to be written to the EEPROM 94262306a36Sopenharmony_ci * 94362306a36Sopenharmony_ci * If ixgbe_eeprom_update_checksum is not called after this function, the 94462306a36Sopenharmony_ci * EEPROM will most likely contain an invalid checksum. 94562306a36Sopenharmony_ci **/ 94662306a36Sopenharmony_cistatic s32 ixgbe_write_eeprom_buffer_bit_bang(struct ixgbe_hw *hw, u16 offset, 94762306a36Sopenharmony_ci u16 words, u16 *data) 94862306a36Sopenharmony_ci{ 94962306a36Sopenharmony_ci s32 status; 95062306a36Sopenharmony_ci u16 word; 95162306a36Sopenharmony_ci u16 page_size; 95262306a36Sopenharmony_ci u16 i; 95362306a36Sopenharmony_ci u8 write_opcode = IXGBE_EEPROM_WRITE_OPCODE_SPI; 95462306a36Sopenharmony_ci 95562306a36Sopenharmony_ci /* Prepare the EEPROM for writing */ 95662306a36Sopenharmony_ci status = ixgbe_acquire_eeprom(hw); 95762306a36Sopenharmony_ci if (status) 95862306a36Sopenharmony_ci return status; 95962306a36Sopenharmony_ci 96062306a36Sopenharmony_ci if (ixgbe_ready_eeprom(hw) != 0) { 96162306a36Sopenharmony_ci ixgbe_release_eeprom(hw); 96262306a36Sopenharmony_ci return -EIO; 96362306a36Sopenharmony_ci } 96462306a36Sopenharmony_ci 96562306a36Sopenharmony_ci for (i = 0; i < words; i++) { 96662306a36Sopenharmony_ci ixgbe_standby_eeprom(hw); 96762306a36Sopenharmony_ci 96862306a36Sopenharmony_ci /* Send the WRITE ENABLE command (8 bit opcode) */ 96962306a36Sopenharmony_ci ixgbe_shift_out_eeprom_bits(hw, 97062306a36Sopenharmony_ci IXGBE_EEPROM_WREN_OPCODE_SPI, 97162306a36Sopenharmony_ci IXGBE_EEPROM_OPCODE_BITS); 97262306a36Sopenharmony_ci 97362306a36Sopenharmony_ci ixgbe_standby_eeprom(hw); 97462306a36Sopenharmony_ci 97562306a36Sopenharmony_ci /* Some SPI eeproms use the 8th address bit embedded 97662306a36Sopenharmony_ci * in the opcode 97762306a36Sopenharmony_ci */ 97862306a36Sopenharmony_ci if ((hw->eeprom.address_bits == 8) && 97962306a36Sopenharmony_ci ((offset + i) >= 128)) 98062306a36Sopenharmony_ci write_opcode |= IXGBE_EEPROM_A8_OPCODE_SPI; 98162306a36Sopenharmony_ci 98262306a36Sopenharmony_ci /* Send the Write command (8-bit opcode + addr) */ 98362306a36Sopenharmony_ci ixgbe_shift_out_eeprom_bits(hw, write_opcode, 98462306a36Sopenharmony_ci IXGBE_EEPROM_OPCODE_BITS); 98562306a36Sopenharmony_ci ixgbe_shift_out_eeprom_bits(hw, (u16)((offset + i) * 2), 98662306a36Sopenharmony_ci hw->eeprom.address_bits); 98762306a36Sopenharmony_ci 98862306a36Sopenharmony_ci page_size = hw->eeprom.word_page_size; 98962306a36Sopenharmony_ci 99062306a36Sopenharmony_ci /* Send the data in burst via SPI */ 99162306a36Sopenharmony_ci do { 99262306a36Sopenharmony_ci word = data[i]; 99362306a36Sopenharmony_ci word = (word >> 8) | (word << 8); 99462306a36Sopenharmony_ci ixgbe_shift_out_eeprom_bits(hw, word, 16); 99562306a36Sopenharmony_ci 99662306a36Sopenharmony_ci if (page_size == 0) 99762306a36Sopenharmony_ci break; 99862306a36Sopenharmony_ci 99962306a36Sopenharmony_ci /* do not wrap around page */ 100062306a36Sopenharmony_ci if (((offset + i) & (page_size - 1)) == 100162306a36Sopenharmony_ci (page_size - 1)) 100262306a36Sopenharmony_ci break; 100362306a36Sopenharmony_ci } while (++i < words); 100462306a36Sopenharmony_ci 100562306a36Sopenharmony_ci ixgbe_standby_eeprom(hw); 100662306a36Sopenharmony_ci usleep_range(10000, 20000); 100762306a36Sopenharmony_ci } 100862306a36Sopenharmony_ci /* Done with writing - release the EEPROM */ 100962306a36Sopenharmony_ci ixgbe_release_eeprom(hw); 101062306a36Sopenharmony_ci 101162306a36Sopenharmony_ci return 0; 101262306a36Sopenharmony_ci} 101362306a36Sopenharmony_ci 101462306a36Sopenharmony_ci/** 101562306a36Sopenharmony_ci * ixgbe_write_eeprom_generic - Writes 16 bit value to EEPROM 101662306a36Sopenharmony_ci * @hw: pointer to hardware structure 101762306a36Sopenharmony_ci * @offset: offset within the EEPROM to be written to 101862306a36Sopenharmony_ci * @data: 16 bit word to be written to the EEPROM 101962306a36Sopenharmony_ci * 102062306a36Sopenharmony_ci * If ixgbe_eeprom_update_checksum is not called after this function, the 102162306a36Sopenharmony_ci * EEPROM will most likely contain an invalid checksum. 102262306a36Sopenharmony_ci **/ 102362306a36Sopenharmony_cis32 ixgbe_write_eeprom_generic(struct ixgbe_hw *hw, u16 offset, u16 data) 102462306a36Sopenharmony_ci{ 102562306a36Sopenharmony_ci hw->eeprom.ops.init_params(hw); 102662306a36Sopenharmony_ci 102762306a36Sopenharmony_ci if (offset >= hw->eeprom.word_size) 102862306a36Sopenharmony_ci return -EINVAL; 102962306a36Sopenharmony_ci 103062306a36Sopenharmony_ci return ixgbe_write_eeprom_buffer_bit_bang(hw, offset, 1, &data); 103162306a36Sopenharmony_ci} 103262306a36Sopenharmony_ci 103362306a36Sopenharmony_ci/** 103462306a36Sopenharmony_ci * ixgbe_read_eeprom_buffer_bit_bang_generic - Read EEPROM using bit-bang 103562306a36Sopenharmony_ci * @hw: pointer to hardware structure 103662306a36Sopenharmony_ci * @offset: offset within the EEPROM to be read 103762306a36Sopenharmony_ci * @words: number of word(s) 103862306a36Sopenharmony_ci * @data: read 16 bit words(s) from EEPROM 103962306a36Sopenharmony_ci * 104062306a36Sopenharmony_ci * Reads 16 bit word(s) from EEPROM through bit-bang method 104162306a36Sopenharmony_ci **/ 104262306a36Sopenharmony_cis32 ixgbe_read_eeprom_buffer_bit_bang_generic(struct ixgbe_hw *hw, u16 offset, 104362306a36Sopenharmony_ci u16 words, u16 *data) 104462306a36Sopenharmony_ci{ 104562306a36Sopenharmony_ci s32 status; 104662306a36Sopenharmony_ci u16 i, count; 104762306a36Sopenharmony_ci 104862306a36Sopenharmony_ci hw->eeprom.ops.init_params(hw); 104962306a36Sopenharmony_ci 105062306a36Sopenharmony_ci if (words == 0 || (offset + words > hw->eeprom.word_size)) 105162306a36Sopenharmony_ci return -EINVAL; 105262306a36Sopenharmony_ci 105362306a36Sopenharmony_ci /* 105462306a36Sopenharmony_ci * We cannot hold synchronization semaphores for too long 105562306a36Sopenharmony_ci * to avoid other entity starvation. However it is more efficient 105662306a36Sopenharmony_ci * to read in bursts than synchronizing access for each word. 105762306a36Sopenharmony_ci */ 105862306a36Sopenharmony_ci for (i = 0; i < words; i += IXGBE_EEPROM_RD_BUFFER_MAX_COUNT) { 105962306a36Sopenharmony_ci count = (words - i) / IXGBE_EEPROM_RD_BUFFER_MAX_COUNT > 0 ? 106062306a36Sopenharmony_ci IXGBE_EEPROM_RD_BUFFER_MAX_COUNT : (words - i); 106162306a36Sopenharmony_ci 106262306a36Sopenharmony_ci status = ixgbe_read_eeprom_buffer_bit_bang(hw, offset + i, 106362306a36Sopenharmony_ci count, &data[i]); 106462306a36Sopenharmony_ci 106562306a36Sopenharmony_ci if (status) 106662306a36Sopenharmony_ci return status; 106762306a36Sopenharmony_ci } 106862306a36Sopenharmony_ci 106962306a36Sopenharmony_ci return 0; 107062306a36Sopenharmony_ci} 107162306a36Sopenharmony_ci 107262306a36Sopenharmony_ci/** 107362306a36Sopenharmony_ci * ixgbe_read_eeprom_buffer_bit_bang - Read EEPROM using bit-bang 107462306a36Sopenharmony_ci * @hw: pointer to hardware structure 107562306a36Sopenharmony_ci * @offset: offset within the EEPROM to be read 107662306a36Sopenharmony_ci * @words: number of word(s) 107762306a36Sopenharmony_ci * @data: read 16 bit word(s) from EEPROM 107862306a36Sopenharmony_ci * 107962306a36Sopenharmony_ci * Reads 16 bit word(s) from EEPROM through bit-bang method 108062306a36Sopenharmony_ci **/ 108162306a36Sopenharmony_cistatic s32 ixgbe_read_eeprom_buffer_bit_bang(struct ixgbe_hw *hw, u16 offset, 108262306a36Sopenharmony_ci u16 words, u16 *data) 108362306a36Sopenharmony_ci{ 108462306a36Sopenharmony_ci s32 status; 108562306a36Sopenharmony_ci u16 word_in; 108662306a36Sopenharmony_ci u8 read_opcode = IXGBE_EEPROM_READ_OPCODE_SPI; 108762306a36Sopenharmony_ci u16 i; 108862306a36Sopenharmony_ci 108962306a36Sopenharmony_ci /* Prepare the EEPROM for reading */ 109062306a36Sopenharmony_ci status = ixgbe_acquire_eeprom(hw); 109162306a36Sopenharmony_ci if (status) 109262306a36Sopenharmony_ci return status; 109362306a36Sopenharmony_ci 109462306a36Sopenharmony_ci if (ixgbe_ready_eeprom(hw) != 0) { 109562306a36Sopenharmony_ci ixgbe_release_eeprom(hw); 109662306a36Sopenharmony_ci return -EIO; 109762306a36Sopenharmony_ci } 109862306a36Sopenharmony_ci 109962306a36Sopenharmony_ci for (i = 0; i < words; i++) { 110062306a36Sopenharmony_ci ixgbe_standby_eeprom(hw); 110162306a36Sopenharmony_ci /* Some SPI eeproms use the 8th address bit embedded 110262306a36Sopenharmony_ci * in the opcode 110362306a36Sopenharmony_ci */ 110462306a36Sopenharmony_ci if ((hw->eeprom.address_bits == 8) && 110562306a36Sopenharmony_ci ((offset + i) >= 128)) 110662306a36Sopenharmony_ci read_opcode |= IXGBE_EEPROM_A8_OPCODE_SPI; 110762306a36Sopenharmony_ci 110862306a36Sopenharmony_ci /* Send the READ command (opcode + addr) */ 110962306a36Sopenharmony_ci ixgbe_shift_out_eeprom_bits(hw, read_opcode, 111062306a36Sopenharmony_ci IXGBE_EEPROM_OPCODE_BITS); 111162306a36Sopenharmony_ci ixgbe_shift_out_eeprom_bits(hw, (u16)((offset + i) * 2), 111262306a36Sopenharmony_ci hw->eeprom.address_bits); 111362306a36Sopenharmony_ci 111462306a36Sopenharmony_ci /* Read the data. */ 111562306a36Sopenharmony_ci word_in = ixgbe_shift_in_eeprom_bits(hw, 16); 111662306a36Sopenharmony_ci data[i] = (word_in >> 8) | (word_in << 8); 111762306a36Sopenharmony_ci } 111862306a36Sopenharmony_ci 111962306a36Sopenharmony_ci /* End this read operation */ 112062306a36Sopenharmony_ci ixgbe_release_eeprom(hw); 112162306a36Sopenharmony_ci 112262306a36Sopenharmony_ci return 0; 112362306a36Sopenharmony_ci} 112462306a36Sopenharmony_ci 112562306a36Sopenharmony_ci/** 112662306a36Sopenharmony_ci * ixgbe_read_eeprom_bit_bang_generic - Read EEPROM word using bit-bang 112762306a36Sopenharmony_ci * @hw: pointer to hardware structure 112862306a36Sopenharmony_ci * @offset: offset within the EEPROM to be read 112962306a36Sopenharmony_ci * @data: read 16 bit value from EEPROM 113062306a36Sopenharmony_ci * 113162306a36Sopenharmony_ci * Reads 16 bit value from EEPROM through bit-bang method 113262306a36Sopenharmony_ci **/ 113362306a36Sopenharmony_cis32 ixgbe_read_eeprom_bit_bang_generic(struct ixgbe_hw *hw, u16 offset, 113462306a36Sopenharmony_ci u16 *data) 113562306a36Sopenharmony_ci{ 113662306a36Sopenharmony_ci hw->eeprom.ops.init_params(hw); 113762306a36Sopenharmony_ci 113862306a36Sopenharmony_ci if (offset >= hw->eeprom.word_size) 113962306a36Sopenharmony_ci return -EINVAL; 114062306a36Sopenharmony_ci 114162306a36Sopenharmony_ci return ixgbe_read_eeprom_buffer_bit_bang(hw, offset, 1, data); 114262306a36Sopenharmony_ci} 114362306a36Sopenharmony_ci 114462306a36Sopenharmony_ci/** 114562306a36Sopenharmony_ci * ixgbe_read_eerd_buffer_generic - Read EEPROM word(s) using EERD 114662306a36Sopenharmony_ci * @hw: pointer to hardware structure 114762306a36Sopenharmony_ci * @offset: offset of word in the EEPROM to read 114862306a36Sopenharmony_ci * @words: number of word(s) 114962306a36Sopenharmony_ci * @data: 16 bit word(s) from the EEPROM 115062306a36Sopenharmony_ci * 115162306a36Sopenharmony_ci * Reads a 16 bit word(s) from the EEPROM using the EERD register. 115262306a36Sopenharmony_ci **/ 115362306a36Sopenharmony_cis32 ixgbe_read_eerd_buffer_generic(struct ixgbe_hw *hw, u16 offset, 115462306a36Sopenharmony_ci u16 words, u16 *data) 115562306a36Sopenharmony_ci{ 115662306a36Sopenharmony_ci u32 eerd; 115762306a36Sopenharmony_ci s32 status; 115862306a36Sopenharmony_ci u32 i; 115962306a36Sopenharmony_ci 116062306a36Sopenharmony_ci hw->eeprom.ops.init_params(hw); 116162306a36Sopenharmony_ci 116262306a36Sopenharmony_ci if (words == 0 || offset >= hw->eeprom.word_size) 116362306a36Sopenharmony_ci return -EINVAL; 116462306a36Sopenharmony_ci 116562306a36Sopenharmony_ci for (i = 0; i < words; i++) { 116662306a36Sopenharmony_ci eerd = ((offset + i) << IXGBE_EEPROM_RW_ADDR_SHIFT) | 116762306a36Sopenharmony_ci IXGBE_EEPROM_RW_REG_START; 116862306a36Sopenharmony_ci 116962306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_EERD, eerd); 117062306a36Sopenharmony_ci status = ixgbe_poll_eerd_eewr_done(hw, IXGBE_NVM_POLL_READ); 117162306a36Sopenharmony_ci 117262306a36Sopenharmony_ci if (status == 0) { 117362306a36Sopenharmony_ci data[i] = (IXGBE_READ_REG(hw, IXGBE_EERD) >> 117462306a36Sopenharmony_ci IXGBE_EEPROM_RW_REG_DATA); 117562306a36Sopenharmony_ci } else { 117662306a36Sopenharmony_ci hw_dbg(hw, "Eeprom read timed out\n"); 117762306a36Sopenharmony_ci return status; 117862306a36Sopenharmony_ci } 117962306a36Sopenharmony_ci } 118062306a36Sopenharmony_ci 118162306a36Sopenharmony_ci return 0; 118262306a36Sopenharmony_ci} 118362306a36Sopenharmony_ci 118462306a36Sopenharmony_ci/** 118562306a36Sopenharmony_ci * ixgbe_detect_eeprom_page_size_generic - Detect EEPROM page size 118662306a36Sopenharmony_ci * @hw: pointer to hardware structure 118762306a36Sopenharmony_ci * @offset: offset within the EEPROM to be used as a scratch pad 118862306a36Sopenharmony_ci * 118962306a36Sopenharmony_ci * Discover EEPROM page size by writing marching data at given offset. 119062306a36Sopenharmony_ci * This function is called only when we are writing a new large buffer 119162306a36Sopenharmony_ci * at given offset so the data would be overwritten anyway. 119262306a36Sopenharmony_ci **/ 119362306a36Sopenharmony_cistatic s32 ixgbe_detect_eeprom_page_size_generic(struct ixgbe_hw *hw, 119462306a36Sopenharmony_ci u16 offset) 119562306a36Sopenharmony_ci{ 119662306a36Sopenharmony_ci u16 data[IXGBE_EEPROM_PAGE_SIZE_MAX]; 119762306a36Sopenharmony_ci s32 status; 119862306a36Sopenharmony_ci u16 i; 119962306a36Sopenharmony_ci 120062306a36Sopenharmony_ci for (i = 0; i < IXGBE_EEPROM_PAGE_SIZE_MAX; i++) 120162306a36Sopenharmony_ci data[i] = i; 120262306a36Sopenharmony_ci 120362306a36Sopenharmony_ci hw->eeprom.word_page_size = IXGBE_EEPROM_PAGE_SIZE_MAX; 120462306a36Sopenharmony_ci status = ixgbe_write_eeprom_buffer_bit_bang(hw, offset, 120562306a36Sopenharmony_ci IXGBE_EEPROM_PAGE_SIZE_MAX, data); 120662306a36Sopenharmony_ci hw->eeprom.word_page_size = 0; 120762306a36Sopenharmony_ci if (status) 120862306a36Sopenharmony_ci return status; 120962306a36Sopenharmony_ci 121062306a36Sopenharmony_ci status = ixgbe_read_eeprom_buffer_bit_bang(hw, offset, 1, data); 121162306a36Sopenharmony_ci if (status) 121262306a36Sopenharmony_ci return status; 121362306a36Sopenharmony_ci 121462306a36Sopenharmony_ci /* 121562306a36Sopenharmony_ci * When writing in burst more than the actual page size 121662306a36Sopenharmony_ci * EEPROM address wraps around current page. 121762306a36Sopenharmony_ci */ 121862306a36Sopenharmony_ci hw->eeprom.word_page_size = IXGBE_EEPROM_PAGE_SIZE_MAX - data[0]; 121962306a36Sopenharmony_ci 122062306a36Sopenharmony_ci hw_dbg(hw, "Detected EEPROM page size = %d words.\n", 122162306a36Sopenharmony_ci hw->eeprom.word_page_size); 122262306a36Sopenharmony_ci return 0; 122362306a36Sopenharmony_ci} 122462306a36Sopenharmony_ci 122562306a36Sopenharmony_ci/** 122662306a36Sopenharmony_ci * ixgbe_read_eerd_generic - Read EEPROM word using EERD 122762306a36Sopenharmony_ci * @hw: pointer to hardware structure 122862306a36Sopenharmony_ci * @offset: offset of word in the EEPROM to read 122962306a36Sopenharmony_ci * @data: word read from the EEPROM 123062306a36Sopenharmony_ci * 123162306a36Sopenharmony_ci * Reads a 16 bit word from the EEPROM using the EERD register. 123262306a36Sopenharmony_ci **/ 123362306a36Sopenharmony_cis32 ixgbe_read_eerd_generic(struct ixgbe_hw *hw, u16 offset, u16 *data) 123462306a36Sopenharmony_ci{ 123562306a36Sopenharmony_ci return ixgbe_read_eerd_buffer_generic(hw, offset, 1, data); 123662306a36Sopenharmony_ci} 123762306a36Sopenharmony_ci 123862306a36Sopenharmony_ci/** 123962306a36Sopenharmony_ci * ixgbe_write_eewr_buffer_generic - Write EEPROM word(s) using EEWR 124062306a36Sopenharmony_ci * @hw: pointer to hardware structure 124162306a36Sopenharmony_ci * @offset: offset of word in the EEPROM to write 124262306a36Sopenharmony_ci * @words: number of words 124362306a36Sopenharmony_ci * @data: word(s) write to the EEPROM 124462306a36Sopenharmony_ci * 124562306a36Sopenharmony_ci * Write a 16 bit word(s) to the EEPROM using the EEWR register. 124662306a36Sopenharmony_ci **/ 124762306a36Sopenharmony_cis32 ixgbe_write_eewr_buffer_generic(struct ixgbe_hw *hw, u16 offset, 124862306a36Sopenharmony_ci u16 words, u16 *data) 124962306a36Sopenharmony_ci{ 125062306a36Sopenharmony_ci u32 eewr; 125162306a36Sopenharmony_ci s32 status; 125262306a36Sopenharmony_ci u16 i; 125362306a36Sopenharmony_ci 125462306a36Sopenharmony_ci hw->eeprom.ops.init_params(hw); 125562306a36Sopenharmony_ci 125662306a36Sopenharmony_ci if (words == 0 || offset >= hw->eeprom.word_size) 125762306a36Sopenharmony_ci return -EINVAL; 125862306a36Sopenharmony_ci 125962306a36Sopenharmony_ci for (i = 0; i < words; i++) { 126062306a36Sopenharmony_ci eewr = ((offset + i) << IXGBE_EEPROM_RW_ADDR_SHIFT) | 126162306a36Sopenharmony_ci (data[i] << IXGBE_EEPROM_RW_REG_DATA) | 126262306a36Sopenharmony_ci IXGBE_EEPROM_RW_REG_START; 126362306a36Sopenharmony_ci 126462306a36Sopenharmony_ci status = ixgbe_poll_eerd_eewr_done(hw, IXGBE_NVM_POLL_WRITE); 126562306a36Sopenharmony_ci if (status) { 126662306a36Sopenharmony_ci hw_dbg(hw, "Eeprom write EEWR timed out\n"); 126762306a36Sopenharmony_ci return status; 126862306a36Sopenharmony_ci } 126962306a36Sopenharmony_ci 127062306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_EEWR, eewr); 127162306a36Sopenharmony_ci 127262306a36Sopenharmony_ci status = ixgbe_poll_eerd_eewr_done(hw, IXGBE_NVM_POLL_WRITE); 127362306a36Sopenharmony_ci if (status) { 127462306a36Sopenharmony_ci hw_dbg(hw, "Eeprom write EEWR timed out\n"); 127562306a36Sopenharmony_ci return status; 127662306a36Sopenharmony_ci } 127762306a36Sopenharmony_ci } 127862306a36Sopenharmony_ci 127962306a36Sopenharmony_ci return 0; 128062306a36Sopenharmony_ci} 128162306a36Sopenharmony_ci 128262306a36Sopenharmony_ci/** 128362306a36Sopenharmony_ci * ixgbe_write_eewr_generic - Write EEPROM word using EEWR 128462306a36Sopenharmony_ci * @hw: pointer to hardware structure 128562306a36Sopenharmony_ci * @offset: offset of word in the EEPROM to write 128662306a36Sopenharmony_ci * @data: word write to the EEPROM 128762306a36Sopenharmony_ci * 128862306a36Sopenharmony_ci * Write a 16 bit word to the EEPROM using the EEWR register. 128962306a36Sopenharmony_ci **/ 129062306a36Sopenharmony_cis32 ixgbe_write_eewr_generic(struct ixgbe_hw *hw, u16 offset, u16 data) 129162306a36Sopenharmony_ci{ 129262306a36Sopenharmony_ci return ixgbe_write_eewr_buffer_generic(hw, offset, 1, &data); 129362306a36Sopenharmony_ci} 129462306a36Sopenharmony_ci 129562306a36Sopenharmony_ci/** 129662306a36Sopenharmony_ci * ixgbe_poll_eerd_eewr_done - Poll EERD read or EEWR write status 129762306a36Sopenharmony_ci * @hw: pointer to hardware structure 129862306a36Sopenharmony_ci * @ee_reg: EEPROM flag for polling 129962306a36Sopenharmony_ci * 130062306a36Sopenharmony_ci * Polls the status bit (bit 1) of the EERD or EEWR to determine when the 130162306a36Sopenharmony_ci * read or write is done respectively. 130262306a36Sopenharmony_ci **/ 130362306a36Sopenharmony_cistatic s32 ixgbe_poll_eerd_eewr_done(struct ixgbe_hw *hw, u32 ee_reg) 130462306a36Sopenharmony_ci{ 130562306a36Sopenharmony_ci u32 i; 130662306a36Sopenharmony_ci u32 reg; 130762306a36Sopenharmony_ci 130862306a36Sopenharmony_ci for (i = 0; i < IXGBE_EERD_EEWR_ATTEMPTS; i++) { 130962306a36Sopenharmony_ci if (ee_reg == IXGBE_NVM_POLL_READ) 131062306a36Sopenharmony_ci reg = IXGBE_READ_REG(hw, IXGBE_EERD); 131162306a36Sopenharmony_ci else 131262306a36Sopenharmony_ci reg = IXGBE_READ_REG(hw, IXGBE_EEWR); 131362306a36Sopenharmony_ci 131462306a36Sopenharmony_ci if (reg & IXGBE_EEPROM_RW_REG_DONE) { 131562306a36Sopenharmony_ci return 0; 131662306a36Sopenharmony_ci } 131762306a36Sopenharmony_ci udelay(5); 131862306a36Sopenharmony_ci } 131962306a36Sopenharmony_ci return -EIO; 132062306a36Sopenharmony_ci} 132162306a36Sopenharmony_ci 132262306a36Sopenharmony_ci/** 132362306a36Sopenharmony_ci * ixgbe_acquire_eeprom - Acquire EEPROM using bit-bang 132462306a36Sopenharmony_ci * @hw: pointer to hardware structure 132562306a36Sopenharmony_ci * 132662306a36Sopenharmony_ci * Prepares EEPROM for access using bit-bang method. This function should 132762306a36Sopenharmony_ci * be called before issuing a command to the EEPROM. 132862306a36Sopenharmony_ci **/ 132962306a36Sopenharmony_cistatic s32 ixgbe_acquire_eeprom(struct ixgbe_hw *hw) 133062306a36Sopenharmony_ci{ 133162306a36Sopenharmony_ci u32 eec; 133262306a36Sopenharmony_ci u32 i; 133362306a36Sopenharmony_ci 133462306a36Sopenharmony_ci if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) != 0) 133562306a36Sopenharmony_ci return -EBUSY; 133662306a36Sopenharmony_ci 133762306a36Sopenharmony_ci eec = IXGBE_READ_REG(hw, IXGBE_EEC(hw)); 133862306a36Sopenharmony_ci 133962306a36Sopenharmony_ci /* Request EEPROM Access */ 134062306a36Sopenharmony_ci eec |= IXGBE_EEC_REQ; 134162306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_EEC(hw), eec); 134262306a36Sopenharmony_ci 134362306a36Sopenharmony_ci for (i = 0; i < IXGBE_EEPROM_GRANT_ATTEMPTS; i++) { 134462306a36Sopenharmony_ci eec = IXGBE_READ_REG(hw, IXGBE_EEC(hw)); 134562306a36Sopenharmony_ci if (eec & IXGBE_EEC_GNT) 134662306a36Sopenharmony_ci break; 134762306a36Sopenharmony_ci udelay(5); 134862306a36Sopenharmony_ci } 134962306a36Sopenharmony_ci 135062306a36Sopenharmony_ci /* Release if grant not acquired */ 135162306a36Sopenharmony_ci if (!(eec & IXGBE_EEC_GNT)) { 135262306a36Sopenharmony_ci eec &= ~IXGBE_EEC_REQ; 135362306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_EEC(hw), eec); 135462306a36Sopenharmony_ci hw_dbg(hw, "Could not acquire EEPROM grant\n"); 135562306a36Sopenharmony_ci 135662306a36Sopenharmony_ci hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM); 135762306a36Sopenharmony_ci return -EIO; 135862306a36Sopenharmony_ci } 135962306a36Sopenharmony_ci 136062306a36Sopenharmony_ci /* Setup EEPROM for Read/Write */ 136162306a36Sopenharmony_ci /* Clear CS and SK */ 136262306a36Sopenharmony_ci eec &= ~(IXGBE_EEC_CS | IXGBE_EEC_SK); 136362306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_EEC(hw), eec); 136462306a36Sopenharmony_ci IXGBE_WRITE_FLUSH(hw); 136562306a36Sopenharmony_ci udelay(1); 136662306a36Sopenharmony_ci return 0; 136762306a36Sopenharmony_ci} 136862306a36Sopenharmony_ci 136962306a36Sopenharmony_ci/** 137062306a36Sopenharmony_ci * ixgbe_get_eeprom_semaphore - Get hardware semaphore 137162306a36Sopenharmony_ci * @hw: pointer to hardware structure 137262306a36Sopenharmony_ci * 137362306a36Sopenharmony_ci * Sets the hardware semaphores so EEPROM access can occur for bit-bang method 137462306a36Sopenharmony_ci **/ 137562306a36Sopenharmony_cistatic s32 ixgbe_get_eeprom_semaphore(struct ixgbe_hw *hw) 137662306a36Sopenharmony_ci{ 137762306a36Sopenharmony_ci u32 timeout = 2000; 137862306a36Sopenharmony_ci u32 i; 137962306a36Sopenharmony_ci u32 swsm; 138062306a36Sopenharmony_ci 138162306a36Sopenharmony_ci /* Get SMBI software semaphore between device drivers first */ 138262306a36Sopenharmony_ci for (i = 0; i < timeout; i++) { 138362306a36Sopenharmony_ci /* 138462306a36Sopenharmony_ci * If the SMBI bit is 0 when we read it, then the bit will be 138562306a36Sopenharmony_ci * set and we have the semaphore 138662306a36Sopenharmony_ci */ 138762306a36Sopenharmony_ci swsm = IXGBE_READ_REG(hw, IXGBE_SWSM(hw)); 138862306a36Sopenharmony_ci if (!(swsm & IXGBE_SWSM_SMBI)) 138962306a36Sopenharmony_ci break; 139062306a36Sopenharmony_ci usleep_range(50, 100); 139162306a36Sopenharmony_ci } 139262306a36Sopenharmony_ci 139362306a36Sopenharmony_ci if (i == timeout) { 139462306a36Sopenharmony_ci hw_dbg(hw, "Driver can't access the Eeprom - SMBI Semaphore not granted.\n"); 139562306a36Sopenharmony_ci /* this release is particularly important because our attempts 139662306a36Sopenharmony_ci * above to get the semaphore may have succeeded, and if there 139762306a36Sopenharmony_ci * was a timeout, we should unconditionally clear the semaphore 139862306a36Sopenharmony_ci * bits to free the driver to make progress 139962306a36Sopenharmony_ci */ 140062306a36Sopenharmony_ci ixgbe_release_eeprom_semaphore(hw); 140162306a36Sopenharmony_ci 140262306a36Sopenharmony_ci usleep_range(50, 100); 140362306a36Sopenharmony_ci /* one last try 140462306a36Sopenharmony_ci * If the SMBI bit is 0 when we read it, then the bit will be 140562306a36Sopenharmony_ci * set and we have the semaphore 140662306a36Sopenharmony_ci */ 140762306a36Sopenharmony_ci swsm = IXGBE_READ_REG(hw, IXGBE_SWSM(hw)); 140862306a36Sopenharmony_ci if (swsm & IXGBE_SWSM_SMBI) { 140962306a36Sopenharmony_ci hw_dbg(hw, "Software semaphore SMBI between device drivers not granted.\n"); 141062306a36Sopenharmony_ci return -EIO; 141162306a36Sopenharmony_ci } 141262306a36Sopenharmony_ci } 141362306a36Sopenharmony_ci 141462306a36Sopenharmony_ci /* Now get the semaphore between SW/FW through the SWESMBI bit */ 141562306a36Sopenharmony_ci for (i = 0; i < timeout; i++) { 141662306a36Sopenharmony_ci swsm = IXGBE_READ_REG(hw, IXGBE_SWSM(hw)); 141762306a36Sopenharmony_ci 141862306a36Sopenharmony_ci /* Set the SW EEPROM semaphore bit to request access */ 141962306a36Sopenharmony_ci swsm |= IXGBE_SWSM_SWESMBI; 142062306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_SWSM(hw), swsm); 142162306a36Sopenharmony_ci 142262306a36Sopenharmony_ci /* If we set the bit successfully then we got the 142362306a36Sopenharmony_ci * semaphore. 142462306a36Sopenharmony_ci */ 142562306a36Sopenharmony_ci swsm = IXGBE_READ_REG(hw, IXGBE_SWSM(hw)); 142662306a36Sopenharmony_ci if (swsm & IXGBE_SWSM_SWESMBI) 142762306a36Sopenharmony_ci break; 142862306a36Sopenharmony_ci 142962306a36Sopenharmony_ci usleep_range(50, 100); 143062306a36Sopenharmony_ci } 143162306a36Sopenharmony_ci 143262306a36Sopenharmony_ci /* Release semaphores and return error if SW EEPROM semaphore 143362306a36Sopenharmony_ci * was not granted because we don't have access to the EEPROM 143462306a36Sopenharmony_ci */ 143562306a36Sopenharmony_ci if (i >= timeout) { 143662306a36Sopenharmony_ci hw_dbg(hw, "SWESMBI Software EEPROM semaphore not granted.\n"); 143762306a36Sopenharmony_ci ixgbe_release_eeprom_semaphore(hw); 143862306a36Sopenharmony_ci return -EIO; 143962306a36Sopenharmony_ci } 144062306a36Sopenharmony_ci 144162306a36Sopenharmony_ci return 0; 144262306a36Sopenharmony_ci} 144362306a36Sopenharmony_ci 144462306a36Sopenharmony_ci/** 144562306a36Sopenharmony_ci * ixgbe_release_eeprom_semaphore - Release hardware semaphore 144662306a36Sopenharmony_ci * @hw: pointer to hardware structure 144762306a36Sopenharmony_ci * 144862306a36Sopenharmony_ci * This function clears hardware semaphore bits. 144962306a36Sopenharmony_ci **/ 145062306a36Sopenharmony_cistatic void ixgbe_release_eeprom_semaphore(struct ixgbe_hw *hw) 145162306a36Sopenharmony_ci{ 145262306a36Sopenharmony_ci u32 swsm; 145362306a36Sopenharmony_ci 145462306a36Sopenharmony_ci swsm = IXGBE_READ_REG(hw, IXGBE_SWSM(hw)); 145562306a36Sopenharmony_ci 145662306a36Sopenharmony_ci /* Release both semaphores by writing 0 to the bits SWESMBI and SMBI */ 145762306a36Sopenharmony_ci swsm &= ~(IXGBE_SWSM_SWESMBI | IXGBE_SWSM_SMBI); 145862306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_SWSM(hw), swsm); 145962306a36Sopenharmony_ci IXGBE_WRITE_FLUSH(hw); 146062306a36Sopenharmony_ci} 146162306a36Sopenharmony_ci 146262306a36Sopenharmony_ci/** 146362306a36Sopenharmony_ci * ixgbe_ready_eeprom - Polls for EEPROM ready 146462306a36Sopenharmony_ci * @hw: pointer to hardware structure 146562306a36Sopenharmony_ci **/ 146662306a36Sopenharmony_cistatic s32 ixgbe_ready_eeprom(struct ixgbe_hw *hw) 146762306a36Sopenharmony_ci{ 146862306a36Sopenharmony_ci u16 i; 146962306a36Sopenharmony_ci u8 spi_stat_reg; 147062306a36Sopenharmony_ci 147162306a36Sopenharmony_ci /* 147262306a36Sopenharmony_ci * Read "Status Register" repeatedly until the LSB is cleared. The 147362306a36Sopenharmony_ci * EEPROM will signal that the command has been completed by clearing 147462306a36Sopenharmony_ci * bit 0 of the internal status register. If it's not cleared within 147562306a36Sopenharmony_ci * 5 milliseconds, then error out. 147662306a36Sopenharmony_ci */ 147762306a36Sopenharmony_ci for (i = 0; i < IXGBE_EEPROM_MAX_RETRY_SPI; i += 5) { 147862306a36Sopenharmony_ci ixgbe_shift_out_eeprom_bits(hw, IXGBE_EEPROM_RDSR_OPCODE_SPI, 147962306a36Sopenharmony_ci IXGBE_EEPROM_OPCODE_BITS); 148062306a36Sopenharmony_ci spi_stat_reg = (u8)ixgbe_shift_in_eeprom_bits(hw, 8); 148162306a36Sopenharmony_ci if (!(spi_stat_reg & IXGBE_EEPROM_STATUS_RDY_SPI)) 148262306a36Sopenharmony_ci break; 148362306a36Sopenharmony_ci 148462306a36Sopenharmony_ci udelay(5); 148562306a36Sopenharmony_ci ixgbe_standby_eeprom(hw); 148662306a36Sopenharmony_ci } 148762306a36Sopenharmony_ci 148862306a36Sopenharmony_ci /* 148962306a36Sopenharmony_ci * On some parts, SPI write time could vary from 0-20mSec on 3.3V 149062306a36Sopenharmony_ci * devices (and only 0-5mSec on 5V devices) 149162306a36Sopenharmony_ci */ 149262306a36Sopenharmony_ci if (i >= IXGBE_EEPROM_MAX_RETRY_SPI) { 149362306a36Sopenharmony_ci hw_dbg(hw, "SPI EEPROM Status error\n"); 149462306a36Sopenharmony_ci return -EIO; 149562306a36Sopenharmony_ci } 149662306a36Sopenharmony_ci 149762306a36Sopenharmony_ci return 0; 149862306a36Sopenharmony_ci} 149962306a36Sopenharmony_ci 150062306a36Sopenharmony_ci/** 150162306a36Sopenharmony_ci * ixgbe_standby_eeprom - Returns EEPROM to a "standby" state 150262306a36Sopenharmony_ci * @hw: pointer to hardware structure 150362306a36Sopenharmony_ci **/ 150462306a36Sopenharmony_cistatic void ixgbe_standby_eeprom(struct ixgbe_hw *hw) 150562306a36Sopenharmony_ci{ 150662306a36Sopenharmony_ci u32 eec; 150762306a36Sopenharmony_ci 150862306a36Sopenharmony_ci eec = IXGBE_READ_REG(hw, IXGBE_EEC(hw)); 150962306a36Sopenharmony_ci 151062306a36Sopenharmony_ci /* Toggle CS to flush commands */ 151162306a36Sopenharmony_ci eec |= IXGBE_EEC_CS; 151262306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_EEC(hw), eec); 151362306a36Sopenharmony_ci IXGBE_WRITE_FLUSH(hw); 151462306a36Sopenharmony_ci udelay(1); 151562306a36Sopenharmony_ci eec &= ~IXGBE_EEC_CS; 151662306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_EEC(hw), eec); 151762306a36Sopenharmony_ci IXGBE_WRITE_FLUSH(hw); 151862306a36Sopenharmony_ci udelay(1); 151962306a36Sopenharmony_ci} 152062306a36Sopenharmony_ci 152162306a36Sopenharmony_ci/** 152262306a36Sopenharmony_ci * ixgbe_shift_out_eeprom_bits - Shift data bits out to the EEPROM. 152362306a36Sopenharmony_ci * @hw: pointer to hardware structure 152462306a36Sopenharmony_ci * @data: data to send to the EEPROM 152562306a36Sopenharmony_ci * @count: number of bits to shift out 152662306a36Sopenharmony_ci **/ 152762306a36Sopenharmony_cistatic void ixgbe_shift_out_eeprom_bits(struct ixgbe_hw *hw, u16 data, 152862306a36Sopenharmony_ci u16 count) 152962306a36Sopenharmony_ci{ 153062306a36Sopenharmony_ci u32 eec; 153162306a36Sopenharmony_ci u32 mask; 153262306a36Sopenharmony_ci u32 i; 153362306a36Sopenharmony_ci 153462306a36Sopenharmony_ci eec = IXGBE_READ_REG(hw, IXGBE_EEC(hw)); 153562306a36Sopenharmony_ci 153662306a36Sopenharmony_ci /* 153762306a36Sopenharmony_ci * Mask is used to shift "count" bits of "data" out to the EEPROM 153862306a36Sopenharmony_ci * one bit at a time. Determine the starting bit based on count 153962306a36Sopenharmony_ci */ 154062306a36Sopenharmony_ci mask = BIT(count - 1); 154162306a36Sopenharmony_ci 154262306a36Sopenharmony_ci for (i = 0; i < count; i++) { 154362306a36Sopenharmony_ci /* 154462306a36Sopenharmony_ci * A "1" is shifted out to the EEPROM by setting bit "DI" to a 154562306a36Sopenharmony_ci * "1", and then raising and then lowering the clock (the SK 154662306a36Sopenharmony_ci * bit controls the clock input to the EEPROM). A "0" is 154762306a36Sopenharmony_ci * shifted out to the EEPROM by setting "DI" to "0" and then 154862306a36Sopenharmony_ci * raising and then lowering the clock. 154962306a36Sopenharmony_ci */ 155062306a36Sopenharmony_ci if (data & mask) 155162306a36Sopenharmony_ci eec |= IXGBE_EEC_DI; 155262306a36Sopenharmony_ci else 155362306a36Sopenharmony_ci eec &= ~IXGBE_EEC_DI; 155462306a36Sopenharmony_ci 155562306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_EEC(hw), eec); 155662306a36Sopenharmony_ci IXGBE_WRITE_FLUSH(hw); 155762306a36Sopenharmony_ci 155862306a36Sopenharmony_ci udelay(1); 155962306a36Sopenharmony_ci 156062306a36Sopenharmony_ci ixgbe_raise_eeprom_clk(hw, &eec); 156162306a36Sopenharmony_ci ixgbe_lower_eeprom_clk(hw, &eec); 156262306a36Sopenharmony_ci 156362306a36Sopenharmony_ci /* 156462306a36Sopenharmony_ci * Shift mask to signify next bit of data to shift in to the 156562306a36Sopenharmony_ci * EEPROM 156662306a36Sopenharmony_ci */ 156762306a36Sopenharmony_ci mask = mask >> 1; 156862306a36Sopenharmony_ci } 156962306a36Sopenharmony_ci 157062306a36Sopenharmony_ci /* We leave the "DI" bit set to "0" when we leave this routine. */ 157162306a36Sopenharmony_ci eec &= ~IXGBE_EEC_DI; 157262306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_EEC(hw), eec); 157362306a36Sopenharmony_ci IXGBE_WRITE_FLUSH(hw); 157462306a36Sopenharmony_ci} 157562306a36Sopenharmony_ci 157662306a36Sopenharmony_ci/** 157762306a36Sopenharmony_ci * ixgbe_shift_in_eeprom_bits - Shift data bits in from the EEPROM 157862306a36Sopenharmony_ci * @hw: pointer to hardware structure 157962306a36Sopenharmony_ci * @count: number of bits to shift 158062306a36Sopenharmony_ci **/ 158162306a36Sopenharmony_cistatic u16 ixgbe_shift_in_eeprom_bits(struct ixgbe_hw *hw, u16 count) 158262306a36Sopenharmony_ci{ 158362306a36Sopenharmony_ci u32 eec; 158462306a36Sopenharmony_ci u32 i; 158562306a36Sopenharmony_ci u16 data = 0; 158662306a36Sopenharmony_ci 158762306a36Sopenharmony_ci /* 158862306a36Sopenharmony_ci * In order to read a register from the EEPROM, we need to shift 158962306a36Sopenharmony_ci * 'count' bits in from the EEPROM. Bits are "shifted in" by raising 159062306a36Sopenharmony_ci * the clock input to the EEPROM (setting the SK bit), and then reading 159162306a36Sopenharmony_ci * the value of the "DO" bit. During this "shifting in" process the 159262306a36Sopenharmony_ci * "DI" bit should always be clear. 159362306a36Sopenharmony_ci */ 159462306a36Sopenharmony_ci eec = IXGBE_READ_REG(hw, IXGBE_EEC(hw)); 159562306a36Sopenharmony_ci 159662306a36Sopenharmony_ci eec &= ~(IXGBE_EEC_DO | IXGBE_EEC_DI); 159762306a36Sopenharmony_ci 159862306a36Sopenharmony_ci for (i = 0; i < count; i++) { 159962306a36Sopenharmony_ci data = data << 1; 160062306a36Sopenharmony_ci ixgbe_raise_eeprom_clk(hw, &eec); 160162306a36Sopenharmony_ci 160262306a36Sopenharmony_ci eec = IXGBE_READ_REG(hw, IXGBE_EEC(hw)); 160362306a36Sopenharmony_ci 160462306a36Sopenharmony_ci eec &= ~(IXGBE_EEC_DI); 160562306a36Sopenharmony_ci if (eec & IXGBE_EEC_DO) 160662306a36Sopenharmony_ci data |= 1; 160762306a36Sopenharmony_ci 160862306a36Sopenharmony_ci ixgbe_lower_eeprom_clk(hw, &eec); 160962306a36Sopenharmony_ci } 161062306a36Sopenharmony_ci 161162306a36Sopenharmony_ci return data; 161262306a36Sopenharmony_ci} 161362306a36Sopenharmony_ci 161462306a36Sopenharmony_ci/** 161562306a36Sopenharmony_ci * ixgbe_raise_eeprom_clk - Raises the EEPROM's clock input. 161662306a36Sopenharmony_ci * @hw: pointer to hardware structure 161762306a36Sopenharmony_ci * @eec: EEC register's current value 161862306a36Sopenharmony_ci **/ 161962306a36Sopenharmony_cistatic void ixgbe_raise_eeprom_clk(struct ixgbe_hw *hw, u32 *eec) 162062306a36Sopenharmony_ci{ 162162306a36Sopenharmony_ci /* 162262306a36Sopenharmony_ci * Raise the clock input to the EEPROM 162362306a36Sopenharmony_ci * (setting the SK bit), then delay 162462306a36Sopenharmony_ci */ 162562306a36Sopenharmony_ci *eec = *eec | IXGBE_EEC_SK; 162662306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_EEC(hw), *eec); 162762306a36Sopenharmony_ci IXGBE_WRITE_FLUSH(hw); 162862306a36Sopenharmony_ci udelay(1); 162962306a36Sopenharmony_ci} 163062306a36Sopenharmony_ci 163162306a36Sopenharmony_ci/** 163262306a36Sopenharmony_ci * ixgbe_lower_eeprom_clk - Lowers the EEPROM's clock input. 163362306a36Sopenharmony_ci * @hw: pointer to hardware structure 163462306a36Sopenharmony_ci * @eec: EEC's current value 163562306a36Sopenharmony_ci **/ 163662306a36Sopenharmony_cistatic void ixgbe_lower_eeprom_clk(struct ixgbe_hw *hw, u32 *eec) 163762306a36Sopenharmony_ci{ 163862306a36Sopenharmony_ci /* 163962306a36Sopenharmony_ci * Lower the clock input to the EEPROM (clearing the SK bit), then 164062306a36Sopenharmony_ci * delay 164162306a36Sopenharmony_ci */ 164262306a36Sopenharmony_ci *eec = *eec & ~IXGBE_EEC_SK; 164362306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_EEC(hw), *eec); 164462306a36Sopenharmony_ci IXGBE_WRITE_FLUSH(hw); 164562306a36Sopenharmony_ci udelay(1); 164662306a36Sopenharmony_ci} 164762306a36Sopenharmony_ci 164862306a36Sopenharmony_ci/** 164962306a36Sopenharmony_ci * ixgbe_release_eeprom - Release EEPROM, release semaphores 165062306a36Sopenharmony_ci * @hw: pointer to hardware structure 165162306a36Sopenharmony_ci **/ 165262306a36Sopenharmony_cistatic void ixgbe_release_eeprom(struct ixgbe_hw *hw) 165362306a36Sopenharmony_ci{ 165462306a36Sopenharmony_ci u32 eec; 165562306a36Sopenharmony_ci 165662306a36Sopenharmony_ci eec = IXGBE_READ_REG(hw, IXGBE_EEC(hw)); 165762306a36Sopenharmony_ci 165862306a36Sopenharmony_ci eec |= IXGBE_EEC_CS; /* Pull CS high */ 165962306a36Sopenharmony_ci eec &= ~IXGBE_EEC_SK; /* Lower SCK */ 166062306a36Sopenharmony_ci 166162306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_EEC(hw), eec); 166262306a36Sopenharmony_ci IXGBE_WRITE_FLUSH(hw); 166362306a36Sopenharmony_ci 166462306a36Sopenharmony_ci udelay(1); 166562306a36Sopenharmony_ci 166662306a36Sopenharmony_ci /* Stop requesting EEPROM access */ 166762306a36Sopenharmony_ci eec &= ~IXGBE_EEC_REQ; 166862306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_EEC(hw), eec); 166962306a36Sopenharmony_ci 167062306a36Sopenharmony_ci hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM); 167162306a36Sopenharmony_ci 167262306a36Sopenharmony_ci /* 167362306a36Sopenharmony_ci * Delay before attempt to obtain semaphore again to allow FW 167462306a36Sopenharmony_ci * access. semaphore_delay is in ms we need us for usleep_range 167562306a36Sopenharmony_ci */ 167662306a36Sopenharmony_ci usleep_range(hw->eeprom.semaphore_delay * 1000, 167762306a36Sopenharmony_ci hw->eeprom.semaphore_delay * 2000); 167862306a36Sopenharmony_ci} 167962306a36Sopenharmony_ci 168062306a36Sopenharmony_ci/** 168162306a36Sopenharmony_ci * ixgbe_calc_eeprom_checksum_generic - Calculates and returns the checksum 168262306a36Sopenharmony_ci * @hw: pointer to hardware structure 168362306a36Sopenharmony_ci **/ 168462306a36Sopenharmony_cis32 ixgbe_calc_eeprom_checksum_generic(struct ixgbe_hw *hw) 168562306a36Sopenharmony_ci{ 168662306a36Sopenharmony_ci u16 i; 168762306a36Sopenharmony_ci u16 j; 168862306a36Sopenharmony_ci u16 checksum = 0; 168962306a36Sopenharmony_ci u16 length = 0; 169062306a36Sopenharmony_ci u16 pointer = 0; 169162306a36Sopenharmony_ci u16 word = 0; 169262306a36Sopenharmony_ci 169362306a36Sopenharmony_ci /* Include 0x0-0x3F in the checksum */ 169462306a36Sopenharmony_ci for (i = 0; i < IXGBE_EEPROM_CHECKSUM; i++) { 169562306a36Sopenharmony_ci if (hw->eeprom.ops.read(hw, i, &word)) { 169662306a36Sopenharmony_ci hw_dbg(hw, "EEPROM read failed\n"); 169762306a36Sopenharmony_ci break; 169862306a36Sopenharmony_ci } 169962306a36Sopenharmony_ci checksum += word; 170062306a36Sopenharmony_ci } 170162306a36Sopenharmony_ci 170262306a36Sopenharmony_ci /* Include all data from pointers except for the fw pointer */ 170362306a36Sopenharmony_ci for (i = IXGBE_PCIE_ANALOG_PTR; i < IXGBE_FW_PTR; i++) { 170462306a36Sopenharmony_ci if (hw->eeprom.ops.read(hw, i, &pointer)) { 170562306a36Sopenharmony_ci hw_dbg(hw, "EEPROM read failed\n"); 170662306a36Sopenharmony_ci return -EIO; 170762306a36Sopenharmony_ci } 170862306a36Sopenharmony_ci 170962306a36Sopenharmony_ci /* If the pointer seems invalid */ 171062306a36Sopenharmony_ci if (pointer == 0xFFFF || pointer == 0) 171162306a36Sopenharmony_ci continue; 171262306a36Sopenharmony_ci 171362306a36Sopenharmony_ci if (hw->eeprom.ops.read(hw, pointer, &length)) { 171462306a36Sopenharmony_ci hw_dbg(hw, "EEPROM read failed\n"); 171562306a36Sopenharmony_ci return -EIO; 171662306a36Sopenharmony_ci } 171762306a36Sopenharmony_ci 171862306a36Sopenharmony_ci if (length == 0xFFFF || length == 0) 171962306a36Sopenharmony_ci continue; 172062306a36Sopenharmony_ci 172162306a36Sopenharmony_ci for (j = pointer + 1; j <= pointer + length; j++) { 172262306a36Sopenharmony_ci if (hw->eeprom.ops.read(hw, j, &word)) { 172362306a36Sopenharmony_ci hw_dbg(hw, "EEPROM read failed\n"); 172462306a36Sopenharmony_ci return -EIO; 172562306a36Sopenharmony_ci } 172662306a36Sopenharmony_ci checksum += word; 172762306a36Sopenharmony_ci } 172862306a36Sopenharmony_ci } 172962306a36Sopenharmony_ci 173062306a36Sopenharmony_ci checksum = (u16)IXGBE_EEPROM_SUM - checksum; 173162306a36Sopenharmony_ci 173262306a36Sopenharmony_ci return (s32)checksum; 173362306a36Sopenharmony_ci} 173462306a36Sopenharmony_ci 173562306a36Sopenharmony_ci/** 173662306a36Sopenharmony_ci * ixgbe_validate_eeprom_checksum_generic - Validate EEPROM checksum 173762306a36Sopenharmony_ci * @hw: pointer to hardware structure 173862306a36Sopenharmony_ci * @checksum_val: calculated checksum 173962306a36Sopenharmony_ci * 174062306a36Sopenharmony_ci * Performs checksum calculation and validates the EEPROM checksum. If the 174162306a36Sopenharmony_ci * caller does not need checksum_val, the value can be NULL. 174262306a36Sopenharmony_ci **/ 174362306a36Sopenharmony_cis32 ixgbe_validate_eeprom_checksum_generic(struct ixgbe_hw *hw, 174462306a36Sopenharmony_ci u16 *checksum_val) 174562306a36Sopenharmony_ci{ 174662306a36Sopenharmony_ci s32 status; 174762306a36Sopenharmony_ci u16 checksum; 174862306a36Sopenharmony_ci u16 read_checksum = 0; 174962306a36Sopenharmony_ci 175062306a36Sopenharmony_ci /* 175162306a36Sopenharmony_ci * Read the first word from the EEPROM. If this times out or fails, do 175262306a36Sopenharmony_ci * not continue or we could be in for a very long wait while every 175362306a36Sopenharmony_ci * EEPROM read fails 175462306a36Sopenharmony_ci */ 175562306a36Sopenharmony_ci status = hw->eeprom.ops.read(hw, 0, &checksum); 175662306a36Sopenharmony_ci if (status) { 175762306a36Sopenharmony_ci hw_dbg(hw, "EEPROM read failed\n"); 175862306a36Sopenharmony_ci return status; 175962306a36Sopenharmony_ci } 176062306a36Sopenharmony_ci 176162306a36Sopenharmony_ci status = hw->eeprom.ops.calc_checksum(hw); 176262306a36Sopenharmony_ci if (status < 0) 176362306a36Sopenharmony_ci return status; 176462306a36Sopenharmony_ci 176562306a36Sopenharmony_ci checksum = (u16)(status & 0xffff); 176662306a36Sopenharmony_ci 176762306a36Sopenharmony_ci status = hw->eeprom.ops.read(hw, IXGBE_EEPROM_CHECKSUM, &read_checksum); 176862306a36Sopenharmony_ci if (status) { 176962306a36Sopenharmony_ci hw_dbg(hw, "EEPROM read failed\n"); 177062306a36Sopenharmony_ci return status; 177162306a36Sopenharmony_ci } 177262306a36Sopenharmony_ci 177362306a36Sopenharmony_ci /* Verify read checksum from EEPROM is the same as 177462306a36Sopenharmony_ci * calculated checksum 177562306a36Sopenharmony_ci */ 177662306a36Sopenharmony_ci if (read_checksum != checksum) 177762306a36Sopenharmony_ci status = -EIO; 177862306a36Sopenharmony_ci 177962306a36Sopenharmony_ci /* If the user cares, return the calculated checksum */ 178062306a36Sopenharmony_ci if (checksum_val) 178162306a36Sopenharmony_ci *checksum_val = checksum; 178262306a36Sopenharmony_ci 178362306a36Sopenharmony_ci return status; 178462306a36Sopenharmony_ci} 178562306a36Sopenharmony_ci 178662306a36Sopenharmony_ci/** 178762306a36Sopenharmony_ci * ixgbe_update_eeprom_checksum_generic - Updates the EEPROM checksum 178862306a36Sopenharmony_ci * @hw: pointer to hardware structure 178962306a36Sopenharmony_ci **/ 179062306a36Sopenharmony_cis32 ixgbe_update_eeprom_checksum_generic(struct ixgbe_hw *hw) 179162306a36Sopenharmony_ci{ 179262306a36Sopenharmony_ci s32 status; 179362306a36Sopenharmony_ci u16 checksum; 179462306a36Sopenharmony_ci 179562306a36Sopenharmony_ci /* 179662306a36Sopenharmony_ci * Read the first word from the EEPROM. If this times out or fails, do 179762306a36Sopenharmony_ci * not continue or we could be in for a very long wait while every 179862306a36Sopenharmony_ci * EEPROM read fails 179962306a36Sopenharmony_ci */ 180062306a36Sopenharmony_ci status = hw->eeprom.ops.read(hw, 0, &checksum); 180162306a36Sopenharmony_ci if (status) { 180262306a36Sopenharmony_ci hw_dbg(hw, "EEPROM read failed\n"); 180362306a36Sopenharmony_ci return status; 180462306a36Sopenharmony_ci } 180562306a36Sopenharmony_ci 180662306a36Sopenharmony_ci status = hw->eeprom.ops.calc_checksum(hw); 180762306a36Sopenharmony_ci if (status < 0) 180862306a36Sopenharmony_ci return status; 180962306a36Sopenharmony_ci 181062306a36Sopenharmony_ci checksum = (u16)(status & 0xffff); 181162306a36Sopenharmony_ci 181262306a36Sopenharmony_ci status = hw->eeprom.ops.write(hw, IXGBE_EEPROM_CHECKSUM, checksum); 181362306a36Sopenharmony_ci 181462306a36Sopenharmony_ci return status; 181562306a36Sopenharmony_ci} 181662306a36Sopenharmony_ci 181762306a36Sopenharmony_ci/** 181862306a36Sopenharmony_ci * ixgbe_set_rar_generic - Set Rx address register 181962306a36Sopenharmony_ci * @hw: pointer to hardware structure 182062306a36Sopenharmony_ci * @index: Receive address register to write 182162306a36Sopenharmony_ci * @addr: Address to put into receive address register 182262306a36Sopenharmony_ci * @vmdq: VMDq "set" or "pool" index 182362306a36Sopenharmony_ci * @enable_addr: set flag that address is active 182462306a36Sopenharmony_ci * 182562306a36Sopenharmony_ci * Puts an ethernet address into a receive address register. 182662306a36Sopenharmony_ci **/ 182762306a36Sopenharmony_cis32 ixgbe_set_rar_generic(struct ixgbe_hw *hw, u32 index, u8 *addr, u32 vmdq, 182862306a36Sopenharmony_ci u32 enable_addr) 182962306a36Sopenharmony_ci{ 183062306a36Sopenharmony_ci u32 rar_low, rar_high; 183162306a36Sopenharmony_ci u32 rar_entries = hw->mac.num_rar_entries; 183262306a36Sopenharmony_ci 183362306a36Sopenharmony_ci /* Make sure we are using a valid rar index range */ 183462306a36Sopenharmony_ci if (index >= rar_entries) { 183562306a36Sopenharmony_ci hw_dbg(hw, "RAR index %d is out of range.\n", index); 183662306a36Sopenharmony_ci return -EINVAL; 183762306a36Sopenharmony_ci } 183862306a36Sopenharmony_ci 183962306a36Sopenharmony_ci /* setup VMDq pool selection before this RAR gets enabled */ 184062306a36Sopenharmony_ci hw->mac.ops.set_vmdq(hw, index, vmdq); 184162306a36Sopenharmony_ci 184262306a36Sopenharmony_ci /* 184362306a36Sopenharmony_ci * HW expects these in little endian so we reverse the byte 184462306a36Sopenharmony_ci * order from network order (big endian) to little endian 184562306a36Sopenharmony_ci */ 184662306a36Sopenharmony_ci rar_low = ((u32)addr[0] | 184762306a36Sopenharmony_ci ((u32)addr[1] << 8) | 184862306a36Sopenharmony_ci ((u32)addr[2] << 16) | 184962306a36Sopenharmony_ci ((u32)addr[3] << 24)); 185062306a36Sopenharmony_ci /* 185162306a36Sopenharmony_ci * Some parts put the VMDq setting in the extra RAH bits, 185262306a36Sopenharmony_ci * so save everything except the lower 16 bits that hold part 185362306a36Sopenharmony_ci * of the address and the address valid bit. 185462306a36Sopenharmony_ci */ 185562306a36Sopenharmony_ci rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(index)); 185662306a36Sopenharmony_ci rar_high &= ~(0x0000FFFF | IXGBE_RAH_AV); 185762306a36Sopenharmony_ci rar_high |= ((u32)addr[4] | ((u32)addr[5] << 8)); 185862306a36Sopenharmony_ci 185962306a36Sopenharmony_ci if (enable_addr != 0) 186062306a36Sopenharmony_ci rar_high |= IXGBE_RAH_AV; 186162306a36Sopenharmony_ci 186262306a36Sopenharmony_ci /* Record lower 32 bits of MAC address and then make 186362306a36Sopenharmony_ci * sure that write is flushed to hardware before writing 186462306a36Sopenharmony_ci * the upper 16 bits and setting the valid bit. 186562306a36Sopenharmony_ci */ 186662306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_RAL(index), rar_low); 186762306a36Sopenharmony_ci IXGBE_WRITE_FLUSH(hw); 186862306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_RAH(index), rar_high); 186962306a36Sopenharmony_ci 187062306a36Sopenharmony_ci return 0; 187162306a36Sopenharmony_ci} 187262306a36Sopenharmony_ci 187362306a36Sopenharmony_ci/** 187462306a36Sopenharmony_ci * ixgbe_clear_rar_generic - Remove Rx address register 187562306a36Sopenharmony_ci * @hw: pointer to hardware structure 187662306a36Sopenharmony_ci * @index: Receive address register to write 187762306a36Sopenharmony_ci * 187862306a36Sopenharmony_ci * Clears an ethernet address from a receive address register. 187962306a36Sopenharmony_ci **/ 188062306a36Sopenharmony_cis32 ixgbe_clear_rar_generic(struct ixgbe_hw *hw, u32 index) 188162306a36Sopenharmony_ci{ 188262306a36Sopenharmony_ci u32 rar_high; 188362306a36Sopenharmony_ci u32 rar_entries = hw->mac.num_rar_entries; 188462306a36Sopenharmony_ci 188562306a36Sopenharmony_ci /* Make sure we are using a valid rar index range */ 188662306a36Sopenharmony_ci if (index >= rar_entries) { 188762306a36Sopenharmony_ci hw_dbg(hw, "RAR index %d is out of range.\n", index); 188862306a36Sopenharmony_ci return -EINVAL; 188962306a36Sopenharmony_ci } 189062306a36Sopenharmony_ci 189162306a36Sopenharmony_ci /* 189262306a36Sopenharmony_ci * Some parts put the VMDq setting in the extra RAH bits, 189362306a36Sopenharmony_ci * so save everything except the lower 16 bits that hold part 189462306a36Sopenharmony_ci * of the address and the address valid bit. 189562306a36Sopenharmony_ci */ 189662306a36Sopenharmony_ci rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(index)); 189762306a36Sopenharmony_ci rar_high &= ~(0x0000FFFF | IXGBE_RAH_AV); 189862306a36Sopenharmony_ci 189962306a36Sopenharmony_ci /* Clear the address valid bit and upper 16 bits of the address 190062306a36Sopenharmony_ci * before clearing the lower bits. This way we aren't updating 190162306a36Sopenharmony_ci * a live filter. 190262306a36Sopenharmony_ci */ 190362306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_RAH(index), rar_high); 190462306a36Sopenharmony_ci IXGBE_WRITE_FLUSH(hw); 190562306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_RAL(index), 0); 190662306a36Sopenharmony_ci 190762306a36Sopenharmony_ci /* clear VMDq pool/queue selection for this RAR */ 190862306a36Sopenharmony_ci hw->mac.ops.clear_vmdq(hw, index, IXGBE_CLEAR_VMDQ_ALL); 190962306a36Sopenharmony_ci 191062306a36Sopenharmony_ci return 0; 191162306a36Sopenharmony_ci} 191262306a36Sopenharmony_ci 191362306a36Sopenharmony_ci/** 191462306a36Sopenharmony_ci * ixgbe_init_rx_addrs_generic - Initializes receive address filters. 191562306a36Sopenharmony_ci * @hw: pointer to hardware structure 191662306a36Sopenharmony_ci * 191762306a36Sopenharmony_ci * Places the MAC address in receive address register 0 and clears the rest 191862306a36Sopenharmony_ci * of the receive address registers. Clears the multicast table. Assumes 191962306a36Sopenharmony_ci * the receiver is in reset when the routine is called. 192062306a36Sopenharmony_ci **/ 192162306a36Sopenharmony_cis32 ixgbe_init_rx_addrs_generic(struct ixgbe_hw *hw) 192262306a36Sopenharmony_ci{ 192362306a36Sopenharmony_ci u32 i; 192462306a36Sopenharmony_ci u32 rar_entries = hw->mac.num_rar_entries; 192562306a36Sopenharmony_ci 192662306a36Sopenharmony_ci /* 192762306a36Sopenharmony_ci * If the current mac address is valid, assume it is a software override 192862306a36Sopenharmony_ci * to the permanent address. 192962306a36Sopenharmony_ci * Otherwise, use the permanent address from the eeprom. 193062306a36Sopenharmony_ci */ 193162306a36Sopenharmony_ci if (!is_valid_ether_addr(hw->mac.addr)) { 193262306a36Sopenharmony_ci /* Get the MAC address from the RAR0 for later reference */ 193362306a36Sopenharmony_ci hw->mac.ops.get_mac_addr(hw, hw->mac.addr); 193462306a36Sopenharmony_ci 193562306a36Sopenharmony_ci hw_dbg(hw, " Keeping Current RAR0 Addr =%pM\n", hw->mac.addr); 193662306a36Sopenharmony_ci } else { 193762306a36Sopenharmony_ci /* Setup the receive address. */ 193862306a36Sopenharmony_ci hw_dbg(hw, "Overriding MAC Address in RAR[0]\n"); 193962306a36Sopenharmony_ci hw_dbg(hw, " New MAC Addr =%pM\n", hw->mac.addr); 194062306a36Sopenharmony_ci 194162306a36Sopenharmony_ci hw->mac.ops.set_rar(hw, 0, hw->mac.addr, 0, IXGBE_RAH_AV); 194262306a36Sopenharmony_ci } 194362306a36Sopenharmony_ci 194462306a36Sopenharmony_ci /* clear VMDq pool/queue selection for RAR 0 */ 194562306a36Sopenharmony_ci hw->mac.ops.clear_vmdq(hw, 0, IXGBE_CLEAR_VMDQ_ALL); 194662306a36Sopenharmony_ci 194762306a36Sopenharmony_ci hw->addr_ctrl.overflow_promisc = 0; 194862306a36Sopenharmony_ci 194962306a36Sopenharmony_ci hw->addr_ctrl.rar_used_count = 1; 195062306a36Sopenharmony_ci 195162306a36Sopenharmony_ci /* Zero out the other receive addresses. */ 195262306a36Sopenharmony_ci hw_dbg(hw, "Clearing RAR[1-%d]\n", rar_entries - 1); 195362306a36Sopenharmony_ci for (i = 1; i < rar_entries; i++) { 195462306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_RAL(i), 0); 195562306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_RAH(i), 0); 195662306a36Sopenharmony_ci } 195762306a36Sopenharmony_ci 195862306a36Sopenharmony_ci /* Clear the MTA */ 195962306a36Sopenharmony_ci hw->addr_ctrl.mta_in_use = 0; 196062306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_MCSTCTRL, hw->mac.mc_filter_type); 196162306a36Sopenharmony_ci 196262306a36Sopenharmony_ci hw_dbg(hw, " Clearing MTA\n"); 196362306a36Sopenharmony_ci for (i = 0; i < hw->mac.mcft_size; i++) 196462306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_MTA(i), 0); 196562306a36Sopenharmony_ci 196662306a36Sopenharmony_ci if (hw->mac.ops.init_uta_tables) 196762306a36Sopenharmony_ci hw->mac.ops.init_uta_tables(hw); 196862306a36Sopenharmony_ci 196962306a36Sopenharmony_ci return 0; 197062306a36Sopenharmony_ci} 197162306a36Sopenharmony_ci 197262306a36Sopenharmony_ci/** 197362306a36Sopenharmony_ci * ixgbe_mta_vector - Determines bit-vector in multicast table to set 197462306a36Sopenharmony_ci * @hw: pointer to hardware structure 197562306a36Sopenharmony_ci * @mc_addr: the multicast address 197662306a36Sopenharmony_ci * 197762306a36Sopenharmony_ci * Extracts the 12 bits, from a multicast address, to determine which 197862306a36Sopenharmony_ci * bit-vector to set in the multicast table. The hardware uses 12 bits, from 197962306a36Sopenharmony_ci * incoming rx multicast addresses, to determine the bit-vector to check in 198062306a36Sopenharmony_ci * the MTA. Which of the 4 combination, of 12-bits, the hardware uses is set 198162306a36Sopenharmony_ci * by the MO field of the MCSTCTRL. The MO field is set during initialization 198262306a36Sopenharmony_ci * to mc_filter_type. 198362306a36Sopenharmony_ci **/ 198462306a36Sopenharmony_cistatic s32 ixgbe_mta_vector(struct ixgbe_hw *hw, u8 *mc_addr) 198562306a36Sopenharmony_ci{ 198662306a36Sopenharmony_ci u32 vector = 0; 198762306a36Sopenharmony_ci 198862306a36Sopenharmony_ci switch (hw->mac.mc_filter_type) { 198962306a36Sopenharmony_ci case 0: /* use bits [47:36] of the address */ 199062306a36Sopenharmony_ci vector = ((mc_addr[4] >> 4) | (((u16)mc_addr[5]) << 4)); 199162306a36Sopenharmony_ci break; 199262306a36Sopenharmony_ci case 1: /* use bits [46:35] of the address */ 199362306a36Sopenharmony_ci vector = ((mc_addr[4] >> 3) | (((u16)mc_addr[5]) << 5)); 199462306a36Sopenharmony_ci break; 199562306a36Sopenharmony_ci case 2: /* use bits [45:34] of the address */ 199662306a36Sopenharmony_ci vector = ((mc_addr[4] >> 2) | (((u16)mc_addr[5]) << 6)); 199762306a36Sopenharmony_ci break; 199862306a36Sopenharmony_ci case 3: /* use bits [43:32] of the address */ 199962306a36Sopenharmony_ci vector = ((mc_addr[4]) | (((u16)mc_addr[5]) << 8)); 200062306a36Sopenharmony_ci break; 200162306a36Sopenharmony_ci default: /* Invalid mc_filter_type */ 200262306a36Sopenharmony_ci hw_dbg(hw, "MC filter type param set incorrectly\n"); 200362306a36Sopenharmony_ci break; 200462306a36Sopenharmony_ci } 200562306a36Sopenharmony_ci 200662306a36Sopenharmony_ci /* vector can only be 12-bits or boundary will be exceeded */ 200762306a36Sopenharmony_ci vector &= 0xFFF; 200862306a36Sopenharmony_ci return vector; 200962306a36Sopenharmony_ci} 201062306a36Sopenharmony_ci 201162306a36Sopenharmony_ci/** 201262306a36Sopenharmony_ci * ixgbe_set_mta - Set bit-vector in multicast table 201362306a36Sopenharmony_ci * @hw: pointer to hardware structure 201462306a36Sopenharmony_ci * @mc_addr: Multicast address 201562306a36Sopenharmony_ci * 201662306a36Sopenharmony_ci * Sets the bit-vector in the multicast table. 201762306a36Sopenharmony_ci **/ 201862306a36Sopenharmony_cistatic void ixgbe_set_mta(struct ixgbe_hw *hw, u8 *mc_addr) 201962306a36Sopenharmony_ci{ 202062306a36Sopenharmony_ci u32 vector; 202162306a36Sopenharmony_ci u32 vector_bit; 202262306a36Sopenharmony_ci u32 vector_reg; 202362306a36Sopenharmony_ci 202462306a36Sopenharmony_ci hw->addr_ctrl.mta_in_use++; 202562306a36Sopenharmony_ci 202662306a36Sopenharmony_ci vector = ixgbe_mta_vector(hw, mc_addr); 202762306a36Sopenharmony_ci hw_dbg(hw, " bit-vector = 0x%03X\n", vector); 202862306a36Sopenharmony_ci 202962306a36Sopenharmony_ci /* 203062306a36Sopenharmony_ci * The MTA is a register array of 128 32-bit registers. It is treated 203162306a36Sopenharmony_ci * like an array of 4096 bits. We want to set bit 203262306a36Sopenharmony_ci * BitArray[vector_value]. So we figure out what register the bit is 203362306a36Sopenharmony_ci * in, read it, OR in the new bit, then write back the new value. The 203462306a36Sopenharmony_ci * register is determined by the upper 7 bits of the vector value and 203562306a36Sopenharmony_ci * the bit within that register are determined by the lower 5 bits of 203662306a36Sopenharmony_ci * the value. 203762306a36Sopenharmony_ci */ 203862306a36Sopenharmony_ci vector_reg = (vector >> 5) & 0x7F; 203962306a36Sopenharmony_ci vector_bit = vector & 0x1F; 204062306a36Sopenharmony_ci hw->mac.mta_shadow[vector_reg] |= BIT(vector_bit); 204162306a36Sopenharmony_ci} 204262306a36Sopenharmony_ci 204362306a36Sopenharmony_ci/** 204462306a36Sopenharmony_ci * ixgbe_update_mc_addr_list_generic - Updates MAC list of multicast addresses 204562306a36Sopenharmony_ci * @hw: pointer to hardware structure 204662306a36Sopenharmony_ci * @netdev: pointer to net device structure 204762306a36Sopenharmony_ci * 204862306a36Sopenharmony_ci * The given list replaces any existing list. Clears the MC addrs from receive 204962306a36Sopenharmony_ci * address registers and the multicast table. Uses unused receive address 205062306a36Sopenharmony_ci * registers for the first multicast addresses, and hashes the rest into the 205162306a36Sopenharmony_ci * multicast table. 205262306a36Sopenharmony_ci **/ 205362306a36Sopenharmony_cis32 ixgbe_update_mc_addr_list_generic(struct ixgbe_hw *hw, 205462306a36Sopenharmony_ci struct net_device *netdev) 205562306a36Sopenharmony_ci{ 205662306a36Sopenharmony_ci struct netdev_hw_addr *ha; 205762306a36Sopenharmony_ci u32 i; 205862306a36Sopenharmony_ci 205962306a36Sopenharmony_ci /* 206062306a36Sopenharmony_ci * Set the new number of MC addresses that we are being requested to 206162306a36Sopenharmony_ci * use. 206262306a36Sopenharmony_ci */ 206362306a36Sopenharmony_ci hw->addr_ctrl.num_mc_addrs = netdev_mc_count(netdev); 206462306a36Sopenharmony_ci hw->addr_ctrl.mta_in_use = 0; 206562306a36Sopenharmony_ci 206662306a36Sopenharmony_ci /* Clear mta_shadow */ 206762306a36Sopenharmony_ci hw_dbg(hw, " Clearing MTA\n"); 206862306a36Sopenharmony_ci memset(&hw->mac.mta_shadow, 0, sizeof(hw->mac.mta_shadow)); 206962306a36Sopenharmony_ci 207062306a36Sopenharmony_ci /* Update mta shadow */ 207162306a36Sopenharmony_ci netdev_for_each_mc_addr(ha, netdev) { 207262306a36Sopenharmony_ci hw_dbg(hw, " Adding the multicast addresses:\n"); 207362306a36Sopenharmony_ci ixgbe_set_mta(hw, ha->addr); 207462306a36Sopenharmony_ci } 207562306a36Sopenharmony_ci 207662306a36Sopenharmony_ci /* Enable mta */ 207762306a36Sopenharmony_ci for (i = 0; i < hw->mac.mcft_size; i++) 207862306a36Sopenharmony_ci IXGBE_WRITE_REG_ARRAY(hw, IXGBE_MTA(0), i, 207962306a36Sopenharmony_ci hw->mac.mta_shadow[i]); 208062306a36Sopenharmony_ci 208162306a36Sopenharmony_ci if (hw->addr_ctrl.mta_in_use > 0) 208262306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_MCSTCTRL, 208362306a36Sopenharmony_ci IXGBE_MCSTCTRL_MFE | hw->mac.mc_filter_type); 208462306a36Sopenharmony_ci 208562306a36Sopenharmony_ci hw_dbg(hw, "ixgbe_update_mc_addr_list_generic Complete\n"); 208662306a36Sopenharmony_ci return 0; 208762306a36Sopenharmony_ci} 208862306a36Sopenharmony_ci 208962306a36Sopenharmony_ci/** 209062306a36Sopenharmony_ci * ixgbe_enable_mc_generic - Enable multicast address in RAR 209162306a36Sopenharmony_ci * @hw: pointer to hardware structure 209262306a36Sopenharmony_ci * 209362306a36Sopenharmony_ci * Enables multicast address in RAR and the use of the multicast hash table. 209462306a36Sopenharmony_ci **/ 209562306a36Sopenharmony_cis32 ixgbe_enable_mc_generic(struct ixgbe_hw *hw) 209662306a36Sopenharmony_ci{ 209762306a36Sopenharmony_ci struct ixgbe_addr_filter_info *a = &hw->addr_ctrl; 209862306a36Sopenharmony_ci 209962306a36Sopenharmony_ci if (a->mta_in_use > 0) 210062306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_MCSTCTRL, IXGBE_MCSTCTRL_MFE | 210162306a36Sopenharmony_ci hw->mac.mc_filter_type); 210262306a36Sopenharmony_ci 210362306a36Sopenharmony_ci return 0; 210462306a36Sopenharmony_ci} 210562306a36Sopenharmony_ci 210662306a36Sopenharmony_ci/** 210762306a36Sopenharmony_ci * ixgbe_disable_mc_generic - Disable multicast address in RAR 210862306a36Sopenharmony_ci * @hw: pointer to hardware structure 210962306a36Sopenharmony_ci * 211062306a36Sopenharmony_ci * Disables multicast address in RAR and the use of the multicast hash table. 211162306a36Sopenharmony_ci **/ 211262306a36Sopenharmony_cis32 ixgbe_disable_mc_generic(struct ixgbe_hw *hw) 211362306a36Sopenharmony_ci{ 211462306a36Sopenharmony_ci struct ixgbe_addr_filter_info *a = &hw->addr_ctrl; 211562306a36Sopenharmony_ci 211662306a36Sopenharmony_ci if (a->mta_in_use > 0) 211762306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_MCSTCTRL, hw->mac.mc_filter_type); 211862306a36Sopenharmony_ci 211962306a36Sopenharmony_ci return 0; 212062306a36Sopenharmony_ci} 212162306a36Sopenharmony_ci 212262306a36Sopenharmony_ci/** 212362306a36Sopenharmony_ci * ixgbe_fc_enable_generic - Enable flow control 212462306a36Sopenharmony_ci * @hw: pointer to hardware structure 212562306a36Sopenharmony_ci * 212662306a36Sopenharmony_ci * Enable flow control according to the current settings. 212762306a36Sopenharmony_ci **/ 212862306a36Sopenharmony_cis32 ixgbe_fc_enable_generic(struct ixgbe_hw *hw) 212962306a36Sopenharmony_ci{ 213062306a36Sopenharmony_ci u32 mflcn_reg, fccfg_reg; 213162306a36Sopenharmony_ci u32 reg; 213262306a36Sopenharmony_ci u32 fcrtl, fcrth; 213362306a36Sopenharmony_ci int i; 213462306a36Sopenharmony_ci 213562306a36Sopenharmony_ci /* Validate the water mark configuration. */ 213662306a36Sopenharmony_ci if (!hw->fc.pause_time) 213762306a36Sopenharmony_ci return -EINVAL; 213862306a36Sopenharmony_ci 213962306a36Sopenharmony_ci /* Low water mark of zero causes XOFF floods */ 214062306a36Sopenharmony_ci for (i = 0; i < MAX_TRAFFIC_CLASS; i++) { 214162306a36Sopenharmony_ci if ((hw->fc.current_mode & ixgbe_fc_tx_pause) && 214262306a36Sopenharmony_ci hw->fc.high_water[i]) { 214362306a36Sopenharmony_ci if (!hw->fc.low_water[i] || 214462306a36Sopenharmony_ci hw->fc.low_water[i] >= hw->fc.high_water[i]) { 214562306a36Sopenharmony_ci hw_dbg(hw, "Invalid water mark configuration\n"); 214662306a36Sopenharmony_ci return -EINVAL; 214762306a36Sopenharmony_ci } 214862306a36Sopenharmony_ci } 214962306a36Sopenharmony_ci } 215062306a36Sopenharmony_ci 215162306a36Sopenharmony_ci /* Negotiate the fc mode to use */ 215262306a36Sopenharmony_ci hw->mac.ops.fc_autoneg(hw); 215362306a36Sopenharmony_ci 215462306a36Sopenharmony_ci /* Disable any previous flow control settings */ 215562306a36Sopenharmony_ci mflcn_reg = IXGBE_READ_REG(hw, IXGBE_MFLCN); 215662306a36Sopenharmony_ci mflcn_reg &= ~(IXGBE_MFLCN_RPFCE_MASK | IXGBE_MFLCN_RFCE); 215762306a36Sopenharmony_ci 215862306a36Sopenharmony_ci fccfg_reg = IXGBE_READ_REG(hw, IXGBE_FCCFG); 215962306a36Sopenharmony_ci fccfg_reg &= ~(IXGBE_FCCFG_TFCE_802_3X | IXGBE_FCCFG_TFCE_PRIORITY); 216062306a36Sopenharmony_ci 216162306a36Sopenharmony_ci /* 216262306a36Sopenharmony_ci * The possible values of fc.current_mode are: 216362306a36Sopenharmony_ci * 0: Flow control is completely disabled 216462306a36Sopenharmony_ci * 1: Rx flow control is enabled (we can receive pause frames, 216562306a36Sopenharmony_ci * but not send pause frames). 216662306a36Sopenharmony_ci * 2: Tx flow control is enabled (we can send pause frames but 216762306a36Sopenharmony_ci * we do not support receiving pause frames). 216862306a36Sopenharmony_ci * 3: Both Rx and Tx flow control (symmetric) are enabled. 216962306a36Sopenharmony_ci * other: Invalid. 217062306a36Sopenharmony_ci */ 217162306a36Sopenharmony_ci switch (hw->fc.current_mode) { 217262306a36Sopenharmony_ci case ixgbe_fc_none: 217362306a36Sopenharmony_ci /* 217462306a36Sopenharmony_ci * Flow control is disabled by software override or autoneg. 217562306a36Sopenharmony_ci * The code below will actually disable it in the HW. 217662306a36Sopenharmony_ci */ 217762306a36Sopenharmony_ci break; 217862306a36Sopenharmony_ci case ixgbe_fc_rx_pause: 217962306a36Sopenharmony_ci /* 218062306a36Sopenharmony_ci * Rx Flow control is enabled and Tx Flow control is 218162306a36Sopenharmony_ci * disabled by software override. Since there really 218262306a36Sopenharmony_ci * isn't a way to advertise that we are capable of RX 218362306a36Sopenharmony_ci * Pause ONLY, we will advertise that we support both 218462306a36Sopenharmony_ci * symmetric and asymmetric Rx PAUSE. Later, we will 218562306a36Sopenharmony_ci * disable the adapter's ability to send PAUSE frames. 218662306a36Sopenharmony_ci */ 218762306a36Sopenharmony_ci mflcn_reg |= IXGBE_MFLCN_RFCE; 218862306a36Sopenharmony_ci break; 218962306a36Sopenharmony_ci case ixgbe_fc_tx_pause: 219062306a36Sopenharmony_ci /* 219162306a36Sopenharmony_ci * Tx Flow control is enabled, and Rx Flow control is 219262306a36Sopenharmony_ci * disabled by software override. 219362306a36Sopenharmony_ci */ 219462306a36Sopenharmony_ci fccfg_reg |= IXGBE_FCCFG_TFCE_802_3X; 219562306a36Sopenharmony_ci break; 219662306a36Sopenharmony_ci case ixgbe_fc_full: 219762306a36Sopenharmony_ci /* Flow control (both Rx and Tx) is enabled by SW override. */ 219862306a36Sopenharmony_ci mflcn_reg |= IXGBE_MFLCN_RFCE; 219962306a36Sopenharmony_ci fccfg_reg |= IXGBE_FCCFG_TFCE_802_3X; 220062306a36Sopenharmony_ci break; 220162306a36Sopenharmony_ci default: 220262306a36Sopenharmony_ci hw_dbg(hw, "Flow control param set incorrectly\n"); 220362306a36Sopenharmony_ci return -EIO; 220462306a36Sopenharmony_ci } 220562306a36Sopenharmony_ci 220662306a36Sopenharmony_ci /* Set 802.3x based flow control settings. */ 220762306a36Sopenharmony_ci mflcn_reg |= IXGBE_MFLCN_DPF; 220862306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_MFLCN, mflcn_reg); 220962306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_FCCFG, fccfg_reg); 221062306a36Sopenharmony_ci 221162306a36Sopenharmony_ci /* Set up and enable Rx high/low water mark thresholds, enable XON. */ 221262306a36Sopenharmony_ci for (i = 0; i < MAX_TRAFFIC_CLASS; i++) { 221362306a36Sopenharmony_ci if ((hw->fc.current_mode & ixgbe_fc_tx_pause) && 221462306a36Sopenharmony_ci hw->fc.high_water[i]) { 221562306a36Sopenharmony_ci fcrtl = (hw->fc.low_water[i] << 10) | IXGBE_FCRTL_XONE; 221662306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_FCRTL_82599(i), fcrtl); 221762306a36Sopenharmony_ci fcrth = (hw->fc.high_water[i] << 10) | IXGBE_FCRTH_FCEN; 221862306a36Sopenharmony_ci } else { 221962306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_FCRTL_82599(i), 0); 222062306a36Sopenharmony_ci /* 222162306a36Sopenharmony_ci * In order to prevent Tx hangs when the internal Tx 222262306a36Sopenharmony_ci * switch is enabled we must set the high water mark 222362306a36Sopenharmony_ci * to the Rx packet buffer size - 24KB. This allows 222462306a36Sopenharmony_ci * the Tx switch to function even under heavy Rx 222562306a36Sopenharmony_ci * workloads. 222662306a36Sopenharmony_ci */ 222762306a36Sopenharmony_ci fcrth = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(i)) - 24576; 222862306a36Sopenharmony_ci } 222962306a36Sopenharmony_ci 223062306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_FCRTH_82599(i), fcrth); 223162306a36Sopenharmony_ci } 223262306a36Sopenharmony_ci 223362306a36Sopenharmony_ci /* Configure pause time (2 TCs per register) */ 223462306a36Sopenharmony_ci reg = hw->fc.pause_time * 0x00010001U; 223562306a36Sopenharmony_ci for (i = 0; i < (MAX_TRAFFIC_CLASS / 2); i++) 223662306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_FCTTV(i), reg); 223762306a36Sopenharmony_ci 223862306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_FCRTV, hw->fc.pause_time / 2); 223962306a36Sopenharmony_ci 224062306a36Sopenharmony_ci return 0; 224162306a36Sopenharmony_ci} 224262306a36Sopenharmony_ci 224362306a36Sopenharmony_ci/** 224462306a36Sopenharmony_ci * ixgbe_negotiate_fc - Negotiate flow control 224562306a36Sopenharmony_ci * @hw: pointer to hardware structure 224662306a36Sopenharmony_ci * @adv_reg: flow control advertised settings 224762306a36Sopenharmony_ci * @lp_reg: link partner's flow control settings 224862306a36Sopenharmony_ci * @adv_sym: symmetric pause bit in advertisement 224962306a36Sopenharmony_ci * @adv_asm: asymmetric pause bit in advertisement 225062306a36Sopenharmony_ci * @lp_sym: symmetric pause bit in link partner advertisement 225162306a36Sopenharmony_ci * @lp_asm: asymmetric pause bit in link partner advertisement 225262306a36Sopenharmony_ci * 225362306a36Sopenharmony_ci * Find the intersection between advertised settings and link partner's 225462306a36Sopenharmony_ci * advertised settings 225562306a36Sopenharmony_ci **/ 225662306a36Sopenharmony_cis32 ixgbe_negotiate_fc(struct ixgbe_hw *hw, u32 adv_reg, u32 lp_reg, 225762306a36Sopenharmony_ci u32 adv_sym, u32 adv_asm, u32 lp_sym, u32 lp_asm) 225862306a36Sopenharmony_ci{ 225962306a36Sopenharmony_ci if ((!(adv_reg)) || (!(lp_reg))) 226062306a36Sopenharmony_ci return -EINVAL; 226162306a36Sopenharmony_ci 226262306a36Sopenharmony_ci if ((adv_reg & adv_sym) && (lp_reg & lp_sym)) { 226362306a36Sopenharmony_ci /* 226462306a36Sopenharmony_ci * Now we need to check if the user selected Rx ONLY 226562306a36Sopenharmony_ci * of pause frames. In this case, we had to advertise 226662306a36Sopenharmony_ci * FULL flow control because we could not advertise RX 226762306a36Sopenharmony_ci * ONLY. Hence, we must now check to see if we need to 226862306a36Sopenharmony_ci * turn OFF the TRANSMISSION of PAUSE frames. 226962306a36Sopenharmony_ci */ 227062306a36Sopenharmony_ci if (hw->fc.requested_mode == ixgbe_fc_full) { 227162306a36Sopenharmony_ci hw->fc.current_mode = ixgbe_fc_full; 227262306a36Sopenharmony_ci hw_dbg(hw, "Flow Control = FULL.\n"); 227362306a36Sopenharmony_ci } else { 227462306a36Sopenharmony_ci hw->fc.current_mode = ixgbe_fc_rx_pause; 227562306a36Sopenharmony_ci hw_dbg(hw, "Flow Control=RX PAUSE frames only\n"); 227662306a36Sopenharmony_ci } 227762306a36Sopenharmony_ci } else if (!(adv_reg & adv_sym) && (adv_reg & adv_asm) && 227862306a36Sopenharmony_ci (lp_reg & lp_sym) && (lp_reg & lp_asm)) { 227962306a36Sopenharmony_ci hw->fc.current_mode = ixgbe_fc_tx_pause; 228062306a36Sopenharmony_ci hw_dbg(hw, "Flow Control = TX PAUSE frames only.\n"); 228162306a36Sopenharmony_ci } else if ((adv_reg & adv_sym) && (adv_reg & adv_asm) && 228262306a36Sopenharmony_ci !(lp_reg & lp_sym) && (lp_reg & lp_asm)) { 228362306a36Sopenharmony_ci hw->fc.current_mode = ixgbe_fc_rx_pause; 228462306a36Sopenharmony_ci hw_dbg(hw, "Flow Control = RX PAUSE frames only.\n"); 228562306a36Sopenharmony_ci } else { 228662306a36Sopenharmony_ci hw->fc.current_mode = ixgbe_fc_none; 228762306a36Sopenharmony_ci hw_dbg(hw, "Flow Control = NONE.\n"); 228862306a36Sopenharmony_ci } 228962306a36Sopenharmony_ci return 0; 229062306a36Sopenharmony_ci} 229162306a36Sopenharmony_ci 229262306a36Sopenharmony_ci/** 229362306a36Sopenharmony_ci * ixgbe_fc_autoneg_fiber - Enable flow control on 1 gig fiber 229462306a36Sopenharmony_ci * @hw: pointer to hardware structure 229562306a36Sopenharmony_ci * 229662306a36Sopenharmony_ci * Enable flow control according on 1 gig fiber. 229762306a36Sopenharmony_ci **/ 229862306a36Sopenharmony_cistatic s32 ixgbe_fc_autoneg_fiber(struct ixgbe_hw *hw) 229962306a36Sopenharmony_ci{ 230062306a36Sopenharmony_ci u32 pcs_anadv_reg, pcs_lpab_reg, linkstat; 230162306a36Sopenharmony_ci s32 ret_val; 230262306a36Sopenharmony_ci 230362306a36Sopenharmony_ci /* 230462306a36Sopenharmony_ci * On multispeed fiber at 1g, bail out if 230562306a36Sopenharmony_ci * - link is up but AN did not complete, or if 230662306a36Sopenharmony_ci * - link is up and AN completed but timed out 230762306a36Sopenharmony_ci */ 230862306a36Sopenharmony_ci 230962306a36Sopenharmony_ci linkstat = IXGBE_READ_REG(hw, IXGBE_PCS1GLSTA); 231062306a36Sopenharmony_ci if ((!!(linkstat & IXGBE_PCS1GLSTA_AN_COMPLETE) == 0) || 231162306a36Sopenharmony_ci (!!(linkstat & IXGBE_PCS1GLSTA_AN_TIMED_OUT) == 1)) 231262306a36Sopenharmony_ci return -EIO; 231362306a36Sopenharmony_ci 231462306a36Sopenharmony_ci pcs_anadv_reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANA); 231562306a36Sopenharmony_ci pcs_lpab_reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANLP); 231662306a36Sopenharmony_ci 231762306a36Sopenharmony_ci ret_val = ixgbe_negotiate_fc(hw, pcs_anadv_reg, 231862306a36Sopenharmony_ci pcs_lpab_reg, IXGBE_PCS1GANA_SYM_PAUSE, 231962306a36Sopenharmony_ci IXGBE_PCS1GANA_ASM_PAUSE, 232062306a36Sopenharmony_ci IXGBE_PCS1GANA_SYM_PAUSE, 232162306a36Sopenharmony_ci IXGBE_PCS1GANA_ASM_PAUSE); 232262306a36Sopenharmony_ci 232362306a36Sopenharmony_ci return ret_val; 232462306a36Sopenharmony_ci} 232562306a36Sopenharmony_ci 232662306a36Sopenharmony_ci/** 232762306a36Sopenharmony_ci * ixgbe_fc_autoneg_backplane - Enable flow control IEEE clause 37 232862306a36Sopenharmony_ci * @hw: pointer to hardware structure 232962306a36Sopenharmony_ci * 233062306a36Sopenharmony_ci * Enable flow control according to IEEE clause 37. 233162306a36Sopenharmony_ci **/ 233262306a36Sopenharmony_cistatic s32 ixgbe_fc_autoneg_backplane(struct ixgbe_hw *hw) 233362306a36Sopenharmony_ci{ 233462306a36Sopenharmony_ci u32 links2, anlp1_reg, autoc_reg, links; 233562306a36Sopenharmony_ci s32 ret_val; 233662306a36Sopenharmony_ci 233762306a36Sopenharmony_ci /* 233862306a36Sopenharmony_ci * On backplane, bail out if 233962306a36Sopenharmony_ci * - backplane autoneg was not completed, or if 234062306a36Sopenharmony_ci * - we are 82599 and link partner is not AN enabled 234162306a36Sopenharmony_ci */ 234262306a36Sopenharmony_ci links = IXGBE_READ_REG(hw, IXGBE_LINKS); 234362306a36Sopenharmony_ci if ((links & IXGBE_LINKS_KX_AN_COMP) == 0) 234462306a36Sopenharmony_ci return -EIO; 234562306a36Sopenharmony_ci 234662306a36Sopenharmony_ci if (hw->mac.type == ixgbe_mac_82599EB) { 234762306a36Sopenharmony_ci links2 = IXGBE_READ_REG(hw, IXGBE_LINKS2); 234862306a36Sopenharmony_ci if ((links2 & IXGBE_LINKS2_AN_SUPPORTED) == 0) 234962306a36Sopenharmony_ci return -EIO; 235062306a36Sopenharmony_ci } 235162306a36Sopenharmony_ci /* 235262306a36Sopenharmony_ci * Read the 10g AN autoc and LP ability registers and resolve 235362306a36Sopenharmony_ci * local flow control settings accordingly 235462306a36Sopenharmony_ci */ 235562306a36Sopenharmony_ci autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC); 235662306a36Sopenharmony_ci anlp1_reg = IXGBE_READ_REG(hw, IXGBE_ANLP1); 235762306a36Sopenharmony_ci 235862306a36Sopenharmony_ci ret_val = ixgbe_negotiate_fc(hw, autoc_reg, 235962306a36Sopenharmony_ci anlp1_reg, IXGBE_AUTOC_SYM_PAUSE, IXGBE_AUTOC_ASM_PAUSE, 236062306a36Sopenharmony_ci IXGBE_ANLP1_SYM_PAUSE, IXGBE_ANLP1_ASM_PAUSE); 236162306a36Sopenharmony_ci 236262306a36Sopenharmony_ci return ret_val; 236362306a36Sopenharmony_ci} 236462306a36Sopenharmony_ci 236562306a36Sopenharmony_ci/** 236662306a36Sopenharmony_ci * ixgbe_fc_autoneg_copper - Enable flow control IEEE clause 37 236762306a36Sopenharmony_ci * @hw: pointer to hardware structure 236862306a36Sopenharmony_ci * 236962306a36Sopenharmony_ci * Enable flow control according to IEEE clause 37. 237062306a36Sopenharmony_ci **/ 237162306a36Sopenharmony_cistatic s32 ixgbe_fc_autoneg_copper(struct ixgbe_hw *hw) 237262306a36Sopenharmony_ci{ 237362306a36Sopenharmony_ci u16 technology_ability_reg = 0; 237462306a36Sopenharmony_ci u16 lp_technology_ability_reg = 0; 237562306a36Sopenharmony_ci 237662306a36Sopenharmony_ci hw->phy.ops.read_reg(hw, MDIO_AN_ADVERTISE, 237762306a36Sopenharmony_ci MDIO_MMD_AN, 237862306a36Sopenharmony_ci &technology_ability_reg); 237962306a36Sopenharmony_ci hw->phy.ops.read_reg(hw, MDIO_AN_LPA, 238062306a36Sopenharmony_ci MDIO_MMD_AN, 238162306a36Sopenharmony_ci &lp_technology_ability_reg); 238262306a36Sopenharmony_ci 238362306a36Sopenharmony_ci return ixgbe_negotiate_fc(hw, (u32)technology_ability_reg, 238462306a36Sopenharmony_ci (u32)lp_technology_ability_reg, 238562306a36Sopenharmony_ci IXGBE_TAF_SYM_PAUSE, IXGBE_TAF_ASM_PAUSE, 238662306a36Sopenharmony_ci IXGBE_TAF_SYM_PAUSE, IXGBE_TAF_ASM_PAUSE); 238762306a36Sopenharmony_ci} 238862306a36Sopenharmony_ci 238962306a36Sopenharmony_ci/** 239062306a36Sopenharmony_ci * ixgbe_fc_autoneg - Configure flow control 239162306a36Sopenharmony_ci * @hw: pointer to hardware structure 239262306a36Sopenharmony_ci * 239362306a36Sopenharmony_ci * Compares our advertised flow control capabilities to those advertised by 239462306a36Sopenharmony_ci * our link partner, and determines the proper flow control mode to use. 239562306a36Sopenharmony_ci **/ 239662306a36Sopenharmony_civoid ixgbe_fc_autoneg(struct ixgbe_hw *hw) 239762306a36Sopenharmony_ci{ 239862306a36Sopenharmony_ci ixgbe_link_speed speed; 239962306a36Sopenharmony_ci s32 ret_val = -EIO; 240062306a36Sopenharmony_ci bool link_up; 240162306a36Sopenharmony_ci 240262306a36Sopenharmony_ci /* 240362306a36Sopenharmony_ci * AN should have completed when the cable was plugged in. 240462306a36Sopenharmony_ci * Look for reasons to bail out. Bail out if: 240562306a36Sopenharmony_ci * - FC autoneg is disabled, or if 240662306a36Sopenharmony_ci * - link is not up. 240762306a36Sopenharmony_ci * 240862306a36Sopenharmony_ci * Since we're being called from an LSC, link is already known to be up. 240962306a36Sopenharmony_ci * So use link_up_wait_to_complete=false. 241062306a36Sopenharmony_ci */ 241162306a36Sopenharmony_ci if (hw->fc.disable_fc_autoneg) 241262306a36Sopenharmony_ci goto out; 241362306a36Sopenharmony_ci 241462306a36Sopenharmony_ci hw->mac.ops.check_link(hw, &speed, &link_up, false); 241562306a36Sopenharmony_ci if (!link_up) 241662306a36Sopenharmony_ci goto out; 241762306a36Sopenharmony_ci 241862306a36Sopenharmony_ci switch (hw->phy.media_type) { 241962306a36Sopenharmony_ci /* Autoneg flow control on fiber adapters */ 242062306a36Sopenharmony_ci case ixgbe_media_type_fiber: 242162306a36Sopenharmony_ci if (speed == IXGBE_LINK_SPEED_1GB_FULL) 242262306a36Sopenharmony_ci ret_val = ixgbe_fc_autoneg_fiber(hw); 242362306a36Sopenharmony_ci break; 242462306a36Sopenharmony_ci 242562306a36Sopenharmony_ci /* Autoneg flow control on backplane adapters */ 242662306a36Sopenharmony_ci case ixgbe_media_type_backplane: 242762306a36Sopenharmony_ci ret_val = ixgbe_fc_autoneg_backplane(hw); 242862306a36Sopenharmony_ci break; 242962306a36Sopenharmony_ci 243062306a36Sopenharmony_ci /* Autoneg flow control on copper adapters */ 243162306a36Sopenharmony_ci case ixgbe_media_type_copper: 243262306a36Sopenharmony_ci if (ixgbe_device_supports_autoneg_fc(hw)) 243362306a36Sopenharmony_ci ret_val = ixgbe_fc_autoneg_copper(hw); 243462306a36Sopenharmony_ci break; 243562306a36Sopenharmony_ci 243662306a36Sopenharmony_ci default: 243762306a36Sopenharmony_ci break; 243862306a36Sopenharmony_ci } 243962306a36Sopenharmony_ci 244062306a36Sopenharmony_ciout: 244162306a36Sopenharmony_ci if (ret_val == 0) { 244262306a36Sopenharmony_ci hw->fc.fc_was_autonegged = true; 244362306a36Sopenharmony_ci } else { 244462306a36Sopenharmony_ci hw->fc.fc_was_autonegged = false; 244562306a36Sopenharmony_ci hw->fc.current_mode = hw->fc.requested_mode; 244662306a36Sopenharmony_ci } 244762306a36Sopenharmony_ci} 244862306a36Sopenharmony_ci 244962306a36Sopenharmony_ci/** 245062306a36Sopenharmony_ci * ixgbe_pcie_timeout_poll - Return number of times to poll for completion 245162306a36Sopenharmony_ci * @hw: pointer to hardware structure 245262306a36Sopenharmony_ci * 245362306a36Sopenharmony_ci * System-wide timeout range is encoded in PCIe Device Control2 register. 245462306a36Sopenharmony_ci * 245562306a36Sopenharmony_ci * Add 10% to specified maximum and return the number of times to poll for 245662306a36Sopenharmony_ci * completion timeout, in units of 100 microsec. Never return less than 245762306a36Sopenharmony_ci * 800 = 80 millisec. 245862306a36Sopenharmony_ci **/ 245962306a36Sopenharmony_cistatic u32 ixgbe_pcie_timeout_poll(struct ixgbe_hw *hw) 246062306a36Sopenharmony_ci{ 246162306a36Sopenharmony_ci s16 devctl2; 246262306a36Sopenharmony_ci u32 pollcnt; 246362306a36Sopenharmony_ci 246462306a36Sopenharmony_ci devctl2 = ixgbe_read_pci_cfg_word(hw, IXGBE_PCI_DEVICE_CONTROL2); 246562306a36Sopenharmony_ci devctl2 &= IXGBE_PCIDEVCTRL2_TIMEO_MASK; 246662306a36Sopenharmony_ci 246762306a36Sopenharmony_ci switch (devctl2) { 246862306a36Sopenharmony_ci case IXGBE_PCIDEVCTRL2_65_130ms: 246962306a36Sopenharmony_ci pollcnt = 1300; /* 130 millisec */ 247062306a36Sopenharmony_ci break; 247162306a36Sopenharmony_ci case IXGBE_PCIDEVCTRL2_260_520ms: 247262306a36Sopenharmony_ci pollcnt = 5200; /* 520 millisec */ 247362306a36Sopenharmony_ci break; 247462306a36Sopenharmony_ci case IXGBE_PCIDEVCTRL2_1_2s: 247562306a36Sopenharmony_ci pollcnt = 20000; /* 2 sec */ 247662306a36Sopenharmony_ci break; 247762306a36Sopenharmony_ci case IXGBE_PCIDEVCTRL2_4_8s: 247862306a36Sopenharmony_ci pollcnt = 80000; /* 8 sec */ 247962306a36Sopenharmony_ci break; 248062306a36Sopenharmony_ci case IXGBE_PCIDEVCTRL2_17_34s: 248162306a36Sopenharmony_ci pollcnt = 34000; /* 34 sec */ 248262306a36Sopenharmony_ci break; 248362306a36Sopenharmony_ci case IXGBE_PCIDEVCTRL2_50_100us: /* 100 microsecs */ 248462306a36Sopenharmony_ci case IXGBE_PCIDEVCTRL2_1_2ms: /* 2 millisecs */ 248562306a36Sopenharmony_ci case IXGBE_PCIDEVCTRL2_16_32ms: /* 32 millisec */ 248662306a36Sopenharmony_ci case IXGBE_PCIDEVCTRL2_16_32ms_def: /* 32 millisec default */ 248762306a36Sopenharmony_ci default: 248862306a36Sopenharmony_ci pollcnt = 800; /* 80 millisec minimum */ 248962306a36Sopenharmony_ci break; 249062306a36Sopenharmony_ci } 249162306a36Sopenharmony_ci 249262306a36Sopenharmony_ci /* add 10% to spec maximum */ 249362306a36Sopenharmony_ci return (pollcnt * 11) / 10; 249462306a36Sopenharmony_ci} 249562306a36Sopenharmony_ci 249662306a36Sopenharmony_ci/** 249762306a36Sopenharmony_ci * ixgbe_disable_pcie_primary - Disable PCI-express primary access 249862306a36Sopenharmony_ci * @hw: pointer to hardware structure 249962306a36Sopenharmony_ci * 250062306a36Sopenharmony_ci * Disables PCI-Express primary access and verifies there are no pending 250162306a36Sopenharmony_ci * requests. -EALREADY is returned if primary disable 250262306a36Sopenharmony_ci * bit hasn't caused the primary requests to be disabled, else 0 250362306a36Sopenharmony_ci * is returned signifying primary requests disabled. 250462306a36Sopenharmony_ci **/ 250562306a36Sopenharmony_cistatic s32 ixgbe_disable_pcie_primary(struct ixgbe_hw *hw) 250662306a36Sopenharmony_ci{ 250762306a36Sopenharmony_ci u32 i, poll; 250862306a36Sopenharmony_ci u16 value; 250962306a36Sopenharmony_ci 251062306a36Sopenharmony_ci /* Always set this bit to ensure any future transactions are blocked */ 251162306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_CTRL, IXGBE_CTRL_GIO_DIS); 251262306a36Sopenharmony_ci 251362306a36Sopenharmony_ci /* Poll for bit to read as set */ 251462306a36Sopenharmony_ci for (i = 0; i < IXGBE_PCI_PRIMARY_DISABLE_TIMEOUT; i++) { 251562306a36Sopenharmony_ci if (IXGBE_READ_REG(hw, IXGBE_CTRL) & IXGBE_CTRL_GIO_DIS) 251662306a36Sopenharmony_ci break; 251762306a36Sopenharmony_ci usleep_range(100, 120); 251862306a36Sopenharmony_ci } 251962306a36Sopenharmony_ci if (i >= IXGBE_PCI_PRIMARY_DISABLE_TIMEOUT) { 252062306a36Sopenharmony_ci hw_dbg(hw, "GIO disable did not set - requesting resets\n"); 252162306a36Sopenharmony_ci goto gio_disable_fail; 252262306a36Sopenharmony_ci } 252362306a36Sopenharmony_ci 252462306a36Sopenharmony_ci /* Exit if primary requests are blocked */ 252562306a36Sopenharmony_ci if (!(IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_GIO) || 252662306a36Sopenharmony_ci ixgbe_removed(hw->hw_addr)) 252762306a36Sopenharmony_ci return 0; 252862306a36Sopenharmony_ci 252962306a36Sopenharmony_ci /* Poll for primary request bit to clear */ 253062306a36Sopenharmony_ci for (i = 0; i < IXGBE_PCI_PRIMARY_DISABLE_TIMEOUT; i++) { 253162306a36Sopenharmony_ci udelay(100); 253262306a36Sopenharmony_ci if (!(IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_GIO)) 253362306a36Sopenharmony_ci return 0; 253462306a36Sopenharmony_ci } 253562306a36Sopenharmony_ci 253662306a36Sopenharmony_ci /* 253762306a36Sopenharmony_ci * Two consecutive resets are required via CTRL.RST per datasheet 253862306a36Sopenharmony_ci * 5.2.5.3.2 Primary Disable. We set a flag to inform the reset routine 253962306a36Sopenharmony_ci * of this need. The first reset prevents new primary requests from 254062306a36Sopenharmony_ci * being issued by our device. We then must wait 1usec or more for any 254162306a36Sopenharmony_ci * remaining completions from the PCIe bus to trickle in, and then reset 254262306a36Sopenharmony_ci * again to clear out any effects they may have had on our device. 254362306a36Sopenharmony_ci */ 254462306a36Sopenharmony_ci hw_dbg(hw, "GIO Primary Disable bit didn't clear - requesting resets\n"); 254562306a36Sopenharmony_cigio_disable_fail: 254662306a36Sopenharmony_ci hw->mac.flags |= IXGBE_FLAGS_DOUBLE_RESET_REQUIRED; 254762306a36Sopenharmony_ci 254862306a36Sopenharmony_ci if (hw->mac.type >= ixgbe_mac_X550) 254962306a36Sopenharmony_ci return 0; 255062306a36Sopenharmony_ci 255162306a36Sopenharmony_ci /* 255262306a36Sopenharmony_ci * Before proceeding, make sure that the PCIe block does not have 255362306a36Sopenharmony_ci * transactions pending. 255462306a36Sopenharmony_ci */ 255562306a36Sopenharmony_ci poll = ixgbe_pcie_timeout_poll(hw); 255662306a36Sopenharmony_ci for (i = 0; i < poll; i++) { 255762306a36Sopenharmony_ci udelay(100); 255862306a36Sopenharmony_ci value = ixgbe_read_pci_cfg_word(hw, IXGBE_PCI_DEVICE_STATUS); 255962306a36Sopenharmony_ci if (ixgbe_removed(hw->hw_addr)) 256062306a36Sopenharmony_ci return 0; 256162306a36Sopenharmony_ci if (!(value & IXGBE_PCI_DEVICE_STATUS_TRANSACTION_PENDING)) 256262306a36Sopenharmony_ci return 0; 256362306a36Sopenharmony_ci } 256462306a36Sopenharmony_ci 256562306a36Sopenharmony_ci hw_dbg(hw, "PCIe transaction pending bit also did not clear.\n"); 256662306a36Sopenharmony_ci return -EALREADY; 256762306a36Sopenharmony_ci} 256862306a36Sopenharmony_ci 256962306a36Sopenharmony_ci/** 257062306a36Sopenharmony_ci * ixgbe_acquire_swfw_sync - Acquire SWFW semaphore 257162306a36Sopenharmony_ci * @hw: pointer to hardware structure 257262306a36Sopenharmony_ci * @mask: Mask to specify which semaphore to acquire 257362306a36Sopenharmony_ci * 257462306a36Sopenharmony_ci * Acquires the SWFW semaphore through the GSSR register for the specified 257562306a36Sopenharmony_ci * function (CSR, PHY0, PHY1, EEPROM, Flash) 257662306a36Sopenharmony_ci **/ 257762306a36Sopenharmony_cis32 ixgbe_acquire_swfw_sync(struct ixgbe_hw *hw, u32 mask) 257862306a36Sopenharmony_ci{ 257962306a36Sopenharmony_ci u32 gssr = 0; 258062306a36Sopenharmony_ci u32 swmask = mask; 258162306a36Sopenharmony_ci u32 fwmask = mask << 5; 258262306a36Sopenharmony_ci u32 timeout = 200; 258362306a36Sopenharmony_ci u32 i; 258462306a36Sopenharmony_ci 258562306a36Sopenharmony_ci for (i = 0; i < timeout; i++) { 258662306a36Sopenharmony_ci /* 258762306a36Sopenharmony_ci * SW NVM semaphore bit is used for access to all 258862306a36Sopenharmony_ci * SW_FW_SYNC bits (not just NVM) 258962306a36Sopenharmony_ci */ 259062306a36Sopenharmony_ci if (ixgbe_get_eeprom_semaphore(hw)) 259162306a36Sopenharmony_ci return -EBUSY; 259262306a36Sopenharmony_ci 259362306a36Sopenharmony_ci gssr = IXGBE_READ_REG(hw, IXGBE_GSSR); 259462306a36Sopenharmony_ci if (!(gssr & (fwmask | swmask))) { 259562306a36Sopenharmony_ci gssr |= swmask; 259662306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_GSSR, gssr); 259762306a36Sopenharmony_ci ixgbe_release_eeprom_semaphore(hw); 259862306a36Sopenharmony_ci return 0; 259962306a36Sopenharmony_ci } else { 260062306a36Sopenharmony_ci /* Resource is currently in use by FW or SW */ 260162306a36Sopenharmony_ci ixgbe_release_eeprom_semaphore(hw); 260262306a36Sopenharmony_ci usleep_range(5000, 10000); 260362306a36Sopenharmony_ci } 260462306a36Sopenharmony_ci } 260562306a36Sopenharmony_ci 260662306a36Sopenharmony_ci /* If time expired clear the bits holding the lock and retry */ 260762306a36Sopenharmony_ci if (gssr & (fwmask | swmask)) 260862306a36Sopenharmony_ci ixgbe_release_swfw_sync(hw, gssr & (fwmask | swmask)); 260962306a36Sopenharmony_ci 261062306a36Sopenharmony_ci usleep_range(5000, 10000); 261162306a36Sopenharmony_ci return -EBUSY; 261262306a36Sopenharmony_ci} 261362306a36Sopenharmony_ci 261462306a36Sopenharmony_ci/** 261562306a36Sopenharmony_ci * ixgbe_release_swfw_sync - Release SWFW semaphore 261662306a36Sopenharmony_ci * @hw: pointer to hardware structure 261762306a36Sopenharmony_ci * @mask: Mask to specify which semaphore to release 261862306a36Sopenharmony_ci * 261962306a36Sopenharmony_ci * Releases the SWFW semaphore through the GSSR register for the specified 262062306a36Sopenharmony_ci * function (CSR, PHY0, PHY1, EEPROM, Flash) 262162306a36Sopenharmony_ci **/ 262262306a36Sopenharmony_civoid ixgbe_release_swfw_sync(struct ixgbe_hw *hw, u32 mask) 262362306a36Sopenharmony_ci{ 262462306a36Sopenharmony_ci u32 gssr; 262562306a36Sopenharmony_ci u32 swmask = mask; 262662306a36Sopenharmony_ci 262762306a36Sopenharmony_ci ixgbe_get_eeprom_semaphore(hw); 262862306a36Sopenharmony_ci 262962306a36Sopenharmony_ci gssr = IXGBE_READ_REG(hw, IXGBE_GSSR); 263062306a36Sopenharmony_ci gssr &= ~swmask; 263162306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_GSSR, gssr); 263262306a36Sopenharmony_ci 263362306a36Sopenharmony_ci ixgbe_release_eeprom_semaphore(hw); 263462306a36Sopenharmony_ci} 263562306a36Sopenharmony_ci 263662306a36Sopenharmony_ci/** 263762306a36Sopenharmony_ci * prot_autoc_read_generic - Hides MAC differences needed for AUTOC read 263862306a36Sopenharmony_ci * @hw: pointer to hardware structure 263962306a36Sopenharmony_ci * @reg_val: Value we read from AUTOC 264062306a36Sopenharmony_ci * @locked: bool to indicate whether the SW/FW lock should be taken. Never 264162306a36Sopenharmony_ci * true in this the generic case. 264262306a36Sopenharmony_ci * 264362306a36Sopenharmony_ci * The default case requires no protection so just to the register read. 264462306a36Sopenharmony_ci **/ 264562306a36Sopenharmony_cis32 prot_autoc_read_generic(struct ixgbe_hw *hw, bool *locked, u32 *reg_val) 264662306a36Sopenharmony_ci{ 264762306a36Sopenharmony_ci *locked = false; 264862306a36Sopenharmony_ci *reg_val = IXGBE_READ_REG(hw, IXGBE_AUTOC); 264962306a36Sopenharmony_ci return 0; 265062306a36Sopenharmony_ci} 265162306a36Sopenharmony_ci 265262306a36Sopenharmony_ci/** 265362306a36Sopenharmony_ci * prot_autoc_write_generic - Hides MAC differences needed for AUTOC write 265462306a36Sopenharmony_ci * @hw: pointer to hardware structure 265562306a36Sopenharmony_ci * @reg_val: value to write to AUTOC 265662306a36Sopenharmony_ci * @locked: bool to indicate whether the SW/FW lock was already taken by 265762306a36Sopenharmony_ci * previous read. 265862306a36Sopenharmony_ci **/ 265962306a36Sopenharmony_cis32 prot_autoc_write_generic(struct ixgbe_hw *hw, u32 reg_val, bool locked) 266062306a36Sopenharmony_ci{ 266162306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_AUTOC, reg_val); 266262306a36Sopenharmony_ci return 0; 266362306a36Sopenharmony_ci} 266462306a36Sopenharmony_ci 266562306a36Sopenharmony_ci/** 266662306a36Sopenharmony_ci * ixgbe_disable_rx_buff_generic - Stops the receive data path 266762306a36Sopenharmony_ci * @hw: pointer to hardware structure 266862306a36Sopenharmony_ci * 266962306a36Sopenharmony_ci * Stops the receive data path and waits for the HW to internally 267062306a36Sopenharmony_ci * empty the Rx security block. 267162306a36Sopenharmony_ci **/ 267262306a36Sopenharmony_cis32 ixgbe_disable_rx_buff_generic(struct ixgbe_hw *hw) 267362306a36Sopenharmony_ci{ 267462306a36Sopenharmony_ci#define IXGBE_MAX_SECRX_POLL 40 267562306a36Sopenharmony_ci int i; 267662306a36Sopenharmony_ci int secrxreg; 267762306a36Sopenharmony_ci 267862306a36Sopenharmony_ci secrxreg = IXGBE_READ_REG(hw, IXGBE_SECRXCTRL); 267962306a36Sopenharmony_ci secrxreg |= IXGBE_SECRXCTRL_RX_DIS; 268062306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_SECRXCTRL, secrxreg); 268162306a36Sopenharmony_ci for (i = 0; i < IXGBE_MAX_SECRX_POLL; i++) { 268262306a36Sopenharmony_ci secrxreg = IXGBE_READ_REG(hw, IXGBE_SECRXSTAT); 268362306a36Sopenharmony_ci if (secrxreg & IXGBE_SECRXSTAT_SECRX_RDY) 268462306a36Sopenharmony_ci break; 268562306a36Sopenharmony_ci else 268662306a36Sopenharmony_ci /* Use interrupt-safe sleep just in case */ 268762306a36Sopenharmony_ci udelay(1000); 268862306a36Sopenharmony_ci } 268962306a36Sopenharmony_ci 269062306a36Sopenharmony_ci /* For informational purposes only */ 269162306a36Sopenharmony_ci if (i >= IXGBE_MAX_SECRX_POLL) 269262306a36Sopenharmony_ci hw_dbg(hw, "Rx unit being enabled before security path fully disabled. Continuing with init.\n"); 269362306a36Sopenharmony_ci 269462306a36Sopenharmony_ci return 0; 269562306a36Sopenharmony_ci 269662306a36Sopenharmony_ci} 269762306a36Sopenharmony_ci 269862306a36Sopenharmony_ci/** 269962306a36Sopenharmony_ci * ixgbe_enable_rx_buff_generic - Enables the receive data path 270062306a36Sopenharmony_ci * @hw: pointer to hardware structure 270162306a36Sopenharmony_ci * 270262306a36Sopenharmony_ci * Enables the receive data path 270362306a36Sopenharmony_ci **/ 270462306a36Sopenharmony_cis32 ixgbe_enable_rx_buff_generic(struct ixgbe_hw *hw) 270562306a36Sopenharmony_ci{ 270662306a36Sopenharmony_ci u32 secrxreg; 270762306a36Sopenharmony_ci 270862306a36Sopenharmony_ci secrxreg = IXGBE_READ_REG(hw, IXGBE_SECRXCTRL); 270962306a36Sopenharmony_ci secrxreg &= ~IXGBE_SECRXCTRL_RX_DIS; 271062306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_SECRXCTRL, secrxreg); 271162306a36Sopenharmony_ci IXGBE_WRITE_FLUSH(hw); 271262306a36Sopenharmony_ci 271362306a36Sopenharmony_ci return 0; 271462306a36Sopenharmony_ci} 271562306a36Sopenharmony_ci 271662306a36Sopenharmony_ci/** 271762306a36Sopenharmony_ci * ixgbe_enable_rx_dma_generic - Enable the Rx DMA unit 271862306a36Sopenharmony_ci * @hw: pointer to hardware structure 271962306a36Sopenharmony_ci * @regval: register value to write to RXCTRL 272062306a36Sopenharmony_ci * 272162306a36Sopenharmony_ci * Enables the Rx DMA unit 272262306a36Sopenharmony_ci **/ 272362306a36Sopenharmony_cis32 ixgbe_enable_rx_dma_generic(struct ixgbe_hw *hw, u32 regval) 272462306a36Sopenharmony_ci{ 272562306a36Sopenharmony_ci if (regval & IXGBE_RXCTRL_RXEN) 272662306a36Sopenharmony_ci hw->mac.ops.enable_rx(hw); 272762306a36Sopenharmony_ci else 272862306a36Sopenharmony_ci hw->mac.ops.disable_rx(hw); 272962306a36Sopenharmony_ci 273062306a36Sopenharmony_ci return 0; 273162306a36Sopenharmony_ci} 273262306a36Sopenharmony_ci 273362306a36Sopenharmony_ci/** 273462306a36Sopenharmony_ci * ixgbe_blink_led_start_generic - Blink LED based on index. 273562306a36Sopenharmony_ci * @hw: pointer to hardware structure 273662306a36Sopenharmony_ci * @index: led number to blink 273762306a36Sopenharmony_ci **/ 273862306a36Sopenharmony_cis32 ixgbe_blink_led_start_generic(struct ixgbe_hw *hw, u32 index) 273962306a36Sopenharmony_ci{ 274062306a36Sopenharmony_ci ixgbe_link_speed speed = 0; 274162306a36Sopenharmony_ci bool link_up = false; 274262306a36Sopenharmony_ci u32 autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC); 274362306a36Sopenharmony_ci u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL); 274462306a36Sopenharmony_ci bool locked = false; 274562306a36Sopenharmony_ci s32 ret_val; 274662306a36Sopenharmony_ci 274762306a36Sopenharmony_ci if (index > 3) 274862306a36Sopenharmony_ci return -EINVAL; 274962306a36Sopenharmony_ci 275062306a36Sopenharmony_ci /* 275162306a36Sopenharmony_ci * Link must be up to auto-blink the LEDs; 275262306a36Sopenharmony_ci * Force it if link is down. 275362306a36Sopenharmony_ci */ 275462306a36Sopenharmony_ci hw->mac.ops.check_link(hw, &speed, &link_up, false); 275562306a36Sopenharmony_ci 275662306a36Sopenharmony_ci if (!link_up) { 275762306a36Sopenharmony_ci ret_val = hw->mac.ops.prot_autoc_read(hw, &locked, &autoc_reg); 275862306a36Sopenharmony_ci if (ret_val) 275962306a36Sopenharmony_ci return ret_val; 276062306a36Sopenharmony_ci 276162306a36Sopenharmony_ci autoc_reg |= IXGBE_AUTOC_AN_RESTART; 276262306a36Sopenharmony_ci autoc_reg |= IXGBE_AUTOC_FLU; 276362306a36Sopenharmony_ci 276462306a36Sopenharmony_ci ret_val = hw->mac.ops.prot_autoc_write(hw, autoc_reg, locked); 276562306a36Sopenharmony_ci if (ret_val) 276662306a36Sopenharmony_ci return ret_val; 276762306a36Sopenharmony_ci 276862306a36Sopenharmony_ci IXGBE_WRITE_FLUSH(hw); 276962306a36Sopenharmony_ci 277062306a36Sopenharmony_ci usleep_range(10000, 20000); 277162306a36Sopenharmony_ci } 277262306a36Sopenharmony_ci 277362306a36Sopenharmony_ci led_reg &= ~IXGBE_LED_MODE_MASK(index); 277462306a36Sopenharmony_ci led_reg |= IXGBE_LED_BLINK(index); 277562306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg); 277662306a36Sopenharmony_ci IXGBE_WRITE_FLUSH(hw); 277762306a36Sopenharmony_ci 277862306a36Sopenharmony_ci return 0; 277962306a36Sopenharmony_ci} 278062306a36Sopenharmony_ci 278162306a36Sopenharmony_ci/** 278262306a36Sopenharmony_ci * ixgbe_blink_led_stop_generic - Stop blinking LED based on index. 278362306a36Sopenharmony_ci * @hw: pointer to hardware structure 278462306a36Sopenharmony_ci * @index: led number to stop blinking 278562306a36Sopenharmony_ci **/ 278662306a36Sopenharmony_cis32 ixgbe_blink_led_stop_generic(struct ixgbe_hw *hw, u32 index) 278762306a36Sopenharmony_ci{ 278862306a36Sopenharmony_ci u32 autoc_reg = 0; 278962306a36Sopenharmony_ci u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL); 279062306a36Sopenharmony_ci bool locked = false; 279162306a36Sopenharmony_ci s32 ret_val; 279262306a36Sopenharmony_ci 279362306a36Sopenharmony_ci if (index > 3) 279462306a36Sopenharmony_ci return -EINVAL; 279562306a36Sopenharmony_ci 279662306a36Sopenharmony_ci ret_val = hw->mac.ops.prot_autoc_read(hw, &locked, &autoc_reg); 279762306a36Sopenharmony_ci if (ret_val) 279862306a36Sopenharmony_ci return ret_val; 279962306a36Sopenharmony_ci 280062306a36Sopenharmony_ci autoc_reg &= ~IXGBE_AUTOC_FLU; 280162306a36Sopenharmony_ci autoc_reg |= IXGBE_AUTOC_AN_RESTART; 280262306a36Sopenharmony_ci 280362306a36Sopenharmony_ci ret_val = hw->mac.ops.prot_autoc_write(hw, autoc_reg, locked); 280462306a36Sopenharmony_ci if (ret_val) 280562306a36Sopenharmony_ci return ret_val; 280662306a36Sopenharmony_ci 280762306a36Sopenharmony_ci led_reg &= ~IXGBE_LED_MODE_MASK(index); 280862306a36Sopenharmony_ci led_reg &= ~IXGBE_LED_BLINK(index); 280962306a36Sopenharmony_ci led_reg |= IXGBE_LED_LINK_ACTIVE << IXGBE_LED_MODE_SHIFT(index); 281062306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg); 281162306a36Sopenharmony_ci IXGBE_WRITE_FLUSH(hw); 281262306a36Sopenharmony_ci 281362306a36Sopenharmony_ci return 0; 281462306a36Sopenharmony_ci} 281562306a36Sopenharmony_ci 281662306a36Sopenharmony_ci/** 281762306a36Sopenharmony_ci * ixgbe_get_san_mac_addr_offset - Get SAN MAC address offset from the EEPROM 281862306a36Sopenharmony_ci * @hw: pointer to hardware structure 281962306a36Sopenharmony_ci * @san_mac_offset: SAN MAC address offset 282062306a36Sopenharmony_ci * 282162306a36Sopenharmony_ci * This function will read the EEPROM location for the SAN MAC address 282262306a36Sopenharmony_ci * pointer, and returns the value at that location. This is used in both 282362306a36Sopenharmony_ci * get and set mac_addr routines. 282462306a36Sopenharmony_ci **/ 282562306a36Sopenharmony_cistatic s32 ixgbe_get_san_mac_addr_offset(struct ixgbe_hw *hw, 282662306a36Sopenharmony_ci u16 *san_mac_offset) 282762306a36Sopenharmony_ci{ 282862306a36Sopenharmony_ci s32 ret_val; 282962306a36Sopenharmony_ci 283062306a36Sopenharmony_ci /* 283162306a36Sopenharmony_ci * First read the EEPROM pointer to see if the MAC addresses are 283262306a36Sopenharmony_ci * available. 283362306a36Sopenharmony_ci */ 283462306a36Sopenharmony_ci ret_val = hw->eeprom.ops.read(hw, IXGBE_SAN_MAC_ADDR_PTR, 283562306a36Sopenharmony_ci san_mac_offset); 283662306a36Sopenharmony_ci if (ret_val) 283762306a36Sopenharmony_ci hw_err(hw, "eeprom read at offset %d failed\n", 283862306a36Sopenharmony_ci IXGBE_SAN_MAC_ADDR_PTR); 283962306a36Sopenharmony_ci 284062306a36Sopenharmony_ci return ret_val; 284162306a36Sopenharmony_ci} 284262306a36Sopenharmony_ci 284362306a36Sopenharmony_ci/** 284462306a36Sopenharmony_ci * ixgbe_get_san_mac_addr_generic - SAN MAC address retrieval from the EEPROM 284562306a36Sopenharmony_ci * @hw: pointer to hardware structure 284662306a36Sopenharmony_ci * @san_mac_addr: SAN MAC address 284762306a36Sopenharmony_ci * 284862306a36Sopenharmony_ci * Reads the SAN MAC address from the EEPROM, if it's available. This is 284962306a36Sopenharmony_ci * per-port, so set_lan_id() must be called before reading the addresses. 285062306a36Sopenharmony_ci * set_lan_id() is called by identify_sfp(), but this cannot be relied 285162306a36Sopenharmony_ci * upon for non-SFP connections, so we must call it here. 285262306a36Sopenharmony_ci **/ 285362306a36Sopenharmony_cis32 ixgbe_get_san_mac_addr_generic(struct ixgbe_hw *hw, u8 *san_mac_addr) 285462306a36Sopenharmony_ci{ 285562306a36Sopenharmony_ci u16 san_mac_data, san_mac_offset; 285662306a36Sopenharmony_ci u8 i; 285762306a36Sopenharmony_ci s32 ret_val; 285862306a36Sopenharmony_ci 285962306a36Sopenharmony_ci /* 286062306a36Sopenharmony_ci * First read the EEPROM pointer to see if the MAC addresses are 286162306a36Sopenharmony_ci * available. If they're not, no point in calling set_lan_id() here. 286262306a36Sopenharmony_ci */ 286362306a36Sopenharmony_ci ret_val = ixgbe_get_san_mac_addr_offset(hw, &san_mac_offset); 286462306a36Sopenharmony_ci if (ret_val || san_mac_offset == 0 || san_mac_offset == 0xFFFF) 286562306a36Sopenharmony_ci 286662306a36Sopenharmony_ci goto san_mac_addr_clr; 286762306a36Sopenharmony_ci 286862306a36Sopenharmony_ci /* make sure we know which port we need to program */ 286962306a36Sopenharmony_ci hw->mac.ops.set_lan_id(hw); 287062306a36Sopenharmony_ci /* apply the port offset to the address offset */ 287162306a36Sopenharmony_ci (hw->bus.func) ? (san_mac_offset += IXGBE_SAN_MAC_ADDR_PORT1_OFFSET) : 287262306a36Sopenharmony_ci (san_mac_offset += IXGBE_SAN_MAC_ADDR_PORT0_OFFSET); 287362306a36Sopenharmony_ci for (i = 0; i < 3; i++) { 287462306a36Sopenharmony_ci ret_val = hw->eeprom.ops.read(hw, san_mac_offset, 287562306a36Sopenharmony_ci &san_mac_data); 287662306a36Sopenharmony_ci if (ret_val) { 287762306a36Sopenharmony_ci hw_err(hw, "eeprom read at offset %d failed\n", 287862306a36Sopenharmony_ci san_mac_offset); 287962306a36Sopenharmony_ci goto san_mac_addr_clr; 288062306a36Sopenharmony_ci } 288162306a36Sopenharmony_ci san_mac_addr[i * 2] = (u8)(san_mac_data); 288262306a36Sopenharmony_ci san_mac_addr[i * 2 + 1] = (u8)(san_mac_data >> 8); 288362306a36Sopenharmony_ci san_mac_offset++; 288462306a36Sopenharmony_ci } 288562306a36Sopenharmony_ci return 0; 288662306a36Sopenharmony_ci 288762306a36Sopenharmony_cisan_mac_addr_clr: 288862306a36Sopenharmony_ci /* No addresses available in this EEPROM. It's not necessarily an 288962306a36Sopenharmony_ci * error though, so just wipe the local address and return. 289062306a36Sopenharmony_ci */ 289162306a36Sopenharmony_ci for (i = 0; i < 6; i++) 289262306a36Sopenharmony_ci san_mac_addr[i] = 0xFF; 289362306a36Sopenharmony_ci return ret_val; 289462306a36Sopenharmony_ci} 289562306a36Sopenharmony_ci 289662306a36Sopenharmony_ci/** 289762306a36Sopenharmony_ci * ixgbe_get_pcie_msix_count_generic - Gets MSI-X vector count 289862306a36Sopenharmony_ci * @hw: pointer to hardware structure 289962306a36Sopenharmony_ci * 290062306a36Sopenharmony_ci * Read PCIe configuration space, and get the MSI-X vector count from 290162306a36Sopenharmony_ci * the capabilities table. 290262306a36Sopenharmony_ci **/ 290362306a36Sopenharmony_ciu16 ixgbe_get_pcie_msix_count_generic(struct ixgbe_hw *hw) 290462306a36Sopenharmony_ci{ 290562306a36Sopenharmony_ci u16 msix_count; 290662306a36Sopenharmony_ci u16 max_msix_count; 290762306a36Sopenharmony_ci u16 pcie_offset; 290862306a36Sopenharmony_ci 290962306a36Sopenharmony_ci switch (hw->mac.type) { 291062306a36Sopenharmony_ci case ixgbe_mac_82598EB: 291162306a36Sopenharmony_ci pcie_offset = IXGBE_PCIE_MSIX_82598_CAPS; 291262306a36Sopenharmony_ci max_msix_count = IXGBE_MAX_MSIX_VECTORS_82598; 291362306a36Sopenharmony_ci break; 291462306a36Sopenharmony_ci case ixgbe_mac_82599EB: 291562306a36Sopenharmony_ci case ixgbe_mac_X540: 291662306a36Sopenharmony_ci case ixgbe_mac_X550: 291762306a36Sopenharmony_ci case ixgbe_mac_X550EM_x: 291862306a36Sopenharmony_ci case ixgbe_mac_x550em_a: 291962306a36Sopenharmony_ci pcie_offset = IXGBE_PCIE_MSIX_82599_CAPS; 292062306a36Sopenharmony_ci max_msix_count = IXGBE_MAX_MSIX_VECTORS_82599; 292162306a36Sopenharmony_ci break; 292262306a36Sopenharmony_ci default: 292362306a36Sopenharmony_ci return 1; 292462306a36Sopenharmony_ci } 292562306a36Sopenharmony_ci 292662306a36Sopenharmony_ci msix_count = ixgbe_read_pci_cfg_word(hw, pcie_offset); 292762306a36Sopenharmony_ci if (ixgbe_removed(hw->hw_addr)) 292862306a36Sopenharmony_ci msix_count = 0; 292962306a36Sopenharmony_ci msix_count &= IXGBE_PCIE_MSIX_TBL_SZ_MASK; 293062306a36Sopenharmony_ci 293162306a36Sopenharmony_ci /* MSI-X count is zero-based in HW */ 293262306a36Sopenharmony_ci msix_count++; 293362306a36Sopenharmony_ci 293462306a36Sopenharmony_ci if (msix_count > max_msix_count) 293562306a36Sopenharmony_ci msix_count = max_msix_count; 293662306a36Sopenharmony_ci 293762306a36Sopenharmony_ci return msix_count; 293862306a36Sopenharmony_ci} 293962306a36Sopenharmony_ci 294062306a36Sopenharmony_ci/** 294162306a36Sopenharmony_ci * ixgbe_clear_vmdq_generic - Disassociate a VMDq pool index from a rx address 294262306a36Sopenharmony_ci * @hw: pointer to hardware struct 294362306a36Sopenharmony_ci * @rar: receive address register index to disassociate 294462306a36Sopenharmony_ci * @vmdq: VMDq pool index to remove from the rar 294562306a36Sopenharmony_ci **/ 294662306a36Sopenharmony_cis32 ixgbe_clear_vmdq_generic(struct ixgbe_hw *hw, u32 rar, u32 vmdq) 294762306a36Sopenharmony_ci{ 294862306a36Sopenharmony_ci u32 mpsar_lo, mpsar_hi; 294962306a36Sopenharmony_ci u32 rar_entries = hw->mac.num_rar_entries; 295062306a36Sopenharmony_ci 295162306a36Sopenharmony_ci /* Make sure we are using a valid rar index range */ 295262306a36Sopenharmony_ci if (rar >= rar_entries) { 295362306a36Sopenharmony_ci hw_dbg(hw, "RAR index %d is out of range.\n", rar); 295462306a36Sopenharmony_ci return -EINVAL; 295562306a36Sopenharmony_ci } 295662306a36Sopenharmony_ci 295762306a36Sopenharmony_ci mpsar_lo = IXGBE_READ_REG(hw, IXGBE_MPSAR_LO(rar)); 295862306a36Sopenharmony_ci mpsar_hi = IXGBE_READ_REG(hw, IXGBE_MPSAR_HI(rar)); 295962306a36Sopenharmony_ci 296062306a36Sopenharmony_ci if (ixgbe_removed(hw->hw_addr)) 296162306a36Sopenharmony_ci return 0; 296262306a36Sopenharmony_ci 296362306a36Sopenharmony_ci if (!mpsar_lo && !mpsar_hi) 296462306a36Sopenharmony_ci return 0; 296562306a36Sopenharmony_ci 296662306a36Sopenharmony_ci if (vmdq == IXGBE_CLEAR_VMDQ_ALL) { 296762306a36Sopenharmony_ci if (mpsar_lo) { 296862306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), 0); 296962306a36Sopenharmony_ci mpsar_lo = 0; 297062306a36Sopenharmony_ci } 297162306a36Sopenharmony_ci if (mpsar_hi) { 297262306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), 0); 297362306a36Sopenharmony_ci mpsar_hi = 0; 297462306a36Sopenharmony_ci } 297562306a36Sopenharmony_ci } else if (vmdq < 32) { 297662306a36Sopenharmony_ci mpsar_lo &= ~BIT(vmdq); 297762306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), mpsar_lo); 297862306a36Sopenharmony_ci } else { 297962306a36Sopenharmony_ci mpsar_hi &= ~BIT(vmdq - 32); 298062306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), mpsar_hi); 298162306a36Sopenharmony_ci } 298262306a36Sopenharmony_ci 298362306a36Sopenharmony_ci /* was that the last pool using this rar? */ 298462306a36Sopenharmony_ci if (mpsar_lo == 0 && mpsar_hi == 0 && 298562306a36Sopenharmony_ci rar != 0 && rar != hw->mac.san_mac_rar_index) 298662306a36Sopenharmony_ci hw->mac.ops.clear_rar(hw, rar); 298762306a36Sopenharmony_ci 298862306a36Sopenharmony_ci return 0; 298962306a36Sopenharmony_ci} 299062306a36Sopenharmony_ci 299162306a36Sopenharmony_ci/** 299262306a36Sopenharmony_ci * ixgbe_set_vmdq_generic - Associate a VMDq pool index with a rx address 299362306a36Sopenharmony_ci * @hw: pointer to hardware struct 299462306a36Sopenharmony_ci * @rar: receive address register index to associate with a VMDq index 299562306a36Sopenharmony_ci * @vmdq: VMDq pool index 299662306a36Sopenharmony_ci **/ 299762306a36Sopenharmony_cis32 ixgbe_set_vmdq_generic(struct ixgbe_hw *hw, u32 rar, u32 vmdq) 299862306a36Sopenharmony_ci{ 299962306a36Sopenharmony_ci u32 mpsar; 300062306a36Sopenharmony_ci u32 rar_entries = hw->mac.num_rar_entries; 300162306a36Sopenharmony_ci 300262306a36Sopenharmony_ci /* Make sure we are using a valid rar index range */ 300362306a36Sopenharmony_ci if (rar >= rar_entries) { 300462306a36Sopenharmony_ci hw_dbg(hw, "RAR index %d is out of range.\n", rar); 300562306a36Sopenharmony_ci return -EINVAL; 300662306a36Sopenharmony_ci } 300762306a36Sopenharmony_ci 300862306a36Sopenharmony_ci if (vmdq < 32) { 300962306a36Sopenharmony_ci mpsar = IXGBE_READ_REG(hw, IXGBE_MPSAR_LO(rar)); 301062306a36Sopenharmony_ci mpsar |= BIT(vmdq); 301162306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), mpsar); 301262306a36Sopenharmony_ci } else { 301362306a36Sopenharmony_ci mpsar = IXGBE_READ_REG(hw, IXGBE_MPSAR_HI(rar)); 301462306a36Sopenharmony_ci mpsar |= BIT(vmdq - 32); 301562306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), mpsar); 301662306a36Sopenharmony_ci } 301762306a36Sopenharmony_ci return 0; 301862306a36Sopenharmony_ci} 301962306a36Sopenharmony_ci 302062306a36Sopenharmony_ci/** 302162306a36Sopenharmony_ci * ixgbe_set_vmdq_san_mac_generic - Associate VMDq pool index with a rx address 302262306a36Sopenharmony_ci * @hw: pointer to hardware struct 302362306a36Sopenharmony_ci * @vmdq: VMDq pool index 302462306a36Sopenharmony_ci * 302562306a36Sopenharmony_ci * This function should only be involved in the IOV mode. 302662306a36Sopenharmony_ci * In IOV mode, Default pool is next pool after the number of 302762306a36Sopenharmony_ci * VFs advertized and not 0. 302862306a36Sopenharmony_ci * MPSAR table needs to be updated for SAN_MAC RAR [hw->mac.san_mac_rar_index] 302962306a36Sopenharmony_ci **/ 303062306a36Sopenharmony_cis32 ixgbe_set_vmdq_san_mac_generic(struct ixgbe_hw *hw, u32 vmdq) 303162306a36Sopenharmony_ci{ 303262306a36Sopenharmony_ci u32 rar = hw->mac.san_mac_rar_index; 303362306a36Sopenharmony_ci 303462306a36Sopenharmony_ci if (vmdq < 32) { 303562306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), BIT(vmdq)); 303662306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), 0); 303762306a36Sopenharmony_ci } else { 303862306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), 0); 303962306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), BIT(vmdq - 32)); 304062306a36Sopenharmony_ci } 304162306a36Sopenharmony_ci 304262306a36Sopenharmony_ci return 0; 304362306a36Sopenharmony_ci} 304462306a36Sopenharmony_ci 304562306a36Sopenharmony_ci/** 304662306a36Sopenharmony_ci * ixgbe_init_uta_tables_generic - Initialize the Unicast Table Array 304762306a36Sopenharmony_ci * @hw: pointer to hardware structure 304862306a36Sopenharmony_ci **/ 304962306a36Sopenharmony_cis32 ixgbe_init_uta_tables_generic(struct ixgbe_hw *hw) 305062306a36Sopenharmony_ci{ 305162306a36Sopenharmony_ci int i; 305262306a36Sopenharmony_ci 305362306a36Sopenharmony_ci for (i = 0; i < 128; i++) 305462306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_UTA(i), 0); 305562306a36Sopenharmony_ci 305662306a36Sopenharmony_ci return 0; 305762306a36Sopenharmony_ci} 305862306a36Sopenharmony_ci 305962306a36Sopenharmony_ci/** 306062306a36Sopenharmony_ci * ixgbe_find_vlvf_slot - find the vlanid or the first empty slot 306162306a36Sopenharmony_ci * @hw: pointer to hardware structure 306262306a36Sopenharmony_ci * @vlan: VLAN id to write to VLAN filter 306362306a36Sopenharmony_ci * @vlvf_bypass: true to find vlanid only, false returns first empty slot if 306462306a36Sopenharmony_ci * vlanid not found 306562306a36Sopenharmony_ci * 306662306a36Sopenharmony_ci * return the VLVF index where this VLAN id should be placed 306762306a36Sopenharmony_ci * 306862306a36Sopenharmony_ci **/ 306962306a36Sopenharmony_cistatic s32 ixgbe_find_vlvf_slot(struct ixgbe_hw *hw, u32 vlan, bool vlvf_bypass) 307062306a36Sopenharmony_ci{ 307162306a36Sopenharmony_ci s32 regindex, first_empty_slot; 307262306a36Sopenharmony_ci u32 bits; 307362306a36Sopenharmony_ci 307462306a36Sopenharmony_ci /* short cut the special case */ 307562306a36Sopenharmony_ci if (vlan == 0) 307662306a36Sopenharmony_ci return 0; 307762306a36Sopenharmony_ci 307862306a36Sopenharmony_ci /* if vlvf_bypass is set we don't want to use an empty slot, we 307962306a36Sopenharmony_ci * will simply bypass the VLVF if there are no entries present in the 308062306a36Sopenharmony_ci * VLVF that contain our VLAN 308162306a36Sopenharmony_ci */ 308262306a36Sopenharmony_ci first_empty_slot = vlvf_bypass ? -ENOSPC : 0; 308362306a36Sopenharmony_ci 308462306a36Sopenharmony_ci /* add VLAN enable bit for comparison */ 308562306a36Sopenharmony_ci vlan |= IXGBE_VLVF_VIEN; 308662306a36Sopenharmony_ci 308762306a36Sopenharmony_ci /* Search for the vlan id in the VLVF entries. Save off the first empty 308862306a36Sopenharmony_ci * slot found along the way. 308962306a36Sopenharmony_ci * 309062306a36Sopenharmony_ci * pre-decrement loop covering (IXGBE_VLVF_ENTRIES - 1) .. 1 309162306a36Sopenharmony_ci */ 309262306a36Sopenharmony_ci for (regindex = IXGBE_VLVF_ENTRIES; --regindex;) { 309362306a36Sopenharmony_ci bits = IXGBE_READ_REG(hw, IXGBE_VLVF(regindex)); 309462306a36Sopenharmony_ci if (bits == vlan) 309562306a36Sopenharmony_ci return regindex; 309662306a36Sopenharmony_ci if (!first_empty_slot && !bits) 309762306a36Sopenharmony_ci first_empty_slot = regindex; 309862306a36Sopenharmony_ci } 309962306a36Sopenharmony_ci 310062306a36Sopenharmony_ci /* If we are here then we didn't find the VLAN. Return first empty 310162306a36Sopenharmony_ci * slot we found during our search, else error. 310262306a36Sopenharmony_ci */ 310362306a36Sopenharmony_ci if (!first_empty_slot) 310462306a36Sopenharmony_ci hw_dbg(hw, "No space in VLVF.\n"); 310562306a36Sopenharmony_ci 310662306a36Sopenharmony_ci return first_empty_slot ? : -ENOSPC; 310762306a36Sopenharmony_ci} 310862306a36Sopenharmony_ci 310962306a36Sopenharmony_ci/** 311062306a36Sopenharmony_ci * ixgbe_set_vfta_generic - Set VLAN filter table 311162306a36Sopenharmony_ci * @hw: pointer to hardware structure 311262306a36Sopenharmony_ci * @vlan: VLAN id to write to VLAN filter 311362306a36Sopenharmony_ci * @vind: VMDq output index that maps queue to VLAN id in VFVFB 311462306a36Sopenharmony_ci * @vlan_on: boolean flag to turn on/off VLAN in VFVF 311562306a36Sopenharmony_ci * @vlvf_bypass: boolean flag indicating updating default pool is okay 311662306a36Sopenharmony_ci * 311762306a36Sopenharmony_ci * Turn on/off specified VLAN in the VLAN filter table. 311862306a36Sopenharmony_ci **/ 311962306a36Sopenharmony_cis32 ixgbe_set_vfta_generic(struct ixgbe_hw *hw, u32 vlan, u32 vind, 312062306a36Sopenharmony_ci bool vlan_on, bool vlvf_bypass) 312162306a36Sopenharmony_ci{ 312262306a36Sopenharmony_ci u32 regidx, vfta_delta, vfta, bits; 312362306a36Sopenharmony_ci s32 vlvf_index; 312462306a36Sopenharmony_ci 312562306a36Sopenharmony_ci if ((vlan > 4095) || (vind > 63)) 312662306a36Sopenharmony_ci return -EINVAL; 312762306a36Sopenharmony_ci 312862306a36Sopenharmony_ci /* 312962306a36Sopenharmony_ci * this is a 2 part operation - first the VFTA, then the 313062306a36Sopenharmony_ci * VLVF and VLVFB if VT Mode is set 313162306a36Sopenharmony_ci * We don't write the VFTA until we know the VLVF part succeeded. 313262306a36Sopenharmony_ci */ 313362306a36Sopenharmony_ci 313462306a36Sopenharmony_ci /* Part 1 313562306a36Sopenharmony_ci * The VFTA is a bitstring made up of 128 32-bit registers 313662306a36Sopenharmony_ci * that enable the particular VLAN id, much like the MTA: 313762306a36Sopenharmony_ci * bits[11-5]: which register 313862306a36Sopenharmony_ci * bits[4-0]: which bit in the register 313962306a36Sopenharmony_ci */ 314062306a36Sopenharmony_ci regidx = vlan / 32; 314162306a36Sopenharmony_ci vfta_delta = BIT(vlan % 32); 314262306a36Sopenharmony_ci vfta = IXGBE_READ_REG(hw, IXGBE_VFTA(regidx)); 314362306a36Sopenharmony_ci 314462306a36Sopenharmony_ci /* vfta_delta represents the difference between the current value 314562306a36Sopenharmony_ci * of vfta and the value we want in the register. Since the diff 314662306a36Sopenharmony_ci * is an XOR mask we can just update vfta using an XOR. 314762306a36Sopenharmony_ci */ 314862306a36Sopenharmony_ci vfta_delta &= vlan_on ? ~vfta : vfta; 314962306a36Sopenharmony_ci vfta ^= vfta_delta; 315062306a36Sopenharmony_ci 315162306a36Sopenharmony_ci /* Part 2 315262306a36Sopenharmony_ci * If VT Mode is set 315362306a36Sopenharmony_ci * Either vlan_on 315462306a36Sopenharmony_ci * make sure the vlan is in VLVF 315562306a36Sopenharmony_ci * set the vind bit in the matching VLVFB 315662306a36Sopenharmony_ci * Or !vlan_on 315762306a36Sopenharmony_ci * clear the pool bit and possibly the vind 315862306a36Sopenharmony_ci */ 315962306a36Sopenharmony_ci if (!(IXGBE_READ_REG(hw, IXGBE_VT_CTL) & IXGBE_VT_CTL_VT_ENABLE)) 316062306a36Sopenharmony_ci goto vfta_update; 316162306a36Sopenharmony_ci 316262306a36Sopenharmony_ci vlvf_index = ixgbe_find_vlvf_slot(hw, vlan, vlvf_bypass); 316362306a36Sopenharmony_ci if (vlvf_index < 0) { 316462306a36Sopenharmony_ci if (vlvf_bypass) 316562306a36Sopenharmony_ci goto vfta_update; 316662306a36Sopenharmony_ci return vlvf_index; 316762306a36Sopenharmony_ci } 316862306a36Sopenharmony_ci 316962306a36Sopenharmony_ci bits = IXGBE_READ_REG(hw, IXGBE_VLVFB(vlvf_index * 2 + vind / 32)); 317062306a36Sopenharmony_ci 317162306a36Sopenharmony_ci /* set the pool bit */ 317262306a36Sopenharmony_ci bits |= BIT(vind % 32); 317362306a36Sopenharmony_ci if (vlan_on) 317462306a36Sopenharmony_ci goto vlvf_update; 317562306a36Sopenharmony_ci 317662306a36Sopenharmony_ci /* clear the pool bit */ 317762306a36Sopenharmony_ci bits ^= BIT(vind % 32); 317862306a36Sopenharmony_ci 317962306a36Sopenharmony_ci if (!bits && 318062306a36Sopenharmony_ci !IXGBE_READ_REG(hw, IXGBE_VLVFB(vlvf_index * 2 + 1 - vind / 32))) { 318162306a36Sopenharmony_ci /* Clear VFTA first, then disable VLVF. Otherwise 318262306a36Sopenharmony_ci * we run the risk of stray packets leaking into 318362306a36Sopenharmony_ci * the PF via the default pool 318462306a36Sopenharmony_ci */ 318562306a36Sopenharmony_ci if (vfta_delta) 318662306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_VFTA(regidx), vfta); 318762306a36Sopenharmony_ci 318862306a36Sopenharmony_ci /* disable VLVF and clear remaining bit from pool */ 318962306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_VLVF(vlvf_index), 0); 319062306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_VLVFB(vlvf_index * 2 + vind / 32), 0); 319162306a36Sopenharmony_ci 319262306a36Sopenharmony_ci return 0; 319362306a36Sopenharmony_ci } 319462306a36Sopenharmony_ci 319562306a36Sopenharmony_ci /* If there are still bits set in the VLVFB registers 319662306a36Sopenharmony_ci * for the VLAN ID indicated we need to see if the 319762306a36Sopenharmony_ci * caller is requesting that we clear the VFTA entry bit. 319862306a36Sopenharmony_ci * If the caller has requested that we clear the VFTA 319962306a36Sopenharmony_ci * entry bit but there are still pools/VFs using this VLAN 320062306a36Sopenharmony_ci * ID entry then ignore the request. We're not worried 320162306a36Sopenharmony_ci * about the case where we're turning the VFTA VLAN ID 320262306a36Sopenharmony_ci * entry bit on, only when requested to turn it off as 320362306a36Sopenharmony_ci * there may be multiple pools and/or VFs using the 320462306a36Sopenharmony_ci * VLAN ID entry. In that case we cannot clear the 320562306a36Sopenharmony_ci * VFTA bit until all pools/VFs using that VLAN ID have also 320662306a36Sopenharmony_ci * been cleared. This will be indicated by "bits" being 320762306a36Sopenharmony_ci * zero. 320862306a36Sopenharmony_ci */ 320962306a36Sopenharmony_ci vfta_delta = 0; 321062306a36Sopenharmony_ci 321162306a36Sopenharmony_civlvf_update: 321262306a36Sopenharmony_ci /* record pool change and enable VLAN ID if not already enabled */ 321362306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_VLVFB(vlvf_index * 2 + vind / 32), bits); 321462306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_VLVF(vlvf_index), IXGBE_VLVF_VIEN | vlan); 321562306a36Sopenharmony_ci 321662306a36Sopenharmony_civfta_update: 321762306a36Sopenharmony_ci /* Update VFTA now that we are ready for traffic */ 321862306a36Sopenharmony_ci if (vfta_delta) 321962306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_VFTA(regidx), vfta); 322062306a36Sopenharmony_ci 322162306a36Sopenharmony_ci return 0; 322262306a36Sopenharmony_ci} 322362306a36Sopenharmony_ci 322462306a36Sopenharmony_ci/** 322562306a36Sopenharmony_ci * ixgbe_clear_vfta_generic - Clear VLAN filter table 322662306a36Sopenharmony_ci * @hw: pointer to hardware structure 322762306a36Sopenharmony_ci * 322862306a36Sopenharmony_ci * Clears the VLAN filter table, and the VMDq index associated with the filter 322962306a36Sopenharmony_ci **/ 323062306a36Sopenharmony_cis32 ixgbe_clear_vfta_generic(struct ixgbe_hw *hw) 323162306a36Sopenharmony_ci{ 323262306a36Sopenharmony_ci u32 offset; 323362306a36Sopenharmony_ci 323462306a36Sopenharmony_ci for (offset = 0; offset < hw->mac.vft_size; offset++) 323562306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_VFTA(offset), 0); 323662306a36Sopenharmony_ci 323762306a36Sopenharmony_ci for (offset = 0; offset < IXGBE_VLVF_ENTRIES; offset++) { 323862306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_VLVF(offset), 0); 323962306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_VLVFB(offset * 2), 0); 324062306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_VLVFB(offset * 2 + 1), 0); 324162306a36Sopenharmony_ci } 324262306a36Sopenharmony_ci 324362306a36Sopenharmony_ci return 0; 324462306a36Sopenharmony_ci} 324562306a36Sopenharmony_ci 324662306a36Sopenharmony_ci/** 324762306a36Sopenharmony_ci * ixgbe_need_crosstalk_fix - Determine if we need to do cross talk fix 324862306a36Sopenharmony_ci * @hw: pointer to hardware structure 324962306a36Sopenharmony_ci * 325062306a36Sopenharmony_ci * Contains the logic to identify if we need to verify link for the 325162306a36Sopenharmony_ci * crosstalk fix 325262306a36Sopenharmony_ci **/ 325362306a36Sopenharmony_cistatic bool ixgbe_need_crosstalk_fix(struct ixgbe_hw *hw) 325462306a36Sopenharmony_ci{ 325562306a36Sopenharmony_ci /* Does FW say we need the fix */ 325662306a36Sopenharmony_ci if (!hw->need_crosstalk_fix) 325762306a36Sopenharmony_ci return false; 325862306a36Sopenharmony_ci 325962306a36Sopenharmony_ci /* Only consider SFP+ PHYs i.e. media type fiber */ 326062306a36Sopenharmony_ci switch (hw->mac.ops.get_media_type(hw)) { 326162306a36Sopenharmony_ci case ixgbe_media_type_fiber: 326262306a36Sopenharmony_ci case ixgbe_media_type_fiber_qsfp: 326362306a36Sopenharmony_ci break; 326462306a36Sopenharmony_ci default: 326562306a36Sopenharmony_ci return false; 326662306a36Sopenharmony_ci } 326762306a36Sopenharmony_ci 326862306a36Sopenharmony_ci return true; 326962306a36Sopenharmony_ci} 327062306a36Sopenharmony_ci 327162306a36Sopenharmony_ci/** 327262306a36Sopenharmony_ci * ixgbe_check_mac_link_generic - Determine link and speed status 327362306a36Sopenharmony_ci * @hw: pointer to hardware structure 327462306a36Sopenharmony_ci * @speed: pointer to link speed 327562306a36Sopenharmony_ci * @link_up: true when link is up 327662306a36Sopenharmony_ci * @link_up_wait_to_complete: bool used to wait for link up or not 327762306a36Sopenharmony_ci * 327862306a36Sopenharmony_ci * Reads the links register to determine if link is up and the current speed 327962306a36Sopenharmony_ci **/ 328062306a36Sopenharmony_cis32 ixgbe_check_mac_link_generic(struct ixgbe_hw *hw, ixgbe_link_speed *speed, 328162306a36Sopenharmony_ci bool *link_up, bool link_up_wait_to_complete) 328262306a36Sopenharmony_ci{ 328362306a36Sopenharmony_ci bool crosstalk_fix_active = ixgbe_need_crosstalk_fix(hw); 328462306a36Sopenharmony_ci u32 links_reg, links_orig; 328562306a36Sopenharmony_ci u32 i; 328662306a36Sopenharmony_ci 328762306a36Sopenharmony_ci /* If Crosstalk fix enabled do the sanity check of making sure 328862306a36Sopenharmony_ci * the SFP+ cage is full. 328962306a36Sopenharmony_ci */ 329062306a36Sopenharmony_ci if (crosstalk_fix_active) { 329162306a36Sopenharmony_ci u32 sfp_cage_full; 329262306a36Sopenharmony_ci 329362306a36Sopenharmony_ci switch (hw->mac.type) { 329462306a36Sopenharmony_ci case ixgbe_mac_82599EB: 329562306a36Sopenharmony_ci sfp_cage_full = IXGBE_READ_REG(hw, IXGBE_ESDP) & 329662306a36Sopenharmony_ci IXGBE_ESDP_SDP2; 329762306a36Sopenharmony_ci break; 329862306a36Sopenharmony_ci case ixgbe_mac_X550EM_x: 329962306a36Sopenharmony_ci case ixgbe_mac_x550em_a: 330062306a36Sopenharmony_ci sfp_cage_full = IXGBE_READ_REG(hw, IXGBE_ESDP) & 330162306a36Sopenharmony_ci IXGBE_ESDP_SDP0; 330262306a36Sopenharmony_ci break; 330362306a36Sopenharmony_ci default: 330462306a36Sopenharmony_ci /* sanity check - No SFP+ devices here */ 330562306a36Sopenharmony_ci sfp_cage_full = false; 330662306a36Sopenharmony_ci break; 330762306a36Sopenharmony_ci } 330862306a36Sopenharmony_ci 330962306a36Sopenharmony_ci if (!sfp_cage_full) { 331062306a36Sopenharmony_ci *link_up = false; 331162306a36Sopenharmony_ci *speed = IXGBE_LINK_SPEED_UNKNOWN; 331262306a36Sopenharmony_ci return 0; 331362306a36Sopenharmony_ci } 331462306a36Sopenharmony_ci } 331562306a36Sopenharmony_ci 331662306a36Sopenharmony_ci /* clear the old state */ 331762306a36Sopenharmony_ci links_orig = IXGBE_READ_REG(hw, IXGBE_LINKS); 331862306a36Sopenharmony_ci 331962306a36Sopenharmony_ci links_reg = IXGBE_READ_REG(hw, IXGBE_LINKS); 332062306a36Sopenharmony_ci 332162306a36Sopenharmony_ci if (links_orig != links_reg) { 332262306a36Sopenharmony_ci hw_dbg(hw, "LINKS changed from %08X to %08X\n", 332362306a36Sopenharmony_ci links_orig, links_reg); 332462306a36Sopenharmony_ci } 332562306a36Sopenharmony_ci 332662306a36Sopenharmony_ci if (link_up_wait_to_complete) { 332762306a36Sopenharmony_ci for (i = 0; i < IXGBE_LINK_UP_TIME; i++) { 332862306a36Sopenharmony_ci if (links_reg & IXGBE_LINKS_UP) { 332962306a36Sopenharmony_ci *link_up = true; 333062306a36Sopenharmony_ci break; 333162306a36Sopenharmony_ci } else { 333262306a36Sopenharmony_ci *link_up = false; 333362306a36Sopenharmony_ci } 333462306a36Sopenharmony_ci msleep(100); 333562306a36Sopenharmony_ci links_reg = IXGBE_READ_REG(hw, IXGBE_LINKS); 333662306a36Sopenharmony_ci } 333762306a36Sopenharmony_ci } else { 333862306a36Sopenharmony_ci if (links_reg & IXGBE_LINKS_UP) { 333962306a36Sopenharmony_ci if (crosstalk_fix_active) { 334062306a36Sopenharmony_ci /* Check the link state again after a delay 334162306a36Sopenharmony_ci * to filter out spurious link up 334262306a36Sopenharmony_ci * notifications. 334362306a36Sopenharmony_ci */ 334462306a36Sopenharmony_ci mdelay(5); 334562306a36Sopenharmony_ci links_reg = IXGBE_READ_REG(hw, IXGBE_LINKS); 334662306a36Sopenharmony_ci if (!(links_reg & IXGBE_LINKS_UP)) { 334762306a36Sopenharmony_ci *link_up = false; 334862306a36Sopenharmony_ci *speed = IXGBE_LINK_SPEED_UNKNOWN; 334962306a36Sopenharmony_ci return 0; 335062306a36Sopenharmony_ci } 335162306a36Sopenharmony_ci } 335262306a36Sopenharmony_ci *link_up = true; 335362306a36Sopenharmony_ci } else { 335462306a36Sopenharmony_ci *link_up = false; 335562306a36Sopenharmony_ci } 335662306a36Sopenharmony_ci } 335762306a36Sopenharmony_ci 335862306a36Sopenharmony_ci switch (links_reg & IXGBE_LINKS_SPEED_82599) { 335962306a36Sopenharmony_ci case IXGBE_LINKS_SPEED_10G_82599: 336062306a36Sopenharmony_ci if ((hw->mac.type >= ixgbe_mac_X550) && 336162306a36Sopenharmony_ci (links_reg & IXGBE_LINKS_SPEED_NON_STD)) 336262306a36Sopenharmony_ci *speed = IXGBE_LINK_SPEED_2_5GB_FULL; 336362306a36Sopenharmony_ci else 336462306a36Sopenharmony_ci *speed = IXGBE_LINK_SPEED_10GB_FULL; 336562306a36Sopenharmony_ci break; 336662306a36Sopenharmony_ci case IXGBE_LINKS_SPEED_1G_82599: 336762306a36Sopenharmony_ci *speed = IXGBE_LINK_SPEED_1GB_FULL; 336862306a36Sopenharmony_ci break; 336962306a36Sopenharmony_ci case IXGBE_LINKS_SPEED_100_82599: 337062306a36Sopenharmony_ci if ((hw->mac.type >= ixgbe_mac_X550) && 337162306a36Sopenharmony_ci (links_reg & IXGBE_LINKS_SPEED_NON_STD)) 337262306a36Sopenharmony_ci *speed = IXGBE_LINK_SPEED_5GB_FULL; 337362306a36Sopenharmony_ci else 337462306a36Sopenharmony_ci *speed = IXGBE_LINK_SPEED_100_FULL; 337562306a36Sopenharmony_ci break; 337662306a36Sopenharmony_ci case IXGBE_LINKS_SPEED_10_X550EM_A: 337762306a36Sopenharmony_ci *speed = IXGBE_LINK_SPEED_UNKNOWN; 337862306a36Sopenharmony_ci if (hw->device_id == IXGBE_DEV_ID_X550EM_A_1G_T || 337962306a36Sopenharmony_ci hw->device_id == IXGBE_DEV_ID_X550EM_A_1G_T_L) { 338062306a36Sopenharmony_ci *speed = IXGBE_LINK_SPEED_10_FULL; 338162306a36Sopenharmony_ci } 338262306a36Sopenharmony_ci break; 338362306a36Sopenharmony_ci default: 338462306a36Sopenharmony_ci *speed = IXGBE_LINK_SPEED_UNKNOWN; 338562306a36Sopenharmony_ci } 338662306a36Sopenharmony_ci 338762306a36Sopenharmony_ci return 0; 338862306a36Sopenharmony_ci} 338962306a36Sopenharmony_ci 339062306a36Sopenharmony_ci/** 339162306a36Sopenharmony_ci * ixgbe_get_wwn_prefix_generic - Get alternative WWNN/WWPN prefix from 339262306a36Sopenharmony_ci * the EEPROM 339362306a36Sopenharmony_ci * @hw: pointer to hardware structure 339462306a36Sopenharmony_ci * @wwnn_prefix: the alternative WWNN prefix 339562306a36Sopenharmony_ci * @wwpn_prefix: the alternative WWPN prefix 339662306a36Sopenharmony_ci * 339762306a36Sopenharmony_ci * This function will read the EEPROM from the alternative SAN MAC address 339862306a36Sopenharmony_ci * block to check the support for the alternative WWNN/WWPN prefix support. 339962306a36Sopenharmony_ci **/ 340062306a36Sopenharmony_cis32 ixgbe_get_wwn_prefix_generic(struct ixgbe_hw *hw, u16 *wwnn_prefix, 340162306a36Sopenharmony_ci u16 *wwpn_prefix) 340262306a36Sopenharmony_ci{ 340362306a36Sopenharmony_ci u16 offset, caps; 340462306a36Sopenharmony_ci u16 alt_san_mac_blk_offset; 340562306a36Sopenharmony_ci 340662306a36Sopenharmony_ci /* clear output first */ 340762306a36Sopenharmony_ci *wwnn_prefix = 0xFFFF; 340862306a36Sopenharmony_ci *wwpn_prefix = 0xFFFF; 340962306a36Sopenharmony_ci 341062306a36Sopenharmony_ci /* check if alternative SAN MAC is supported */ 341162306a36Sopenharmony_ci offset = IXGBE_ALT_SAN_MAC_ADDR_BLK_PTR; 341262306a36Sopenharmony_ci if (hw->eeprom.ops.read(hw, offset, &alt_san_mac_blk_offset)) 341362306a36Sopenharmony_ci goto wwn_prefix_err; 341462306a36Sopenharmony_ci 341562306a36Sopenharmony_ci if ((alt_san_mac_blk_offset == 0) || 341662306a36Sopenharmony_ci (alt_san_mac_blk_offset == 0xFFFF)) 341762306a36Sopenharmony_ci return 0; 341862306a36Sopenharmony_ci 341962306a36Sopenharmony_ci /* check capability in alternative san mac address block */ 342062306a36Sopenharmony_ci offset = alt_san_mac_blk_offset + IXGBE_ALT_SAN_MAC_ADDR_CAPS_OFFSET; 342162306a36Sopenharmony_ci if (hw->eeprom.ops.read(hw, offset, &caps)) 342262306a36Sopenharmony_ci goto wwn_prefix_err; 342362306a36Sopenharmony_ci if (!(caps & IXGBE_ALT_SAN_MAC_ADDR_CAPS_ALTWWN)) 342462306a36Sopenharmony_ci return 0; 342562306a36Sopenharmony_ci 342662306a36Sopenharmony_ci /* get the corresponding prefix for WWNN/WWPN */ 342762306a36Sopenharmony_ci offset = alt_san_mac_blk_offset + IXGBE_ALT_SAN_MAC_ADDR_WWNN_OFFSET; 342862306a36Sopenharmony_ci if (hw->eeprom.ops.read(hw, offset, wwnn_prefix)) 342962306a36Sopenharmony_ci hw_err(hw, "eeprom read at offset %d failed\n", offset); 343062306a36Sopenharmony_ci 343162306a36Sopenharmony_ci offset = alt_san_mac_blk_offset + IXGBE_ALT_SAN_MAC_ADDR_WWPN_OFFSET; 343262306a36Sopenharmony_ci if (hw->eeprom.ops.read(hw, offset, wwpn_prefix)) 343362306a36Sopenharmony_ci goto wwn_prefix_err; 343462306a36Sopenharmony_ci 343562306a36Sopenharmony_ci return 0; 343662306a36Sopenharmony_ci 343762306a36Sopenharmony_ciwwn_prefix_err: 343862306a36Sopenharmony_ci hw_err(hw, "eeprom read at offset %d failed\n", offset); 343962306a36Sopenharmony_ci return 0; 344062306a36Sopenharmony_ci} 344162306a36Sopenharmony_ci 344262306a36Sopenharmony_ci/** 344362306a36Sopenharmony_ci * ixgbe_set_mac_anti_spoofing - Enable/Disable MAC anti-spoofing 344462306a36Sopenharmony_ci * @hw: pointer to hardware structure 344562306a36Sopenharmony_ci * @enable: enable or disable switch for MAC anti-spoofing 344662306a36Sopenharmony_ci * @vf: Virtual Function pool - VF Pool to set for MAC anti-spoofing 344762306a36Sopenharmony_ci * 344862306a36Sopenharmony_ci **/ 344962306a36Sopenharmony_civoid ixgbe_set_mac_anti_spoofing(struct ixgbe_hw *hw, bool enable, int vf) 345062306a36Sopenharmony_ci{ 345162306a36Sopenharmony_ci int vf_target_reg = vf >> 3; 345262306a36Sopenharmony_ci int vf_target_shift = vf % 8; 345362306a36Sopenharmony_ci u32 pfvfspoof; 345462306a36Sopenharmony_ci 345562306a36Sopenharmony_ci if (hw->mac.type == ixgbe_mac_82598EB) 345662306a36Sopenharmony_ci return; 345762306a36Sopenharmony_ci 345862306a36Sopenharmony_ci pfvfspoof = IXGBE_READ_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg)); 345962306a36Sopenharmony_ci if (enable) 346062306a36Sopenharmony_ci pfvfspoof |= BIT(vf_target_shift); 346162306a36Sopenharmony_ci else 346262306a36Sopenharmony_ci pfvfspoof &= ~BIT(vf_target_shift); 346362306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg), pfvfspoof); 346462306a36Sopenharmony_ci} 346562306a36Sopenharmony_ci 346662306a36Sopenharmony_ci/** 346762306a36Sopenharmony_ci * ixgbe_set_vlan_anti_spoofing - Enable/Disable VLAN anti-spoofing 346862306a36Sopenharmony_ci * @hw: pointer to hardware structure 346962306a36Sopenharmony_ci * @enable: enable or disable switch for VLAN anti-spoofing 347062306a36Sopenharmony_ci * @vf: Virtual Function pool - VF Pool to set for VLAN anti-spoofing 347162306a36Sopenharmony_ci * 347262306a36Sopenharmony_ci **/ 347362306a36Sopenharmony_civoid ixgbe_set_vlan_anti_spoofing(struct ixgbe_hw *hw, bool enable, int vf) 347462306a36Sopenharmony_ci{ 347562306a36Sopenharmony_ci int vf_target_reg = vf >> 3; 347662306a36Sopenharmony_ci int vf_target_shift = vf % 8 + IXGBE_SPOOF_VLANAS_SHIFT; 347762306a36Sopenharmony_ci u32 pfvfspoof; 347862306a36Sopenharmony_ci 347962306a36Sopenharmony_ci if (hw->mac.type == ixgbe_mac_82598EB) 348062306a36Sopenharmony_ci return; 348162306a36Sopenharmony_ci 348262306a36Sopenharmony_ci pfvfspoof = IXGBE_READ_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg)); 348362306a36Sopenharmony_ci if (enable) 348462306a36Sopenharmony_ci pfvfspoof |= BIT(vf_target_shift); 348562306a36Sopenharmony_ci else 348662306a36Sopenharmony_ci pfvfspoof &= ~BIT(vf_target_shift); 348762306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg), pfvfspoof); 348862306a36Sopenharmony_ci} 348962306a36Sopenharmony_ci 349062306a36Sopenharmony_ci/** 349162306a36Sopenharmony_ci * ixgbe_get_device_caps_generic - Get additional device capabilities 349262306a36Sopenharmony_ci * @hw: pointer to hardware structure 349362306a36Sopenharmony_ci * @device_caps: the EEPROM word with the extra device capabilities 349462306a36Sopenharmony_ci * 349562306a36Sopenharmony_ci * This function will read the EEPROM location for the device capabilities, 349662306a36Sopenharmony_ci * and return the word through device_caps. 349762306a36Sopenharmony_ci **/ 349862306a36Sopenharmony_cis32 ixgbe_get_device_caps_generic(struct ixgbe_hw *hw, u16 *device_caps) 349962306a36Sopenharmony_ci{ 350062306a36Sopenharmony_ci hw->eeprom.ops.read(hw, IXGBE_DEVICE_CAPS, device_caps); 350162306a36Sopenharmony_ci 350262306a36Sopenharmony_ci return 0; 350362306a36Sopenharmony_ci} 350462306a36Sopenharmony_ci 350562306a36Sopenharmony_ci/** 350662306a36Sopenharmony_ci * ixgbe_set_rxpba_generic - Initialize RX packet buffer 350762306a36Sopenharmony_ci * @hw: pointer to hardware structure 350862306a36Sopenharmony_ci * @num_pb: number of packet buffers to allocate 350962306a36Sopenharmony_ci * @headroom: reserve n KB of headroom 351062306a36Sopenharmony_ci * @strategy: packet buffer allocation strategy 351162306a36Sopenharmony_ci **/ 351262306a36Sopenharmony_civoid ixgbe_set_rxpba_generic(struct ixgbe_hw *hw, 351362306a36Sopenharmony_ci int num_pb, 351462306a36Sopenharmony_ci u32 headroom, 351562306a36Sopenharmony_ci int strategy) 351662306a36Sopenharmony_ci{ 351762306a36Sopenharmony_ci u32 pbsize = hw->mac.rx_pb_size; 351862306a36Sopenharmony_ci int i = 0; 351962306a36Sopenharmony_ci u32 rxpktsize, txpktsize, txpbthresh; 352062306a36Sopenharmony_ci 352162306a36Sopenharmony_ci /* Reserve headroom */ 352262306a36Sopenharmony_ci pbsize -= headroom; 352362306a36Sopenharmony_ci 352462306a36Sopenharmony_ci if (!num_pb) 352562306a36Sopenharmony_ci num_pb = 1; 352662306a36Sopenharmony_ci 352762306a36Sopenharmony_ci /* Divide remaining packet buffer space amongst the number 352862306a36Sopenharmony_ci * of packet buffers requested using supplied strategy. 352962306a36Sopenharmony_ci */ 353062306a36Sopenharmony_ci switch (strategy) { 353162306a36Sopenharmony_ci case (PBA_STRATEGY_WEIGHTED): 353262306a36Sopenharmony_ci /* pba_80_48 strategy weight first half of packet buffer with 353362306a36Sopenharmony_ci * 5/8 of the packet buffer space. 353462306a36Sopenharmony_ci */ 353562306a36Sopenharmony_ci rxpktsize = ((pbsize * 5 * 2) / (num_pb * 8)); 353662306a36Sopenharmony_ci pbsize -= rxpktsize * (num_pb / 2); 353762306a36Sopenharmony_ci rxpktsize <<= IXGBE_RXPBSIZE_SHIFT; 353862306a36Sopenharmony_ci for (; i < (num_pb / 2); i++) 353962306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), rxpktsize); 354062306a36Sopenharmony_ci fallthrough; /* configure remaining packet buffers */ 354162306a36Sopenharmony_ci case (PBA_STRATEGY_EQUAL): 354262306a36Sopenharmony_ci /* Divide the remaining Rx packet buffer evenly among the TCs */ 354362306a36Sopenharmony_ci rxpktsize = (pbsize / (num_pb - i)) << IXGBE_RXPBSIZE_SHIFT; 354462306a36Sopenharmony_ci for (; i < num_pb; i++) 354562306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), rxpktsize); 354662306a36Sopenharmony_ci break; 354762306a36Sopenharmony_ci default: 354862306a36Sopenharmony_ci break; 354962306a36Sopenharmony_ci } 355062306a36Sopenharmony_ci 355162306a36Sopenharmony_ci /* 355262306a36Sopenharmony_ci * Setup Tx packet buffer and threshold equally for all TCs 355362306a36Sopenharmony_ci * TXPBTHRESH register is set in K so divide by 1024 and subtract 355462306a36Sopenharmony_ci * 10 since the largest packet we support is just over 9K. 355562306a36Sopenharmony_ci */ 355662306a36Sopenharmony_ci txpktsize = IXGBE_TXPBSIZE_MAX / num_pb; 355762306a36Sopenharmony_ci txpbthresh = (txpktsize / 1024) - IXGBE_TXPKT_SIZE_MAX; 355862306a36Sopenharmony_ci for (i = 0; i < num_pb; i++) { 355962306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_TXPBSIZE(i), txpktsize); 356062306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_TXPBTHRESH(i), txpbthresh); 356162306a36Sopenharmony_ci } 356262306a36Sopenharmony_ci 356362306a36Sopenharmony_ci /* Clear unused TCs, if any, to zero buffer size*/ 356462306a36Sopenharmony_ci for (; i < IXGBE_MAX_PB; i++) { 356562306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), 0); 356662306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_TXPBSIZE(i), 0); 356762306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_TXPBTHRESH(i), 0); 356862306a36Sopenharmony_ci } 356962306a36Sopenharmony_ci} 357062306a36Sopenharmony_ci 357162306a36Sopenharmony_ci/** 357262306a36Sopenharmony_ci * ixgbe_calculate_checksum - Calculate checksum for buffer 357362306a36Sopenharmony_ci * @buffer: pointer to EEPROM 357462306a36Sopenharmony_ci * @length: size of EEPROM to calculate a checksum for 357562306a36Sopenharmony_ci * 357662306a36Sopenharmony_ci * Calculates the checksum for some buffer on a specified length. The 357762306a36Sopenharmony_ci * checksum calculated is returned. 357862306a36Sopenharmony_ci **/ 357962306a36Sopenharmony_ciu8 ixgbe_calculate_checksum(u8 *buffer, u32 length) 358062306a36Sopenharmony_ci{ 358162306a36Sopenharmony_ci u32 i; 358262306a36Sopenharmony_ci u8 sum = 0; 358362306a36Sopenharmony_ci 358462306a36Sopenharmony_ci if (!buffer) 358562306a36Sopenharmony_ci return 0; 358662306a36Sopenharmony_ci 358762306a36Sopenharmony_ci for (i = 0; i < length; i++) 358862306a36Sopenharmony_ci sum += buffer[i]; 358962306a36Sopenharmony_ci 359062306a36Sopenharmony_ci return (u8) (0 - sum); 359162306a36Sopenharmony_ci} 359262306a36Sopenharmony_ci 359362306a36Sopenharmony_ci/** 359462306a36Sopenharmony_ci * ixgbe_hic_unlocked - Issue command to manageability block unlocked 359562306a36Sopenharmony_ci * @hw: pointer to the HW structure 359662306a36Sopenharmony_ci * @buffer: command to write and where the return status will be placed 359762306a36Sopenharmony_ci * @length: length of buffer, must be multiple of 4 bytes 359862306a36Sopenharmony_ci * @timeout: time in ms to wait for command completion 359962306a36Sopenharmony_ci * 360062306a36Sopenharmony_ci * Communicates with the manageability block. On success return 0 360162306a36Sopenharmony_ci * else returns semaphore error when encountering an error acquiring 360262306a36Sopenharmony_ci * semaphore, -EINVAL when incorrect parameters passed or -EIO when 360362306a36Sopenharmony_ci * command fails. 360462306a36Sopenharmony_ci * 360562306a36Sopenharmony_ci * This function assumes that the IXGBE_GSSR_SW_MNG_SM semaphore is held 360662306a36Sopenharmony_ci * by the caller. 360762306a36Sopenharmony_ci **/ 360862306a36Sopenharmony_cis32 ixgbe_hic_unlocked(struct ixgbe_hw *hw, u32 *buffer, u32 length, 360962306a36Sopenharmony_ci u32 timeout) 361062306a36Sopenharmony_ci{ 361162306a36Sopenharmony_ci u32 hicr, i, fwsts; 361262306a36Sopenharmony_ci u16 dword_len; 361362306a36Sopenharmony_ci 361462306a36Sopenharmony_ci if (!length || length > IXGBE_HI_MAX_BLOCK_BYTE_LENGTH) { 361562306a36Sopenharmony_ci hw_dbg(hw, "Buffer length failure buffersize-%d.\n", length); 361662306a36Sopenharmony_ci return -EINVAL; 361762306a36Sopenharmony_ci } 361862306a36Sopenharmony_ci 361962306a36Sopenharmony_ci /* Set bit 9 of FWSTS clearing FW reset indication */ 362062306a36Sopenharmony_ci fwsts = IXGBE_READ_REG(hw, IXGBE_FWSTS); 362162306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_FWSTS, fwsts | IXGBE_FWSTS_FWRI); 362262306a36Sopenharmony_ci 362362306a36Sopenharmony_ci /* Check that the host interface is enabled. */ 362462306a36Sopenharmony_ci hicr = IXGBE_READ_REG(hw, IXGBE_HICR); 362562306a36Sopenharmony_ci if (!(hicr & IXGBE_HICR_EN)) { 362662306a36Sopenharmony_ci hw_dbg(hw, "IXGBE_HOST_EN bit disabled.\n"); 362762306a36Sopenharmony_ci return -EIO; 362862306a36Sopenharmony_ci } 362962306a36Sopenharmony_ci 363062306a36Sopenharmony_ci /* Calculate length in DWORDs. We must be DWORD aligned */ 363162306a36Sopenharmony_ci if (length % sizeof(u32)) { 363262306a36Sopenharmony_ci hw_dbg(hw, "Buffer length failure, not aligned to dword"); 363362306a36Sopenharmony_ci return -EINVAL; 363462306a36Sopenharmony_ci } 363562306a36Sopenharmony_ci 363662306a36Sopenharmony_ci dword_len = length >> 2; 363762306a36Sopenharmony_ci 363862306a36Sopenharmony_ci /* The device driver writes the relevant command block 363962306a36Sopenharmony_ci * into the ram area. 364062306a36Sopenharmony_ci */ 364162306a36Sopenharmony_ci for (i = 0; i < dword_len; i++) 364262306a36Sopenharmony_ci IXGBE_WRITE_REG_ARRAY(hw, IXGBE_FLEX_MNG, 364362306a36Sopenharmony_ci i, (__force u32)cpu_to_le32(buffer[i])); 364462306a36Sopenharmony_ci 364562306a36Sopenharmony_ci /* Setting this bit tells the ARC that a new command is pending. */ 364662306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_HICR, hicr | IXGBE_HICR_C); 364762306a36Sopenharmony_ci 364862306a36Sopenharmony_ci for (i = 0; i < timeout; i++) { 364962306a36Sopenharmony_ci hicr = IXGBE_READ_REG(hw, IXGBE_HICR); 365062306a36Sopenharmony_ci if (!(hicr & IXGBE_HICR_C)) 365162306a36Sopenharmony_ci break; 365262306a36Sopenharmony_ci usleep_range(1000, 2000); 365362306a36Sopenharmony_ci } 365462306a36Sopenharmony_ci 365562306a36Sopenharmony_ci /* Check command successful completion. */ 365662306a36Sopenharmony_ci if ((timeout && i == timeout) || 365762306a36Sopenharmony_ci !(IXGBE_READ_REG(hw, IXGBE_HICR) & IXGBE_HICR_SV)) 365862306a36Sopenharmony_ci return -EIO; 365962306a36Sopenharmony_ci 366062306a36Sopenharmony_ci return 0; 366162306a36Sopenharmony_ci} 366262306a36Sopenharmony_ci 366362306a36Sopenharmony_ci/** 366462306a36Sopenharmony_ci * ixgbe_host_interface_command - Issue command to manageability block 366562306a36Sopenharmony_ci * @hw: pointer to the HW structure 366662306a36Sopenharmony_ci * @buffer: contains the command to write and where the return status will 366762306a36Sopenharmony_ci * be placed 366862306a36Sopenharmony_ci * @length: length of buffer, must be multiple of 4 bytes 366962306a36Sopenharmony_ci * @timeout: time in ms to wait for command completion 367062306a36Sopenharmony_ci * @return_data: read and return data from the buffer (true) or not (false) 367162306a36Sopenharmony_ci * Needed because FW structures are big endian and decoding of 367262306a36Sopenharmony_ci * these fields can be 8 bit or 16 bit based on command. Decoding 367362306a36Sopenharmony_ci * is not easily understood without making a table of commands. 367462306a36Sopenharmony_ci * So we will leave this up to the caller to read back the data 367562306a36Sopenharmony_ci * in these cases. 367662306a36Sopenharmony_ci * 367762306a36Sopenharmony_ci * Communicates with the manageability block. On success return 0 367862306a36Sopenharmony_ci * else return -EIO or -EINVAL. 367962306a36Sopenharmony_ci **/ 368062306a36Sopenharmony_cis32 ixgbe_host_interface_command(struct ixgbe_hw *hw, void *buffer, 368162306a36Sopenharmony_ci u32 length, u32 timeout, 368262306a36Sopenharmony_ci bool return_data) 368362306a36Sopenharmony_ci{ 368462306a36Sopenharmony_ci u32 hdr_size = sizeof(struct ixgbe_hic_hdr); 368562306a36Sopenharmony_ci struct ixgbe_hic_hdr *hdr = buffer; 368662306a36Sopenharmony_ci u32 *u32arr = buffer; 368762306a36Sopenharmony_ci u16 buf_len, dword_len; 368862306a36Sopenharmony_ci s32 status; 368962306a36Sopenharmony_ci u32 bi; 369062306a36Sopenharmony_ci 369162306a36Sopenharmony_ci if (!length || length > IXGBE_HI_MAX_BLOCK_BYTE_LENGTH) { 369262306a36Sopenharmony_ci hw_dbg(hw, "Buffer length failure buffersize-%d.\n", length); 369362306a36Sopenharmony_ci return -EINVAL; 369462306a36Sopenharmony_ci } 369562306a36Sopenharmony_ci /* Take management host interface semaphore */ 369662306a36Sopenharmony_ci status = hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_SW_MNG_SM); 369762306a36Sopenharmony_ci if (status) 369862306a36Sopenharmony_ci return status; 369962306a36Sopenharmony_ci 370062306a36Sopenharmony_ci status = ixgbe_hic_unlocked(hw, buffer, length, timeout); 370162306a36Sopenharmony_ci if (status) 370262306a36Sopenharmony_ci goto rel_out; 370362306a36Sopenharmony_ci 370462306a36Sopenharmony_ci if (!return_data) 370562306a36Sopenharmony_ci goto rel_out; 370662306a36Sopenharmony_ci 370762306a36Sopenharmony_ci /* Calculate length in DWORDs */ 370862306a36Sopenharmony_ci dword_len = hdr_size >> 2; 370962306a36Sopenharmony_ci 371062306a36Sopenharmony_ci /* first pull in the header so we know the buffer length */ 371162306a36Sopenharmony_ci for (bi = 0; bi < dword_len; bi++) { 371262306a36Sopenharmony_ci u32arr[bi] = IXGBE_READ_REG_ARRAY(hw, IXGBE_FLEX_MNG, bi); 371362306a36Sopenharmony_ci le32_to_cpus(&u32arr[bi]); 371462306a36Sopenharmony_ci } 371562306a36Sopenharmony_ci 371662306a36Sopenharmony_ci /* If there is any thing in data position pull it in */ 371762306a36Sopenharmony_ci buf_len = hdr->buf_len; 371862306a36Sopenharmony_ci if (!buf_len) 371962306a36Sopenharmony_ci goto rel_out; 372062306a36Sopenharmony_ci 372162306a36Sopenharmony_ci if (length < round_up(buf_len, 4) + hdr_size) { 372262306a36Sopenharmony_ci hw_dbg(hw, "Buffer not large enough for reply message.\n"); 372362306a36Sopenharmony_ci status = -EIO; 372462306a36Sopenharmony_ci goto rel_out; 372562306a36Sopenharmony_ci } 372662306a36Sopenharmony_ci 372762306a36Sopenharmony_ci /* Calculate length in DWORDs, add 3 for odd lengths */ 372862306a36Sopenharmony_ci dword_len = (buf_len + 3) >> 2; 372962306a36Sopenharmony_ci 373062306a36Sopenharmony_ci /* Pull in the rest of the buffer (bi is where we left off) */ 373162306a36Sopenharmony_ci for (; bi <= dword_len; bi++) { 373262306a36Sopenharmony_ci u32arr[bi] = IXGBE_READ_REG_ARRAY(hw, IXGBE_FLEX_MNG, bi); 373362306a36Sopenharmony_ci le32_to_cpus(&u32arr[bi]); 373462306a36Sopenharmony_ci } 373562306a36Sopenharmony_ci 373662306a36Sopenharmony_cirel_out: 373762306a36Sopenharmony_ci hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_SW_MNG_SM); 373862306a36Sopenharmony_ci 373962306a36Sopenharmony_ci return status; 374062306a36Sopenharmony_ci} 374162306a36Sopenharmony_ci 374262306a36Sopenharmony_ci/** 374362306a36Sopenharmony_ci * ixgbe_set_fw_drv_ver_generic - Sends driver version to firmware 374462306a36Sopenharmony_ci * @hw: pointer to the HW structure 374562306a36Sopenharmony_ci * @maj: driver version major number 374662306a36Sopenharmony_ci * @min: driver version minor number 374762306a36Sopenharmony_ci * @build: driver version build number 374862306a36Sopenharmony_ci * @sub: driver version sub build number 374962306a36Sopenharmony_ci * @len: length of driver_ver string 375062306a36Sopenharmony_ci * @driver_ver: driver string 375162306a36Sopenharmony_ci * 375262306a36Sopenharmony_ci * Sends driver version number to firmware through the manageability 375362306a36Sopenharmony_ci * block. On success return 0 375462306a36Sopenharmony_ci * else returns -EBUSY when encountering an error acquiring 375562306a36Sopenharmony_ci * semaphore or -EIO when command fails. 375662306a36Sopenharmony_ci **/ 375762306a36Sopenharmony_cis32 ixgbe_set_fw_drv_ver_generic(struct ixgbe_hw *hw, u8 maj, u8 min, 375862306a36Sopenharmony_ci u8 build, u8 sub, __always_unused u16 len, 375962306a36Sopenharmony_ci __always_unused const char *driver_ver) 376062306a36Sopenharmony_ci{ 376162306a36Sopenharmony_ci struct ixgbe_hic_drv_info fw_cmd; 376262306a36Sopenharmony_ci int i; 376362306a36Sopenharmony_ci s32 ret_val; 376462306a36Sopenharmony_ci 376562306a36Sopenharmony_ci fw_cmd.hdr.cmd = FW_CEM_CMD_DRIVER_INFO; 376662306a36Sopenharmony_ci fw_cmd.hdr.buf_len = FW_CEM_CMD_DRIVER_INFO_LEN; 376762306a36Sopenharmony_ci fw_cmd.hdr.cmd_or_resp.cmd_resv = FW_CEM_CMD_RESERVED; 376862306a36Sopenharmony_ci fw_cmd.port_num = hw->bus.func; 376962306a36Sopenharmony_ci fw_cmd.ver_maj = maj; 377062306a36Sopenharmony_ci fw_cmd.ver_min = min; 377162306a36Sopenharmony_ci fw_cmd.ver_build = build; 377262306a36Sopenharmony_ci fw_cmd.ver_sub = sub; 377362306a36Sopenharmony_ci fw_cmd.hdr.checksum = 0; 377462306a36Sopenharmony_ci fw_cmd.pad = 0; 377562306a36Sopenharmony_ci fw_cmd.pad2 = 0; 377662306a36Sopenharmony_ci fw_cmd.hdr.checksum = ixgbe_calculate_checksum((u8 *)&fw_cmd, 377762306a36Sopenharmony_ci (FW_CEM_HDR_LEN + fw_cmd.hdr.buf_len)); 377862306a36Sopenharmony_ci 377962306a36Sopenharmony_ci for (i = 0; i <= FW_CEM_MAX_RETRIES; i++) { 378062306a36Sopenharmony_ci ret_val = ixgbe_host_interface_command(hw, &fw_cmd, 378162306a36Sopenharmony_ci sizeof(fw_cmd), 378262306a36Sopenharmony_ci IXGBE_HI_COMMAND_TIMEOUT, 378362306a36Sopenharmony_ci true); 378462306a36Sopenharmony_ci if (ret_val != 0) 378562306a36Sopenharmony_ci continue; 378662306a36Sopenharmony_ci 378762306a36Sopenharmony_ci if (fw_cmd.hdr.cmd_or_resp.ret_status == 378862306a36Sopenharmony_ci FW_CEM_RESP_STATUS_SUCCESS) 378962306a36Sopenharmony_ci ret_val = 0; 379062306a36Sopenharmony_ci else 379162306a36Sopenharmony_ci ret_val = -EIO; 379262306a36Sopenharmony_ci 379362306a36Sopenharmony_ci break; 379462306a36Sopenharmony_ci } 379562306a36Sopenharmony_ci 379662306a36Sopenharmony_ci return ret_val; 379762306a36Sopenharmony_ci} 379862306a36Sopenharmony_ci 379962306a36Sopenharmony_ci/** 380062306a36Sopenharmony_ci * ixgbe_clear_tx_pending - Clear pending TX work from the PCIe fifo 380162306a36Sopenharmony_ci * @hw: pointer to the hardware structure 380262306a36Sopenharmony_ci * 380362306a36Sopenharmony_ci * The 82599 and x540 MACs can experience issues if TX work is still pending 380462306a36Sopenharmony_ci * when a reset occurs. This function prevents this by flushing the PCIe 380562306a36Sopenharmony_ci * buffers on the system. 380662306a36Sopenharmony_ci **/ 380762306a36Sopenharmony_civoid ixgbe_clear_tx_pending(struct ixgbe_hw *hw) 380862306a36Sopenharmony_ci{ 380962306a36Sopenharmony_ci u32 gcr_ext, hlreg0, i, poll; 381062306a36Sopenharmony_ci u16 value; 381162306a36Sopenharmony_ci 381262306a36Sopenharmony_ci /* 381362306a36Sopenharmony_ci * If double reset is not requested then all transactions should 381462306a36Sopenharmony_ci * already be clear and as such there is no work to do 381562306a36Sopenharmony_ci */ 381662306a36Sopenharmony_ci if (!(hw->mac.flags & IXGBE_FLAGS_DOUBLE_RESET_REQUIRED)) 381762306a36Sopenharmony_ci return; 381862306a36Sopenharmony_ci 381962306a36Sopenharmony_ci /* 382062306a36Sopenharmony_ci * Set loopback enable to prevent any transmits from being sent 382162306a36Sopenharmony_ci * should the link come up. This assumes that the RXCTRL.RXEN bit 382262306a36Sopenharmony_ci * has already been cleared. 382362306a36Sopenharmony_ci */ 382462306a36Sopenharmony_ci hlreg0 = IXGBE_READ_REG(hw, IXGBE_HLREG0); 382562306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg0 | IXGBE_HLREG0_LPBK); 382662306a36Sopenharmony_ci 382762306a36Sopenharmony_ci /* wait for a last completion before clearing buffers */ 382862306a36Sopenharmony_ci IXGBE_WRITE_FLUSH(hw); 382962306a36Sopenharmony_ci usleep_range(3000, 6000); 383062306a36Sopenharmony_ci 383162306a36Sopenharmony_ci /* Before proceeding, make sure that the PCIe block does not have 383262306a36Sopenharmony_ci * transactions pending. 383362306a36Sopenharmony_ci */ 383462306a36Sopenharmony_ci poll = ixgbe_pcie_timeout_poll(hw); 383562306a36Sopenharmony_ci for (i = 0; i < poll; i++) { 383662306a36Sopenharmony_ci usleep_range(100, 200); 383762306a36Sopenharmony_ci value = ixgbe_read_pci_cfg_word(hw, IXGBE_PCI_DEVICE_STATUS); 383862306a36Sopenharmony_ci if (ixgbe_removed(hw->hw_addr)) 383962306a36Sopenharmony_ci break; 384062306a36Sopenharmony_ci if (!(value & IXGBE_PCI_DEVICE_STATUS_TRANSACTION_PENDING)) 384162306a36Sopenharmony_ci break; 384262306a36Sopenharmony_ci } 384362306a36Sopenharmony_ci 384462306a36Sopenharmony_ci /* initiate cleaning flow for buffers in the PCIe transaction layer */ 384562306a36Sopenharmony_ci gcr_ext = IXGBE_READ_REG(hw, IXGBE_GCR_EXT); 384662306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_GCR_EXT, 384762306a36Sopenharmony_ci gcr_ext | IXGBE_GCR_EXT_BUFFERS_CLEAR); 384862306a36Sopenharmony_ci 384962306a36Sopenharmony_ci /* Flush all writes and allow 20usec for all transactions to clear */ 385062306a36Sopenharmony_ci IXGBE_WRITE_FLUSH(hw); 385162306a36Sopenharmony_ci udelay(20); 385262306a36Sopenharmony_ci 385362306a36Sopenharmony_ci /* restore previous register values */ 385462306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_GCR_EXT, gcr_ext); 385562306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg0); 385662306a36Sopenharmony_ci} 385762306a36Sopenharmony_ci 385862306a36Sopenharmony_cistatic const u8 ixgbe_emc_temp_data[4] = { 385962306a36Sopenharmony_ci IXGBE_EMC_INTERNAL_DATA, 386062306a36Sopenharmony_ci IXGBE_EMC_DIODE1_DATA, 386162306a36Sopenharmony_ci IXGBE_EMC_DIODE2_DATA, 386262306a36Sopenharmony_ci IXGBE_EMC_DIODE3_DATA 386362306a36Sopenharmony_ci}; 386462306a36Sopenharmony_cistatic const u8 ixgbe_emc_therm_limit[4] = { 386562306a36Sopenharmony_ci IXGBE_EMC_INTERNAL_THERM_LIMIT, 386662306a36Sopenharmony_ci IXGBE_EMC_DIODE1_THERM_LIMIT, 386762306a36Sopenharmony_ci IXGBE_EMC_DIODE2_THERM_LIMIT, 386862306a36Sopenharmony_ci IXGBE_EMC_DIODE3_THERM_LIMIT 386962306a36Sopenharmony_ci}; 387062306a36Sopenharmony_ci 387162306a36Sopenharmony_ci/** 387262306a36Sopenharmony_ci * ixgbe_get_ets_data - Extracts the ETS bit data 387362306a36Sopenharmony_ci * @hw: pointer to hardware structure 387462306a36Sopenharmony_ci * @ets_cfg: extected ETS data 387562306a36Sopenharmony_ci * @ets_offset: offset of ETS data 387662306a36Sopenharmony_ci * 387762306a36Sopenharmony_ci * Returns error code. 387862306a36Sopenharmony_ci **/ 387962306a36Sopenharmony_cistatic s32 ixgbe_get_ets_data(struct ixgbe_hw *hw, u16 *ets_cfg, 388062306a36Sopenharmony_ci u16 *ets_offset) 388162306a36Sopenharmony_ci{ 388262306a36Sopenharmony_ci s32 status; 388362306a36Sopenharmony_ci 388462306a36Sopenharmony_ci status = hw->eeprom.ops.read(hw, IXGBE_ETS_CFG, ets_offset); 388562306a36Sopenharmony_ci if (status) 388662306a36Sopenharmony_ci return status; 388762306a36Sopenharmony_ci 388862306a36Sopenharmony_ci if ((*ets_offset == 0x0000) || (*ets_offset == 0xFFFF)) 388962306a36Sopenharmony_ci return -EOPNOTSUPP; 389062306a36Sopenharmony_ci 389162306a36Sopenharmony_ci status = hw->eeprom.ops.read(hw, *ets_offset, ets_cfg); 389262306a36Sopenharmony_ci if (status) 389362306a36Sopenharmony_ci return status; 389462306a36Sopenharmony_ci 389562306a36Sopenharmony_ci if ((*ets_cfg & IXGBE_ETS_TYPE_MASK) != IXGBE_ETS_TYPE_EMC_SHIFTED) 389662306a36Sopenharmony_ci return -EOPNOTSUPP; 389762306a36Sopenharmony_ci 389862306a36Sopenharmony_ci return 0; 389962306a36Sopenharmony_ci} 390062306a36Sopenharmony_ci 390162306a36Sopenharmony_ci/** 390262306a36Sopenharmony_ci * ixgbe_get_thermal_sensor_data_generic - Gathers thermal sensor data 390362306a36Sopenharmony_ci * @hw: pointer to hardware structure 390462306a36Sopenharmony_ci * 390562306a36Sopenharmony_ci * Returns the thermal sensor data structure 390662306a36Sopenharmony_ci **/ 390762306a36Sopenharmony_cis32 ixgbe_get_thermal_sensor_data_generic(struct ixgbe_hw *hw) 390862306a36Sopenharmony_ci{ 390962306a36Sopenharmony_ci s32 status; 391062306a36Sopenharmony_ci u16 ets_offset; 391162306a36Sopenharmony_ci u16 ets_cfg; 391262306a36Sopenharmony_ci u16 ets_sensor; 391362306a36Sopenharmony_ci u8 num_sensors; 391462306a36Sopenharmony_ci u8 i; 391562306a36Sopenharmony_ci struct ixgbe_thermal_sensor_data *data = &hw->mac.thermal_sensor_data; 391662306a36Sopenharmony_ci 391762306a36Sopenharmony_ci /* Only support thermal sensors attached to physical port 0 */ 391862306a36Sopenharmony_ci if ((IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_LAN_ID_1)) 391962306a36Sopenharmony_ci return -EOPNOTSUPP; 392062306a36Sopenharmony_ci 392162306a36Sopenharmony_ci status = ixgbe_get_ets_data(hw, &ets_cfg, &ets_offset); 392262306a36Sopenharmony_ci if (status) 392362306a36Sopenharmony_ci return status; 392462306a36Sopenharmony_ci 392562306a36Sopenharmony_ci num_sensors = (ets_cfg & IXGBE_ETS_NUM_SENSORS_MASK); 392662306a36Sopenharmony_ci if (num_sensors > IXGBE_MAX_SENSORS) 392762306a36Sopenharmony_ci num_sensors = IXGBE_MAX_SENSORS; 392862306a36Sopenharmony_ci 392962306a36Sopenharmony_ci for (i = 0; i < num_sensors; i++) { 393062306a36Sopenharmony_ci u8 sensor_index; 393162306a36Sopenharmony_ci u8 sensor_location; 393262306a36Sopenharmony_ci 393362306a36Sopenharmony_ci status = hw->eeprom.ops.read(hw, (ets_offset + 1 + i), 393462306a36Sopenharmony_ci &ets_sensor); 393562306a36Sopenharmony_ci if (status) 393662306a36Sopenharmony_ci return status; 393762306a36Sopenharmony_ci 393862306a36Sopenharmony_ci sensor_index = ((ets_sensor & IXGBE_ETS_DATA_INDEX_MASK) >> 393962306a36Sopenharmony_ci IXGBE_ETS_DATA_INDEX_SHIFT); 394062306a36Sopenharmony_ci sensor_location = ((ets_sensor & IXGBE_ETS_DATA_LOC_MASK) >> 394162306a36Sopenharmony_ci IXGBE_ETS_DATA_LOC_SHIFT); 394262306a36Sopenharmony_ci 394362306a36Sopenharmony_ci if (sensor_location != 0) { 394462306a36Sopenharmony_ci status = hw->phy.ops.read_i2c_byte(hw, 394562306a36Sopenharmony_ci ixgbe_emc_temp_data[sensor_index], 394662306a36Sopenharmony_ci IXGBE_I2C_THERMAL_SENSOR_ADDR, 394762306a36Sopenharmony_ci &data->sensor[i].temp); 394862306a36Sopenharmony_ci if (status) 394962306a36Sopenharmony_ci return status; 395062306a36Sopenharmony_ci } 395162306a36Sopenharmony_ci } 395262306a36Sopenharmony_ci 395362306a36Sopenharmony_ci return 0; 395462306a36Sopenharmony_ci} 395562306a36Sopenharmony_ci 395662306a36Sopenharmony_ci/** 395762306a36Sopenharmony_ci * ixgbe_init_thermal_sensor_thresh_generic - Inits thermal sensor thresholds 395862306a36Sopenharmony_ci * @hw: pointer to hardware structure 395962306a36Sopenharmony_ci * 396062306a36Sopenharmony_ci * Inits the thermal sensor thresholds according to the NVM map 396162306a36Sopenharmony_ci * and save off the threshold and location values into mac.thermal_sensor_data 396262306a36Sopenharmony_ci **/ 396362306a36Sopenharmony_cis32 ixgbe_init_thermal_sensor_thresh_generic(struct ixgbe_hw *hw) 396462306a36Sopenharmony_ci{ 396562306a36Sopenharmony_ci s32 status; 396662306a36Sopenharmony_ci u16 ets_offset; 396762306a36Sopenharmony_ci u16 ets_cfg; 396862306a36Sopenharmony_ci u16 ets_sensor; 396962306a36Sopenharmony_ci u8 low_thresh_delta; 397062306a36Sopenharmony_ci u8 num_sensors; 397162306a36Sopenharmony_ci u8 therm_limit; 397262306a36Sopenharmony_ci u8 i; 397362306a36Sopenharmony_ci struct ixgbe_thermal_sensor_data *data = &hw->mac.thermal_sensor_data; 397462306a36Sopenharmony_ci 397562306a36Sopenharmony_ci memset(data, 0, sizeof(struct ixgbe_thermal_sensor_data)); 397662306a36Sopenharmony_ci 397762306a36Sopenharmony_ci /* Only support thermal sensors attached to physical port 0 */ 397862306a36Sopenharmony_ci if ((IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_LAN_ID_1)) 397962306a36Sopenharmony_ci return -EOPNOTSUPP; 398062306a36Sopenharmony_ci 398162306a36Sopenharmony_ci status = ixgbe_get_ets_data(hw, &ets_cfg, &ets_offset); 398262306a36Sopenharmony_ci if (status) 398362306a36Sopenharmony_ci return status; 398462306a36Sopenharmony_ci 398562306a36Sopenharmony_ci low_thresh_delta = ((ets_cfg & IXGBE_ETS_LTHRES_DELTA_MASK) >> 398662306a36Sopenharmony_ci IXGBE_ETS_LTHRES_DELTA_SHIFT); 398762306a36Sopenharmony_ci num_sensors = (ets_cfg & IXGBE_ETS_NUM_SENSORS_MASK); 398862306a36Sopenharmony_ci if (num_sensors > IXGBE_MAX_SENSORS) 398962306a36Sopenharmony_ci num_sensors = IXGBE_MAX_SENSORS; 399062306a36Sopenharmony_ci 399162306a36Sopenharmony_ci for (i = 0; i < num_sensors; i++) { 399262306a36Sopenharmony_ci u8 sensor_index; 399362306a36Sopenharmony_ci u8 sensor_location; 399462306a36Sopenharmony_ci 399562306a36Sopenharmony_ci if (hw->eeprom.ops.read(hw, ets_offset + 1 + i, &ets_sensor)) { 399662306a36Sopenharmony_ci hw_err(hw, "eeprom read at offset %d failed\n", 399762306a36Sopenharmony_ci ets_offset + 1 + i); 399862306a36Sopenharmony_ci continue; 399962306a36Sopenharmony_ci } 400062306a36Sopenharmony_ci sensor_index = ((ets_sensor & IXGBE_ETS_DATA_INDEX_MASK) >> 400162306a36Sopenharmony_ci IXGBE_ETS_DATA_INDEX_SHIFT); 400262306a36Sopenharmony_ci sensor_location = ((ets_sensor & IXGBE_ETS_DATA_LOC_MASK) >> 400362306a36Sopenharmony_ci IXGBE_ETS_DATA_LOC_SHIFT); 400462306a36Sopenharmony_ci therm_limit = ets_sensor & IXGBE_ETS_DATA_HTHRESH_MASK; 400562306a36Sopenharmony_ci 400662306a36Sopenharmony_ci hw->phy.ops.write_i2c_byte(hw, 400762306a36Sopenharmony_ci ixgbe_emc_therm_limit[sensor_index], 400862306a36Sopenharmony_ci IXGBE_I2C_THERMAL_SENSOR_ADDR, therm_limit); 400962306a36Sopenharmony_ci 401062306a36Sopenharmony_ci if (sensor_location == 0) 401162306a36Sopenharmony_ci continue; 401262306a36Sopenharmony_ci 401362306a36Sopenharmony_ci data->sensor[i].location = sensor_location; 401462306a36Sopenharmony_ci data->sensor[i].caution_thresh = therm_limit; 401562306a36Sopenharmony_ci data->sensor[i].max_op_thresh = therm_limit - low_thresh_delta; 401662306a36Sopenharmony_ci } 401762306a36Sopenharmony_ci 401862306a36Sopenharmony_ci return 0; 401962306a36Sopenharmony_ci} 402062306a36Sopenharmony_ci 402162306a36Sopenharmony_ci/** 402262306a36Sopenharmony_ci * ixgbe_get_orom_version - Return option ROM from EEPROM 402362306a36Sopenharmony_ci * 402462306a36Sopenharmony_ci * @hw: pointer to hardware structure 402562306a36Sopenharmony_ci * @nvm_ver: pointer to output structure 402662306a36Sopenharmony_ci * 402762306a36Sopenharmony_ci * if valid option ROM version, nvm_ver->or_valid set to true 402862306a36Sopenharmony_ci * else nvm_ver->or_valid is false. 402962306a36Sopenharmony_ci **/ 403062306a36Sopenharmony_civoid ixgbe_get_orom_version(struct ixgbe_hw *hw, 403162306a36Sopenharmony_ci struct ixgbe_nvm_version *nvm_ver) 403262306a36Sopenharmony_ci{ 403362306a36Sopenharmony_ci u16 offset, eeprom_cfg_blkh, eeprom_cfg_blkl; 403462306a36Sopenharmony_ci 403562306a36Sopenharmony_ci nvm_ver->or_valid = false; 403662306a36Sopenharmony_ci /* Option Rom may or may not be present. Start with pointer */ 403762306a36Sopenharmony_ci hw->eeprom.ops.read(hw, NVM_OROM_OFFSET, &offset); 403862306a36Sopenharmony_ci 403962306a36Sopenharmony_ci /* make sure offset is valid */ 404062306a36Sopenharmony_ci if (offset == 0x0 || offset == NVM_INVALID_PTR) 404162306a36Sopenharmony_ci return; 404262306a36Sopenharmony_ci 404362306a36Sopenharmony_ci hw->eeprom.ops.read(hw, offset + NVM_OROM_BLK_HI, &eeprom_cfg_blkh); 404462306a36Sopenharmony_ci hw->eeprom.ops.read(hw, offset + NVM_OROM_BLK_LOW, &eeprom_cfg_blkl); 404562306a36Sopenharmony_ci 404662306a36Sopenharmony_ci /* option rom exists and is valid */ 404762306a36Sopenharmony_ci if ((eeprom_cfg_blkl | eeprom_cfg_blkh) == 0x0 || 404862306a36Sopenharmony_ci eeprom_cfg_blkl == NVM_VER_INVALID || 404962306a36Sopenharmony_ci eeprom_cfg_blkh == NVM_VER_INVALID) 405062306a36Sopenharmony_ci return; 405162306a36Sopenharmony_ci 405262306a36Sopenharmony_ci nvm_ver->or_valid = true; 405362306a36Sopenharmony_ci nvm_ver->or_major = eeprom_cfg_blkl >> NVM_OROM_SHIFT; 405462306a36Sopenharmony_ci nvm_ver->or_build = (eeprom_cfg_blkl << NVM_OROM_SHIFT) | 405562306a36Sopenharmony_ci (eeprom_cfg_blkh >> NVM_OROM_SHIFT); 405662306a36Sopenharmony_ci nvm_ver->or_patch = eeprom_cfg_blkh & NVM_OROM_PATCH_MASK; 405762306a36Sopenharmony_ci} 405862306a36Sopenharmony_ci 405962306a36Sopenharmony_ci/** 406062306a36Sopenharmony_ci * ixgbe_get_oem_prod_version - Etrack ID from EEPROM 406162306a36Sopenharmony_ci * @hw: pointer to hardware structure 406262306a36Sopenharmony_ci * @nvm_ver: pointer to output structure 406362306a36Sopenharmony_ci * 406462306a36Sopenharmony_ci * if valid OEM product version, nvm_ver->oem_valid set to true 406562306a36Sopenharmony_ci * else nvm_ver->oem_valid is false. 406662306a36Sopenharmony_ci **/ 406762306a36Sopenharmony_civoid ixgbe_get_oem_prod_version(struct ixgbe_hw *hw, 406862306a36Sopenharmony_ci struct ixgbe_nvm_version *nvm_ver) 406962306a36Sopenharmony_ci{ 407062306a36Sopenharmony_ci u16 rel_num, prod_ver, mod_len, cap, offset; 407162306a36Sopenharmony_ci 407262306a36Sopenharmony_ci nvm_ver->oem_valid = false; 407362306a36Sopenharmony_ci hw->eeprom.ops.read(hw, NVM_OEM_PROD_VER_PTR, &offset); 407462306a36Sopenharmony_ci 407562306a36Sopenharmony_ci /* Return is offset to OEM Product Version block is invalid */ 407662306a36Sopenharmony_ci if (offset == 0x0 || offset == NVM_INVALID_PTR) 407762306a36Sopenharmony_ci return; 407862306a36Sopenharmony_ci 407962306a36Sopenharmony_ci /* Read product version block */ 408062306a36Sopenharmony_ci hw->eeprom.ops.read(hw, offset, &mod_len); 408162306a36Sopenharmony_ci hw->eeprom.ops.read(hw, offset + NVM_OEM_PROD_VER_CAP_OFF, &cap); 408262306a36Sopenharmony_ci 408362306a36Sopenharmony_ci /* Return if OEM product version block is invalid */ 408462306a36Sopenharmony_ci if (mod_len != NVM_OEM_PROD_VER_MOD_LEN || 408562306a36Sopenharmony_ci (cap & NVM_OEM_PROD_VER_CAP_MASK) != 0x0) 408662306a36Sopenharmony_ci return; 408762306a36Sopenharmony_ci 408862306a36Sopenharmony_ci hw->eeprom.ops.read(hw, offset + NVM_OEM_PROD_VER_OFF_L, &prod_ver); 408962306a36Sopenharmony_ci hw->eeprom.ops.read(hw, offset + NVM_OEM_PROD_VER_OFF_H, &rel_num); 409062306a36Sopenharmony_ci 409162306a36Sopenharmony_ci /* Return if version is invalid */ 409262306a36Sopenharmony_ci if ((rel_num | prod_ver) == 0x0 || 409362306a36Sopenharmony_ci rel_num == NVM_VER_INVALID || prod_ver == NVM_VER_INVALID) 409462306a36Sopenharmony_ci return; 409562306a36Sopenharmony_ci 409662306a36Sopenharmony_ci nvm_ver->oem_major = prod_ver >> NVM_VER_SHIFT; 409762306a36Sopenharmony_ci nvm_ver->oem_minor = prod_ver & NVM_VER_MASK; 409862306a36Sopenharmony_ci nvm_ver->oem_release = rel_num; 409962306a36Sopenharmony_ci nvm_ver->oem_valid = true; 410062306a36Sopenharmony_ci} 410162306a36Sopenharmony_ci 410262306a36Sopenharmony_ci/** 410362306a36Sopenharmony_ci * ixgbe_get_etk_id - Return Etrack ID from EEPROM 410462306a36Sopenharmony_ci * 410562306a36Sopenharmony_ci * @hw: pointer to hardware structure 410662306a36Sopenharmony_ci * @nvm_ver: pointer to output structure 410762306a36Sopenharmony_ci * 410862306a36Sopenharmony_ci * word read errors will return 0xFFFF 410962306a36Sopenharmony_ci **/ 411062306a36Sopenharmony_civoid ixgbe_get_etk_id(struct ixgbe_hw *hw, 411162306a36Sopenharmony_ci struct ixgbe_nvm_version *nvm_ver) 411262306a36Sopenharmony_ci{ 411362306a36Sopenharmony_ci u16 etk_id_l, etk_id_h; 411462306a36Sopenharmony_ci 411562306a36Sopenharmony_ci if (hw->eeprom.ops.read(hw, NVM_ETK_OFF_LOW, &etk_id_l)) 411662306a36Sopenharmony_ci etk_id_l = NVM_VER_INVALID; 411762306a36Sopenharmony_ci if (hw->eeprom.ops.read(hw, NVM_ETK_OFF_HI, &etk_id_h)) 411862306a36Sopenharmony_ci etk_id_h = NVM_VER_INVALID; 411962306a36Sopenharmony_ci 412062306a36Sopenharmony_ci /* The word order for the version format is determined by high order 412162306a36Sopenharmony_ci * word bit 15. 412262306a36Sopenharmony_ci */ 412362306a36Sopenharmony_ci if ((etk_id_h & NVM_ETK_VALID) == 0) { 412462306a36Sopenharmony_ci nvm_ver->etk_id = etk_id_h; 412562306a36Sopenharmony_ci nvm_ver->etk_id |= (etk_id_l << NVM_ETK_SHIFT); 412662306a36Sopenharmony_ci } else { 412762306a36Sopenharmony_ci nvm_ver->etk_id = etk_id_l; 412862306a36Sopenharmony_ci nvm_ver->etk_id |= (etk_id_h << NVM_ETK_SHIFT); 412962306a36Sopenharmony_ci } 413062306a36Sopenharmony_ci} 413162306a36Sopenharmony_ci 413262306a36Sopenharmony_civoid ixgbe_disable_rx_generic(struct ixgbe_hw *hw) 413362306a36Sopenharmony_ci{ 413462306a36Sopenharmony_ci u32 rxctrl; 413562306a36Sopenharmony_ci 413662306a36Sopenharmony_ci rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL); 413762306a36Sopenharmony_ci if (rxctrl & IXGBE_RXCTRL_RXEN) { 413862306a36Sopenharmony_ci if (hw->mac.type != ixgbe_mac_82598EB) { 413962306a36Sopenharmony_ci u32 pfdtxgswc; 414062306a36Sopenharmony_ci 414162306a36Sopenharmony_ci pfdtxgswc = IXGBE_READ_REG(hw, IXGBE_PFDTXGSWC); 414262306a36Sopenharmony_ci if (pfdtxgswc & IXGBE_PFDTXGSWC_VT_LBEN) { 414362306a36Sopenharmony_ci pfdtxgswc &= ~IXGBE_PFDTXGSWC_VT_LBEN; 414462306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_PFDTXGSWC, pfdtxgswc); 414562306a36Sopenharmony_ci hw->mac.set_lben = true; 414662306a36Sopenharmony_ci } else { 414762306a36Sopenharmony_ci hw->mac.set_lben = false; 414862306a36Sopenharmony_ci } 414962306a36Sopenharmony_ci } 415062306a36Sopenharmony_ci rxctrl &= ~IXGBE_RXCTRL_RXEN; 415162306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, rxctrl); 415262306a36Sopenharmony_ci } 415362306a36Sopenharmony_ci} 415462306a36Sopenharmony_ci 415562306a36Sopenharmony_civoid ixgbe_enable_rx_generic(struct ixgbe_hw *hw) 415662306a36Sopenharmony_ci{ 415762306a36Sopenharmony_ci u32 rxctrl; 415862306a36Sopenharmony_ci 415962306a36Sopenharmony_ci rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL); 416062306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, (rxctrl | IXGBE_RXCTRL_RXEN)); 416162306a36Sopenharmony_ci 416262306a36Sopenharmony_ci if (hw->mac.type != ixgbe_mac_82598EB) { 416362306a36Sopenharmony_ci if (hw->mac.set_lben) { 416462306a36Sopenharmony_ci u32 pfdtxgswc; 416562306a36Sopenharmony_ci 416662306a36Sopenharmony_ci pfdtxgswc = IXGBE_READ_REG(hw, IXGBE_PFDTXGSWC); 416762306a36Sopenharmony_ci pfdtxgswc |= IXGBE_PFDTXGSWC_VT_LBEN; 416862306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_PFDTXGSWC, pfdtxgswc); 416962306a36Sopenharmony_ci hw->mac.set_lben = false; 417062306a36Sopenharmony_ci } 417162306a36Sopenharmony_ci } 417262306a36Sopenharmony_ci} 417362306a36Sopenharmony_ci 417462306a36Sopenharmony_ci/** ixgbe_mng_present - returns true when management capability is present 417562306a36Sopenharmony_ci * @hw: pointer to hardware structure 417662306a36Sopenharmony_ci **/ 417762306a36Sopenharmony_cibool ixgbe_mng_present(struct ixgbe_hw *hw) 417862306a36Sopenharmony_ci{ 417962306a36Sopenharmony_ci u32 fwsm; 418062306a36Sopenharmony_ci 418162306a36Sopenharmony_ci if (hw->mac.type < ixgbe_mac_82599EB) 418262306a36Sopenharmony_ci return false; 418362306a36Sopenharmony_ci 418462306a36Sopenharmony_ci fwsm = IXGBE_READ_REG(hw, IXGBE_FWSM(hw)); 418562306a36Sopenharmony_ci 418662306a36Sopenharmony_ci return !!(fwsm & IXGBE_FWSM_FW_MODE_PT); 418762306a36Sopenharmony_ci} 418862306a36Sopenharmony_ci 418962306a36Sopenharmony_ci/** 419062306a36Sopenharmony_ci * ixgbe_setup_mac_link_multispeed_fiber - Set MAC link speed 419162306a36Sopenharmony_ci * @hw: pointer to hardware structure 419262306a36Sopenharmony_ci * @speed: new link speed 419362306a36Sopenharmony_ci * @autoneg_wait_to_complete: true when waiting for completion is needed 419462306a36Sopenharmony_ci * 419562306a36Sopenharmony_ci * Set the link speed in the MAC and/or PHY register and restarts link. 419662306a36Sopenharmony_ci */ 419762306a36Sopenharmony_cis32 ixgbe_setup_mac_link_multispeed_fiber(struct ixgbe_hw *hw, 419862306a36Sopenharmony_ci ixgbe_link_speed speed, 419962306a36Sopenharmony_ci bool autoneg_wait_to_complete) 420062306a36Sopenharmony_ci{ 420162306a36Sopenharmony_ci ixgbe_link_speed link_speed = IXGBE_LINK_SPEED_UNKNOWN; 420262306a36Sopenharmony_ci ixgbe_link_speed highest_link_speed = IXGBE_LINK_SPEED_UNKNOWN; 420362306a36Sopenharmony_ci s32 status = 0; 420462306a36Sopenharmony_ci u32 speedcnt = 0; 420562306a36Sopenharmony_ci u32 i = 0; 420662306a36Sopenharmony_ci bool autoneg, link_up = false; 420762306a36Sopenharmony_ci 420862306a36Sopenharmony_ci /* Mask off requested but non-supported speeds */ 420962306a36Sopenharmony_ci status = hw->mac.ops.get_link_capabilities(hw, &link_speed, &autoneg); 421062306a36Sopenharmony_ci if (status) 421162306a36Sopenharmony_ci return status; 421262306a36Sopenharmony_ci 421362306a36Sopenharmony_ci speed &= link_speed; 421462306a36Sopenharmony_ci 421562306a36Sopenharmony_ci /* Try each speed one by one, highest priority first. We do this in 421662306a36Sopenharmony_ci * software because 10Gb fiber doesn't support speed autonegotiation. 421762306a36Sopenharmony_ci */ 421862306a36Sopenharmony_ci if (speed & IXGBE_LINK_SPEED_10GB_FULL) { 421962306a36Sopenharmony_ci speedcnt++; 422062306a36Sopenharmony_ci highest_link_speed = IXGBE_LINK_SPEED_10GB_FULL; 422162306a36Sopenharmony_ci 422262306a36Sopenharmony_ci /* Set the module link speed */ 422362306a36Sopenharmony_ci switch (hw->phy.media_type) { 422462306a36Sopenharmony_ci case ixgbe_media_type_fiber: 422562306a36Sopenharmony_ci hw->mac.ops.set_rate_select_speed(hw, 422662306a36Sopenharmony_ci IXGBE_LINK_SPEED_10GB_FULL); 422762306a36Sopenharmony_ci break; 422862306a36Sopenharmony_ci case ixgbe_media_type_fiber_qsfp: 422962306a36Sopenharmony_ci /* QSFP module automatically detects MAC link speed */ 423062306a36Sopenharmony_ci break; 423162306a36Sopenharmony_ci default: 423262306a36Sopenharmony_ci hw_dbg(hw, "Unexpected media type\n"); 423362306a36Sopenharmony_ci break; 423462306a36Sopenharmony_ci } 423562306a36Sopenharmony_ci 423662306a36Sopenharmony_ci /* Allow module to change analog characteristics (1G->10G) */ 423762306a36Sopenharmony_ci msleep(40); 423862306a36Sopenharmony_ci 423962306a36Sopenharmony_ci status = hw->mac.ops.setup_mac_link(hw, 424062306a36Sopenharmony_ci IXGBE_LINK_SPEED_10GB_FULL, 424162306a36Sopenharmony_ci autoneg_wait_to_complete); 424262306a36Sopenharmony_ci if (status) 424362306a36Sopenharmony_ci return status; 424462306a36Sopenharmony_ci 424562306a36Sopenharmony_ci /* Flap the Tx laser if it has not already been done */ 424662306a36Sopenharmony_ci if (hw->mac.ops.flap_tx_laser) 424762306a36Sopenharmony_ci hw->mac.ops.flap_tx_laser(hw); 424862306a36Sopenharmony_ci 424962306a36Sopenharmony_ci /* Wait for the controller to acquire link. Per IEEE 802.3ap, 425062306a36Sopenharmony_ci * Section 73.10.2, we may have to wait up to 500ms if KR is 425162306a36Sopenharmony_ci * attempted. 82599 uses the same timing for 10g SFI. 425262306a36Sopenharmony_ci */ 425362306a36Sopenharmony_ci for (i = 0; i < 5; i++) { 425462306a36Sopenharmony_ci /* Wait for the link partner to also set speed */ 425562306a36Sopenharmony_ci msleep(100); 425662306a36Sopenharmony_ci 425762306a36Sopenharmony_ci /* If we have link, just jump out */ 425862306a36Sopenharmony_ci status = hw->mac.ops.check_link(hw, &link_speed, 425962306a36Sopenharmony_ci &link_up, false); 426062306a36Sopenharmony_ci if (status) 426162306a36Sopenharmony_ci return status; 426262306a36Sopenharmony_ci 426362306a36Sopenharmony_ci if (link_up) 426462306a36Sopenharmony_ci goto out; 426562306a36Sopenharmony_ci } 426662306a36Sopenharmony_ci } 426762306a36Sopenharmony_ci 426862306a36Sopenharmony_ci if (speed & IXGBE_LINK_SPEED_1GB_FULL) { 426962306a36Sopenharmony_ci speedcnt++; 427062306a36Sopenharmony_ci if (highest_link_speed == IXGBE_LINK_SPEED_UNKNOWN) 427162306a36Sopenharmony_ci highest_link_speed = IXGBE_LINK_SPEED_1GB_FULL; 427262306a36Sopenharmony_ci 427362306a36Sopenharmony_ci /* Set the module link speed */ 427462306a36Sopenharmony_ci switch (hw->phy.media_type) { 427562306a36Sopenharmony_ci case ixgbe_media_type_fiber: 427662306a36Sopenharmony_ci hw->mac.ops.set_rate_select_speed(hw, 427762306a36Sopenharmony_ci IXGBE_LINK_SPEED_1GB_FULL); 427862306a36Sopenharmony_ci break; 427962306a36Sopenharmony_ci case ixgbe_media_type_fiber_qsfp: 428062306a36Sopenharmony_ci /* QSFP module automatically detects link speed */ 428162306a36Sopenharmony_ci break; 428262306a36Sopenharmony_ci default: 428362306a36Sopenharmony_ci hw_dbg(hw, "Unexpected media type\n"); 428462306a36Sopenharmony_ci break; 428562306a36Sopenharmony_ci } 428662306a36Sopenharmony_ci 428762306a36Sopenharmony_ci /* Allow module to change analog characteristics (10G->1G) */ 428862306a36Sopenharmony_ci msleep(40); 428962306a36Sopenharmony_ci 429062306a36Sopenharmony_ci status = hw->mac.ops.setup_mac_link(hw, 429162306a36Sopenharmony_ci IXGBE_LINK_SPEED_1GB_FULL, 429262306a36Sopenharmony_ci autoneg_wait_to_complete); 429362306a36Sopenharmony_ci if (status) 429462306a36Sopenharmony_ci return status; 429562306a36Sopenharmony_ci 429662306a36Sopenharmony_ci /* Flap the Tx laser if it has not already been done */ 429762306a36Sopenharmony_ci if (hw->mac.ops.flap_tx_laser) 429862306a36Sopenharmony_ci hw->mac.ops.flap_tx_laser(hw); 429962306a36Sopenharmony_ci 430062306a36Sopenharmony_ci /* Wait for the link partner to also set speed */ 430162306a36Sopenharmony_ci msleep(100); 430262306a36Sopenharmony_ci 430362306a36Sopenharmony_ci /* If we have link, just jump out */ 430462306a36Sopenharmony_ci status = hw->mac.ops.check_link(hw, &link_speed, &link_up, 430562306a36Sopenharmony_ci false); 430662306a36Sopenharmony_ci if (status) 430762306a36Sopenharmony_ci return status; 430862306a36Sopenharmony_ci 430962306a36Sopenharmony_ci if (link_up) 431062306a36Sopenharmony_ci goto out; 431162306a36Sopenharmony_ci } 431262306a36Sopenharmony_ci 431362306a36Sopenharmony_ci /* We didn't get link. Configure back to the highest speed we tried, 431462306a36Sopenharmony_ci * (if there was more than one). We call ourselves back with just the 431562306a36Sopenharmony_ci * single highest speed that the user requested. 431662306a36Sopenharmony_ci */ 431762306a36Sopenharmony_ci if (speedcnt > 1) 431862306a36Sopenharmony_ci status = ixgbe_setup_mac_link_multispeed_fiber(hw, 431962306a36Sopenharmony_ci highest_link_speed, 432062306a36Sopenharmony_ci autoneg_wait_to_complete); 432162306a36Sopenharmony_ci 432262306a36Sopenharmony_ciout: 432362306a36Sopenharmony_ci /* Set autoneg_advertised value based on input link speed */ 432462306a36Sopenharmony_ci hw->phy.autoneg_advertised = 0; 432562306a36Sopenharmony_ci 432662306a36Sopenharmony_ci if (speed & IXGBE_LINK_SPEED_10GB_FULL) 432762306a36Sopenharmony_ci hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_10GB_FULL; 432862306a36Sopenharmony_ci 432962306a36Sopenharmony_ci if (speed & IXGBE_LINK_SPEED_1GB_FULL) 433062306a36Sopenharmony_ci hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_1GB_FULL; 433162306a36Sopenharmony_ci 433262306a36Sopenharmony_ci return status; 433362306a36Sopenharmony_ci} 433462306a36Sopenharmony_ci 433562306a36Sopenharmony_ci/** 433662306a36Sopenharmony_ci * ixgbe_set_soft_rate_select_speed - Set module link speed 433762306a36Sopenharmony_ci * @hw: pointer to hardware structure 433862306a36Sopenharmony_ci * @speed: link speed to set 433962306a36Sopenharmony_ci * 434062306a36Sopenharmony_ci * Set module link speed via the soft rate select. 434162306a36Sopenharmony_ci */ 434262306a36Sopenharmony_civoid ixgbe_set_soft_rate_select_speed(struct ixgbe_hw *hw, 434362306a36Sopenharmony_ci ixgbe_link_speed speed) 434462306a36Sopenharmony_ci{ 434562306a36Sopenharmony_ci s32 status; 434662306a36Sopenharmony_ci u8 rs, eeprom_data; 434762306a36Sopenharmony_ci 434862306a36Sopenharmony_ci switch (speed) { 434962306a36Sopenharmony_ci case IXGBE_LINK_SPEED_10GB_FULL: 435062306a36Sopenharmony_ci /* one bit mask same as setting on */ 435162306a36Sopenharmony_ci rs = IXGBE_SFF_SOFT_RS_SELECT_10G; 435262306a36Sopenharmony_ci break; 435362306a36Sopenharmony_ci case IXGBE_LINK_SPEED_1GB_FULL: 435462306a36Sopenharmony_ci rs = IXGBE_SFF_SOFT_RS_SELECT_1G; 435562306a36Sopenharmony_ci break; 435662306a36Sopenharmony_ci default: 435762306a36Sopenharmony_ci hw_dbg(hw, "Invalid fixed module speed\n"); 435862306a36Sopenharmony_ci return; 435962306a36Sopenharmony_ci } 436062306a36Sopenharmony_ci 436162306a36Sopenharmony_ci /* Set RS0 */ 436262306a36Sopenharmony_ci status = hw->phy.ops.read_i2c_byte(hw, IXGBE_SFF_SFF_8472_OSCB, 436362306a36Sopenharmony_ci IXGBE_I2C_EEPROM_DEV_ADDR2, 436462306a36Sopenharmony_ci &eeprom_data); 436562306a36Sopenharmony_ci if (status) { 436662306a36Sopenharmony_ci hw_dbg(hw, "Failed to read Rx Rate Select RS0\n"); 436762306a36Sopenharmony_ci return; 436862306a36Sopenharmony_ci } 436962306a36Sopenharmony_ci 437062306a36Sopenharmony_ci eeprom_data = (eeprom_data & ~IXGBE_SFF_SOFT_RS_SELECT_MASK) | rs; 437162306a36Sopenharmony_ci 437262306a36Sopenharmony_ci status = hw->phy.ops.write_i2c_byte(hw, IXGBE_SFF_SFF_8472_OSCB, 437362306a36Sopenharmony_ci IXGBE_I2C_EEPROM_DEV_ADDR2, 437462306a36Sopenharmony_ci eeprom_data); 437562306a36Sopenharmony_ci if (status) { 437662306a36Sopenharmony_ci hw_dbg(hw, "Failed to write Rx Rate Select RS0\n"); 437762306a36Sopenharmony_ci return; 437862306a36Sopenharmony_ci } 437962306a36Sopenharmony_ci 438062306a36Sopenharmony_ci /* Set RS1 */ 438162306a36Sopenharmony_ci status = hw->phy.ops.read_i2c_byte(hw, IXGBE_SFF_SFF_8472_ESCB, 438262306a36Sopenharmony_ci IXGBE_I2C_EEPROM_DEV_ADDR2, 438362306a36Sopenharmony_ci &eeprom_data); 438462306a36Sopenharmony_ci if (status) { 438562306a36Sopenharmony_ci hw_dbg(hw, "Failed to read Rx Rate Select RS1\n"); 438662306a36Sopenharmony_ci return; 438762306a36Sopenharmony_ci } 438862306a36Sopenharmony_ci 438962306a36Sopenharmony_ci eeprom_data = (eeprom_data & ~IXGBE_SFF_SOFT_RS_SELECT_MASK) | rs; 439062306a36Sopenharmony_ci 439162306a36Sopenharmony_ci status = hw->phy.ops.write_i2c_byte(hw, IXGBE_SFF_SFF_8472_ESCB, 439262306a36Sopenharmony_ci IXGBE_I2C_EEPROM_DEV_ADDR2, 439362306a36Sopenharmony_ci eeprom_data); 439462306a36Sopenharmony_ci if (status) { 439562306a36Sopenharmony_ci hw_dbg(hw, "Failed to write Rx Rate Select RS1\n"); 439662306a36Sopenharmony_ci return; 439762306a36Sopenharmony_ci } 439862306a36Sopenharmony_ci} 4399