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