18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* Copyright(c) 1999 - 2018 Intel Corporation. */ 38c2ecf20Sopenharmony_ci 48c2ecf20Sopenharmony_ci#include <linux/pci.h> 58c2ecf20Sopenharmony_ci#include <linux/delay.h> 68c2ecf20Sopenharmony_ci#include <linux/sched.h> 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#include "ixgbe.h" 98c2ecf20Sopenharmony_ci#include "ixgbe_phy.h" 108c2ecf20Sopenharmony_ci#include "ixgbe_mbx.h" 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci#define IXGBE_82599_MAX_TX_QUEUES 128 138c2ecf20Sopenharmony_ci#define IXGBE_82599_MAX_RX_QUEUES 128 148c2ecf20Sopenharmony_ci#define IXGBE_82599_RAR_ENTRIES 128 158c2ecf20Sopenharmony_ci#define IXGBE_82599_MC_TBL_SIZE 128 168c2ecf20Sopenharmony_ci#define IXGBE_82599_VFT_TBL_SIZE 128 178c2ecf20Sopenharmony_ci#define IXGBE_82599_RX_PB_SIZE 512 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_cistatic void ixgbe_disable_tx_laser_multispeed_fiber(struct ixgbe_hw *hw); 208c2ecf20Sopenharmony_cistatic void ixgbe_enable_tx_laser_multispeed_fiber(struct ixgbe_hw *hw); 218c2ecf20Sopenharmony_cistatic void ixgbe_flap_tx_laser_multispeed_fiber(struct ixgbe_hw *hw); 228c2ecf20Sopenharmony_cistatic void 238c2ecf20Sopenharmony_ciixgbe_set_hard_rate_select_speed(struct ixgbe_hw *, ixgbe_link_speed); 248c2ecf20Sopenharmony_cistatic s32 ixgbe_setup_mac_link_smartspeed(struct ixgbe_hw *hw, 258c2ecf20Sopenharmony_ci ixgbe_link_speed speed, 268c2ecf20Sopenharmony_ci bool autoneg_wait_to_complete); 278c2ecf20Sopenharmony_cistatic void ixgbe_stop_mac_link_on_d3_82599(struct ixgbe_hw *hw); 288c2ecf20Sopenharmony_cistatic s32 ixgbe_start_mac_link_82599(struct ixgbe_hw *hw, 298c2ecf20Sopenharmony_ci bool autoneg_wait_to_complete); 308c2ecf20Sopenharmony_cistatic s32 ixgbe_setup_mac_link_82599(struct ixgbe_hw *hw, 318c2ecf20Sopenharmony_ci ixgbe_link_speed speed, 328c2ecf20Sopenharmony_ci bool autoneg_wait_to_complete); 338c2ecf20Sopenharmony_cistatic s32 ixgbe_setup_copper_link_82599(struct ixgbe_hw *hw, 348c2ecf20Sopenharmony_ci ixgbe_link_speed speed, 358c2ecf20Sopenharmony_ci bool autoneg_wait_to_complete); 368c2ecf20Sopenharmony_cistatic s32 ixgbe_verify_fw_version_82599(struct ixgbe_hw *hw); 378c2ecf20Sopenharmony_cistatic s32 ixgbe_read_i2c_byte_82599(struct ixgbe_hw *hw, u8 byte_offset, 388c2ecf20Sopenharmony_ci u8 dev_addr, u8 *data); 398c2ecf20Sopenharmony_cistatic s32 ixgbe_write_i2c_byte_82599(struct ixgbe_hw *hw, u8 byte_offset, 408c2ecf20Sopenharmony_ci u8 dev_addr, u8 data); 418c2ecf20Sopenharmony_cistatic s32 ixgbe_reset_pipeline_82599(struct ixgbe_hw *hw); 428c2ecf20Sopenharmony_cistatic bool ixgbe_verify_lesm_fw_enabled_82599(struct ixgbe_hw *hw); 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_cibool ixgbe_mng_enabled(struct ixgbe_hw *hw) 458c2ecf20Sopenharmony_ci{ 468c2ecf20Sopenharmony_ci u32 fwsm, manc, factps; 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ci fwsm = IXGBE_READ_REG(hw, IXGBE_FWSM(hw)); 498c2ecf20Sopenharmony_ci if ((fwsm & IXGBE_FWSM_MODE_MASK) != IXGBE_FWSM_FW_MODE_PT) 508c2ecf20Sopenharmony_ci return false; 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci manc = IXGBE_READ_REG(hw, IXGBE_MANC); 538c2ecf20Sopenharmony_ci if (!(manc & IXGBE_MANC_RCV_TCO_EN)) 548c2ecf20Sopenharmony_ci return false; 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ci factps = IXGBE_READ_REG(hw, IXGBE_FACTPS(hw)); 578c2ecf20Sopenharmony_ci if (factps & IXGBE_FACTPS_MNGCG) 588c2ecf20Sopenharmony_ci return false; 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_ci return true; 618c2ecf20Sopenharmony_ci} 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_cistatic void ixgbe_init_mac_link_ops_82599(struct ixgbe_hw *hw) 648c2ecf20Sopenharmony_ci{ 658c2ecf20Sopenharmony_ci struct ixgbe_mac_info *mac = &hw->mac; 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_ci /* enable the laser control functions for SFP+ fiber 688c2ecf20Sopenharmony_ci * and MNG not enabled 698c2ecf20Sopenharmony_ci */ 708c2ecf20Sopenharmony_ci if ((mac->ops.get_media_type(hw) == ixgbe_media_type_fiber) && 718c2ecf20Sopenharmony_ci !ixgbe_mng_enabled(hw)) { 728c2ecf20Sopenharmony_ci mac->ops.disable_tx_laser = 738c2ecf20Sopenharmony_ci &ixgbe_disable_tx_laser_multispeed_fiber; 748c2ecf20Sopenharmony_ci mac->ops.enable_tx_laser = 758c2ecf20Sopenharmony_ci &ixgbe_enable_tx_laser_multispeed_fiber; 768c2ecf20Sopenharmony_ci mac->ops.flap_tx_laser = &ixgbe_flap_tx_laser_multispeed_fiber; 778c2ecf20Sopenharmony_ci } else { 788c2ecf20Sopenharmony_ci mac->ops.disable_tx_laser = NULL; 798c2ecf20Sopenharmony_ci mac->ops.enable_tx_laser = NULL; 808c2ecf20Sopenharmony_ci mac->ops.flap_tx_laser = NULL; 818c2ecf20Sopenharmony_ci } 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci if (hw->phy.multispeed_fiber) { 848c2ecf20Sopenharmony_ci /* Set up dual speed SFP+ support */ 858c2ecf20Sopenharmony_ci mac->ops.setup_link = &ixgbe_setup_mac_link_multispeed_fiber; 868c2ecf20Sopenharmony_ci mac->ops.setup_mac_link = ixgbe_setup_mac_link_82599; 878c2ecf20Sopenharmony_ci mac->ops.set_rate_select_speed = 888c2ecf20Sopenharmony_ci ixgbe_set_hard_rate_select_speed; 898c2ecf20Sopenharmony_ci } else { 908c2ecf20Sopenharmony_ci if ((mac->ops.get_media_type(hw) == 918c2ecf20Sopenharmony_ci ixgbe_media_type_backplane) && 928c2ecf20Sopenharmony_ci (hw->phy.smart_speed == ixgbe_smart_speed_auto || 938c2ecf20Sopenharmony_ci hw->phy.smart_speed == ixgbe_smart_speed_on) && 948c2ecf20Sopenharmony_ci !ixgbe_verify_lesm_fw_enabled_82599(hw)) 958c2ecf20Sopenharmony_ci mac->ops.setup_link = &ixgbe_setup_mac_link_smartspeed; 968c2ecf20Sopenharmony_ci else 978c2ecf20Sopenharmony_ci mac->ops.setup_link = &ixgbe_setup_mac_link_82599; 988c2ecf20Sopenharmony_ci } 998c2ecf20Sopenharmony_ci} 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_cistatic s32 ixgbe_setup_sfp_modules_82599(struct ixgbe_hw *hw) 1028c2ecf20Sopenharmony_ci{ 1038c2ecf20Sopenharmony_ci s32 ret_val; 1048c2ecf20Sopenharmony_ci u16 list_offset, data_offset, data_value; 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ci if (hw->phy.sfp_type != ixgbe_sfp_type_unknown) { 1078c2ecf20Sopenharmony_ci ixgbe_init_mac_link_ops_82599(hw); 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_ci hw->phy.ops.reset = NULL; 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_ci ret_val = ixgbe_get_sfp_init_sequence_offsets(hw, &list_offset, 1128c2ecf20Sopenharmony_ci &data_offset); 1138c2ecf20Sopenharmony_ci if (ret_val) 1148c2ecf20Sopenharmony_ci return ret_val; 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_ci /* PHY config will finish before releasing the semaphore */ 1178c2ecf20Sopenharmony_ci ret_val = hw->mac.ops.acquire_swfw_sync(hw, 1188c2ecf20Sopenharmony_ci IXGBE_GSSR_MAC_CSR_SM); 1198c2ecf20Sopenharmony_ci if (ret_val) 1208c2ecf20Sopenharmony_ci return -EBUSY; 1218c2ecf20Sopenharmony_ci 1228c2ecf20Sopenharmony_ci if (hw->eeprom.ops.read(hw, ++data_offset, &data_value)) 1238c2ecf20Sopenharmony_ci goto setup_sfp_err; 1248c2ecf20Sopenharmony_ci while (data_value != 0xffff) { 1258c2ecf20Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_CORECTL, data_value); 1268c2ecf20Sopenharmony_ci IXGBE_WRITE_FLUSH(hw); 1278c2ecf20Sopenharmony_ci if (hw->eeprom.ops.read(hw, ++data_offset, &data_value)) 1288c2ecf20Sopenharmony_ci goto setup_sfp_err; 1298c2ecf20Sopenharmony_ci } 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_ci /* Release the semaphore */ 1328c2ecf20Sopenharmony_ci hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_MAC_CSR_SM); 1338c2ecf20Sopenharmony_ci /* 1348c2ecf20Sopenharmony_ci * Delay obtaining semaphore again to allow FW access, 1358c2ecf20Sopenharmony_ci * semaphore_delay is in ms usleep_range needs us. 1368c2ecf20Sopenharmony_ci */ 1378c2ecf20Sopenharmony_ci usleep_range(hw->eeprom.semaphore_delay * 1000, 1388c2ecf20Sopenharmony_ci hw->eeprom.semaphore_delay * 2000); 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_ci /* Restart DSP and set SFI mode */ 1418c2ecf20Sopenharmony_ci ret_val = hw->mac.ops.prot_autoc_write(hw, 1428c2ecf20Sopenharmony_ci hw->mac.orig_autoc | IXGBE_AUTOC_LMS_10G_SERIAL, 1438c2ecf20Sopenharmony_ci false); 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_ci if (ret_val) { 1468c2ecf20Sopenharmony_ci hw_dbg(hw, " sfp module setup not complete\n"); 1478c2ecf20Sopenharmony_ci return -EIO; 1488c2ecf20Sopenharmony_ci } 1498c2ecf20Sopenharmony_ci } 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_ci return 0; 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_cisetup_sfp_err: 1548c2ecf20Sopenharmony_ci /* Release the semaphore */ 1558c2ecf20Sopenharmony_ci hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_MAC_CSR_SM); 1568c2ecf20Sopenharmony_ci /* Delay obtaining semaphore again to allow FW access, 1578c2ecf20Sopenharmony_ci * semaphore_delay is in ms usleep_range needs us. 1588c2ecf20Sopenharmony_ci */ 1598c2ecf20Sopenharmony_ci usleep_range(hw->eeprom.semaphore_delay * 1000, 1608c2ecf20Sopenharmony_ci hw->eeprom.semaphore_delay * 2000); 1618c2ecf20Sopenharmony_ci hw_err(hw, "eeprom read at offset %d failed\n", data_offset); 1628c2ecf20Sopenharmony_ci return -EIO; 1638c2ecf20Sopenharmony_ci} 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_ci/** 1668c2ecf20Sopenharmony_ci * prot_autoc_read_82599 - Hides MAC differences needed for AUTOC read 1678c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 1688c2ecf20Sopenharmony_ci * @locked: Return the if we locked for this read. 1698c2ecf20Sopenharmony_ci * @reg_val: Value we read from AUTOC 1708c2ecf20Sopenharmony_ci * 1718c2ecf20Sopenharmony_ci * For this part (82599) we need to wrap read-modify-writes with a possible 1728c2ecf20Sopenharmony_ci * FW/SW lock. It is assumed this lock will be freed with the next 1738c2ecf20Sopenharmony_ci * prot_autoc_write_82599(). Note, that locked can only be true in cases 1748c2ecf20Sopenharmony_ci * where this function doesn't return an error. 1758c2ecf20Sopenharmony_ci **/ 1768c2ecf20Sopenharmony_cistatic s32 prot_autoc_read_82599(struct ixgbe_hw *hw, bool *locked, 1778c2ecf20Sopenharmony_ci u32 *reg_val) 1788c2ecf20Sopenharmony_ci{ 1798c2ecf20Sopenharmony_ci s32 ret_val; 1808c2ecf20Sopenharmony_ci 1818c2ecf20Sopenharmony_ci *locked = false; 1828c2ecf20Sopenharmony_ci /* If LESM is on then we need to hold the SW/FW semaphore. */ 1838c2ecf20Sopenharmony_ci if (ixgbe_verify_lesm_fw_enabled_82599(hw)) { 1848c2ecf20Sopenharmony_ci ret_val = hw->mac.ops.acquire_swfw_sync(hw, 1858c2ecf20Sopenharmony_ci IXGBE_GSSR_MAC_CSR_SM); 1868c2ecf20Sopenharmony_ci if (ret_val) 1878c2ecf20Sopenharmony_ci return -EBUSY; 1888c2ecf20Sopenharmony_ci 1898c2ecf20Sopenharmony_ci *locked = true; 1908c2ecf20Sopenharmony_ci } 1918c2ecf20Sopenharmony_ci 1928c2ecf20Sopenharmony_ci *reg_val = IXGBE_READ_REG(hw, IXGBE_AUTOC); 1938c2ecf20Sopenharmony_ci return 0; 1948c2ecf20Sopenharmony_ci} 1958c2ecf20Sopenharmony_ci 1968c2ecf20Sopenharmony_ci/** 1978c2ecf20Sopenharmony_ci * prot_autoc_write_82599 - Hides MAC differences needed for AUTOC write 1988c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 1998c2ecf20Sopenharmony_ci * @autoc: value to write to AUTOC 2008c2ecf20Sopenharmony_ci * @locked: bool to indicate whether the SW/FW lock was already taken by 2018c2ecf20Sopenharmony_ci * previous proc_autoc_read_82599. 2028c2ecf20Sopenharmony_ci * 2038c2ecf20Sopenharmony_ci * This part (82599) may need to hold a the SW/FW lock around all writes to 2048c2ecf20Sopenharmony_ci * AUTOC. Likewise after a write we need to do a pipeline reset. 2058c2ecf20Sopenharmony_ci **/ 2068c2ecf20Sopenharmony_cistatic s32 prot_autoc_write_82599(struct ixgbe_hw *hw, u32 autoc, bool locked) 2078c2ecf20Sopenharmony_ci{ 2088c2ecf20Sopenharmony_ci s32 ret_val = 0; 2098c2ecf20Sopenharmony_ci 2108c2ecf20Sopenharmony_ci /* Blocked by MNG FW so bail */ 2118c2ecf20Sopenharmony_ci if (ixgbe_check_reset_blocked(hw)) 2128c2ecf20Sopenharmony_ci goto out; 2138c2ecf20Sopenharmony_ci 2148c2ecf20Sopenharmony_ci /* We only need to get the lock if: 2158c2ecf20Sopenharmony_ci * - We didn't do it already (in the read part of a read-modify-write) 2168c2ecf20Sopenharmony_ci * - LESM is enabled. 2178c2ecf20Sopenharmony_ci */ 2188c2ecf20Sopenharmony_ci if (!locked && ixgbe_verify_lesm_fw_enabled_82599(hw)) { 2198c2ecf20Sopenharmony_ci ret_val = hw->mac.ops.acquire_swfw_sync(hw, 2208c2ecf20Sopenharmony_ci IXGBE_GSSR_MAC_CSR_SM); 2218c2ecf20Sopenharmony_ci if (ret_val) 2228c2ecf20Sopenharmony_ci return -EBUSY; 2238c2ecf20Sopenharmony_ci 2248c2ecf20Sopenharmony_ci locked = true; 2258c2ecf20Sopenharmony_ci } 2268c2ecf20Sopenharmony_ci 2278c2ecf20Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc); 2288c2ecf20Sopenharmony_ci ret_val = ixgbe_reset_pipeline_82599(hw); 2298c2ecf20Sopenharmony_ci 2308c2ecf20Sopenharmony_ciout: 2318c2ecf20Sopenharmony_ci /* Free the SW/FW semaphore as we either grabbed it here or 2328c2ecf20Sopenharmony_ci * already had it when this function was called. 2338c2ecf20Sopenharmony_ci */ 2348c2ecf20Sopenharmony_ci if (locked) 2358c2ecf20Sopenharmony_ci hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_MAC_CSR_SM); 2368c2ecf20Sopenharmony_ci 2378c2ecf20Sopenharmony_ci return ret_val; 2388c2ecf20Sopenharmony_ci} 2398c2ecf20Sopenharmony_ci 2408c2ecf20Sopenharmony_cistatic s32 ixgbe_get_invariants_82599(struct ixgbe_hw *hw) 2418c2ecf20Sopenharmony_ci{ 2428c2ecf20Sopenharmony_ci struct ixgbe_mac_info *mac = &hw->mac; 2438c2ecf20Sopenharmony_ci 2448c2ecf20Sopenharmony_ci ixgbe_init_mac_link_ops_82599(hw); 2458c2ecf20Sopenharmony_ci 2468c2ecf20Sopenharmony_ci mac->mcft_size = IXGBE_82599_MC_TBL_SIZE; 2478c2ecf20Sopenharmony_ci mac->vft_size = IXGBE_82599_VFT_TBL_SIZE; 2488c2ecf20Sopenharmony_ci mac->num_rar_entries = IXGBE_82599_RAR_ENTRIES; 2498c2ecf20Sopenharmony_ci mac->rx_pb_size = IXGBE_82599_RX_PB_SIZE; 2508c2ecf20Sopenharmony_ci mac->max_rx_queues = IXGBE_82599_MAX_RX_QUEUES; 2518c2ecf20Sopenharmony_ci mac->max_tx_queues = IXGBE_82599_MAX_TX_QUEUES; 2528c2ecf20Sopenharmony_ci mac->max_msix_vectors = ixgbe_get_pcie_msix_count_generic(hw); 2538c2ecf20Sopenharmony_ci 2548c2ecf20Sopenharmony_ci return 0; 2558c2ecf20Sopenharmony_ci} 2568c2ecf20Sopenharmony_ci 2578c2ecf20Sopenharmony_ci/** 2588c2ecf20Sopenharmony_ci * ixgbe_init_phy_ops_82599 - PHY/SFP specific init 2598c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 2608c2ecf20Sopenharmony_ci * 2618c2ecf20Sopenharmony_ci * Initialize any function pointers that were not able to be 2628c2ecf20Sopenharmony_ci * set during get_invariants because the PHY/SFP type was 2638c2ecf20Sopenharmony_ci * not known. Perform the SFP init if necessary. 2648c2ecf20Sopenharmony_ci * 2658c2ecf20Sopenharmony_ci **/ 2668c2ecf20Sopenharmony_cistatic s32 ixgbe_init_phy_ops_82599(struct ixgbe_hw *hw) 2678c2ecf20Sopenharmony_ci{ 2688c2ecf20Sopenharmony_ci struct ixgbe_mac_info *mac = &hw->mac; 2698c2ecf20Sopenharmony_ci struct ixgbe_phy_info *phy = &hw->phy; 2708c2ecf20Sopenharmony_ci s32 ret_val; 2718c2ecf20Sopenharmony_ci u32 esdp; 2728c2ecf20Sopenharmony_ci 2738c2ecf20Sopenharmony_ci if (hw->device_id == IXGBE_DEV_ID_82599_QSFP_SF_QP) { 2748c2ecf20Sopenharmony_ci /* Store flag indicating I2C bus access control unit. */ 2758c2ecf20Sopenharmony_ci hw->phy.qsfp_shared_i2c_bus = true; 2768c2ecf20Sopenharmony_ci 2778c2ecf20Sopenharmony_ci /* Initialize access to QSFP+ I2C bus */ 2788c2ecf20Sopenharmony_ci esdp = IXGBE_READ_REG(hw, IXGBE_ESDP); 2798c2ecf20Sopenharmony_ci esdp |= IXGBE_ESDP_SDP0_DIR; 2808c2ecf20Sopenharmony_ci esdp &= ~IXGBE_ESDP_SDP1_DIR; 2818c2ecf20Sopenharmony_ci esdp &= ~IXGBE_ESDP_SDP0; 2828c2ecf20Sopenharmony_ci esdp &= ~IXGBE_ESDP_SDP0_NATIVE; 2838c2ecf20Sopenharmony_ci esdp &= ~IXGBE_ESDP_SDP1_NATIVE; 2848c2ecf20Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); 2858c2ecf20Sopenharmony_ci IXGBE_WRITE_FLUSH(hw); 2868c2ecf20Sopenharmony_ci 2878c2ecf20Sopenharmony_ci phy->ops.read_i2c_byte = &ixgbe_read_i2c_byte_82599; 2888c2ecf20Sopenharmony_ci phy->ops.write_i2c_byte = &ixgbe_write_i2c_byte_82599; 2898c2ecf20Sopenharmony_ci } 2908c2ecf20Sopenharmony_ci 2918c2ecf20Sopenharmony_ci /* Identify the PHY or SFP module */ 2928c2ecf20Sopenharmony_ci ret_val = phy->ops.identify(hw); 2938c2ecf20Sopenharmony_ci 2948c2ecf20Sopenharmony_ci /* Setup function pointers based on detected SFP module and speeds */ 2958c2ecf20Sopenharmony_ci ixgbe_init_mac_link_ops_82599(hw); 2968c2ecf20Sopenharmony_ci 2978c2ecf20Sopenharmony_ci /* If copper media, overwrite with copper function pointers */ 2988c2ecf20Sopenharmony_ci if (mac->ops.get_media_type(hw) == ixgbe_media_type_copper) { 2998c2ecf20Sopenharmony_ci mac->ops.setup_link = &ixgbe_setup_copper_link_82599; 3008c2ecf20Sopenharmony_ci mac->ops.get_link_capabilities = 3018c2ecf20Sopenharmony_ci &ixgbe_get_copper_link_capabilities_generic; 3028c2ecf20Sopenharmony_ci } 3038c2ecf20Sopenharmony_ci 3048c2ecf20Sopenharmony_ci /* Set necessary function pointers based on phy type */ 3058c2ecf20Sopenharmony_ci switch (hw->phy.type) { 3068c2ecf20Sopenharmony_ci case ixgbe_phy_tn: 3078c2ecf20Sopenharmony_ci phy->ops.check_link = &ixgbe_check_phy_link_tnx; 3088c2ecf20Sopenharmony_ci phy->ops.setup_link = &ixgbe_setup_phy_link_tnx; 3098c2ecf20Sopenharmony_ci break; 3108c2ecf20Sopenharmony_ci default: 3118c2ecf20Sopenharmony_ci break; 3128c2ecf20Sopenharmony_ci } 3138c2ecf20Sopenharmony_ci 3148c2ecf20Sopenharmony_ci return ret_val; 3158c2ecf20Sopenharmony_ci} 3168c2ecf20Sopenharmony_ci 3178c2ecf20Sopenharmony_ci/** 3188c2ecf20Sopenharmony_ci * ixgbe_get_link_capabilities_82599 - Determines link capabilities 3198c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 3208c2ecf20Sopenharmony_ci * @speed: pointer to link speed 3218c2ecf20Sopenharmony_ci * @autoneg: true when autoneg or autotry is enabled 3228c2ecf20Sopenharmony_ci * 3238c2ecf20Sopenharmony_ci * Determines the link capabilities by reading the AUTOC register. 3248c2ecf20Sopenharmony_ci **/ 3258c2ecf20Sopenharmony_cistatic s32 ixgbe_get_link_capabilities_82599(struct ixgbe_hw *hw, 3268c2ecf20Sopenharmony_ci ixgbe_link_speed *speed, 3278c2ecf20Sopenharmony_ci bool *autoneg) 3288c2ecf20Sopenharmony_ci{ 3298c2ecf20Sopenharmony_ci u32 autoc = 0; 3308c2ecf20Sopenharmony_ci 3318c2ecf20Sopenharmony_ci /* Determine 1G link capabilities off of SFP+ type */ 3328c2ecf20Sopenharmony_ci if (hw->phy.sfp_type == ixgbe_sfp_type_1g_cu_core0 || 3338c2ecf20Sopenharmony_ci hw->phy.sfp_type == ixgbe_sfp_type_1g_cu_core1 || 3348c2ecf20Sopenharmony_ci hw->phy.sfp_type == ixgbe_sfp_type_1g_lx_core0 || 3358c2ecf20Sopenharmony_ci hw->phy.sfp_type == ixgbe_sfp_type_1g_lx_core1 || 3368c2ecf20Sopenharmony_ci hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core0 || 3378c2ecf20Sopenharmony_ci hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core1) { 3388c2ecf20Sopenharmony_ci *speed = IXGBE_LINK_SPEED_1GB_FULL; 3398c2ecf20Sopenharmony_ci *autoneg = true; 3408c2ecf20Sopenharmony_ci return 0; 3418c2ecf20Sopenharmony_ci } 3428c2ecf20Sopenharmony_ci 3438c2ecf20Sopenharmony_ci /* 3448c2ecf20Sopenharmony_ci * Determine link capabilities based on the stored value of AUTOC, 3458c2ecf20Sopenharmony_ci * which represents EEPROM defaults. If AUTOC value has not been 3468c2ecf20Sopenharmony_ci * stored, use the current register value. 3478c2ecf20Sopenharmony_ci */ 3488c2ecf20Sopenharmony_ci if (hw->mac.orig_link_settings_stored) 3498c2ecf20Sopenharmony_ci autoc = hw->mac.orig_autoc; 3508c2ecf20Sopenharmony_ci else 3518c2ecf20Sopenharmony_ci autoc = IXGBE_READ_REG(hw, IXGBE_AUTOC); 3528c2ecf20Sopenharmony_ci 3538c2ecf20Sopenharmony_ci switch (autoc & IXGBE_AUTOC_LMS_MASK) { 3548c2ecf20Sopenharmony_ci case IXGBE_AUTOC_LMS_1G_LINK_NO_AN: 3558c2ecf20Sopenharmony_ci *speed = IXGBE_LINK_SPEED_1GB_FULL; 3568c2ecf20Sopenharmony_ci *autoneg = false; 3578c2ecf20Sopenharmony_ci break; 3588c2ecf20Sopenharmony_ci 3598c2ecf20Sopenharmony_ci case IXGBE_AUTOC_LMS_10G_LINK_NO_AN: 3608c2ecf20Sopenharmony_ci *speed = IXGBE_LINK_SPEED_10GB_FULL; 3618c2ecf20Sopenharmony_ci *autoneg = false; 3628c2ecf20Sopenharmony_ci break; 3638c2ecf20Sopenharmony_ci 3648c2ecf20Sopenharmony_ci case IXGBE_AUTOC_LMS_1G_AN: 3658c2ecf20Sopenharmony_ci *speed = IXGBE_LINK_SPEED_1GB_FULL; 3668c2ecf20Sopenharmony_ci *autoneg = true; 3678c2ecf20Sopenharmony_ci break; 3688c2ecf20Sopenharmony_ci 3698c2ecf20Sopenharmony_ci case IXGBE_AUTOC_LMS_10G_SERIAL: 3708c2ecf20Sopenharmony_ci *speed = IXGBE_LINK_SPEED_10GB_FULL; 3718c2ecf20Sopenharmony_ci *autoneg = false; 3728c2ecf20Sopenharmony_ci break; 3738c2ecf20Sopenharmony_ci 3748c2ecf20Sopenharmony_ci case IXGBE_AUTOC_LMS_KX4_KX_KR: 3758c2ecf20Sopenharmony_ci case IXGBE_AUTOC_LMS_KX4_KX_KR_1G_AN: 3768c2ecf20Sopenharmony_ci *speed = IXGBE_LINK_SPEED_UNKNOWN; 3778c2ecf20Sopenharmony_ci if (autoc & IXGBE_AUTOC_KR_SUPP) 3788c2ecf20Sopenharmony_ci *speed |= IXGBE_LINK_SPEED_10GB_FULL; 3798c2ecf20Sopenharmony_ci if (autoc & IXGBE_AUTOC_KX4_SUPP) 3808c2ecf20Sopenharmony_ci *speed |= IXGBE_LINK_SPEED_10GB_FULL; 3818c2ecf20Sopenharmony_ci if (autoc & IXGBE_AUTOC_KX_SUPP) 3828c2ecf20Sopenharmony_ci *speed |= IXGBE_LINK_SPEED_1GB_FULL; 3838c2ecf20Sopenharmony_ci *autoneg = true; 3848c2ecf20Sopenharmony_ci break; 3858c2ecf20Sopenharmony_ci 3868c2ecf20Sopenharmony_ci case IXGBE_AUTOC_LMS_KX4_KX_KR_SGMII: 3878c2ecf20Sopenharmony_ci *speed = IXGBE_LINK_SPEED_100_FULL; 3888c2ecf20Sopenharmony_ci if (autoc & IXGBE_AUTOC_KR_SUPP) 3898c2ecf20Sopenharmony_ci *speed |= IXGBE_LINK_SPEED_10GB_FULL; 3908c2ecf20Sopenharmony_ci if (autoc & IXGBE_AUTOC_KX4_SUPP) 3918c2ecf20Sopenharmony_ci *speed |= IXGBE_LINK_SPEED_10GB_FULL; 3928c2ecf20Sopenharmony_ci if (autoc & IXGBE_AUTOC_KX_SUPP) 3938c2ecf20Sopenharmony_ci *speed |= IXGBE_LINK_SPEED_1GB_FULL; 3948c2ecf20Sopenharmony_ci *autoneg = true; 3958c2ecf20Sopenharmony_ci break; 3968c2ecf20Sopenharmony_ci 3978c2ecf20Sopenharmony_ci case IXGBE_AUTOC_LMS_SGMII_1G_100M: 3988c2ecf20Sopenharmony_ci *speed = IXGBE_LINK_SPEED_1GB_FULL | IXGBE_LINK_SPEED_100_FULL; 3998c2ecf20Sopenharmony_ci *autoneg = false; 4008c2ecf20Sopenharmony_ci break; 4018c2ecf20Sopenharmony_ci 4028c2ecf20Sopenharmony_ci default: 4038c2ecf20Sopenharmony_ci return -EIO; 4048c2ecf20Sopenharmony_ci } 4058c2ecf20Sopenharmony_ci 4068c2ecf20Sopenharmony_ci if (hw->phy.multispeed_fiber) { 4078c2ecf20Sopenharmony_ci *speed |= IXGBE_LINK_SPEED_10GB_FULL | 4088c2ecf20Sopenharmony_ci IXGBE_LINK_SPEED_1GB_FULL; 4098c2ecf20Sopenharmony_ci 4108c2ecf20Sopenharmony_ci /* QSFP must not enable auto-negotiation */ 4118c2ecf20Sopenharmony_ci if (hw->phy.media_type == ixgbe_media_type_fiber_qsfp) 4128c2ecf20Sopenharmony_ci *autoneg = false; 4138c2ecf20Sopenharmony_ci else 4148c2ecf20Sopenharmony_ci *autoneg = true; 4158c2ecf20Sopenharmony_ci } 4168c2ecf20Sopenharmony_ci 4178c2ecf20Sopenharmony_ci return 0; 4188c2ecf20Sopenharmony_ci} 4198c2ecf20Sopenharmony_ci 4208c2ecf20Sopenharmony_ci/** 4218c2ecf20Sopenharmony_ci * ixgbe_get_media_type_82599 - Get media type 4228c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 4238c2ecf20Sopenharmony_ci * 4248c2ecf20Sopenharmony_ci * Returns the media type (fiber, copper, backplane) 4258c2ecf20Sopenharmony_ci **/ 4268c2ecf20Sopenharmony_cistatic enum ixgbe_media_type ixgbe_get_media_type_82599(struct ixgbe_hw *hw) 4278c2ecf20Sopenharmony_ci{ 4288c2ecf20Sopenharmony_ci /* Detect if there is a copper PHY attached. */ 4298c2ecf20Sopenharmony_ci switch (hw->phy.type) { 4308c2ecf20Sopenharmony_ci case ixgbe_phy_cu_unknown: 4318c2ecf20Sopenharmony_ci case ixgbe_phy_tn: 4328c2ecf20Sopenharmony_ci return ixgbe_media_type_copper; 4338c2ecf20Sopenharmony_ci 4348c2ecf20Sopenharmony_ci default: 4358c2ecf20Sopenharmony_ci break; 4368c2ecf20Sopenharmony_ci } 4378c2ecf20Sopenharmony_ci 4388c2ecf20Sopenharmony_ci switch (hw->device_id) { 4398c2ecf20Sopenharmony_ci case IXGBE_DEV_ID_82599_KX4: 4408c2ecf20Sopenharmony_ci case IXGBE_DEV_ID_82599_KX4_MEZZ: 4418c2ecf20Sopenharmony_ci case IXGBE_DEV_ID_82599_COMBO_BACKPLANE: 4428c2ecf20Sopenharmony_ci case IXGBE_DEV_ID_82599_KR: 4438c2ecf20Sopenharmony_ci case IXGBE_DEV_ID_82599_BACKPLANE_FCOE: 4448c2ecf20Sopenharmony_ci case IXGBE_DEV_ID_82599_XAUI_LOM: 4458c2ecf20Sopenharmony_ci /* Default device ID is mezzanine card KX/KX4 */ 4468c2ecf20Sopenharmony_ci return ixgbe_media_type_backplane; 4478c2ecf20Sopenharmony_ci 4488c2ecf20Sopenharmony_ci case IXGBE_DEV_ID_82599_SFP: 4498c2ecf20Sopenharmony_ci case IXGBE_DEV_ID_82599_SFP_FCOE: 4508c2ecf20Sopenharmony_ci case IXGBE_DEV_ID_82599_SFP_EM: 4518c2ecf20Sopenharmony_ci case IXGBE_DEV_ID_82599_SFP_SF2: 4528c2ecf20Sopenharmony_ci case IXGBE_DEV_ID_82599_SFP_SF_QP: 4538c2ecf20Sopenharmony_ci case IXGBE_DEV_ID_82599EN_SFP: 4548c2ecf20Sopenharmony_ci return ixgbe_media_type_fiber; 4558c2ecf20Sopenharmony_ci 4568c2ecf20Sopenharmony_ci case IXGBE_DEV_ID_82599_CX4: 4578c2ecf20Sopenharmony_ci return ixgbe_media_type_cx4; 4588c2ecf20Sopenharmony_ci 4598c2ecf20Sopenharmony_ci case IXGBE_DEV_ID_82599_T3_LOM: 4608c2ecf20Sopenharmony_ci return ixgbe_media_type_copper; 4618c2ecf20Sopenharmony_ci 4628c2ecf20Sopenharmony_ci case IXGBE_DEV_ID_82599_LS: 4638c2ecf20Sopenharmony_ci return ixgbe_media_type_fiber_lco; 4648c2ecf20Sopenharmony_ci 4658c2ecf20Sopenharmony_ci case IXGBE_DEV_ID_82599_QSFP_SF_QP: 4668c2ecf20Sopenharmony_ci return ixgbe_media_type_fiber_qsfp; 4678c2ecf20Sopenharmony_ci 4688c2ecf20Sopenharmony_ci default: 4698c2ecf20Sopenharmony_ci return ixgbe_media_type_unknown; 4708c2ecf20Sopenharmony_ci } 4718c2ecf20Sopenharmony_ci} 4728c2ecf20Sopenharmony_ci 4738c2ecf20Sopenharmony_ci/** 4748c2ecf20Sopenharmony_ci * ixgbe_stop_mac_link_on_d3_82599 - Disables link on D3 4758c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 4768c2ecf20Sopenharmony_ci * 4778c2ecf20Sopenharmony_ci * Disables link, should be called during D3 power down sequence. 4788c2ecf20Sopenharmony_ci * 4798c2ecf20Sopenharmony_ci **/ 4808c2ecf20Sopenharmony_cistatic void ixgbe_stop_mac_link_on_d3_82599(struct ixgbe_hw *hw) 4818c2ecf20Sopenharmony_ci{ 4828c2ecf20Sopenharmony_ci u32 autoc2_reg; 4838c2ecf20Sopenharmony_ci u16 ee_ctrl_2 = 0; 4848c2ecf20Sopenharmony_ci 4858c2ecf20Sopenharmony_ci hw->eeprom.ops.read(hw, IXGBE_EEPROM_CTRL_2, &ee_ctrl_2); 4868c2ecf20Sopenharmony_ci 4878c2ecf20Sopenharmony_ci if (!ixgbe_mng_present(hw) && !hw->wol_enabled && 4888c2ecf20Sopenharmony_ci ee_ctrl_2 & IXGBE_EEPROM_CCD_BIT) { 4898c2ecf20Sopenharmony_ci autoc2_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC2); 4908c2ecf20Sopenharmony_ci autoc2_reg |= IXGBE_AUTOC2_LINK_DISABLE_ON_D3_MASK; 4918c2ecf20Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_AUTOC2, autoc2_reg); 4928c2ecf20Sopenharmony_ci } 4938c2ecf20Sopenharmony_ci} 4948c2ecf20Sopenharmony_ci 4958c2ecf20Sopenharmony_ci/** 4968c2ecf20Sopenharmony_ci * ixgbe_start_mac_link_82599 - Setup MAC link settings 4978c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 4988c2ecf20Sopenharmony_ci * @autoneg_wait_to_complete: true when waiting for completion is needed 4998c2ecf20Sopenharmony_ci * 5008c2ecf20Sopenharmony_ci * Configures link settings based on values in the ixgbe_hw struct. 5018c2ecf20Sopenharmony_ci * Restarts the link. Performs autonegotiation if needed. 5028c2ecf20Sopenharmony_ci **/ 5038c2ecf20Sopenharmony_cistatic s32 ixgbe_start_mac_link_82599(struct ixgbe_hw *hw, 5048c2ecf20Sopenharmony_ci bool autoneg_wait_to_complete) 5058c2ecf20Sopenharmony_ci{ 5068c2ecf20Sopenharmony_ci u32 autoc_reg; 5078c2ecf20Sopenharmony_ci u32 links_reg; 5088c2ecf20Sopenharmony_ci u32 i; 5098c2ecf20Sopenharmony_ci s32 status = 0; 5108c2ecf20Sopenharmony_ci bool got_lock = false; 5118c2ecf20Sopenharmony_ci 5128c2ecf20Sopenharmony_ci if (ixgbe_verify_lesm_fw_enabled_82599(hw)) { 5138c2ecf20Sopenharmony_ci status = hw->mac.ops.acquire_swfw_sync(hw, 5148c2ecf20Sopenharmony_ci IXGBE_GSSR_MAC_CSR_SM); 5158c2ecf20Sopenharmony_ci if (status) 5168c2ecf20Sopenharmony_ci return status; 5178c2ecf20Sopenharmony_ci 5188c2ecf20Sopenharmony_ci got_lock = true; 5198c2ecf20Sopenharmony_ci } 5208c2ecf20Sopenharmony_ci 5218c2ecf20Sopenharmony_ci /* Restart link */ 5228c2ecf20Sopenharmony_ci ixgbe_reset_pipeline_82599(hw); 5238c2ecf20Sopenharmony_ci 5248c2ecf20Sopenharmony_ci if (got_lock) 5258c2ecf20Sopenharmony_ci hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_MAC_CSR_SM); 5268c2ecf20Sopenharmony_ci 5278c2ecf20Sopenharmony_ci /* Only poll for autoneg to complete if specified to do so */ 5288c2ecf20Sopenharmony_ci if (autoneg_wait_to_complete) { 5298c2ecf20Sopenharmony_ci autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC); 5308c2ecf20Sopenharmony_ci if ((autoc_reg & IXGBE_AUTOC_LMS_MASK) == 5318c2ecf20Sopenharmony_ci IXGBE_AUTOC_LMS_KX4_KX_KR || 5328c2ecf20Sopenharmony_ci (autoc_reg & IXGBE_AUTOC_LMS_MASK) == 5338c2ecf20Sopenharmony_ci IXGBE_AUTOC_LMS_KX4_KX_KR_1G_AN || 5348c2ecf20Sopenharmony_ci (autoc_reg & IXGBE_AUTOC_LMS_MASK) == 5358c2ecf20Sopenharmony_ci IXGBE_AUTOC_LMS_KX4_KX_KR_SGMII) { 5368c2ecf20Sopenharmony_ci links_reg = 0; /* Just in case Autoneg time = 0 */ 5378c2ecf20Sopenharmony_ci for (i = 0; i < IXGBE_AUTO_NEG_TIME; i++) { 5388c2ecf20Sopenharmony_ci links_reg = IXGBE_READ_REG(hw, IXGBE_LINKS); 5398c2ecf20Sopenharmony_ci if (links_reg & IXGBE_LINKS_KX_AN_COMP) 5408c2ecf20Sopenharmony_ci break; 5418c2ecf20Sopenharmony_ci msleep(100); 5428c2ecf20Sopenharmony_ci } 5438c2ecf20Sopenharmony_ci if (!(links_reg & IXGBE_LINKS_KX_AN_COMP)) { 5448c2ecf20Sopenharmony_ci status = -EIO; 5458c2ecf20Sopenharmony_ci hw_dbg(hw, "Autoneg did not complete.\n"); 5468c2ecf20Sopenharmony_ci } 5478c2ecf20Sopenharmony_ci } 5488c2ecf20Sopenharmony_ci } 5498c2ecf20Sopenharmony_ci 5508c2ecf20Sopenharmony_ci /* Add delay to filter out noises during initial link setup */ 5518c2ecf20Sopenharmony_ci msleep(50); 5528c2ecf20Sopenharmony_ci 5538c2ecf20Sopenharmony_ci return status; 5548c2ecf20Sopenharmony_ci} 5558c2ecf20Sopenharmony_ci 5568c2ecf20Sopenharmony_ci/** 5578c2ecf20Sopenharmony_ci * ixgbe_disable_tx_laser_multispeed_fiber - Disable Tx laser 5588c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 5598c2ecf20Sopenharmony_ci * 5608c2ecf20Sopenharmony_ci * The base drivers may require better control over SFP+ module 5618c2ecf20Sopenharmony_ci * PHY states. This includes selectively shutting down the Tx 5628c2ecf20Sopenharmony_ci * laser on the PHY, effectively halting physical link. 5638c2ecf20Sopenharmony_ci **/ 5648c2ecf20Sopenharmony_cistatic void ixgbe_disable_tx_laser_multispeed_fiber(struct ixgbe_hw *hw) 5658c2ecf20Sopenharmony_ci{ 5668c2ecf20Sopenharmony_ci u32 esdp_reg = IXGBE_READ_REG(hw, IXGBE_ESDP); 5678c2ecf20Sopenharmony_ci 5688c2ecf20Sopenharmony_ci /* Blocked by MNG FW so bail */ 5698c2ecf20Sopenharmony_ci if (ixgbe_check_reset_blocked(hw)) 5708c2ecf20Sopenharmony_ci return; 5718c2ecf20Sopenharmony_ci 5728c2ecf20Sopenharmony_ci /* Disable tx laser; allow 100us to go dark per spec */ 5738c2ecf20Sopenharmony_ci esdp_reg |= IXGBE_ESDP_SDP3; 5748c2ecf20Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp_reg); 5758c2ecf20Sopenharmony_ci IXGBE_WRITE_FLUSH(hw); 5768c2ecf20Sopenharmony_ci udelay(100); 5778c2ecf20Sopenharmony_ci} 5788c2ecf20Sopenharmony_ci 5798c2ecf20Sopenharmony_ci/** 5808c2ecf20Sopenharmony_ci * ixgbe_enable_tx_laser_multispeed_fiber - Enable Tx laser 5818c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 5828c2ecf20Sopenharmony_ci * 5838c2ecf20Sopenharmony_ci * The base drivers may require better control over SFP+ module 5848c2ecf20Sopenharmony_ci * PHY states. This includes selectively turning on the Tx 5858c2ecf20Sopenharmony_ci * laser on the PHY, effectively starting physical link. 5868c2ecf20Sopenharmony_ci **/ 5878c2ecf20Sopenharmony_cistatic void ixgbe_enable_tx_laser_multispeed_fiber(struct ixgbe_hw *hw) 5888c2ecf20Sopenharmony_ci{ 5898c2ecf20Sopenharmony_ci u32 esdp_reg = IXGBE_READ_REG(hw, IXGBE_ESDP); 5908c2ecf20Sopenharmony_ci 5918c2ecf20Sopenharmony_ci /* Enable tx laser; allow 100ms to light up */ 5928c2ecf20Sopenharmony_ci esdp_reg &= ~IXGBE_ESDP_SDP3; 5938c2ecf20Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp_reg); 5948c2ecf20Sopenharmony_ci IXGBE_WRITE_FLUSH(hw); 5958c2ecf20Sopenharmony_ci msleep(100); 5968c2ecf20Sopenharmony_ci} 5978c2ecf20Sopenharmony_ci 5988c2ecf20Sopenharmony_ci/** 5998c2ecf20Sopenharmony_ci * ixgbe_flap_tx_laser_multispeed_fiber - Flap Tx laser 6008c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 6018c2ecf20Sopenharmony_ci * 6028c2ecf20Sopenharmony_ci * When the driver changes the link speeds that it can support, 6038c2ecf20Sopenharmony_ci * it sets autotry_restart to true to indicate that we need to 6048c2ecf20Sopenharmony_ci * initiate a new autotry session with the link partner. To do 6058c2ecf20Sopenharmony_ci * so, we set the speed then disable and re-enable the tx laser, to 6068c2ecf20Sopenharmony_ci * alert the link partner that it also needs to restart autotry on its 6078c2ecf20Sopenharmony_ci * end. This is consistent with true clause 37 autoneg, which also 6088c2ecf20Sopenharmony_ci * involves a loss of signal. 6098c2ecf20Sopenharmony_ci **/ 6108c2ecf20Sopenharmony_cistatic void ixgbe_flap_tx_laser_multispeed_fiber(struct ixgbe_hw *hw) 6118c2ecf20Sopenharmony_ci{ 6128c2ecf20Sopenharmony_ci /* Blocked by MNG FW so bail */ 6138c2ecf20Sopenharmony_ci if (ixgbe_check_reset_blocked(hw)) 6148c2ecf20Sopenharmony_ci return; 6158c2ecf20Sopenharmony_ci 6168c2ecf20Sopenharmony_ci if (hw->mac.autotry_restart) { 6178c2ecf20Sopenharmony_ci ixgbe_disable_tx_laser_multispeed_fiber(hw); 6188c2ecf20Sopenharmony_ci ixgbe_enable_tx_laser_multispeed_fiber(hw); 6198c2ecf20Sopenharmony_ci hw->mac.autotry_restart = false; 6208c2ecf20Sopenharmony_ci } 6218c2ecf20Sopenharmony_ci} 6228c2ecf20Sopenharmony_ci 6238c2ecf20Sopenharmony_ci/** 6248c2ecf20Sopenharmony_ci * ixgbe_set_hard_rate_select_speed - Set module link speed 6258c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 6268c2ecf20Sopenharmony_ci * @speed: link speed to set 6278c2ecf20Sopenharmony_ci * 6288c2ecf20Sopenharmony_ci * Set module link speed via RS0/RS1 rate select pins. 6298c2ecf20Sopenharmony_ci */ 6308c2ecf20Sopenharmony_cistatic void 6318c2ecf20Sopenharmony_ciixgbe_set_hard_rate_select_speed(struct ixgbe_hw *hw, ixgbe_link_speed speed) 6328c2ecf20Sopenharmony_ci{ 6338c2ecf20Sopenharmony_ci u32 esdp_reg = IXGBE_READ_REG(hw, IXGBE_ESDP); 6348c2ecf20Sopenharmony_ci 6358c2ecf20Sopenharmony_ci switch (speed) { 6368c2ecf20Sopenharmony_ci case IXGBE_LINK_SPEED_10GB_FULL: 6378c2ecf20Sopenharmony_ci esdp_reg |= (IXGBE_ESDP_SDP5_DIR | IXGBE_ESDP_SDP5); 6388c2ecf20Sopenharmony_ci break; 6398c2ecf20Sopenharmony_ci case IXGBE_LINK_SPEED_1GB_FULL: 6408c2ecf20Sopenharmony_ci esdp_reg &= ~IXGBE_ESDP_SDP5; 6418c2ecf20Sopenharmony_ci esdp_reg |= IXGBE_ESDP_SDP5_DIR; 6428c2ecf20Sopenharmony_ci break; 6438c2ecf20Sopenharmony_ci default: 6448c2ecf20Sopenharmony_ci hw_dbg(hw, "Invalid fixed module speed\n"); 6458c2ecf20Sopenharmony_ci return; 6468c2ecf20Sopenharmony_ci } 6478c2ecf20Sopenharmony_ci 6488c2ecf20Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp_reg); 6498c2ecf20Sopenharmony_ci IXGBE_WRITE_FLUSH(hw); 6508c2ecf20Sopenharmony_ci} 6518c2ecf20Sopenharmony_ci 6528c2ecf20Sopenharmony_ci/** 6538c2ecf20Sopenharmony_ci * ixgbe_setup_mac_link_smartspeed - Set MAC link speed using SmartSpeed 6548c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 6558c2ecf20Sopenharmony_ci * @speed: new link speed 6568c2ecf20Sopenharmony_ci * @autoneg_wait_to_complete: true when waiting for completion is needed 6578c2ecf20Sopenharmony_ci * 6588c2ecf20Sopenharmony_ci * Implements the Intel SmartSpeed algorithm. 6598c2ecf20Sopenharmony_ci **/ 6608c2ecf20Sopenharmony_cistatic s32 ixgbe_setup_mac_link_smartspeed(struct ixgbe_hw *hw, 6618c2ecf20Sopenharmony_ci ixgbe_link_speed speed, 6628c2ecf20Sopenharmony_ci bool autoneg_wait_to_complete) 6638c2ecf20Sopenharmony_ci{ 6648c2ecf20Sopenharmony_ci s32 status = 0; 6658c2ecf20Sopenharmony_ci ixgbe_link_speed link_speed = IXGBE_LINK_SPEED_UNKNOWN; 6668c2ecf20Sopenharmony_ci s32 i, j; 6678c2ecf20Sopenharmony_ci bool link_up = false; 6688c2ecf20Sopenharmony_ci u32 autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC); 6698c2ecf20Sopenharmony_ci 6708c2ecf20Sopenharmony_ci /* Set autoneg_advertised value based on input link speed */ 6718c2ecf20Sopenharmony_ci hw->phy.autoneg_advertised = 0; 6728c2ecf20Sopenharmony_ci 6738c2ecf20Sopenharmony_ci if (speed & IXGBE_LINK_SPEED_10GB_FULL) 6748c2ecf20Sopenharmony_ci hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_10GB_FULL; 6758c2ecf20Sopenharmony_ci 6768c2ecf20Sopenharmony_ci if (speed & IXGBE_LINK_SPEED_1GB_FULL) 6778c2ecf20Sopenharmony_ci hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_1GB_FULL; 6788c2ecf20Sopenharmony_ci 6798c2ecf20Sopenharmony_ci if (speed & IXGBE_LINK_SPEED_100_FULL) 6808c2ecf20Sopenharmony_ci hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_100_FULL; 6818c2ecf20Sopenharmony_ci 6828c2ecf20Sopenharmony_ci /* 6838c2ecf20Sopenharmony_ci * Implement Intel SmartSpeed algorithm. SmartSpeed will reduce the 6848c2ecf20Sopenharmony_ci * autoneg advertisement if link is unable to be established at the 6858c2ecf20Sopenharmony_ci * highest negotiated rate. This can sometimes happen due to integrity 6868c2ecf20Sopenharmony_ci * issues with the physical media connection. 6878c2ecf20Sopenharmony_ci */ 6888c2ecf20Sopenharmony_ci 6898c2ecf20Sopenharmony_ci /* First, try to get link with full advertisement */ 6908c2ecf20Sopenharmony_ci hw->phy.smart_speed_active = false; 6918c2ecf20Sopenharmony_ci for (j = 0; j < IXGBE_SMARTSPEED_MAX_RETRIES; j++) { 6928c2ecf20Sopenharmony_ci status = ixgbe_setup_mac_link_82599(hw, speed, 6938c2ecf20Sopenharmony_ci autoneg_wait_to_complete); 6948c2ecf20Sopenharmony_ci if (status != 0) 6958c2ecf20Sopenharmony_ci goto out; 6968c2ecf20Sopenharmony_ci 6978c2ecf20Sopenharmony_ci /* 6988c2ecf20Sopenharmony_ci * Wait for the controller to acquire link. Per IEEE 802.3ap, 6998c2ecf20Sopenharmony_ci * Section 73.10.2, we may have to wait up to 500ms if KR is 7008c2ecf20Sopenharmony_ci * attempted, or 200ms if KX/KX4/BX/BX4 is attempted, per 7018c2ecf20Sopenharmony_ci * Table 9 in the AN MAS. 7028c2ecf20Sopenharmony_ci */ 7038c2ecf20Sopenharmony_ci for (i = 0; i < 5; i++) { 7048c2ecf20Sopenharmony_ci mdelay(100); 7058c2ecf20Sopenharmony_ci 7068c2ecf20Sopenharmony_ci /* If we have link, just jump out */ 7078c2ecf20Sopenharmony_ci status = hw->mac.ops.check_link(hw, &link_speed, 7088c2ecf20Sopenharmony_ci &link_up, false); 7098c2ecf20Sopenharmony_ci if (status != 0) 7108c2ecf20Sopenharmony_ci goto out; 7118c2ecf20Sopenharmony_ci 7128c2ecf20Sopenharmony_ci if (link_up) 7138c2ecf20Sopenharmony_ci goto out; 7148c2ecf20Sopenharmony_ci } 7158c2ecf20Sopenharmony_ci } 7168c2ecf20Sopenharmony_ci 7178c2ecf20Sopenharmony_ci /* 7188c2ecf20Sopenharmony_ci * We didn't get link. If we advertised KR plus one of KX4/KX 7198c2ecf20Sopenharmony_ci * (or BX4/BX), then disable KR and try again. 7208c2ecf20Sopenharmony_ci */ 7218c2ecf20Sopenharmony_ci if (((autoc_reg & IXGBE_AUTOC_KR_SUPP) == 0) || 7228c2ecf20Sopenharmony_ci ((autoc_reg & IXGBE_AUTOC_KX4_KX_SUPP_MASK) == 0)) 7238c2ecf20Sopenharmony_ci goto out; 7248c2ecf20Sopenharmony_ci 7258c2ecf20Sopenharmony_ci /* Turn SmartSpeed on to disable KR support */ 7268c2ecf20Sopenharmony_ci hw->phy.smart_speed_active = true; 7278c2ecf20Sopenharmony_ci status = ixgbe_setup_mac_link_82599(hw, speed, 7288c2ecf20Sopenharmony_ci autoneg_wait_to_complete); 7298c2ecf20Sopenharmony_ci if (status != 0) 7308c2ecf20Sopenharmony_ci goto out; 7318c2ecf20Sopenharmony_ci 7328c2ecf20Sopenharmony_ci /* 7338c2ecf20Sopenharmony_ci * Wait for the controller to acquire link. 600ms will allow for 7348c2ecf20Sopenharmony_ci * the AN link_fail_inhibit_timer as well for multiple cycles of 7358c2ecf20Sopenharmony_ci * parallel detect, both 10g and 1g. This allows for the maximum 7368c2ecf20Sopenharmony_ci * connect attempts as defined in the AN MAS table 73-7. 7378c2ecf20Sopenharmony_ci */ 7388c2ecf20Sopenharmony_ci for (i = 0; i < 6; i++) { 7398c2ecf20Sopenharmony_ci mdelay(100); 7408c2ecf20Sopenharmony_ci 7418c2ecf20Sopenharmony_ci /* If we have link, just jump out */ 7428c2ecf20Sopenharmony_ci status = hw->mac.ops.check_link(hw, &link_speed, 7438c2ecf20Sopenharmony_ci &link_up, false); 7448c2ecf20Sopenharmony_ci if (status != 0) 7458c2ecf20Sopenharmony_ci goto out; 7468c2ecf20Sopenharmony_ci 7478c2ecf20Sopenharmony_ci if (link_up) 7488c2ecf20Sopenharmony_ci goto out; 7498c2ecf20Sopenharmony_ci } 7508c2ecf20Sopenharmony_ci 7518c2ecf20Sopenharmony_ci /* We didn't get link. Turn SmartSpeed back off. */ 7528c2ecf20Sopenharmony_ci hw->phy.smart_speed_active = false; 7538c2ecf20Sopenharmony_ci status = ixgbe_setup_mac_link_82599(hw, speed, 7548c2ecf20Sopenharmony_ci autoneg_wait_to_complete); 7558c2ecf20Sopenharmony_ci 7568c2ecf20Sopenharmony_ciout: 7578c2ecf20Sopenharmony_ci if (link_up && (link_speed == IXGBE_LINK_SPEED_1GB_FULL)) 7588c2ecf20Sopenharmony_ci hw_dbg(hw, "Smartspeed has downgraded the link speed from the maximum advertised\n"); 7598c2ecf20Sopenharmony_ci return status; 7608c2ecf20Sopenharmony_ci} 7618c2ecf20Sopenharmony_ci 7628c2ecf20Sopenharmony_ci/** 7638c2ecf20Sopenharmony_ci * ixgbe_setup_mac_link_82599 - Set MAC link speed 7648c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 7658c2ecf20Sopenharmony_ci * @speed: new link speed 7668c2ecf20Sopenharmony_ci * @autoneg_wait_to_complete: true when waiting for completion is needed 7678c2ecf20Sopenharmony_ci * 7688c2ecf20Sopenharmony_ci * Set the link speed in the AUTOC register and restarts link. 7698c2ecf20Sopenharmony_ci **/ 7708c2ecf20Sopenharmony_cistatic s32 ixgbe_setup_mac_link_82599(struct ixgbe_hw *hw, 7718c2ecf20Sopenharmony_ci ixgbe_link_speed speed, 7728c2ecf20Sopenharmony_ci bool autoneg_wait_to_complete) 7738c2ecf20Sopenharmony_ci{ 7748c2ecf20Sopenharmony_ci bool autoneg = false; 7758c2ecf20Sopenharmony_ci s32 status; 7768c2ecf20Sopenharmony_ci u32 pma_pmd_1g, link_mode, links_reg, i; 7778c2ecf20Sopenharmony_ci u32 autoc2 = IXGBE_READ_REG(hw, IXGBE_AUTOC2); 7788c2ecf20Sopenharmony_ci u32 pma_pmd_10g_serial = autoc2 & IXGBE_AUTOC2_10G_SERIAL_PMA_PMD_MASK; 7798c2ecf20Sopenharmony_ci ixgbe_link_speed link_capabilities = IXGBE_LINK_SPEED_UNKNOWN; 7808c2ecf20Sopenharmony_ci 7818c2ecf20Sopenharmony_ci /* holds the value of AUTOC register at this current point in time */ 7828c2ecf20Sopenharmony_ci u32 current_autoc = IXGBE_READ_REG(hw, IXGBE_AUTOC); 7838c2ecf20Sopenharmony_ci /* holds the cached value of AUTOC register */ 7848c2ecf20Sopenharmony_ci u32 orig_autoc = 0; 7858c2ecf20Sopenharmony_ci /* temporary variable used for comparison purposes */ 7868c2ecf20Sopenharmony_ci u32 autoc = current_autoc; 7878c2ecf20Sopenharmony_ci 7888c2ecf20Sopenharmony_ci /* Check to see if speed passed in is supported. */ 7898c2ecf20Sopenharmony_ci status = hw->mac.ops.get_link_capabilities(hw, &link_capabilities, 7908c2ecf20Sopenharmony_ci &autoneg); 7918c2ecf20Sopenharmony_ci if (status) 7928c2ecf20Sopenharmony_ci return status; 7938c2ecf20Sopenharmony_ci 7948c2ecf20Sopenharmony_ci speed &= link_capabilities; 7958c2ecf20Sopenharmony_ci 7968c2ecf20Sopenharmony_ci if (speed == IXGBE_LINK_SPEED_UNKNOWN) 7978c2ecf20Sopenharmony_ci return -EINVAL; 7988c2ecf20Sopenharmony_ci 7998c2ecf20Sopenharmony_ci /* Use stored value (EEPROM defaults) of AUTOC to find KR/KX4 support*/ 8008c2ecf20Sopenharmony_ci if (hw->mac.orig_link_settings_stored) 8018c2ecf20Sopenharmony_ci orig_autoc = hw->mac.orig_autoc; 8028c2ecf20Sopenharmony_ci else 8038c2ecf20Sopenharmony_ci orig_autoc = autoc; 8048c2ecf20Sopenharmony_ci 8058c2ecf20Sopenharmony_ci link_mode = autoc & IXGBE_AUTOC_LMS_MASK; 8068c2ecf20Sopenharmony_ci pma_pmd_1g = autoc & IXGBE_AUTOC_1G_PMA_PMD_MASK; 8078c2ecf20Sopenharmony_ci 8088c2ecf20Sopenharmony_ci if (link_mode == IXGBE_AUTOC_LMS_KX4_KX_KR || 8098c2ecf20Sopenharmony_ci link_mode == IXGBE_AUTOC_LMS_KX4_KX_KR_1G_AN || 8108c2ecf20Sopenharmony_ci link_mode == IXGBE_AUTOC_LMS_KX4_KX_KR_SGMII) { 8118c2ecf20Sopenharmony_ci /* Set KX4/KX/KR support according to speed requested */ 8128c2ecf20Sopenharmony_ci autoc &= ~(IXGBE_AUTOC_KX4_KX_SUPP_MASK | IXGBE_AUTOC_KR_SUPP); 8138c2ecf20Sopenharmony_ci if (speed & IXGBE_LINK_SPEED_10GB_FULL) { 8148c2ecf20Sopenharmony_ci if (orig_autoc & IXGBE_AUTOC_KX4_SUPP) 8158c2ecf20Sopenharmony_ci autoc |= IXGBE_AUTOC_KX4_SUPP; 8168c2ecf20Sopenharmony_ci if ((orig_autoc & IXGBE_AUTOC_KR_SUPP) && 8178c2ecf20Sopenharmony_ci (hw->phy.smart_speed_active == false)) 8188c2ecf20Sopenharmony_ci autoc |= IXGBE_AUTOC_KR_SUPP; 8198c2ecf20Sopenharmony_ci } 8208c2ecf20Sopenharmony_ci if (speed & IXGBE_LINK_SPEED_1GB_FULL) 8218c2ecf20Sopenharmony_ci autoc |= IXGBE_AUTOC_KX_SUPP; 8228c2ecf20Sopenharmony_ci } else if ((pma_pmd_1g == IXGBE_AUTOC_1G_SFI) && 8238c2ecf20Sopenharmony_ci (link_mode == IXGBE_AUTOC_LMS_1G_LINK_NO_AN || 8248c2ecf20Sopenharmony_ci link_mode == IXGBE_AUTOC_LMS_1G_AN)) { 8258c2ecf20Sopenharmony_ci /* Switch from 1G SFI to 10G SFI if requested */ 8268c2ecf20Sopenharmony_ci if ((speed == IXGBE_LINK_SPEED_10GB_FULL) && 8278c2ecf20Sopenharmony_ci (pma_pmd_10g_serial == IXGBE_AUTOC2_10G_SFI)) { 8288c2ecf20Sopenharmony_ci autoc &= ~IXGBE_AUTOC_LMS_MASK; 8298c2ecf20Sopenharmony_ci autoc |= IXGBE_AUTOC_LMS_10G_SERIAL; 8308c2ecf20Sopenharmony_ci } 8318c2ecf20Sopenharmony_ci } else if ((pma_pmd_10g_serial == IXGBE_AUTOC2_10G_SFI) && 8328c2ecf20Sopenharmony_ci (link_mode == IXGBE_AUTOC_LMS_10G_SERIAL)) { 8338c2ecf20Sopenharmony_ci /* Switch from 10G SFI to 1G SFI if requested */ 8348c2ecf20Sopenharmony_ci if ((speed == IXGBE_LINK_SPEED_1GB_FULL) && 8358c2ecf20Sopenharmony_ci (pma_pmd_1g == IXGBE_AUTOC_1G_SFI)) { 8368c2ecf20Sopenharmony_ci autoc &= ~IXGBE_AUTOC_LMS_MASK; 8378c2ecf20Sopenharmony_ci if (autoneg) 8388c2ecf20Sopenharmony_ci autoc |= IXGBE_AUTOC_LMS_1G_AN; 8398c2ecf20Sopenharmony_ci else 8408c2ecf20Sopenharmony_ci autoc |= IXGBE_AUTOC_LMS_1G_LINK_NO_AN; 8418c2ecf20Sopenharmony_ci } 8428c2ecf20Sopenharmony_ci } 8438c2ecf20Sopenharmony_ci 8448c2ecf20Sopenharmony_ci if (autoc != current_autoc) { 8458c2ecf20Sopenharmony_ci /* Restart link */ 8468c2ecf20Sopenharmony_ci status = hw->mac.ops.prot_autoc_write(hw, autoc, false); 8478c2ecf20Sopenharmony_ci if (status) 8488c2ecf20Sopenharmony_ci return status; 8498c2ecf20Sopenharmony_ci 8508c2ecf20Sopenharmony_ci /* Only poll for autoneg to complete if specified to do so */ 8518c2ecf20Sopenharmony_ci if (autoneg_wait_to_complete) { 8528c2ecf20Sopenharmony_ci if (link_mode == IXGBE_AUTOC_LMS_KX4_KX_KR || 8538c2ecf20Sopenharmony_ci link_mode == IXGBE_AUTOC_LMS_KX4_KX_KR_1G_AN || 8548c2ecf20Sopenharmony_ci link_mode == IXGBE_AUTOC_LMS_KX4_KX_KR_SGMII) { 8558c2ecf20Sopenharmony_ci links_reg = 0; /*Just in case Autoneg time=0*/ 8568c2ecf20Sopenharmony_ci for (i = 0; i < IXGBE_AUTO_NEG_TIME; i++) { 8578c2ecf20Sopenharmony_ci links_reg = 8588c2ecf20Sopenharmony_ci IXGBE_READ_REG(hw, IXGBE_LINKS); 8598c2ecf20Sopenharmony_ci if (links_reg & IXGBE_LINKS_KX_AN_COMP) 8608c2ecf20Sopenharmony_ci break; 8618c2ecf20Sopenharmony_ci msleep(100); 8628c2ecf20Sopenharmony_ci } 8638c2ecf20Sopenharmony_ci if (!(links_reg & IXGBE_LINKS_KX_AN_COMP)) { 8648c2ecf20Sopenharmony_ci status = -EIO; 8658c2ecf20Sopenharmony_ci hw_dbg(hw, "Autoneg did not complete.\n"); 8668c2ecf20Sopenharmony_ci } 8678c2ecf20Sopenharmony_ci } 8688c2ecf20Sopenharmony_ci } 8698c2ecf20Sopenharmony_ci 8708c2ecf20Sopenharmony_ci /* Add delay to filter out noises during initial link setup */ 8718c2ecf20Sopenharmony_ci msleep(50); 8728c2ecf20Sopenharmony_ci } 8738c2ecf20Sopenharmony_ci 8748c2ecf20Sopenharmony_ci return status; 8758c2ecf20Sopenharmony_ci} 8768c2ecf20Sopenharmony_ci 8778c2ecf20Sopenharmony_ci/** 8788c2ecf20Sopenharmony_ci * ixgbe_setup_copper_link_82599 - Set the PHY autoneg advertised field 8798c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 8808c2ecf20Sopenharmony_ci * @speed: new link speed 8818c2ecf20Sopenharmony_ci * @autoneg_wait_to_complete: true if waiting is needed to complete 8828c2ecf20Sopenharmony_ci * 8838c2ecf20Sopenharmony_ci * Restarts link on PHY and MAC based on settings passed in. 8848c2ecf20Sopenharmony_ci **/ 8858c2ecf20Sopenharmony_cistatic s32 ixgbe_setup_copper_link_82599(struct ixgbe_hw *hw, 8868c2ecf20Sopenharmony_ci ixgbe_link_speed speed, 8878c2ecf20Sopenharmony_ci bool autoneg_wait_to_complete) 8888c2ecf20Sopenharmony_ci{ 8898c2ecf20Sopenharmony_ci s32 status; 8908c2ecf20Sopenharmony_ci 8918c2ecf20Sopenharmony_ci /* Setup the PHY according to input speed */ 8928c2ecf20Sopenharmony_ci status = hw->phy.ops.setup_link_speed(hw, speed, 8938c2ecf20Sopenharmony_ci autoneg_wait_to_complete); 8948c2ecf20Sopenharmony_ci /* Set up MAC */ 8958c2ecf20Sopenharmony_ci ixgbe_start_mac_link_82599(hw, autoneg_wait_to_complete); 8968c2ecf20Sopenharmony_ci 8978c2ecf20Sopenharmony_ci return status; 8988c2ecf20Sopenharmony_ci} 8998c2ecf20Sopenharmony_ci 9008c2ecf20Sopenharmony_ci/** 9018c2ecf20Sopenharmony_ci * ixgbe_reset_hw_82599 - Perform hardware reset 9028c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 9038c2ecf20Sopenharmony_ci * 9048c2ecf20Sopenharmony_ci * Resets the hardware by resetting the transmit and receive units, masks 9058c2ecf20Sopenharmony_ci * and clears all interrupts, perform a PHY reset, and perform a link (MAC) 9068c2ecf20Sopenharmony_ci * reset. 9078c2ecf20Sopenharmony_ci **/ 9088c2ecf20Sopenharmony_cistatic s32 ixgbe_reset_hw_82599(struct ixgbe_hw *hw) 9098c2ecf20Sopenharmony_ci{ 9108c2ecf20Sopenharmony_ci ixgbe_link_speed link_speed; 9118c2ecf20Sopenharmony_ci s32 status; 9128c2ecf20Sopenharmony_ci u32 ctrl, i, autoc, autoc2; 9138c2ecf20Sopenharmony_ci u32 curr_lms; 9148c2ecf20Sopenharmony_ci bool link_up = false; 9158c2ecf20Sopenharmony_ci 9168c2ecf20Sopenharmony_ci /* Call adapter stop to disable tx/rx and clear interrupts */ 9178c2ecf20Sopenharmony_ci status = hw->mac.ops.stop_adapter(hw); 9188c2ecf20Sopenharmony_ci if (status) 9198c2ecf20Sopenharmony_ci return status; 9208c2ecf20Sopenharmony_ci 9218c2ecf20Sopenharmony_ci /* flush pending Tx transactions */ 9228c2ecf20Sopenharmony_ci ixgbe_clear_tx_pending(hw); 9238c2ecf20Sopenharmony_ci 9248c2ecf20Sopenharmony_ci /* PHY ops must be identified and initialized prior to reset */ 9258c2ecf20Sopenharmony_ci 9268c2ecf20Sopenharmony_ci /* Identify PHY and related function pointers */ 9278c2ecf20Sopenharmony_ci status = hw->phy.ops.init(hw); 9288c2ecf20Sopenharmony_ci 9298c2ecf20Sopenharmony_ci if (status == -EOPNOTSUPP) 9308c2ecf20Sopenharmony_ci return status; 9318c2ecf20Sopenharmony_ci 9328c2ecf20Sopenharmony_ci /* Setup SFP module if there is one present. */ 9338c2ecf20Sopenharmony_ci if (hw->phy.sfp_setup_needed) { 9348c2ecf20Sopenharmony_ci status = hw->mac.ops.setup_sfp(hw); 9358c2ecf20Sopenharmony_ci hw->phy.sfp_setup_needed = false; 9368c2ecf20Sopenharmony_ci } 9378c2ecf20Sopenharmony_ci 9388c2ecf20Sopenharmony_ci if (status == -EOPNOTSUPP) 9398c2ecf20Sopenharmony_ci return status; 9408c2ecf20Sopenharmony_ci 9418c2ecf20Sopenharmony_ci /* Reset PHY */ 9428c2ecf20Sopenharmony_ci if (hw->phy.reset_disable == false && hw->phy.ops.reset != NULL) 9438c2ecf20Sopenharmony_ci hw->phy.ops.reset(hw); 9448c2ecf20Sopenharmony_ci 9458c2ecf20Sopenharmony_ci /* remember AUTOC from before we reset */ 9468c2ecf20Sopenharmony_ci curr_lms = IXGBE_READ_REG(hw, IXGBE_AUTOC) & IXGBE_AUTOC_LMS_MASK; 9478c2ecf20Sopenharmony_ci 9488c2ecf20Sopenharmony_cimac_reset_top: 9498c2ecf20Sopenharmony_ci /* 9508c2ecf20Sopenharmony_ci * Issue global reset to the MAC. Needs to be SW reset if link is up. 9518c2ecf20Sopenharmony_ci * If link reset is used when link is up, it might reset the PHY when 9528c2ecf20Sopenharmony_ci * mng is using it. If link is down or the flag to force full link 9538c2ecf20Sopenharmony_ci * reset is set, then perform link reset. 9548c2ecf20Sopenharmony_ci */ 9558c2ecf20Sopenharmony_ci ctrl = IXGBE_CTRL_LNK_RST; 9568c2ecf20Sopenharmony_ci if (!hw->force_full_reset) { 9578c2ecf20Sopenharmony_ci hw->mac.ops.check_link(hw, &link_speed, &link_up, false); 9588c2ecf20Sopenharmony_ci if (link_up) 9598c2ecf20Sopenharmony_ci ctrl = IXGBE_CTRL_RST; 9608c2ecf20Sopenharmony_ci } 9618c2ecf20Sopenharmony_ci 9628c2ecf20Sopenharmony_ci ctrl |= IXGBE_READ_REG(hw, IXGBE_CTRL); 9638c2ecf20Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_CTRL, ctrl); 9648c2ecf20Sopenharmony_ci IXGBE_WRITE_FLUSH(hw); 9658c2ecf20Sopenharmony_ci usleep_range(1000, 1200); 9668c2ecf20Sopenharmony_ci 9678c2ecf20Sopenharmony_ci /* Poll for reset bit to self-clear indicating reset is complete */ 9688c2ecf20Sopenharmony_ci for (i = 0; i < 10; i++) { 9698c2ecf20Sopenharmony_ci ctrl = IXGBE_READ_REG(hw, IXGBE_CTRL); 9708c2ecf20Sopenharmony_ci if (!(ctrl & IXGBE_CTRL_RST_MASK)) 9718c2ecf20Sopenharmony_ci break; 9728c2ecf20Sopenharmony_ci udelay(1); 9738c2ecf20Sopenharmony_ci } 9748c2ecf20Sopenharmony_ci 9758c2ecf20Sopenharmony_ci if (ctrl & IXGBE_CTRL_RST_MASK) { 9768c2ecf20Sopenharmony_ci status = -EIO; 9778c2ecf20Sopenharmony_ci hw_dbg(hw, "Reset polling failed to complete.\n"); 9788c2ecf20Sopenharmony_ci } 9798c2ecf20Sopenharmony_ci 9808c2ecf20Sopenharmony_ci msleep(50); 9818c2ecf20Sopenharmony_ci 9828c2ecf20Sopenharmony_ci /* 9838c2ecf20Sopenharmony_ci * Double resets are required for recovery from certain error 9848c2ecf20Sopenharmony_ci * conditions. Between resets, it is necessary to stall to allow time 9858c2ecf20Sopenharmony_ci * for any pending HW events to complete. 9868c2ecf20Sopenharmony_ci */ 9878c2ecf20Sopenharmony_ci if (hw->mac.flags & IXGBE_FLAGS_DOUBLE_RESET_REQUIRED) { 9888c2ecf20Sopenharmony_ci hw->mac.flags &= ~IXGBE_FLAGS_DOUBLE_RESET_REQUIRED; 9898c2ecf20Sopenharmony_ci goto mac_reset_top; 9908c2ecf20Sopenharmony_ci } 9918c2ecf20Sopenharmony_ci 9928c2ecf20Sopenharmony_ci /* 9938c2ecf20Sopenharmony_ci * Store the original AUTOC/AUTOC2 values if they have not been 9948c2ecf20Sopenharmony_ci * stored off yet. Otherwise restore the stored original 9958c2ecf20Sopenharmony_ci * values since the reset operation sets back to defaults. 9968c2ecf20Sopenharmony_ci */ 9978c2ecf20Sopenharmony_ci autoc = IXGBE_READ_REG(hw, IXGBE_AUTOC); 9988c2ecf20Sopenharmony_ci autoc2 = IXGBE_READ_REG(hw, IXGBE_AUTOC2); 9998c2ecf20Sopenharmony_ci 10008c2ecf20Sopenharmony_ci /* Enable link if disabled in NVM */ 10018c2ecf20Sopenharmony_ci if (autoc2 & IXGBE_AUTOC2_LINK_DISABLE_MASK) { 10028c2ecf20Sopenharmony_ci autoc2 &= ~IXGBE_AUTOC2_LINK_DISABLE_MASK; 10038c2ecf20Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_AUTOC2, autoc2); 10048c2ecf20Sopenharmony_ci IXGBE_WRITE_FLUSH(hw); 10058c2ecf20Sopenharmony_ci } 10068c2ecf20Sopenharmony_ci 10078c2ecf20Sopenharmony_ci if (hw->mac.orig_link_settings_stored == false) { 10088c2ecf20Sopenharmony_ci hw->mac.orig_autoc = autoc; 10098c2ecf20Sopenharmony_ci hw->mac.orig_autoc2 = autoc2; 10108c2ecf20Sopenharmony_ci hw->mac.orig_link_settings_stored = true; 10118c2ecf20Sopenharmony_ci } else { 10128c2ecf20Sopenharmony_ci 10138c2ecf20Sopenharmony_ci /* If MNG FW is running on a multi-speed device that 10148c2ecf20Sopenharmony_ci * doesn't autoneg with out driver support we need to 10158c2ecf20Sopenharmony_ci * leave LMS in the state it was before we MAC reset. 10168c2ecf20Sopenharmony_ci * Likewise if we support WoL we don't want change the 10178c2ecf20Sopenharmony_ci * LMS state either. 10188c2ecf20Sopenharmony_ci */ 10198c2ecf20Sopenharmony_ci if ((hw->phy.multispeed_fiber && ixgbe_mng_enabled(hw)) || 10208c2ecf20Sopenharmony_ci hw->wol_enabled) 10218c2ecf20Sopenharmony_ci hw->mac.orig_autoc = 10228c2ecf20Sopenharmony_ci (hw->mac.orig_autoc & ~IXGBE_AUTOC_LMS_MASK) | 10238c2ecf20Sopenharmony_ci curr_lms; 10248c2ecf20Sopenharmony_ci 10258c2ecf20Sopenharmony_ci if (autoc != hw->mac.orig_autoc) { 10268c2ecf20Sopenharmony_ci status = hw->mac.ops.prot_autoc_write(hw, 10278c2ecf20Sopenharmony_ci hw->mac.orig_autoc, 10288c2ecf20Sopenharmony_ci false); 10298c2ecf20Sopenharmony_ci if (status) 10308c2ecf20Sopenharmony_ci return status; 10318c2ecf20Sopenharmony_ci } 10328c2ecf20Sopenharmony_ci 10338c2ecf20Sopenharmony_ci if ((autoc2 & IXGBE_AUTOC2_UPPER_MASK) != 10348c2ecf20Sopenharmony_ci (hw->mac.orig_autoc2 & IXGBE_AUTOC2_UPPER_MASK)) { 10358c2ecf20Sopenharmony_ci autoc2 &= ~IXGBE_AUTOC2_UPPER_MASK; 10368c2ecf20Sopenharmony_ci autoc2 |= (hw->mac.orig_autoc2 & 10378c2ecf20Sopenharmony_ci IXGBE_AUTOC2_UPPER_MASK); 10388c2ecf20Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_AUTOC2, autoc2); 10398c2ecf20Sopenharmony_ci } 10408c2ecf20Sopenharmony_ci } 10418c2ecf20Sopenharmony_ci 10428c2ecf20Sopenharmony_ci /* Store the permanent mac address */ 10438c2ecf20Sopenharmony_ci hw->mac.ops.get_mac_addr(hw, hw->mac.perm_addr); 10448c2ecf20Sopenharmony_ci 10458c2ecf20Sopenharmony_ci /* 10468c2ecf20Sopenharmony_ci * Store MAC address from RAR0, clear receive address registers, and 10478c2ecf20Sopenharmony_ci * clear the multicast table. Also reset num_rar_entries to 128, 10488c2ecf20Sopenharmony_ci * since we modify this value when programming the SAN MAC address. 10498c2ecf20Sopenharmony_ci */ 10508c2ecf20Sopenharmony_ci hw->mac.num_rar_entries = IXGBE_82599_RAR_ENTRIES; 10518c2ecf20Sopenharmony_ci hw->mac.ops.init_rx_addrs(hw); 10528c2ecf20Sopenharmony_ci 10538c2ecf20Sopenharmony_ci /* Store the permanent SAN mac address */ 10548c2ecf20Sopenharmony_ci hw->mac.ops.get_san_mac_addr(hw, hw->mac.san_addr); 10558c2ecf20Sopenharmony_ci 10568c2ecf20Sopenharmony_ci /* Add the SAN MAC address to the RAR only if it's a valid address */ 10578c2ecf20Sopenharmony_ci if (is_valid_ether_addr(hw->mac.san_addr)) { 10588c2ecf20Sopenharmony_ci /* Save the SAN MAC RAR index */ 10598c2ecf20Sopenharmony_ci hw->mac.san_mac_rar_index = hw->mac.num_rar_entries - 1; 10608c2ecf20Sopenharmony_ci 10618c2ecf20Sopenharmony_ci hw->mac.ops.set_rar(hw, hw->mac.san_mac_rar_index, 10628c2ecf20Sopenharmony_ci hw->mac.san_addr, 0, IXGBE_RAH_AV); 10638c2ecf20Sopenharmony_ci 10648c2ecf20Sopenharmony_ci /* clear VMDq pool/queue selection for this RAR */ 10658c2ecf20Sopenharmony_ci hw->mac.ops.clear_vmdq(hw, hw->mac.san_mac_rar_index, 10668c2ecf20Sopenharmony_ci IXGBE_CLEAR_VMDQ_ALL); 10678c2ecf20Sopenharmony_ci 10688c2ecf20Sopenharmony_ci /* Reserve the last RAR for the SAN MAC address */ 10698c2ecf20Sopenharmony_ci hw->mac.num_rar_entries--; 10708c2ecf20Sopenharmony_ci } 10718c2ecf20Sopenharmony_ci 10728c2ecf20Sopenharmony_ci /* Store the alternative WWNN/WWPN prefix */ 10738c2ecf20Sopenharmony_ci hw->mac.ops.get_wwn_prefix(hw, &hw->mac.wwnn_prefix, 10748c2ecf20Sopenharmony_ci &hw->mac.wwpn_prefix); 10758c2ecf20Sopenharmony_ci 10768c2ecf20Sopenharmony_ci return status; 10778c2ecf20Sopenharmony_ci} 10788c2ecf20Sopenharmony_ci 10798c2ecf20Sopenharmony_ci/** 10808c2ecf20Sopenharmony_ci * ixgbe_fdir_check_cmd_complete - poll to check whether FDIRCMD is complete 10818c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 10828c2ecf20Sopenharmony_ci * @fdircmd: current value of FDIRCMD register 10838c2ecf20Sopenharmony_ci */ 10848c2ecf20Sopenharmony_cistatic s32 ixgbe_fdir_check_cmd_complete(struct ixgbe_hw *hw, u32 *fdircmd) 10858c2ecf20Sopenharmony_ci{ 10868c2ecf20Sopenharmony_ci int i; 10878c2ecf20Sopenharmony_ci 10888c2ecf20Sopenharmony_ci for (i = 0; i < IXGBE_FDIRCMD_CMD_POLL; i++) { 10898c2ecf20Sopenharmony_ci *fdircmd = IXGBE_READ_REG(hw, IXGBE_FDIRCMD); 10908c2ecf20Sopenharmony_ci if (!(*fdircmd & IXGBE_FDIRCMD_CMD_MASK)) 10918c2ecf20Sopenharmony_ci return 0; 10928c2ecf20Sopenharmony_ci udelay(10); 10938c2ecf20Sopenharmony_ci } 10948c2ecf20Sopenharmony_ci 10958c2ecf20Sopenharmony_ci return -EIO; 10968c2ecf20Sopenharmony_ci} 10978c2ecf20Sopenharmony_ci 10988c2ecf20Sopenharmony_ci/** 10998c2ecf20Sopenharmony_ci * ixgbe_reinit_fdir_tables_82599 - Reinitialize Flow Director tables. 11008c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 11018c2ecf20Sopenharmony_ci **/ 11028c2ecf20Sopenharmony_cis32 ixgbe_reinit_fdir_tables_82599(struct ixgbe_hw *hw) 11038c2ecf20Sopenharmony_ci{ 11048c2ecf20Sopenharmony_ci int i; 11058c2ecf20Sopenharmony_ci u32 fdirctrl = IXGBE_READ_REG(hw, IXGBE_FDIRCTRL); 11068c2ecf20Sopenharmony_ci u32 fdircmd; 11078c2ecf20Sopenharmony_ci s32 err; 11088c2ecf20Sopenharmony_ci 11098c2ecf20Sopenharmony_ci fdirctrl &= ~IXGBE_FDIRCTRL_INIT_DONE; 11108c2ecf20Sopenharmony_ci 11118c2ecf20Sopenharmony_ci /* 11128c2ecf20Sopenharmony_ci * Before starting reinitialization process, 11138c2ecf20Sopenharmony_ci * FDIRCMD.CMD must be zero. 11148c2ecf20Sopenharmony_ci */ 11158c2ecf20Sopenharmony_ci err = ixgbe_fdir_check_cmd_complete(hw, &fdircmd); 11168c2ecf20Sopenharmony_ci if (err) { 11178c2ecf20Sopenharmony_ci hw_dbg(hw, "Flow Director previous command did not complete, aborting table re-initialization.\n"); 11188c2ecf20Sopenharmony_ci return err; 11198c2ecf20Sopenharmony_ci } 11208c2ecf20Sopenharmony_ci 11218c2ecf20Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_FDIRFREE, 0); 11228c2ecf20Sopenharmony_ci IXGBE_WRITE_FLUSH(hw); 11238c2ecf20Sopenharmony_ci /* 11248c2ecf20Sopenharmony_ci * 82599 adapters flow director init flow cannot be restarted, 11258c2ecf20Sopenharmony_ci * Workaround 82599 silicon errata by performing the following steps 11268c2ecf20Sopenharmony_ci * before re-writing the FDIRCTRL control register with the same value. 11278c2ecf20Sopenharmony_ci * - write 1 to bit 8 of FDIRCMD register & 11288c2ecf20Sopenharmony_ci * - write 0 to bit 8 of FDIRCMD register 11298c2ecf20Sopenharmony_ci */ 11308c2ecf20Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_FDIRCMD, 11318c2ecf20Sopenharmony_ci (IXGBE_READ_REG(hw, IXGBE_FDIRCMD) | 11328c2ecf20Sopenharmony_ci IXGBE_FDIRCMD_CLEARHT)); 11338c2ecf20Sopenharmony_ci IXGBE_WRITE_FLUSH(hw); 11348c2ecf20Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_FDIRCMD, 11358c2ecf20Sopenharmony_ci (IXGBE_READ_REG(hw, IXGBE_FDIRCMD) & 11368c2ecf20Sopenharmony_ci ~IXGBE_FDIRCMD_CLEARHT)); 11378c2ecf20Sopenharmony_ci IXGBE_WRITE_FLUSH(hw); 11388c2ecf20Sopenharmony_ci /* 11398c2ecf20Sopenharmony_ci * Clear FDIR Hash register to clear any leftover hashes 11408c2ecf20Sopenharmony_ci * waiting to be programmed. 11418c2ecf20Sopenharmony_ci */ 11428c2ecf20Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_FDIRHASH, 0x00); 11438c2ecf20Sopenharmony_ci IXGBE_WRITE_FLUSH(hw); 11448c2ecf20Sopenharmony_ci 11458c2ecf20Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_FDIRCTRL, fdirctrl); 11468c2ecf20Sopenharmony_ci IXGBE_WRITE_FLUSH(hw); 11478c2ecf20Sopenharmony_ci 11488c2ecf20Sopenharmony_ci /* Poll init-done after we write FDIRCTRL register */ 11498c2ecf20Sopenharmony_ci for (i = 0; i < IXGBE_FDIR_INIT_DONE_POLL; i++) { 11508c2ecf20Sopenharmony_ci if (IXGBE_READ_REG(hw, IXGBE_FDIRCTRL) & 11518c2ecf20Sopenharmony_ci IXGBE_FDIRCTRL_INIT_DONE) 11528c2ecf20Sopenharmony_ci break; 11538c2ecf20Sopenharmony_ci usleep_range(1000, 2000); 11548c2ecf20Sopenharmony_ci } 11558c2ecf20Sopenharmony_ci if (i >= IXGBE_FDIR_INIT_DONE_POLL) { 11568c2ecf20Sopenharmony_ci hw_dbg(hw, "Flow Director Signature poll time exceeded!\n"); 11578c2ecf20Sopenharmony_ci return -EIO; 11588c2ecf20Sopenharmony_ci } 11598c2ecf20Sopenharmony_ci 11608c2ecf20Sopenharmony_ci /* Clear FDIR statistics registers (read to clear) */ 11618c2ecf20Sopenharmony_ci IXGBE_READ_REG(hw, IXGBE_FDIRUSTAT); 11628c2ecf20Sopenharmony_ci IXGBE_READ_REG(hw, IXGBE_FDIRFSTAT); 11638c2ecf20Sopenharmony_ci IXGBE_READ_REG(hw, IXGBE_FDIRMATCH); 11648c2ecf20Sopenharmony_ci IXGBE_READ_REG(hw, IXGBE_FDIRMISS); 11658c2ecf20Sopenharmony_ci IXGBE_READ_REG(hw, IXGBE_FDIRLEN); 11668c2ecf20Sopenharmony_ci 11678c2ecf20Sopenharmony_ci return 0; 11688c2ecf20Sopenharmony_ci} 11698c2ecf20Sopenharmony_ci 11708c2ecf20Sopenharmony_ci/** 11718c2ecf20Sopenharmony_ci * ixgbe_fdir_enable_82599 - Initialize Flow Director control registers 11728c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 11738c2ecf20Sopenharmony_ci * @fdirctrl: value to write to flow director control register 11748c2ecf20Sopenharmony_ci **/ 11758c2ecf20Sopenharmony_cistatic void ixgbe_fdir_enable_82599(struct ixgbe_hw *hw, u32 fdirctrl) 11768c2ecf20Sopenharmony_ci{ 11778c2ecf20Sopenharmony_ci int i; 11788c2ecf20Sopenharmony_ci 11798c2ecf20Sopenharmony_ci /* Prime the keys for hashing */ 11808c2ecf20Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_FDIRHKEY, IXGBE_ATR_BUCKET_HASH_KEY); 11818c2ecf20Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_FDIRSKEY, IXGBE_ATR_SIGNATURE_HASH_KEY); 11828c2ecf20Sopenharmony_ci 11838c2ecf20Sopenharmony_ci /* 11848c2ecf20Sopenharmony_ci * Poll init-done after we write the register. Estimated times: 11858c2ecf20Sopenharmony_ci * 10G: PBALLOC = 11b, timing is 60us 11868c2ecf20Sopenharmony_ci * 1G: PBALLOC = 11b, timing is 600us 11878c2ecf20Sopenharmony_ci * 100M: PBALLOC = 11b, timing is 6ms 11888c2ecf20Sopenharmony_ci * 11898c2ecf20Sopenharmony_ci * Multiple these timings by 4 if under full Rx load 11908c2ecf20Sopenharmony_ci * 11918c2ecf20Sopenharmony_ci * So we'll poll for IXGBE_FDIR_INIT_DONE_POLL times, sleeping for 11928c2ecf20Sopenharmony_ci * 1 msec per poll time. If we're at line rate and drop to 100M, then 11938c2ecf20Sopenharmony_ci * this might not finish in our poll time, but we can live with that 11948c2ecf20Sopenharmony_ci * for now. 11958c2ecf20Sopenharmony_ci */ 11968c2ecf20Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_FDIRCTRL, fdirctrl); 11978c2ecf20Sopenharmony_ci IXGBE_WRITE_FLUSH(hw); 11988c2ecf20Sopenharmony_ci for (i = 0; i < IXGBE_FDIR_INIT_DONE_POLL; i++) { 11998c2ecf20Sopenharmony_ci if (IXGBE_READ_REG(hw, IXGBE_FDIRCTRL) & 12008c2ecf20Sopenharmony_ci IXGBE_FDIRCTRL_INIT_DONE) 12018c2ecf20Sopenharmony_ci break; 12028c2ecf20Sopenharmony_ci usleep_range(1000, 2000); 12038c2ecf20Sopenharmony_ci } 12048c2ecf20Sopenharmony_ci 12058c2ecf20Sopenharmony_ci if (i >= IXGBE_FDIR_INIT_DONE_POLL) 12068c2ecf20Sopenharmony_ci hw_dbg(hw, "Flow Director poll time exceeded!\n"); 12078c2ecf20Sopenharmony_ci} 12088c2ecf20Sopenharmony_ci 12098c2ecf20Sopenharmony_ci/** 12108c2ecf20Sopenharmony_ci * ixgbe_init_fdir_signature_82599 - Initialize Flow Director signature filters 12118c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 12128c2ecf20Sopenharmony_ci * @fdirctrl: value to write to flow director control register, initially 12138c2ecf20Sopenharmony_ci * contains just the value of the Rx packet buffer allocation 12148c2ecf20Sopenharmony_ci **/ 12158c2ecf20Sopenharmony_cis32 ixgbe_init_fdir_signature_82599(struct ixgbe_hw *hw, u32 fdirctrl) 12168c2ecf20Sopenharmony_ci{ 12178c2ecf20Sopenharmony_ci /* 12188c2ecf20Sopenharmony_ci * Continue setup of fdirctrl register bits: 12198c2ecf20Sopenharmony_ci * Move the flexible bytes to use the ethertype - shift 6 words 12208c2ecf20Sopenharmony_ci * Set the maximum length per hash bucket to 0xA filters 12218c2ecf20Sopenharmony_ci * Send interrupt when 64 filters are left 12228c2ecf20Sopenharmony_ci */ 12238c2ecf20Sopenharmony_ci fdirctrl |= (0x6 << IXGBE_FDIRCTRL_FLEX_SHIFT) | 12248c2ecf20Sopenharmony_ci (0xA << IXGBE_FDIRCTRL_MAX_LENGTH_SHIFT) | 12258c2ecf20Sopenharmony_ci (4 << IXGBE_FDIRCTRL_FULL_THRESH_SHIFT); 12268c2ecf20Sopenharmony_ci 12278c2ecf20Sopenharmony_ci /* write hashes and fdirctrl register, poll for completion */ 12288c2ecf20Sopenharmony_ci ixgbe_fdir_enable_82599(hw, fdirctrl); 12298c2ecf20Sopenharmony_ci 12308c2ecf20Sopenharmony_ci return 0; 12318c2ecf20Sopenharmony_ci} 12328c2ecf20Sopenharmony_ci 12338c2ecf20Sopenharmony_ci/** 12348c2ecf20Sopenharmony_ci * ixgbe_init_fdir_perfect_82599 - Initialize Flow Director perfect filters 12358c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 12368c2ecf20Sopenharmony_ci * @fdirctrl: value to write to flow director control register, initially 12378c2ecf20Sopenharmony_ci * contains just the value of the Rx packet buffer allocation 12388c2ecf20Sopenharmony_ci **/ 12398c2ecf20Sopenharmony_cis32 ixgbe_init_fdir_perfect_82599(struct ixgbe_hw *hw, u32 fdirctrl) 12408c2ecf20Sopenharmony_ci{ 12418c2ecf20Sopenharmony_ci /* 12428c2ecf20Sopenharmony_ci * Continue setup of fdirctrl register bits: 12438c2ecf20Sopenharmony_ci * Turn perfect match filtering on 12448c2ecf20Sopenharmony_ci * Initialize the drop queue 12458c2ecf20Sopenharmony_ci * Move the flexible bytes to use the ethertype - shift 6 words 12468c2ecf20Sopenharmony_ci * Set the maximum length per hash bucket to 0xA filters 12478c2ecf20Sopenharmony_ci * Send interrupt when 64 (0x4 * 16) filters are left 12488c2ecf20Sopenharmony_ci */ 12498c2ecf20Sopenharmony_ci fdirctrl |= IXGBE_FDIRCTRL_PERFECT_MATCH | 12508c2ecf20Sopenharmony_ci (IXGBE_FDIR_DROP_QUEUE << IXGBE_FDIRCTRL_DROP_Q_SHIFT) | 12518c2ecf20Sopenharmony_ci (0x6 << IXGBE_FDIRCTRL_FLEX_SHIFT) | 12528c2ecf20Sopenharmony_ci (0xA << IXGBE_FDIRCTRL_MAX_LENGTH_SHIFT) | 12538c2ecf20Sopenharmony_ci (4 << IXGBE_FDIRCTRL_FULL_THRESH_SHIFT); 12548c2ecf20Sopenharmony_ci 12558c2ecf20Sopenharmony_ci /* write hashes and fdirctrl register, poll for completion */ 12568c2ecf20Sopenharmony_ci ixgbe_fdir_enable_82599(hw, fdirctrl); 12578c2ecf20Sopenharmony_ci 12588c2ecf20Sopenharmony_ci return 0; 12598c2ecf20Sopenharmony_ci} 12608c2ecf20Sopenharmony_ci 12618c2ecf20Sopenharmony_ci/* 12628c2ecf20Sopenharmony_ci * These defines allow us to quickly generate all of the necessary instructions 12638c2ecf20Sopenharmony_ci * in the function below by simply calling out IXGBE_COMPUTE_SIG_HASH_ITERATION 12648c2ecf20Sopenharmony_ci * for values 0 through 15 12658c2ecf20Sopenharmony_ci */ 12668c2ecf20Sopenharmony_ci#define IXGBE_ATR_COMMON_HASH_KEY \ 12678c2ecf20Sopenharmony_ci (IXGBE_ATR_BUCKET_HASH_KEY & IXGBE_ATR_SIGNATURE_HASH_KEY) 12688c2ecf20Sopenharmony_ci#define IXGBE_COMPUTE_SIG_HASH_ITERATION(_n) \ 12698c2ecf20Sopenharmony_cido { \ 12708c2ecf20Sopenharmony_ci u32 n = (_n); \ 12718c2ecf20Sopenharmony_ci if (IXGBE_ATR_COMMON_HASH_KEY & BIT(n)) \ 12728c2ecf20Sopenharmony_ci common_hash ^= lo_hash_dword >> n; \ 12738c2ecf20Sopenharmony_ci else if (IXGBE_ATR_BUCKET_HASH_KEY & BIT(n)) \ 12748c2ecf20Sopenharmony_ci bucket_hash ^= lo_hash_dword >> n; \ 12758c2ecf20Sopenharmony_ci else if (IXGBE_ATR_SIGNATURE_HASH_KEY & BIT(n)) \ 12768c2ecf20Sopenharmony_ci sig_hash ^= lo_hash_dword << (16 - n); \ 12778c2ecf20Sopenharmony_ci if (IXGBE_ATR_COMMON_HASH_KEY & BIT(n + 16)) \ 12788c2ecf20Sopenharmony_ci common_hash ^= hi_hash_dword >> n; \ 12798c2ecf20Sopenharmony_ci else if (IXGBE_ATR_BUCKET_HASH_KEY & BIT(n + 16)) \ 12808c2ecf20Sopenharmony_ci bucket_hash ^= hi_hash_dword >> n; \ 12818c2ecf20Sopenharmony_ci else if (IXGBE_ATR_SIGNATURE_HASH_KEY & BIT(n + 16)) \ 12828c2ecf20Sopenharmony_ci sig_hash ^= hi_hash_dword << (16 - n); \ 12838c2ecf20Sopenharmony_ci} while (0) 12848c2ecf20Sopenharmony_ci 12858c2ecf20Sopenharmony_ci/** 12868c2ecf20Sopenharmony_ci * ixgbe_atr_compute_sig_hash_82599 - Compute the signature hash 12878c2ecf20Sopenharmony_ci * @input: input bitstream to compute the hash on 12888c2ecf20Sopenharmony_ci * @common: compressed common input dword 12898c2ecf20Sopenharmony_ci * 12908c2ecf20Sopenharmony_ci * This function is almost identical to the function above but contains 12918c2ecf20Sopenharmony_ci * several optimizations such as unwinding all of the loops, letting the 12928c2ecf20Sopenharmony_ci * compiler work out all of the conditional ifs since the keys are static 12938c2ecf20Sopenharmony_ci * defines, and computing two keys at once since the hashed dword stream 12948c2ecf20Sopenharmony_ci * will be the same for both keys. 12958c2ecf20Sopenharmony_ci **/ 12968c2ecf20Sopenharmony_cistatic u32 ixgbe_atr_compute_sig_hash_82599(union ixgbe_atr_hash_dword input, 12978c2ecf20Sopenharmony_ci union ixgbe_atr_hash_dword common) 12988c2ecf20Sopenharmony_ci{ 12998c2ecf20Sopenharmony_ci u32 hi_hash_dword, lo_hash_dword, flow_vm_vlan; 13008c2ecf20Sopenharmony_ci u32 sig_hash = 0, bucket_hash = 0, common_hash = 0; 13018c2ecf20Sopenharmony_ci 13028c2ecf20Sopenharmony_ci /* record the flow_vm_vlan bits as they are a key part to the hash */ 13038c2ecf20Sopenharmony_ci flow_vm_vlan = ntohl(input.dword); 13048c2ecf20Sopenharmony_ci 13058c2ecf20Sopenharmony_ci /* generate common hash dword */ 13068c2ecf20Sopenharmony_ci hi_hash_dword = ntohl(common.dword); 13078c2ecf20Sopenharmony_ci 13088c2ecf20Sopenharmony_ci /* low dword is word swapped version of common */ 13098c2ecf20Sopenharmony_ci lo_hash_dword = (hi_hash_dword >> 16) | (hi_hash_dword << 16); 13108c2ecf20Sopenharmony_ci 13118c2ecf20Sopenharmony_ci /* apply flow ID/VM pool/VLAN ID bits to hash words */ 13128c2ecf20Sopenharmony_ci hi_hash_dword ^= flow_vm_vlan ^ (flow_vm_vlan >> 16); 13138c2ecf20Sopenharmony_ci 13148c2ecf20Sopenharmony_ci /* Process bits 0 and 16 */ 13158c2ecf20Sopenharmony_ci IXGBE_COMPUTE_SIG_HASH_ITERATION(0); 13168c2ecf20Sopenharmony_ci 13178c2ecf20Sopenharmony_ci /* 13188c2ecf20Sopenharmony_ci * apply flow ID/VM pool/VLAN ID bits to lo hash dword, we had to 13198c2ecf20Sopenharmony_ci * delay this because bit 0 of the stream should not be processed 13208c2ecf20Sopenharmony_ci * so we do not add the vlan until after bit 0 was processed 13218c2ecf20Sopenharmony_ci */ 13228c2ecf20Sopenharmony_ci lo_hash_dword ^= flow_vm_vlan ^ (flow_vm_vlan << 16); 13238c2ecf20Sopenharmony_ci 13248c2ecf20Sopenharmony_ci /* Process remaining 30 bit of the key */ 13258c2ecf20Sopenharmony_ci IXGBE_COMPUTE_SIG_HASH_ITERATION(1); 13268c2ecf20Sopenharmony_ci IXGBE_COMPUTE_SIG_HASH_ITERATION(2); 13278c2ecf20Sopenharmony_ci IXGBE_COMPUTE_SIG_HASH_ITERATION(3); 13288c2ecf20Sopenharmony_ci IXGBE_COMPUTE_SIG_HASH_ITERATION(4); 13298c2ecf20Sopenharmony_ci IXGBE_COMPUTE_SIG_HASH_ITERATION(5); 13308c2ecf20Sopenharmony_ci IXGBE_COMPUTE_SIG_HASH_ITERATION(6); 13318c2ecf20Sopenharmony_ci IXGBE_COMPUTE_SIG_HASH_ITERATION(7); 13328c2ecf20Sopenharmony_ci IXGBE_COMPUTE_SIG_HASH_ITERATION(8); 13338c2ecf20Sopenharmony_ci IXGBE_COMPUTE_SIG_HASH_ITERATION(9); 13348c2ecf20Sopenharmony_ci IXGBE_COMPUTE_SIG_HASH_ITERATION(10); 13358c2ecf20Sopenharmony_ci IXGBE_COMPUTE_SIG_HASH_ITERATION(11); 13368c2ecf20Sopenharmony_ci IXGBE_COMPUTE_SIG_HASH_ITERATION(12); 13378c2ecf20Sopenharmony_ci IXGBE_COMPUTE_SIG_HASH_ITERATION(13); 13388c2ecf20Sopenharmony_ci IXGBE_COMPUTE_SIG_HASH_ITERATION(14); 13398c2ecf20Sopenharmony_ci IXGBE_COMPUTE_SIG_HASH_ITERATION(15); 13408c2ecf20Sopenharmony_ci 13418c2ecf20Sopenharmony_ci /* combine common_hash result with signature and bucket hashes */ 13428c2ecf20Sopenharmony_ci bucket_hash ^= common_hash; 13438c2ecf20Sopenharmony_ci bucket_hash &= IXGBE_ATR_HASH_MASK; 13448c2ecf20Sopenharmony_ci 13458c2ecf20Sopenharmony_ci sig_hash ^= common_hash << 16; 13468c2ecf20Sopenharmony_ci sig_hash &= IXGBE_ATR_HASH_MASK << 16; 13478c2ecf20Sopenharmony_ci 13488c2ecf20Sopenharmony_ci /* return completed signature hash */ 13498c2ecf20Sopenharmony_ci return sig_hash ^ bucket_hash; 13508c2ecf20Sopenharmony_ci} 13518c2ecf20Sopenharmony_ci 13528c2ecf20Sopenharmony_ci/** 13538c2ecf20Sopenharmony_ci * ixgbe_atr_add_signature_filter_82599 - Adds a signature hash filter 13548c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 13558c2ecf20Sopenharmony_ci * @input: unique input dword 13568c2ecf20Sopenharmony_ci * @common: compressed common input dword 13578c2ecf20Sopenharmony_ci * @queue: queue index to direct traffic to 13588c2ecf20Sopenharmony_ci * 13598c2ecf20Sopenharmony_ci * Note that the tunnel bit in input must not be set when the hardware 13608c2ecf20Sopenharmony_ci * tunneling support does not exist. 13618c2ecf20Sopenharmony_ci **/ 13628c2ecf20Sopenharmony_cis32 ixgbe_fdir_add_signature_filter_82599(struct ixgbe_hw *hw, 13638c2ecf20Sopenharmony_ci union ixgbe_atr_hash_dword input, 13648c2ecf20Sopenharmony_ci union ixgbe_atr_hash_dword common, 13658c2ecf20Sopenharmony_ci u8 queue) 13668c2ecf20Sopenharmony_ci{ 13678c2ecf20Sopenharmony_ci u64 fdirhashcmd; 13688c2ecf20Sopenharmony_ci u8 flow_type; 13698c2ecf20Sopenharmony_ci bool tunnel; 13708c2ecf20Sopenharmony_ci u32 fdircmd; 13718c2ecf20Sopenharmony_ci 13728c2ecf20Sopenharmony_ci /* 13738c2ecf20Sopenharmony_ci * Get the flow_type in order to program FDIRCMD properly 13748c2ecf20Sopenharmony_ci * lowest 2 bits are FDIRCMD.L4TYPE, third lowest bit is FDIRCMD.IPV6 13758c2ecf20Sopenharmony_ci */ 13768c2ecf20Sopenharmony_ci tunnel = !!(input.formatted.flow_type & IXGBE_ATR_L4TYPE_TUNNEL_MASK); 13778c2ecf20Sopenharmony_ci flow_type = input.formatted.flow_type & 13788c2ecf20Sopenharmony_ci (IXGBE_ATR_L4TYPE_TUNNEL_MASK - 1); 13798c2ecf20Sopenharmony_ci switch (flow_type) { 13808c2ecf20Sopenharmony_ci case IXGBE_ATR_FLOW_TYPE_TCPV4: 13818c2ecf20Sopenharmony_ci case IXGBE_ATR_FLOW_TYPE_UDPV4: 13828c2ecf20Sopenharmony_ci case IXGBE_ATR_FLOW_TYPE_SCTPV4: 13838c2ecf20Sopenharmony_ci case IXGBE_ATR_FLOW_TYPE_TCPV6: 13848c2ecf20Sopenharmony_ci case IXGBE_ATR_FLOW_TYPE_UDPV6: 13858c2ecf20Sopenharmony_ci case IXGBE_ATR_FLOW_TYPE_SCTPV6: 13868c2ecf20Sopenharmony_ci break; 13878c2ecf20Sopenharmony_ci default: 13888c2ecf20Sopenharmony_ci hw_dbg(hw, " Error on flow type input\n"); 13898c2ecf20Sopenharmony_ci return -EIO; 13908c2ecf20Sopenharmony_ci } 13918c2ecf20Sopenharmony_ci 13928c2ecf20Sopenharmony_ci /* configure FDIRCMD register */ 13938c2ecf20Sopenharmony_ci fdircmd = IXGBE_FDIRCMD_CMD_ADD_FLOW | IXGBE_FDIRCMD_FILTER_UPDATE | 13948c2ecf20Sopenharmony_ci IXGBE_FDIRCMD_LAST | IXGBE_FDIRCMD_QUEUE_EN; 13958c2ecf20Sopenharmony_ci fdircmd |= (u32)flow_type << IXGBE_FDIRCMD_FLOW_TYPE_SHIFT; 13968c2ecf20Sopenharmony_ci fdircmd |= (u32)queue << IXGBE_FDIRCMD_RX_QUEUE_SHIFT; 13978c2ecf20Sopenharmony_ci if (tunnel) 13988c2ecf20Sopenharmony_ci fdircmd |= IXGBE_FDIRCMD_TUNNEL_FILTER; 13998c2ecf20Sopenharmony_ci 14008c2ecf20Sopenharmony_ci /* 14018c2ecf20Sopenharmony_ci * The lower 32-bits of fdirhashcmd is for FDIRHASH, the upper 32-bits 14028c2ecf20Sopenharmony_ci * is for FDIRCMD. Then do a 64-bit register write from FDIRHASH. 14038c2ecf20Sopenharmony_ci */ 14048c2ecf20Sopenharmony_ci fdirhashcmd = (u64)fdircmd << 32; 14058c2ecf20Sopenharmony_ci fdirhashcmd |= ixgbe_atr_compute_sig_hash_82599(input, common); 14068c2ecf20Sopenharmony_ci IXGBE_WRITE_REG64(hw, IXGBE_FDIRHASH, fdirhashcmd); 14078c2ecf20Sopenharmony_ci 14088c2ecf20Sopenharmony_ci hw_dbg(hw, "Tx Queue=%x hash=%x\n", queue, (u32)fdirhashcmd); 14098c2ecf20Sopenharmony_ci 14108c2ecf20Sopenharmony_ci return 0; 14118c2ecf20Sopenharmony_ci} 14128c2ecf20Sopenharmony_ci 14138c2ecf20Sopenharmony_ci#define IXGBE_COMPUTE_BKT_HASH_ITERATION(_n) \ 14148c2ecf20Sopenharmony_cido { \ 14158c2ecf20Sopenharmony_ci u32 n = (_n); \ 14168c2ecf20Sopenharmony_ci if (IXGBE_ATR_BUCKET_HASH_KEY & BIT(n)) \ 14178c2ecf20Sopenharmony_ci bucket_hash ^= lo_hash_dword >> n; \ 14188c2ecf20Sopenharmony_ci if (IXGBE_ATR_BUCKET_HASH_KEY & BIT(n + 16)) \ 14198c2ecf20Sopenharmony_ci bucket_hash ^= hi_hash_dword >> n; \ 14208c2ecf20Sopenharmony_ci} while (0) 14218c2ecf20Sopenharmony_ci 14228c2ecf20Sopenharmony_ci/** 14238c2ecf20Sopenharmony_ci * ixgbe_atr_compute_perfect_hash_82599 - Compute the perfect filter hash 14248c2ecf20Sopenharmony_ci * @input: input bitstream to compute the hash on 14258c2ecf20Sopenharmony_ci * @input_mask: mask for the input bitstream 14268c2ecf20Sopenharmony_ci * 14278c2ecf20Sopenharmony_ci * This function serves two main purposes. First it applies the input_mask 14288c2ecf20Sopenharmony_ci * to the atr_input resulting in a cleaned up atr_input data stream. 14298c2ecf20Sopenharmony_ci * Secondly it computes the hash and stores it in the bkt_hash field at 14308c2ecf20Sopenharmony_ci * the end of the input byte stream. This way it will be available for 14318c2ecf20Sopenharmony_ci * future use without needing to recompute the hash. 14328c2ecf20Sopenharmony_ci **/ 14338c2ecf20Sopenharmony_civoid ixgbe_atr_compute_perfect_hash_82599(union ixgbe_atr_input *input, 14348c2ecf20Sopenharmony_ci union ixgbe_atr_input *input_mask) 14358c2ecf20Sopenharmony_ci{ 14368c2ecf20Sopenharmony_ci 14378c2ecf20Sopenharmony_ci u32 hi_hash_dword, lo_hash_dword, flow_vm_vlan; 14388c2ecf20Sopenharmony_ci u32 bucket_hash = 0; 14398c2ecf20Sopenharmony_ci __be32 hi_dword = 0; 14408c2ecf20Sopenharmony_ci int i; 14418c2ecf20Sopenharmony_ci 14428c2ecf20Sopenharmony_ci /* Apply masks to input data */ 14438c2ecf20Sopenharmony_ci for (i = 0; i <= 10; i++) 14448c2ecf20Sopenharmony_ci input->dword_stream[i] &= input_mask->dword_stream[i]; 14458c2ecf20Sopenharmony_ci 14468c2ecf20Sopenharmony_ci /* record the flow_vm_vlan bits as they are a key part to the hash */ 14478c2ecf20Sopenharmony_ci flow_vm_vlan = ntohl(input->dword_stream[0]); 14488c2ecf20Sopenharmony_ci 14498c2ecf20Sopenharmony_ci /* generate common hash dword */ 14508c2ecf20Sopenharmony_ci for (i = 1; i <= 10; i++) 14518c2ecf20Sopenharmony_ci hi_dword ^= input->dword_stream[i]; 14528c2ecf20Sopenharmony_ci hi_hash_dword = ntohl(hi_dword); 14538c2ecf20Sopenharmony_ci 14548c2ecf20Sopenharmony_ci /* low dword is word swapped version of common */ 14558c2ecf20Sopenharmony_ci lo_hash_dword = (hi_hash_dword >> 16) | (hi_hash_dword << 16); 14568c2ecf20Sopenharmony_ci 14578c2ecf20Sopenharmony_ci /* apply flow ID/VM pool/VLAN ID bits to hash words */ 14588c2ecf20Sopenharmony_ci hi_hash_dword ^= flow_vm_vlan ^ (flow_vm_vlan >> 16); 14598c2ecf20Sopenharmony_ci 14608c2ecf20Sopenharmony_ci /* Process bits 0 and 16 */ 14618c2ecf20Sopenharmony_ci IXGBE_COMPUTE_BKT_HASH_ITERATION(0); 14628c2ecf20Sopenharmony_ci 14638c2ecf20Sopenharmony_ci /* 14648c2ecf20Sopenharmony_ci * apply flow ID/VM pool/VLAN ID bits to lo hash dword, we had to 14658c2ecf20Sopenharmony_ci * delay this because bit 0 of the stream should not be processed 14668c2ecf20Sopenharmony_ci * so we do not add the vlan until after bit 0 was processed 14678c2ecf20Sopenharmony_ci */ 14688c2ecf20Sopenharmony_ci lo_hash_dword ^= flow_vm_vlan ^ (flow_vm_vlan << 16); 14698c2ecf20Sopenharmony_ci 14708c2ecf20Sopenharmony_ci /* Process remaining 30 bit of the key */ 14718c2ecf20Sopenharmony_ci for (i = 1; i <= 15; i++) 14728c2ecf20Sopenharmony_ci IXGBE_COMPUTE_BKT_HASH_ITERATION(i); 14738c2ecf20Sopenharmony_ci 14748c2ecf20Sopenharmony_ci /* 14758c2ecf20Sopenharmony_ci * Limit hash to 13 bits since max bucket count is 8K. 14768c2ecf20Sopenharmony_ci * Store result at the end of the input stream. 14778c2ecf20Sopenharmony_ci */ 14788c2ecf20Sopenharmony_ci input->formatted.bkt_hash = (__force __be16)(bucket_hash & 0x1FFF); 14798c2ecf20Sopenharmony_ci} 14808c2ecf20Sopenharmony_ci 14818c2ecf20Sopenharmony_ci/** 14828c2ecf20Sopenharmony_ci * ixgbe_get_fdirtcpm_82599 - generate a tcp port from atr_input_masks 14838c2ecf20Sopenharmony_ci * @input_mask: mask to be bit swapped 14848c2ecf20Sopenharmony_ci * 14858c2ecf20Sopenharmony_ci * The source and destination port masks for flow director are bit swapped 14868c2ecf20Sopenharmony_ci * in that bit 15 effects bit 0, 14 effects 1, 13, 2 etc. In order to 14878c2ecf20Sopenharmony_ci * generate a correctly swapped value we need to bit swap the mask and that 14888c2ecf20Sopenharmony_ci * is what is accomplished by this function. 14898c2ecf20Sopenharmony_ci **/ 14908c2ecf20Sopenharmony_cistatic u32 ixgbe_get_fdirtcpm_82599(union ixgbe_atr_input *input_mask) 14918c2ecf20Sopenharmony_ci{ 14928c2ecf20Sopenharmony_ci u32 mask = ntohs(input_mask->formatted.dst_port); 14938c2ecf20Sopenharmony_ci 14948c2ecf20Sopenharmony_ci mask <<= IXGBE_FDIRTCPM_DPORTM_SHIFT; 14958c2ecf20Sopenharmony_ci mask |= ntohs(input_mask->formatted.src_port); 14968c2ecf20Sopenharmony_ci mask = ((mask & 0x55555555) << 1) | ((mask & 0xAAAAAAAA) >> 1); 14978c2ecf20Sopenharmony_ci mask = ((mask & 0x33333333) << 2) | ((mask & 0xCCCCCCCC) >> 2); 14988c2ecf20Sopenharmony_ci mask = ((mask & 0x0F0F0F0F) << 4) | ((mask & 0xF0F0F0F0) >> 4); 14998c2ecf20Sopenharmony_ci return ((mask & 0x00FF00FF) << 8) | ((mask & 0xFF00FF00) >> 8); 15008c2ecf20Sopenharmony_ci} 15018c2ecf20Sopenharmony_ci 15028c2ecf20Sopenharmony_ci/* 15038c2ecf20Sopenharmony_ci * These two macros are meant to address the fact that we have registers 15048c2ecf20Sopenharmony_ci * that are either all or in part big-endian. As a result on big-endian 15058c2ecf20Sopenharmony_ci * systems we will end up byte swapping the value to little-endian before 15068c2ecf20Sopenharmony_ci * it is byte swapped again and written to the hardware in the original 15078c2ecf20Sopenharmony_ci * big-endian format. 15088c2ecf20Sopenharmony_ci */ 15098c2ecf20Sopenharmony_ci#define IXGBE_STORE_AS_BE32(_value) \ 15108c2ecf20Sopenharmony_ci (((u32)(_value) >> 24) | (((u32)(_value) & 0x00FF0000) >> 8) | \ 15118c2ecf20Sopenharmony_ci (((u32)(_value) & 0x0000FF00) << 8) | ((u32)(_value) << 24)) 15128c2ecf20Sopenharmony_ci 15138c2ecf20Sopenharmony_ci#define IXGBE_WRITE_REG_BE32(a, reg, value) \ 15148c2ecf20Sopenharmony_ci IXGBE_WRITE_REG((a), (reg), IXGBE_STORE_AS_BE32(ntohl(value))) 15158c2ecf20Sopenharmony_ci 15168c2ecf20Sopenharmony_ci#define IXGBE_STORE_AS_BE16(_value) \ 15178c2ecf20Sopenharmony_ci ntohs(((u16)(_value) >> 8) | ((u16)(_value) << 8)) 15188c2ecf20Sopenharmony_ci 15198c2ecf20Sopenharmony_cis32 ixgbe_fdir_set_input_mask_82599(struct ixgbe_hw *hw, 15208c2ecf20Sopenharmony_ci union ixgbe_atr_input *input_mask) 15218c2ecf20Sopenharmony_ci{ 15228c2ecf20Sopenharmony_ci /* mask IPv6 since it is currently not supported */ 15238c2ecf20Sopenharmony_ci u32 fdirm = IXGBE_FDIRM_DIPv6; 15248c2ecf20Sopenharmony_ci u32 fdirtcpm; 15258c2ecf20Sopenharmony_ci 15268c2ecf20Sopenharmony_ci /* 15278c2ecf20Sopenharmony_ci * Program the relevant mask registers. If src/dst_port or src/dst_addr 15288c2ecf20Sopenharmony_ci * are zero, then assume a full mask for that field. Also assume that 15298c2ecf20Sopenharmony_ci * a VLAN of 0 is unspecified, so mask that out as well. L4type 15308c2ecf20Sopenharmony_ci * cannot be masked out in this implementation. 15318c2ecf20Sopenharmony_ci * 15328c2ecf20Sopenharmony_ci * This also assumes IPv4 only. IPv6 masking isn't supported at this 15338c2ecf20Sopenharmony_ci * point in time. 15348c2ecf20Sopenharmony_ci */ 15358c2ecf20Sopenharmony_ci 15368c2ecf20Sopenharmony_ci /* verify bucket hash is cleared on hash generation */ 15378c2ecf20Sopenharmony_ci if (input_mask->formatted.bkt_hash) 15388c2ecf20Sopenharmony_ci hw_dbg(hw, " bucket hash should always be 0 in mask\n"); 15398c2ecf20Sopenharmony_ci 15408c2ecf20Sopenharmony_ci /* Program FDIRM and verify partial masks */ 15418c2ecf20Sopenharmony_ci switch (input_mask->formatted.vm_pool & 0x7F) { 15428c2ecf20Sopenharmony_ci case 0x0: 15438c2ecf20Sopenharmony_ci fdirm |= IXGBE_FDIRM_POOL; 15448c2ecf20Sopenharmony_ci case 0x7F: 15458c2ecf20Sopenharmony_ci break; 15468c2ecf20Sopenharmony_ci default: 15478c2ecf20Sopenharmony_ci hw_dbg(hw, " Error on vm pool mask\n"); 15488c2ecf20Sopenharmony_ci return -EIO; 15498c2ecf20Sopenharmony_ci } 15508c2ecf20Sopenharmony_ci 15518c2ecf20Sopenharmony_ci switch (input_mask->formatted.flow_type & IXGBE_ATR_L4TYPE_MASK) { 15528c2ecf20Sopenharmony_ci case 0x0: 15538c2ecf20Sopenharmony_ci fdirm |= IXGBE_FDIRM_L4P; 15548c2ecf20Sopenharmony_ci if (input_mask->formatted.dst_port || 15558c2ecf20Sopenharmony_ci input_mask->formatted.src_port) { 15568c2ecf20Sopenharmony_ci hw_dbg(hw, " Error on src/dst port mask\n"); 15578c2ecf20Sopenharmony_ci return -EIO; 15588c2ecf20Sopenharmony_ci } 15598c2ecf20Sopenharmony_ci case IXGBE_ATR_L4TYPE_MASK: 15608c2ecf20Sopenharmony_ci break; 15618c2ecf20Sopenharmony_ci default: 15628c2ecf20Sopenharmony_ci hw_dbg(hw, " Error on flow type mask\n"); 15638c2ecf20Sopenharmony_ci return -EIO; 15648c2ecf20Sopenharmony_ci } 15658c2ecf20Sopenharmony_ci 15668c2ecf20Sopenharmony_ci switch (ntohs(input_mask->formatted.vlan_id) & 0xEFFF) { 15678c2ecf20Sopenharmony_ci case 0x0000: 15688c2ecf20Sopenharmony_ci /* mask VLAN ID */ 15698c2ecf20Sopenharmony_ci fdirm |= IXGBE_FDIRM_VLANID; 15708c2ecf20Sopenharmony_ci fallthrough; 15718c2ecf20Sopenharmony_ci case 0x0FFF: 15728c2ecf20Sopenharmony_ci /* mask VLAN priority */ 15738c2ecf20Sopenharmony_ci fdirm |= IXGBE_FDIRM_VLANP; 15748c2ecf20Sopenharmony_ci break; 15758c2ecf20Sopenharmony_ci case 0xE000: 15768c2ecf20Sopenharmony_ci /* mask VLAN ID only */ 15778c2ecf20Sopenharmony_ci fdirm |= IXGBE_FDIRM_VLANID; 15788c2ecf20Sopenharmony_ci fallthrough; 15798c2ecf20Sopenharmony_ci case 0xEFFF: 15808c2ecf20Sopenharmony_ci /* no VLAN fields masked */ 15818c2ecf20Sopenharmony_ci break; 15828c2ecf20Sopenharmony_ci default: 15838c2ecf20Sopenharmony_ci hw_dbg(hw, " Error on VLAN mask\n"); 15848c2ecf20Sopenharmony_ci return -EIO; 15858c2ecf20Sopenharmony_ci } 15868c2ecf20Sopenharmony_ci 15878c2ecf20Sopenharmony_ci switch ((__force u16)input_mask->formatted.flex_bytes & 0xFFFF) { 15888c2ecf20Sopenharmony_ci case 0x0000: 15898c2ecf20Sopenharmony_ci /* Mask Flex Bytes */ 15908c2ecf20Sopenharmony_ci fdirm |= IXGBE_FDIRM_FLEX; 15918c2ecf20Sopenharmony_ci fallthrough; 15928c2ecf20Sopenharmony_ci case 0xFFFF: 15938c2ecf20Sopenharmony_ci break; 15948c2ecf20Sopenharmony_ci default: 15958c2ecf20Sopenharmony_ci hw_dbg(hw, " Error on flexible byte mask\n"); 15968c2ecf20Sopenharmony_ci return -EIO; 15978c2ecf20Sopenharmony_ci } 15988c2ecf20Sopenharmony_ci 15998c2ecf20Sopenharmony_ci /* Now mask VM pool and destination IPv6 - bits 5 and 2 */ 16008c2ecf20Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_FDIRM, fdirm); 16018c2ecf20Sopenharmony_ci 16028c2ecf20Sopenharmony_ci /* store the TCP/UDP port masks, bit reversed from port layout */ 16038c2ecf20Sopenharmony_ci fdirtcpm = ixgbe_get_fdirtcpm_82599(input_mask); 16048c2ecf20Sopenharmony_ci 16058c2ecf20Sopenharmony_ci /* write both the same so that UDP and TCP use the same mask */ 16068c2ecf20Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_FDIRTCPM, ~fdirtcpm); 16078c2ecf20Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_FDIRUDPM, ~fdirtcpm); 16088c2ecf20Sopenharmony_ci 16098c2ecf20Sopenharmony_ci /* also use it for SCTP */ 16108c2ecf20Sopenharmony_ci switch (hw->mac.type) { 16118c2ecf20Sopenharmony_ci case ixgbe_mac_X550: 16128c2ecf20Sopenharmony_ci case ixgbe_mac_X550EM_x: 16138c2ecf20Sopenharmony_ci case ixgbe_mac_x550em_a: 16148c2ecf20Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_FDIRSCTPM, ~fdirtcpm); 16158c2ecf20Sopenharmony_ci break; 16168c2ecf20Sopenharmony_ci default: 16178c2ecf20Sopenharmony_ci break; 16188c2ecf20Sopenharmony_ci } 16198c2ecf20Sopenharmony_ci 16208c2ecf20Sopenharmony_ci /* store source and destination IP masks (big-enian) */ 16218c2ecf20Sopenharmony_ci IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRSIP4M, 16228c2ecf20Sopenharmony_ci ~input_mask->formatted.src_ip[0]); 16238c2ecf20Sopenharmony_ci IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRDIP4M, 16248c2ecf20Sopenharmony_ci ~input_mask->formatted.dst_ip[0]); 16258c2ecf20Sopenharmony_ci 16268c2ecf20Sopenharmony_ci return 0; 16278c2ecf20Sopenharmony_ci} 16288c2ecf20Sopenharmony_ci 16298c2ecf20Sopenharmony_cis32 ixgbe_fdir_write_perfect_filter_82599(struct ixgbe_hw *hw, 16308c2ecf20Sopenharmony_ci union ixgbe_atr_input *input, 16318c2ecf20Sopenharmony_ci u16 soft_id, u8 queue) 16328c2ecf20Sopenharmony_ci{ 16338c2ecf20Sopenharmony_ci u32 fdirport, fdirvlan, fdirhash, fdircmd; 16348c2ecf20Sopenharmony_ci s32 err; 16358c2ecf20Sopenharmony_ci 16368c2ecf20Sopenharmony_ci /* currently IPv6 is not supported, must be programmed with 0 */ 16378c2ecf20Sopenharmony_ci IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRSIPv6(0), 16388c2ecf20Sopenharmony_ci input->formatted.src_ip[0]); 16398c2ecf20Sopenharmony_ci IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRSIPv6(1), 16408c2ecf20Sopenharmony_ci input->formatted.src_ip[1]); 16418c2ecf20Sopenharmony_ci IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRSIPv6(2), 16428c2ecf20Sopenharmony_ci input->formatted.src_ip[2]); 16438c2ecf20Sopenharmony_ci 16448c2ecf20Sopenharmony_ci /* record the source address (big-endian) */ 16458c2ecf20Sopenharmony_ci IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRIPSA, input->formatted.src_ip[0]); 16468c2ecf20Sopenharmony_ci 16478c2ecf20Sopenharmony_ci /* record the first 32 bits of the destination address (big-endian) */ 16488c2ecf20Sopenharmony_ci IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRIPDA, input->formatted.dst_ip[0]); 16498c2ecf20Sopenharmony_ci 16508c2ecf20Sopenharmony_ci /* record source and destination port (little-endian)*/ 16518c2ecf20Sopenharmony_ci fdirport = ntohs(input->formatted.dst_port); 16528c2ecf20Sopenharmony_ci fdirport <<= IXGBE_FDIRPORT_DESTINATION_SHIFT; 16538c2ecf20Sopenharmony_ci fdirport |= ntohs(input->formatted.src_port); 16548c2ecf20Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_FDIRPORT, fdirport); 16558c2ecf20Sopenharmony_ci 16568c2ecf20Sopenharmony_ci /* record vlan (little-endian) and flex_bytes(big-endian) */ 16578c2ecf20Sopenharmony_ci fdirvlan = IXGBE_STORE_AS_BE16((__force u16)input->formatted.flex_bytes); 16588c2ecf20Sopenharmony_ci fdirvlan <<= IXGBE_FDIRVLAN_FLEX_SHIFT; 16598c2ecf20Sopenharmony_ci fdirvlan |= ntohs(input->formatted.vlan_id); 16608c2ecf20Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_FDIRVLAN, fdirvlan); 16618c2ecf20Sopenharmony_ci 16628c2ecf20Sopenharmony_ci /* configure FDIRHASH register */ 16638c2ecf20Sopenharmony_ci fdirhash = (__force u32)input->formatted.bkt_hash; 16648c2ecf20Sopenharmony_ci fdirhash |= soft_id << IXGBE_FDIRHASH_SIG_SW_INDEX_SHIFT; 16658c2ecf20Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_FDIRHASH, fdirhash); 16668c2ecf20Sopenharmony_ci 16678c2ecf20Sopenharmony_ci /* 16688c2ecf20Sopenharmony_ci * flush all previous writes to make certain registers are 16698c2ecf20Sopenharmony_ci * programmed prior to issuing the command 16708c2ecf20Sopenharmony_ci */ 16718c2ecf20Sopenharmony_ci IXGBE_WRITE_FLUSH(hw); 16728c2ecf20Sopenharmony_ci 16738c2ecf20Sopenharmony_ci /* configure FDIRCMD register */ 16748c2ecf20Sopenharmony_ci fdircmd = IXGBE_FDIRCMD_CMD_ADD_FLOW | IXGBE_FDIRCMD_FILTER_UPDATE | 16758c2ecf20Sopenharmony_ci IXGBE_FDIRCMD_LAST | IXGBE_FDIRCMD_QUEUE_EN; 16768c2ecf20Sopenharmony_ci if (queue == IXGBE_FDIR_DROP_QUEUE) 16778c2ecf20Sopenharmony_ci fdircmd |= IXGBE_FDIRCMD_DROP; 16788c2ecf20Sopenharmony_ci fdircmd |= input->formatted.flow_type << IXGBE_FDIRCMD_FLOW_TYPE_SHIFT; 16798c2ecf20Sopenharmony_ci fdircmd |= (u32)queue << IXGBE_FDIRCMD_RX_QUEUE_SHIFT; 16808c2ecf20Sopenharmony_ci fdircmd |= (u32)input->formatted.vm_pool << IXGBE_FDIRCMD_VT_POOL_SHIFT; 16818c2ecf20Sopenharmony_ci 16828c2ecf20Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_FDIRCMD, fdircmd); 16838c2ecf20Sopenharmony_ci err = ixgbe_fdir_check_cmd_complete(hw, &fdircmd); 16848c2ecf20Sopenharmony_ci if (err) { 16858c2ecf20Sopenharmony_ci hw_dbg(hw, "Flow Director command did not complete!\n"); 16868c2ecf20Sopenharmony_ci return err; 16878c2ecf20Sopenharmony_ci } 16888c2ecf20Sopenharmony_ci 16898c2ecf20Sopenharmony_ci return 0; 16908c2ecf20Sopenharmony_ci} 16918c2ecf20Sopenharmony_ci 16928c2ecf20Sopenharmony_cis32 ixgbe_fdir_erase_perfect_filter_82599(struct ixgbe_hw *hw, 16938c2ecf20Sopenharmony_ci union ixgbe_atr_input *input, 16948c2ecf20Sopenharmony_ci u16 soft_id) 16958c2ecf20Sopenharmony_ci{ 16968c2ecf20Sopenharmony_ci u32 fdirhash; 16978c2ecf20Sopenharmony_ci u32 fdircmd; 16988c2ecf20Sopenharmony_ci s32 err; 16998c2ecf20Sopenharmony_ci 17008c2ecf20Sopenharmony_ci /* configure FDIRHASH register */ 17018c2ecf20Sopenharmony_ci fdirhash = (__force u32)input->formatted.bkt_hash; 17028c2ecf20Sopenharmony_ci fdirhash |= soft_id << IXGBE_FDIRHASH_SIG_SW_INDEX_SHIFT; 17038c2ecf20Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_FDIRHASH, fdirhash); 17048c2ecf20Sopenharmony_ci 17058c2ecf20Sopenharmony_ci /* flush hash to HW */ 17068c2ecf20Sopenharmony_ci IXGBE_WRITE_FLUSH(hw); 17078c2ecf20Sopenharmony_ci 17088c2ecf20Sopenharmony_ci /* Query if filter is present */ 17098c2ecf20Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_FDIRCMD, IXGBE_FDIRCMD_CMD_QUERY_REM_FILT); 17108c2ecf20Sopenharmony_ci 17118c2ecf20Sopenharmony_ci err = ixgbe_fdir_check_cmd_complete(hw, &fdircmd); 17128c2ecf20Sopenharmony_ci if (err) { 17138c2ecf20Sopenharmony_ci hw_dbg(hw, "Flow Director command did not complete!\n"); 17148c2ecf20Sopenharmony_ci return err; 17158c2ecf20Sopenharmony_ci } 17168c2ecf20Sopenharmony_ci 17178c2ecf20Sopenharmony_ci /* if filter exists in hardware then remove it */ 17188c2ecf20Sopenharmony_ci if (fdircmd & IXGBE_FDIRCMD_FILTER_VALID) { 17198c2ecf20Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_FDIRHASH, fdirhash); 17208c2ecf20Sopenharmony_ci IXGBE_WRITE_FLUSH(hw); 17218c2ecf20Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_FDIRCMD, 17228c2ecf20Sopenharmony_ci IXGBE_FDIRCMD_CMD_REMOVE_FLOW); 17238c2ecf20Sopenharmony_ci } 17248c2ecf20Sopenharmony_ci 17258c2ecf20Sopenharmony_ci return 0; 17268c2ecf20Sopenharmony_ci} 17278c2ecf20Sopenharmony_ci 17288c2ecf20Sopenharmony_ci/** 17298c2ecf20Sopenharmony_ci * ixgbe_read_analog_reg8_82599 - Reads 8 bit Omer analog register 17308c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 17318c2ecf20Sopenharmony_ci * @reg: analog register to read 17328c2ecf20Sopenharmony_ci * @val: read value 17338c2ecf20Sopenharmony_ci * 17348c2ecf20Sopenharmony_ci * Performs read operation to Omer analog register specified. 17358c2ecf20Sopenharmony_ci **/ 17368c2ecf20Sopenharmony_cistatic s32 ixgbe_read_analog_reg8_82599(struct ixgbe_hw *hw, u32 reg, u8 *val) 17378c2ecf20Sopenharmony_ci{ 17388c2ecf20Sopenharmony_ci u32 core_ctl; 17398c2ecf20Sopenharmony_ci 17408c2ecf20Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_CORECTL, IXGBE_CORECTL_WRITE_CMD | 17418c2ecf20Sopenharmony_ci (reg << 8)); 17428c2ecf20Sopenharmony_ci IXGBE_WRITE_FLUSH(hw); 17438c2ecf20Sopenharmony_ci udelay(10); 17448c2ecf20Sopenharmony_ci core_ctl = IXGBE_READ_REG(hw, IXGBE_CORECTL); 17458c2ecf20Sopenharmony_ci *val = (u8)core_ctl; 17468c2ecf20Sopenharmony_ci 17478c2ecf20Sopenharmony_ci return 0; 17488c2ecf20Sopenharmony_ci} 17498c2ecf20Sopenharmony_ci 17508c2ecf20Sopenharmony_ci/** 17518c2ecf20Sopenharmony_ci * ixgbe_write_analog_reg8_82599 - Writes 8 bit Omer analog register 17528c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 17538c2ecf20Sopenharmony_ci * @reg: atlas register to write 17548c2ecf20Sopenharmony_ci * @val: value to write 17558c2ecf20Sopenharmony_ci * 17568c2ecf20Sopenharmony_ci * Performs write operation to Omer analog register specified. 17578c2ecf20Sopenharmony_ci **/ 17588c2ecf20Sopenharmony_cistatic s32 ixgbe_write_analog_reg8_82599(struct ixgbe_hw *hw, u32 reg, u8 val) 17598c2ecf20Sopenharmony_ci{ 17608c2ecf20Sopenharmony_ci u32 core_ctl; 17618c2ecf20Sopenharmony_ci 17628c2ecf20Sopenharmony_ci core_ctl = (reg << 8) | val; 17638c2ecf20Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_CORECTL, core_ctl); 17648c2ecf20Sopenharmony_ci IXGBE_WRITE_FLUSH(hw); 17658c2ecf20Sopenharmony_ci udelay(10); 17668c2ecf20Sopenharmony_ci 17678c2ecf20Sopenharmony_ci return 0; 17688c2ecf20Sopenharmony_ci} 17698c2ecf20Sopenharmony_ci 17708c2ecf20Sopenharmony_ci/** 17718c2ecf20Sopenharmony_ci * ixgbe_start_hw_82599 - Prepare hardware for Tx/Rx 17728c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 17738c2ecf20Sopenharmony_ci * 17748c2ecf20Sopenharmony_ci * Starts the hardware using the generic start_hw function 17758c2ecf20Sopenharmony_ci * and the generation start_hw function. 17768c2ecf20Sopenharmony_ci * Then performs revision-specific operations, if any. 17778c2ecf20Sopenharmony_ci **/ 17788c2ecf20Sopenharmony_cistatic s32 ixgbe_start_hw_82599(struct ixgbe_hw *hw) 17798c2ecf20Sopenharmony_ci{ 17808c2ecf20Sopenharmony_ci s32 ret_val = 0; 17818c2ecf20Sopenharmony_ci 17828c2ecf20Sopenharmony_ci ret_val = ixgbe_start_hw_generic(hw); 17838c2ecf20Sopenharmony_ci if (ret_val) 17848c2ecf20Sopenharmony_ci return ret_val; 17858c2ecf20Sopenharmony_ci 17868c2ecf20Sopenharmony_ci ret_val = ixgbe_start_hw_gen2(hw); 17878c2ecf20Sopenharmony_ci if (ret_val) 17888c2ecf20Sopenharmony_ci return ret_val; 17898c2ecf20Sopenharmony_ci 17908c2ecf20Sopenharmony_ci /* We need to run link autotry after the driver loads */ 17918c2ecf20Sopenharmony_ci hw->mac.autotry_restart = true; 17928c2ecf20Sopenharmony_ci 17938c2ecf20Sopenharmony_ci return ixgbe_verify_fw_version_82599(hw); 17948c2ecf20Sopenharmony_ci} 17958c2ecf20Sopenharmony_ci 17968c2ecf20Sopenharmony_ci/** 17978c2ecf20Sopenharmony_ci * ixgbe_identify_phy_82599 - Get physical layer module 17988c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 17998c2ecf20Sopenharmony_ci * 18008c2ecf20Sopenharmony_ci * Determines the physical layer module found on the current adapter. 18018c2ecf20Sopenharmony_ci * If PHY already detected, maintains current PHY type in hw struct, 18028c2ecf20Sopenharmony_ci * otherwise executes the PHY detection routine. 18038c2ecf20Sopenharmony_ci **/ 18048c2ecf20Sopenharmony_cistatic s32 ixgbe_identify_phy_82599(struct ixgbe_hw *hw) 18058c2ecf20Sopenharmony_ci{ 18068c2ecf20Sopenharmony_ci s32 status; 18078c2ecf20Sopenharmony_ci 18088c2ecf20Sopenharmony_ci /* Detect PHY if not unknown - returns success if already detected. */ 18098c2ecf20Sopenharmony_ci status = ixgbe_identify_phy_generic(hw); 18108c2ecf20Sopenharmony_ci if (status) { 18118c2ecf20Sopenharmony_ci /* 82599 10GBASE-T requires an external PHY */ 18128c2ecf20Sopenharmony_ci if (hw->mac.ops.get_media_type(hw) == ixgbe_media_type_copper) 18138c2ecf20Sopenharmony_ci return status; 18148c2ecf20Sopenharmony_ci status = ixgbe_identify_module_generic(hw); 18158c2ecf20Sopenharmony_ci } 18168c2ecf20Sopenharmony_ci 18178c2ecf20Sopenharmony_ci /* Set PHY type none if no PHY detected */ 18188c2ecf20Sopenharmony_ci if (hw->phy.type == ixgbe_phy_unknown) { 18198c2ecf20Sopenharmony_ci hw->phy.type = ixgbe_phy_none; 18208c2ecf20Sopenharmony_ci status = 0; 18218c2ecf20Sopenharmony_ci } 18228c2ecf20Sopenharmony_ci 18238c2ecf20Sopenharmony_ci /* Return error if SFP module has been detected but is not supported */ 18248c2ecf20Sopenharmony_ci if (hw->phy.type == ixgbe_phy_sfp_unsupported) 18258c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 18268c2ecf20Sopenharmony_ci 18278c2ecf20Sopenharmony_ci return status; 18288c2ecf20Sopenharmony_ci} 18298c2ecf20Sopenharmony_ci 18308c2ecf20Sopenharmony_ci/** 18318c2ecf20Sopenharmony_ci * ixgbe_enable_rx_dma_82599 - Enable the Rx DMA unit on 82599 18328c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 18338c2ecf20Sopenharmony_ci * @regval: register value to write to RXCTRL 18348c2ecf20Sopenharmony_ci * 18358c2ecf20Sopenharmony_ci * Enables the Rx DMA unit for 82599 18368c2ecf20Sopenharmony_ci **/ 18378c2ecf20Sopenharmony_cistatic s32 ixgbe_enable_rx_dma_82599(struct ixgbe_hw *hw, u32 regval) 18388c2ecf20Sopenharmony_ci{ 18398c2ecf20Sopenharmony_ci /* 18408c2ecf20Sopenharmony_ci * Workaround for 82599 silicon errata when enabling the Rx datapath. 18418c2ecf20Sopenharmony_ci * If traffic is incoming before we enable the Rx unit, it could hang 18428c2ecf20Sopenharmony_ci * the Rx DMA unit. Therefore, make sure the security engine is 18438c2ecf20Sopenharmony_ci * completely disabled prior to enabling the Rx unit. 18448c2ecf20Sopenharmony_ci */ 18458c2ecf20Sopenharmony_ci hw->mac.ops.disable_rx_buff(hw); 18468c2ecf20Sopenharmony_ci 18478c2ecf20Sopenharmony_ci if (regval & IXGBE_RXCTRL_RXEN) 18488c2ecf20Sopenharmony_ci hw->mac.ops.enable_rx(hw); 18498c2ecf20Sopenharmony_ci else 18508c2ecf20Sopenharmony_ci hw->mac.ops.disable_rx(hw); 18518c2ecf20Sopenharmony_ci 18528c2ecf20Sopenharmony_ci hw->mac.ops.enable_rx_buff(hw); 18538c2ecf20Sopenharmony_ci 18548c2ecf20Sopenharmony_ci return 0; 18558c2ecf20Sopenharmony_ci} 18568c2ecf20Sopenharmony_ci 18578c2ecf20Sopenharmony_ci/** 18588c2ecf20Sopenharmony_ci * ixgbe_verify_fw_version_82599 - verify fw version for 82599 18598c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 18608c2ecf20Sopenharmony_ci * 18618c2ecf20Sopenharmony_ci * Verifies that installed the firmware version is 0.6 or higher 18628c2ecf20Sopenharmony_ci * for SFI devices. All 82599 SFI devices should have version 0.6 or higher. 18638c2ecf20Sopenharmony_ci * 18648c2ecf20Sopenharmony_ci * Return: -EACCES if the FW is not present or if the FW version is 18658c2ecf20Sopenharmony_ci * not supported. 18668c2ecf20Sopenharmony_ci **/ 18678c2ecf20Sopenharmony_cistatic s32 ixgbe_verify_fw_version_82599(struct ixgbe_hw *hw) 18688c2ecf20Sopenharmony_ci{ 18698c2ecf20Sopenharmony_ci u16 fw_offset, fw_ptp_cfg_offset; 18708c2ecf20Sopenharmony_ci s32 status = -EACCES; 18718c2ecf20Sopenharmony_ci u16 offset; 18728c2ecf20Sopenharmony_ci u16 fw_version = 0; 18738c2ecf20Sopenharmony_ci 18748c2ecf20Sopenharmony_ci /* firmware check is only necessary for SFI devices */ 18758c2ecf20Sopenharmony_ci if (hw->phy.media_type != ixgbe_media_type_fiber) 18768c2ecf20Sopenharmony_ci return 0; 18778c2ecf20Sopenharmony_ci 18788c2ecf20Sopenharmony_ci /* get the offset to the Firmware Module block */ 18798c2ecf20Sopenharmony_ci offset = IXGBE_FW_PTR; 18808c2ecf20Sopenharmony_ci if (hw->eeprom.ops.read(hw, offset, &fw_offset)) 18818c2ecf20Sopenharmony_ci goto fw_version_err; 18828c2ecf20Sopenharmony_ci 18838c2ecf20Sopenharmony_ci if (fw_offset == 0 || fw_offset == 0xFFFF) 18848c2ecf20Sopenharmony_ci return -EACCES; 18858c2ecf20Sopenharmony_ci 18868c2ecf20Sopenharmony_ci /* get the offset to the Pass Through Patch Configuration block */ 18878c2ecf20Sopenharmony_ci offset = fw_offset + IXGBE_FW_PASSTHROUGH_PATCH_CONFIG_PTR; 18888c2ecf20Sopenharmony_ci if (hw->eeprom.ops.read(hw, offset, &fw_ptp_cfg_offset)) 18898c2ecf20Sopenharmony_ci goto fw_version_err; 18908c2ecf20Sopenharmony_ci 18918c2ecf20Sopenharmony_ci if (fw_ptp_cfg_offset == 0 || fw_ptp_cfg_offset == 0xFFFF) 18928c2ecf20Sopenharmony_ci return -EACCES; 18938c2ecf20Sopenharmony_ci 18948c2ecf20Sopenharmony_ci /* get the firmware version */ 18958c2ecf20Sopenharmony_ci offset = fw_ptp_cfg_offset + IXGBE_FW_PATCH_VERSION_4; 18968c2ecf20Sopenharmony_ci if (hw->eeprom.ops.read(hw, offset, &fw_version)) 18978c2ecf20Sopenharmony_ci goto fw_version_err; 18988c2ecf20Sopenharmony_ci 18998c2ecf20Sopenharmony_ci if (fw_version > 0x5) 19008c2ecf20Sopenharmony_ci status = 0; 19018c2ecf20Sopenharmony_ci 19028c2ecf20Sopenharmony_ci return status; 19038c2ecf20Sopenharmony_ci 19048c2ecf20Sopenharmony_cifw_version_err: 19058c2ecf20Sopenharmony_ci hw_err(hw, "eeprom read at offset %d failed\n", offset); 19068c2ecf20Sopenharmony_ci return -EACCES; 19078c2ecf20Sopenharmony_ci} 19088c2ecf20Sopenharmony_ci 19098c2ecf20Sopenharmony_ci/** 19108c2ecf20Sopenharmony_ci * ixgbe_verify_lesm_fw_enabled_82599 - Checks LESM FW module state. 19118c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 19128c2ecf20Sopenharmony_ci * 19138c2ecf20Sopenharmony_ci * Returns true if the LESM FW module is present and enabled. Otherwise 19148c2ecf20Sopenharmony_ci * returns false. Smart Speed must be disabled if LESM FW module is enabled. 19158c2ecf20Sopenharmony_ci **/ 19168c2ecf20Sopenharmony_cistatic bool ixgbe_verify_lesm_fw_enabled_82599(struct ixgbe_hw *hw) 19178c2ecf20Sopenharmony_ci{ 19188c2ecf20Sopenharmony_ci u16 fw_offset, fw_lesm_param_offset, fw_lesm_state; 19198c2ecf20Sopenharmony_ci s32 status; 19208c2ecf20Sopenharmony_ci 19218c2ecf20Sopenharmony_ci /* get the offset to the Firmware Module block */ 19228c2ecf20Sopenharmony_ci status = hw->eeprom.ops.read(hw, IXGBE_FW_PTR, &fw_offset); 19238c2ecf20Sopenharmony_ci 19248c2ecf20Sopenharmony_ci if (status || fw_offset == 0 || fw_offset == 0xFFFF) 19258c2ecf20Sopenharmony_ci return false; 19268c2ecf20Sopenharmony_ci 19278c2ecf20Sopenharmony_ci /* get the offset to the LESM Parameters block */ 19288c2ecf20Sopenharmony_ci status = hw->eeprom.ops.read(hw, (fw_offset + 19298c2ecf20Sopenharmony_ci IXGBE_FW_LESM_PARAMETERS_PTR), 19308c2ecf20Sopenharmony_ci &fw_lesm_param_offset); 19318c2ecf20Sopenharmony_ci 19328c2ecf20Sopenharmony_ci if (status || 19338c2ecf20Sopenharmony_ci fw_lesm_param_offset == 0 || fw_lesm_param_offset == 0xFFFF) 19348c2ecf20Sopenharmony_ci return false; 19358c2ecf20Sopenharmony_ci 19368c2ecf20Sopenharmony_ci /* get the lesm state word */ 19378c2ecf20Sopenharmony_ci status = hw->eeprom.ops.read(hw, (fw_lesm_param_offset + 19388c2ecf20Sopenharmony_ci IXGBE_FW_LESM_STATE_1), 19398c2ecf20Sopenharmony_ci &fw_lesm_state); 19408c2ecf20Sopenharmony_ci 19418c2ecf20Sopenharmony_ci if (!status && (fw_lesm_state & IXGBE_FW_LESM_STATE_ENABLED)) 19428c2ecf20Sopenharmony_ci return true; 19438c2ecf20Sopenharmony_ci 19448c2ecf20Sopenharmony_ci return false; 19458c2ecf20Sopenharmony_ci} 19468c2ecf20Sopenharmony_ci 19478c2ecf20Sopenharmony_ci/** 19488c2ecf20Sopenharmony_ci * ixgbe_read_eeprom_buffer_82599 - Read EEPROM word(s) using 19498c2ecf20Sopenharmony_ci * fastest available method 19508c2ecf20Sopenharmony_ci * 19518c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 19528c2ecf20Sopenharmony_ci * @offset: offset of word in EEPROM to read 19538c2ecf20Sopenharmony_ci * @words: number of words 19548c2ecf20Sopenharmony_ci * @data: word(s) read from the EEPROM 19558c2ecf20Sopenharmony_ci * 19568c2ecf20Sopenharmony_ci * Retrieves 16 bit word(s) read from EEPROM 19578c2ecf20Sopenharmony_ci **/ 19588c2ecf20Sopenharmony_cistatic s32 ixgbe_read_eeprom_buffer_82599(struct ixgbe_hw *hw, u16 offset, 19598c2ecf20Sopenharmony_ci u16 words, u16 *data) 19608c2ecf20Sopenharmony_ci{ 19618c2ecf20Sopenharmony_ci struct ixgbe_eeprom_info *eeprom = &hw->eeprom; 19628c2ecf20Sopenharmony_ci 19638c2ecf20Sopenharmony_ci /* If EEPROM is detected and can be addressed using 14 bits, 19648c2ecf20Sopenharmony_ci * use EERD otherwise use bit bang 19658c2ecf20Sopenharmony_ci */ 19668c2ecf20Sopenharmony_ci if (eeprom->type == ixgbe_eeprom_spi && 19678c2ecf20Sopenharmony_ci offset + (words - 1) <= IXGBE_EERD_MAX_ADDR) 19688c2ecf20Sopenharmony_ci return ixgbe_read_eerd_buffer_generic(hw, offset, words, data); 19698c2ecf20Sopenharmony_ci 19708c2ecf20Sopenharmony_ci return ixgbe_read_eeprom_buffer_bit_bang_generic(hw, offset, words, 19718c2ecf20Sopenharmony_ci data); 19728c2ecf20Sopenharmony_ci} 19738c2ecf20Sopenharmony_ci 19748c2ecf20Sopenharmony_ci/** 19758c2ecf20Sopenharmony_ci * ixgbe_read_eeprom_82599 - Read EEPROM word using 19768c2ecf20Sopenharmony_ci * fastest available method 19778c2ecf20Sopenharmony_ci * 19788c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 19798c2ecf20Sopenharmony_ci * @offset: offset of word in the EEPROM to read 19808c2ecf20Sopenharmony_ci * @data: word read from the EEPROM 19818c2ecf20Sopenharmony_ci * 19828c2ecf20Sopenharmony_ci * Reads a 16 bit word from the EEPROM 19838c2ecf20Sopenharmony_ci **/ 19848c2ecf20Sopenharmony_cistatic s32 ixgbe_read_eeprom_82599(struct ixgbe_hw *hw, 19858c2ecf20Sopenharmony_ci u16 offset, u16 *data) 19868c2ecf20Sopenharmony_ci{ 19878c2ecf20Sopenharmony_ci struct ixgbe_eeprom_info *eeprom = &hw->eeprom; 19888c2ecf20Sopenharmony_ci 19898c2ecf20Sopenharmony_ci /* 19908c2ecf20Sopenharmony_ci * If EEPROM is detected and can be addressed using 14 bits, 19918c2ecf20Sopenharmony_ci * use EERD otherwise use bit bang 19928c2ecf20Sopenharmony_ci */ 19938c2ecf20Sopenharmony_ci if (eeprom->type == ixgbe_eeprom_spi && offset <= IXGBE_EERD_MAX_ADDR) 19948c2ecf20Sopenharmony_ci return ixgbe_read_eerd_generic(hw, offset, data); 19958c2ecf20Sopenharmony_ci 19968c2ecf20Sopenharmony_ci return ixgbe_read_eeprom_bit_bang_generic(hw, offset, data); 19978c2ecf20Sopenharmony_ci} 19988c2ecf20Sopenharmony_ci 19998c2ecf20Sopenharmony_ci/** 20008c2ecf20Sopenharmony_ci * ixgbe_reset_pipeline_82599 - perform pipeline reset 20018c2ecf20Sopenharmony_ci * 20028c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 20038c2ecf20Sopenharmony_ci * 20048c2ecf20Sopenharmony_ci * Reset pipeline by asserting Restart_AN together with LMS change to ensure 20058c2ecf20Sopenharmony_ci * full pipeline reset. Note - We must hold the SW/FW semaphore before writing 20068c2ecf20Sopenharmony_ci * to AUTOC, so this function assumes the semaphore is held. 20078c2ecf20Sopenharmony_ci **/ 20088c2ecf20Sopenharmony_cistatic s32 ixgbe_reset_pipeline_82599(struct ixgbe_hw *hw) 20098c2ecf20Sopenharmony_ci{ 20108c2ecf20Sopenharmony_ci s32 ret_val; 20118c2ecf20Sopenharmony_ci u32 anlp1_reg = 0; 20128c2ecf20Sopenharmony_ci u32 i, autoc_reg, autoc2_reg; 20138c2ecf20Sopenharmony_ci 20148c2ecf20Sopenharmony_ci /* Enable link if disabled in NVM */ 20158c2ecf20Sopenharmony_ci autoc2_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC2); 20168c2ecf20Sopenharmony_ci if (autoc2_reg & IXGBE_AUTOC2_LINK_DISABLE_MASK) { 20178c2ecf20Sopenharmony_ci autoc2_reg &= ~IXGBE_AUTOC2_LINK_DISABLE_MASK; 20188c2ecf20Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_AUTOC2, autoc2_reg); 20198c2ecf20Sopenharmony_ci IXGBE_WRITE_FLUSH(hw); 20208c2ecf20Sopenharmony_ci } 20218c2ecf20Sopenharmony_ci 20228c2ecf20Sopenharmony_ci autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC); 20238c2ecf20Sopenharmony_ci autoc_reg |= IXGBE_AUTOC_AN_RESTART; 20248c2ecf20Sopenharmony_ci 20258c2ecf20Sopenharmony_ci /* Write AUTOC register with toggled LMS[2] bit and Restart_AN */ 20268c2ecf20Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_AUTOC, 20278c2ecf20Sopenharmony_ci autoc_reg ^ (0x4 << IXGBE_AUTOC_LMS_SHIFT)); 20288c2ecf20Sopenharmony_ci 20298c2ecf20Sopenharmony_ci /* Wait for AN to leave state 0 */ 20308c2ecf20Sopenharmony_ci for (i = 0; i < 10; i++) { 20318c2ecf20Sopenharmony_ci usleep_range(4000, 8000); 20328c2ecf20Sopenharmony_ci anlp1_reg = IXGBE_READ_REG(hw, IXGBE_ANLP1); 20338c2ecf20Sopenharmony_ci if (anlp1_reg & IXGBE_ANLP1_AN_STATE_MASK) 20348c2ecf20Sopenharmony_ci break; 20358c2ecf20Sopenharmony_ci } 20368c2ecf20Sopenharmony_ci 20378c2ecf20Sopenharmony_ci if (!(anlp1_reg & IXGBE_ANLP1_AN_STATE_MASK)) { 20388c2ecf20Sopenharmony_ci hw_dbg(hw, "auto negotiation not completed\n"); 20398c2ecf20Sopenharmony_ci ret_val = -EIO; 20408c2ecf20Sopenharmony_ci goto reset_pipeline_out; 20418c2ecf20Sopenharmony_ci } 20428c2ecf20Sopenharmony_ci 20438c2ecf20Sopenharmony_ci ret_val = 0; 20448c2ecf20Sopenharmony_ci 20458c2ecf20Sopenharmony_cireset_pipeline_out: 20468c2ecf20Sopenharmony_ci /* Write AUTOC register with original LMS field and Restart_AN */ 20478c2ecf20Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc_reg); 20488c2ecf20Sopenharmony_ci IXGBE_WRITE_FLUSH(hw); 20498c2ecf20Sopenharmony_ci 20508c2ecf20Sopenharmony_ci return ret_val; 20518c2ecf20Sopenharmony_ci} 20528c2ecf20Sopenharmony_ci 20538c2ecf20Sopenharmony_ci/** 20548c2ecf20Sopenharmony_ci * ixgbe_read_i2c_byte_82599 - Reads 8 bit word over I2C 20558c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 20568c2ecf20Sopenharmony_ci * @byte_offset: byte offset to read 20578c2ecf20Sopenharmony_ci * @dev_addr: address to read from 20588c2ecf20Sopenharmony_ci * @data: value read 20598c2ecf20Sopenharmony_ci * 20608c2ecf20Sopenharmony_ci * Performs byte read operation to SFP module's EEPROM over I2C interface at 20618c2ecf20Sopenharmony_ci * a specified device address. 20628c2ecf20Sopenharmony_ci **/ 20638c2ecf20Sopenharmony_cistatic s32 ixgbe_read_i2c_byte_82599(struct ixgbe_hw *hw, u8 byte_offset, 20648c2ecf20Sopenharmony_ci u8 dev_addr, u8 *data) 20658c2ecf20Sopenharmony_ci{ 20668c2ecf20Sopenharmony_ci u32 esdp; 20678c2ecf20Sopenharmony_ci s32 status; 20688c2ecf20Sopenharmony_ci s32 timeout = 200; 20698c2ecf20Sopenharmony_ci 20708c2ecf20Sopenharmony_ci if (hw->phy.qsfp_shared_i2c_bus == true) { 20718c2ecf20Sopenharmony_ci /* Acquire I2C bus ownership. */ 20728c2ecf20Sopenharmony_ci esdp = IXGBE_READ_REG(hw, IXGBE_ESDP); 20738c2ecf20Sopenharmony_ci esdp |= IXGBE_ESDP_SDP0; 20748c2ecf20Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); 20758c2ecf20Sopenharmony_ci IXGBE_WRITE_FLUSH(hw); 20768c2ecf20Sopenharmony_ci 20778c2ecf20Sopenharmony_ci while (timeout) { 20788c2ecf20Sopenharmony_ci esdp = IXGBE_READ_REG(hw, IXGBE_ESDP); 20798c2ecf20Sopenharmony_ci if (esdp & IXGBE_ESDP_SDP1) 20808c2ecf20Sopenharmony_ci break; 20818c2ecf20Sopenharmony_ci 20828c2ecf20Sopenharmony_ci usleep_range(5000, 10000); 20838c2ecf20Sopenharmony_ci timeout--; 20848c2ecf20Sopenharmony_ci } 20858c2ecf20Sopenharmony_ci 20868c2ecf20Sopenharmony_ci if (!timeout) { 20878c2ecf20Sopenharmony_ci hw_dbg(hw, "Driver can't access resource, acquiring I2C bus timeout.\n"); 20888c2ecf20Sopenharmony_ci status = -EIO; 20898c2ecf20Sopenharmony_ci goto release_i2c_access; 20908c2ecf20Sopenharmony_ci } 20918c2ecf20Sopenharmony_ci } 20928c2ecf20Sopenharmony_ci 20938c2ecf20Sopenharmony_ci status = ixgbe_read_i2c_byte_generic(hw, byte_offset, dev_addr, data); 20948c2ecf20Sopenharmony_ci 20958c2ecf20Sopenharmony_cirelease_i2c_access: 20968c2ecf20Sopenharmony_ci if (hw->phy.qsfp_shared_i2c_bus == true) { 20978c2ecf20Sopenharmony_ci /* Release I2C bus ownership. */ 20988c2ecf20Sopenharmony_ci esdp = IXGBE_READ_REG(hw, IXGBE_ESDP); 20998c2ecf20Sopenharmony_ci esdp &= ~IXGBE_ESDP_SDP0; 21008c2ecf20Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); 21018c2ecf20Sopenharmony_ci IXGBE_WRITE_FLUSH(hw); 21028c2ecf20Sopenharmony_ci } 21038c2ecf20Sopenharmony_ci 21048c2ecf20Sopenharmony_ci return status; 21058c2ecf20Sopenharmony_ci} 21068c2ecf20Sopenharmony_ci 21078c2ecf20Sopenharmony_ci/** 21088c2ecf20Sopenharmony_ci * ixgbe_write_i2c_byte_82599 - Writes 8 bit word over I2C 21098c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 21108c2ecf20Sopenharmony_ci * @byte_offset: byte offset to write 21118c2ecf20Sopenharmony_ci * @dev_addr: address to write to 21128c2ecf20Sopenharmony_ci * @data: value to write 21138c2ecf20Sopenharmony_ci * 21148c2ecf20Sopenharmony_ci * Performs byte write operation to SFP module's EEPROM over I2C interface at 21158c2ecf20Sopenharmony_ci * a specified device address. 21168c2ecf20Sopenharmony_ci **/ 21178c2ecf20Sopenharmony_cistatic s32 ixgbe_write_i2c_byte_82599(struct ixgbe_hw *hw, u8 byte_offset, 21188c2ecf20Sopenharmony_ci u8 dev_addr, u8 data) 21198c2ecf20Sopenharmony_ci{ 21208c2ecf20Sopenharmony_ci u32 esdp; 21218c2ecf20Sopenharmony_ci s32 status; 21228c2ecf20Sopenharmony_ci s32 timeout = 200; 21238c2ecf20Sopenharmony_ci 21248c2ecf20Sopenharmony_ci if (hw->phy.qsfp_shared_i2c_bus == true) { 21258c2ecf20Sopenharmony_ci /* Acquire I2C bus ownership. */ 21268c2ecf20Sopenharmony_ci esdp = IXGBE_READ_REG(hw, IXGBE_ESDP); 21278c2ecf20Sopenharmony_ci esdp |= IXGBE_ESDP_SDP0; 21288c2ecf20Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); 21298c2ecf20Sopenharmony_ci IXGBE_WRITE_FLUSH(hw); 21308c2ecf20Sopenharmony_ci 21318c2ecf20Sopenharmony_ci while (timeout) { 21328c2ecf20Sopenharmony_ci esdp = IXGBE_READ_REG(hw, IXGBE_ESDP); 21338c2ecf20Sopenharmony_ci if (esdp & IXGBE_ESDP_SDP1) 21348c2ecf20Sopenharmony_ci break; 21358c2ecf20Sopenharmony_ci 21368c2ecf20Sopenharmony_ci usleep_range(5000, 10000); 21378c2ecf20Sopenharmony_ci timeout--; 21388c2ecf20Sopenharmony_ci } 21398c2ecf20Sopenharmony_ci 21408c2ecf20Sopenharmony_ci if (!timeout) { 21418c2ecf20Sopenharmony_ci hw_dbg(hw, "Driver can't access resource, acquiring I2C bus timeout.\n"); 21428c2ecf20Sopenharmony_ci status = -EIO; 21438c2ecf20Sopenharmony_ci goto release_i2c_access; 21448c2ecf20Sopenharmony_ci } 21458c2ecf20Sopenharmony_ci } 21468c2ecf20Sopenharmony_ci 21478c2ecf20Sopenharmony_ci status = ixgbe_write_i2c_byte_generic(hw, byte_offset, dev_addr, data); 21488c2ecf20Sopenharmony_ci 21498c2ecf20Sopenharmony_cirelease_i2c_access: 21508c2ecf20Sopenharmony_ci if (hw->phy.qsfp_shared_i2c_bus == true) { 21518c2ecf20Sopenharmony_ci /* Release I2C bus ownership. */ 21528c2ecf20Sopenharmony_ci esdp = IXGBE_READ_REG(hw, IXGBE_ESDP); 21538c2ecf20Sopenharmony_ci esdp &= ~IXGBE_ESDP_SDP0; 21548c2ecf20Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); 21558c2ecf20Sopenharmony_ci IXGBE_WRITE_FLUSH(hw); 21568c2ecf20Sopenharmony_ci } 21578c2ecf20Sopenharmony_ci 21588c2ecf20Sopenharmony_ci return status; 21598c2ecf20Sopenharmony_ci} 21608c2ecf20Sopenharmony_ci 21618c2ecf20Sopenharmony_cistatic const struct ixgbe_mac_operations mac_ops_82599 = { 21628c2ecf20Sopenharmony_ci .init_hw = &ixgbe_init_hw_generic, 21638c2ecf20Sopenharmony_ci .reset_hw = &ixgbe_reset_hw_82599, 21648c2ecf20Sopenharmony_ci .start_hw = &ixgbe_start_hw_82599, 21658c2ecf20Sopenharmony_ci .clear_hw_cntrs = &ixgbe_clear_hw_cntrs_generic, 21668c2ecf20Sopenharmony_ci .get_media_type = &ixgbe_get_media_type_82599, 21678c2ecf20Sopenharmony_ci .enable_rx_dma = &ixgbe_enable_rx_dma_82599, 21688c2ecf20Sopenharmony_ci .disable_rx_buff = &ixgbe_disable_rx_buff_generic, 21698c2ecf20Sopenharmony_ci .enable_rx_buff = &ixgbe_enable_rx_buff_generic, 21708c2ecf20Sopenharmony_ci .get_mac_addr = &ixgbe_get_mac_addr_generic, 21718c2ecf20Sopenharmony_ci .get_san_mac_addr = &ixgbe_get_san_mac_addr_generic, 21728c2ecf20Sopenharmony_ci .get_device_caps = &ixgbe_get_device_caps_generic, 21738c2ecf20Sopenharmony_ci .get_wwn_prefix = &ixgbe_get_wwn_prefix_generic, 21748c2ecf20Sopenharmony_ci .stop_adapter = &ixgbe_stop_adapter_generic, 21758c2ecf20Sopenharmony_ci .get_bus_info = &ixgbe_get_bus_info_generic, 21768c2ecf20Sopenharmony_ci .set_lan_id = &ixgbe_set_lan_id_multi_port_pcie, 21778c2ecf20Sopenharmony_ci .read_analog_reg8 = &ixgbe_read_analog_reg8_82599, 21788c2ecf20Sopenharmony_ci .write_analog_reg8 = &ixgbe_write_analog_reg8_82599, 21798c2ecf20Sopenharmony_ci .stop_link_on_d3 = &ixgbe_stop_mac_link_on_d3_82599, 21808c2ecf20Sopenharmony_ci .setup_link = &ixgbe_setup_mac_link_82599, 21818c2ecf20Sopenharmony_ci .set_rxpba = &ixgbe_set_rxpba_generic, 21828c2ecf20Sopenharmony_ci .check_link = &ixgbe_check_mac_link_generic, 21838c2ecf20Sopenharmony_ci .get_link_capabilities = &ixgbe_get_link_capabilities_82599, 21848c2ecf20Sopenharmony_ci .led_on = &ixgbe_led_on_generic, 21858c2ecf20Sopenharmony_ci .led_off = &ixgbe_led_off_generic, 21868c2ecf20Sopenharmony_ci .init_led_link_act = ixgbe_init_led_link_act_generic, 21878c2ecf20Sopenharmony_ci .blink_led_start = &ixgbe_blink_led_start_generic, 21888c2ecf20Sopenharmony_ci .blink_led_stop = &ixgbe_blink_led_stop_generic, 21898c2ecf20Sopenharmony_ci .set_rar = &ixgbe_set_rar_generic, 21908c2ecf20Sopenharmony_ci .clear_rar = &ixgbe_clear_rar_generic, 21918c2ecf20Sopenharmony_ci .set_vmdq = &ixgbe_set_vmdq_generic, 21928c2ecf20Sopenharmony_ci .set_vmdq_san_mac = &ixgbe_set_vmdq_san_mac_generic, 21938c2ecf20Sopenharmony_ci .clear_vmdq = &ixgbe_clear_vmdq_generic, 21948c2ecf20Sopenharmony_ci .init_rx_addrs = &ixgbe_init_rx_addrs_generic, 21958c2ecf20Sopenharmony_ci .update_mc_addr_list = &ixgbe_update_mc_addr_list_generic, 21968c2ecf20Sopenharmony_ci .enable_mc = &ixgbe_enable_mc_generic, 21978c2ecf20Sopenharmony_ci .disable_mc = &ixgbe_disable_mc_generic, 21988c2ecf20Sopenharmony_ci .clear_vfta = &ixgbe_clear_vfta_generic, 21998c2ecf20Sopenharmony_ci .set_vfta = &ixgbe_set_vfta_generic, 22008c2ecf20Sopenharmony_ci .fc_enable = &ixgbe_fc_enable_generic, 22018c2ecf20Sopenharmony_ci .setup_fc = ixgbe_setup_fc_generic, 22028c2ecf20Sopenharmony_ci .fc_autoneg = ixgbe_fc_autoneg, 22038c2ecf20Sopenharmony_ci .set_fw_drv_ver = &ixgbe_set_fw_drv_ver_generic, 22048c2ecf20Sopenharmony_ci .init_uta_tables = &ixgbe_init_uta_tables_generic, 22058c2ecf20Sopenharmony_ci .setup_sfp = &ixgbe_setup_sfp_modules_82599, 22068c2ecf20Sopenharmony_ci .set_mac_anti_spoofing = &ixgbe_set_mac_anti_spoofing, 22078c2ecf20Sopenharmony_ci .set_vlan_anti_spoofing = &ixgbe_set_vlan_anti_spoofing, 22088c2ecf20Sopenharmony_ci .acquire_swfw_sync = &ixgbe_acquire_swfw_sync, 22098c2ecf20Sopenharmony_ci .release_swfw_sync = &ixgbe_release_swfw_sync, 22108c2ecf20Sopenharmony_ci .init_swfw_sync = NULL, 22118c2ecf20Sopenharmony_ci .get_thermal_sensor_data = &ixgbe_get_thermal_sensor_data_generic, 22128c2ecf20Sopenharmony_ci .init_thermal_sensor_thresh = &ixgbe_init_thermal_sensor_thresh_generic, 22138c2ecf20Sopenharmony_ci .prot_autoc_read = &prot_autoc_read_82599, 22148c2ecf20Sopenharmony_ci .prot_autoc_write = &prot_autoc_write_82599, 22158c2ecf20Sopenharmony_ci .enable_rx = &ixgbe_enable_rx_generic, 22168c2ecf20Sopenharmony_ci .disable_rx = &ixgbe_disable_rx_generic, 22178c2ecf20Sopenharmony_ci}; 22188c2ecf20Sopenharmony_ci 22198c2ecf20Sopenharmony_cistatic const struct ixgbe_eeprom_operations eeprom_ops_82599 = { 22208c2ecf20Sopenharmony_ci .init_params = &ixgbe_init_eeprom_params_generic, 22218c2ecf20Sopenharmony_ci .read = &ixgbe_read_eeprom_82599, 22228c2ecf20Sopenharmony_ci .read_buffer = &ixgbe_read_eeprom_buffer_82599, 22238c2ecf20Sopenharmony_ci .write = &ixgbe_write_eeprom_generic, 22248c2ecf20Sopenharmony_ci .write_buffer = &ixgbe_write_eeprom_buffer_bit_bang_generic, 22258c2ecf20Sopenharmony_ci .calc_checksum = &ixgbe_calc_eeprom_checksum_generic, 22268c2ecf20Sopenharmony_ci .validate_checksum = &ixgbe_validate_eeprom_checksum_generic, 22278c2ecf20Sopenharmony_ci .update_checksum = &ixgbe_update_eeprom_checksum_generic, 22288c2ecf20Sopenharmony_ci}; 22298c2ecf20Sopenharmony_ci 22308c2ecf20Sopenharmony_cistatic const struct ixgbe_phy_operations phy_ops_82599 = { 22318c2ecf20Sopenharmony_ci .identify = &ixgbe_identify_phy_82599, 22328c2ecf20Sopenharmony_ci .identify_sfp = &ixgbe_identify_module_generic, 22338c2ecf20Sopenharmony_ci .init = &ixgbe_init_phy_ops_82599, 22348c2ecf20Sopenharmony_ci .reset = &ixgbe_reset_phy_generic, 22358c2ecf20Sopenharmony_ci .read_reg = &ixgbe_read_phy_reg_generic, 22368c2ecf20Sopenharmony_ci .write_reg = &ixgbe_write_phy_reg_generic, 22378c2ecf20Sopenharmony_ci .setup_link = &ixgbe_setup_phy_link_generic, 22388c2ecf20Sopenharmony_ci .setup_link_speed = &ixgbe_setup_phy_link_speed_generic, 22398c2ecf20Sopenharmony_ci .read_i2c_byte = &ixgbe_read_i2c_byte_generic, 22408c2ecf20Sopenharmony_ci .write_i2c_byte = &ixgbe_write_i2c_byte_generic, 22418c2ecf20Sopenharmony_ci .read_i2c_sff8472 = &ixgbe_read_i2c_sff8472_generic, 22428c2ecf20Sopenharmony_ci .read_i2c_eeprom = &ixgbe_read_i2c_eeprom_generic, 22438c2ecf20Sopenharmony_ci .write_i2c_eeprom = &ixgbe_write_i2c_eeprom_generic, 22448c2ecf20Sopenharmony_ci .check_overtemp = &ixgbe_tn_check_overtemp, 22458c2ecf20Sopenharmony_ci}; 22468c2ecf20Sopenharmony_ci 22478c2ecf20Sopenharmony_ciconst struct ixgbe_info ixgbe_82599_info = { 22488c2ecf20Sopenharmony_ci .mac = ixgbe_mac_82599EB, 22498c2ecf20Sopenharmony_ci .get_invariants = &ixgbe_get_invariants_82599, 22508c2ecf20Sopenharmony_ci .mac_ops = &mac_ops_82599, 22518c2ecf20Sopenharmony_ci .eeprom_ops = &eeprom_ops_82599, 22528c2ecf20Sopenharmony_ci .phy_ops = &phy_ops_82599, 22538c2ecf20Sopenharmony_ci .mbx_ops = &mbx_ops_generic, 22548c2ecf20Sopenharmony_ci .mvals = ixgbe_mvals_8259X, 22558c2ecf20Sopenharmony_ci}; 2256