162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/* Copyright(c) 1999 - 2018 Intel Corporation. */
362306a36Sopenharmony_ci
462306a36Sopenharmony_ci#include <linux/pci.h>
562306a36Sopenharmony_ci#include <linux/delay.h>
662306a36Sopenharmony_ci#include <linux/sched.h>
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci#include "ixgbe.h"
962306a36Sopenharmony_ci#include "ixgbe_phy.h"
1062306a36Sopenharmony_ci#include "ixgbe_mbx.h"
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ci#define IXGBE_82599_MAX_TX_QUEUES 128
1362306a36Sopenharmony_ci#define IXGBE_82599_MAX_RX_QUEUES 128
1462306a36Sopenharmony_ci#define IXGBE_82599_RAR_ENTRIES   128
1562306a36Sopenharmony_ci#define IXGBE_82599_MC_TBL_SIZE   128
1662306a36Sopenharmony_ci#define IXGBE_82599_VFT_TBL_SIZE  128
1762306a36Sopenharmony_ci#define IXGBE_82599_RX_PB_SIZE	  512
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_cistatic void ixgbe_disable_tx_laser_multispeed_fiber(struct ixgbe_hw *hw);
2062306a36Sopenharmony_cistatic void ixgbe_enable_tx_laser_multispeed_fiber(struct ixgbe_hw *hw);
2162306a36Sopenharmony_cistatic void ixgbe_flap_tx_laser_multispeed_fiber(struct ixgbe_hw *hw);
2262306a36Sopenharmony_cistatic void
2362306a36Sopenharmony_ciixgbe_set_hard_rate_select_speed(struct ixgbe_hw *, ixgbe_link_speed);
2462306a36Sopenharmony_cistatic s32 ixgbe_setup_mac_link_smartspeed(struct ixgbe_hw *hw,
2562306a36Sopenharmony_ci					   ixgbe_link_speed speed,
2662306a36Sopenharmony_ci					   bool autoneg_wait_to_complete);
2762306a36Sopenharmony_cistatic void ixgbe_stop_mac_link_on_d3_82599(struct ixgbe_hw *hw);
2862306a36Sopenharmony_cistatic s32 ixgbe_start_mac_link_82599(struct ixgbe_hw *hw,
2962306a36Sopenharmony_ci				      bool autoneg_wait_to_complete);
3062306a36Sopenharmony_cistatic s32 ixgbe_setup_mac_link_82599(struct ixgbe_hw *hw,
3162306a36Sopenharmony_ci			       ixgbe_link_speed speed,
3262306a36Sopenharmony_ci			       bool autoneg_wait_to_complete);
3362306a36Sopenharmony_cistatic s32 ixgbe_setup_copper_link_82599(struct ixgbe_hw *hw,
3462306a36Sopenharmony_ci					 ixgbe_link_speed speed,
3562306a36Sopenharmony_ci					 bool autoneg_wait_to_complete);
3662306a36Sopenharmony_cistatic s32 ixgbe_verify_fw_version_82599(struct ixgbe_hw *hw);
3762306a36Sopenharmony_cistatic s32 ixgbe_read_i2c_byte_82599(struct ixgbe_hw *hw, u8 byte_offset,
3862306a36Sopenharmony_ci				     u8 dev_addr, u8 *data);
3962306a36Sopenharmony_cistatic s32 ixgbe_write_i2c_byte_82599(struct ixgbe_hw *hw, u8 byte_offset,
4062306a36Sopenharmony_ci				      u8 dev_addr, u8 data);
4162306a36Sopenharmony_cistatic s32 ixgbe_reset_pipeline_82599(struct ixgbe_hw *hw);
4262306a36Sopenharmony_cistatic bool ixgbe_verify_lesm_fw_enabled_82599(struct ixgbe_hw *hw);
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_cibool ixgbe_mng_enabled(struct ixgbe_hw *hw)
4562306a36Sopenharmony_ci{
4662306a36Sopenharmony_ci	u32 fwsm, manc, factps;
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_ci	fwsm = IXGBE_READ_REG(hw, IXGBE_FWSM(hw));
4962306a36Sopenharmony_ci	if ((fwsm & IXGBE_FWSM_MODE_MASK) != IXGBE_FWSM_FW_MODE_PT)
5062306a36Sopenharmony_ci		return false;
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_ci	manc = IXGBE_READ_REG(hw, IXGBE_MANC);
5362306a36Sopenharmony_ci	if (!(manc & IXGBE_MANC_RCV_TCO_EN))
5462306a36Sopenharmony_ci		return false;
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_ci	factps = IXGBE_READ_REG(hw, IXGBE_FACTPS(hw));
5762306a36Sopenharmony_ci	if (factps & IXGBE_FACTPS_MNGCG)
5862306a36Sopenharmony_ci		return false;
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_ci	return true;
6162306a36Sopenharmony_ci}
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_cistatic void ixgbe_init_mac_link_ops_82599(struct ixgbe_hw *hw)
6462306a36Sopenharmony_ci{
6562306a36Sopenharmony_ci	struct ixgbe_mac_info *mac = &hw->mac;
6662306a36Sopenharmony_ci
6762306a36Sopenharmony_ci	/* enable the laser control functions for SFP+ fiber
6862306a36Sopenharmony_ci	 * and MNG not enabled
6962306a36Sopenharmony_ci	 */
7062306a36Sopenharmony_ci	if ((mac->ops.get_media_type(hw) == ixgbe_media_type_fiber) &&
7162306a36Sopenharmony_ci	    !ixgbe_mng_enabled(hw)) {
7262306a36Sopenharmony_ci		mac->ops.disable_tx_laser =
7362306a36Sopenharmony_ci				       &ixgbe_disable_tx_laser_multispeed_fiber;
7462306a36Sopenharmony_ci		mac->ops.enable_tx_laser =
7562306a36Sopenharmony_ci					&ixgbe_enable_tx_laser_multispeed_fiber;
7662306a36Sopenharmony_ci		mac->ops.flap_tx_laser = &ixgbe_flap_tx_laser_multispeed_fiber;
7762306a36Sopenharmony_ci	} else {
7862306a36Sopenharmony_ci		mac->ops.disable_tx_laser = NULL;
7962306a36Sopenharmony_ci		mac->ops.enable_tx_laser = NULL;
8062306a36Sopenharmony_ci		mac->ops.flap_tx_laser = NULL;
8162306a36Sopenharmony_ci	}
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_ci	if (hw->phy.multispeed_fiber) {
8462306a36Sopenharmony_ci		/* Set up dual speed SFP+ support */
8562306a36Sopenharmony_ci		mac->ops.setup_link = &ixgbe_setup_mac_link_multispeed_fiber;
8662306a36Sopenharmony_ci		mac->ops.setup_mac_link = ixgbe_setup_mac_link_82599;
8762306a36Sopenharmony_ci		mac->ops.set_rate_select_speed =
8862306a36Sopenharmony_ci					       ixgbe_set_hard_rate_select_speed;
8962306a36Sopenharmony_ci	} else {
9062306a36Sopenharmony_ci		if ((mac->ops.get_media_type(hw) ==
9162306a36Sopenharmony_ci		     ixgbe_media_type_backplane) &&
9262306a36Sopenharmony_ci		    (hw->phy.smart_speed == ixgbe_smart_speed_auto ||
9362306a36Sopenharmony_ci		     hw->phy.smart_speed == ixgbe_smart_speed_on) &&
9462306a36Sopenharmony_ci		     !ixgbe_verify_lesm_fw_enabled_82599(hw))
9562306a36Sopenharmony_ci			mac->ops.setup_link = &ixgbe_setup_mac_link_smartspeed;
9662306a36Sopenharmony_ci		else
9762306a36Sopenharmony_ci			mac->ops.setup_link = &ixgbe_setup_mac_link_82599;
9862306a36Sopenharmony_ci	}
9962306a36Sopenharmony_ci}
10062306a36Sopenharmony_ci
10162306a36Sopenharmony_cistatic s32 ixgbe_setup_sfp_modules_82599(struct ixgbe_hw *hw)
10262306a36Sopenharmony_ci{
10362306a36Sopenharmony_ci	s32 ret_val;
10462306a36Sopenharmony_ci	u16 list_offset, data_offset, data_value;
10562306a36Sopenharmony_ci
10662306a36Sopenharmony_ci	if (hw->phy.sfp_type != ixgbe_sfp_type_unknown) {
10762306a36Sopenharmony_ci		ixgbe_init_mac_link_ops_82599(hw);
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_ci		hw->phy.ops.reset = NULL;
11062306a36Sopenharmony_ci
11162306a36Sopenharmony_ci		ret_val = ixgbe_get_sfp_init_sequence_offsets(hw, &list_offset,
11262306a36Sopenharmony_ci							      &data_offset);
11362306a36Sopenharmony_ci		if (ret_val)
11462306a36Sopenharmony_ci			return ret_val;
11562306a36Sopenharmony_ci
11662306a36Sopenharmony_ci		/* PHY config will finish before releasing the semaphore */
11762306a36Sopenharmony_ci		ret_val = hw->mac.ops.acquire_swfw_sync(hw,
11862306a36Sopenharmony_ci							IXGBE_GSSR_MAC_CSR_SM);
11962306a36Sopenharmony_ci		if (ret_val)
12062306a36Sopenharmony_ci			return -EBUSY;
12162306a36Sopenharmony_ci
12262306a36Sopenharmony_ci		if (hw->eeprom.ops.read(hw, ++data_offset, &data_value))
12362306a36Sopenharmony_ci			goto setup_sfp_err;
12462306a36Sopenharmony_ci		while (data_value != 0xffff) {
12562306a36Sopenharmony_ci			IXGBE_WRITE_REG(hw, IXGBE_CORECTL, data_value);
12662306a36Sopenharmony_ci			IXGBE_WRITE_FLUSH(hw);
12762306a36Sopenharmony_ci			if (hw->eeprom.ops.read(hw, ++data_offset, &data_value))
12862306a36Sopenharmony_ci				goto setup_sfp_err;
12962306a36Sopenharmony_ci		}
13062306a36Sopenharmony_ci
13162306a36Sopenharmony_ci		/* Release the semaphore */
13262306a36Sopenharmony_ci		hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_MAC_CSR_SM);
13362306a36Sopenharmony_ci		/*
13462306a36Sopenharmony_ci		 * Delay obtaining semaphore again to allow FW access,
13562306a36Sopenharmony_ci		 * semaphore_delay is in ms usleep_range needs us.
13662306a36Sopenharmony_ci		 */
13762306a36Sopenharmony_ci		usleep_range(hw->eeprom.semaphore_delay * 1000,
13862306a36Sopenharmony_ci			     hw->eeprom.semaphore_delay * 2000);
13962306a36Sopenharmony_ci
14062306a36Sopenharmony_ci		/* Restart DSP and set SFI mode */
14162306a36Sopenharmony_ci		ret_val = hw->mac.ops.prot_autoc_write(hw,
14262306a36Sopenharmony_ci			hw->mac.orig_autoc | IXGBE_AUTOC_LMS_10G_SERIAL,
14362306a36Sopenharmony_ci			false);
14462306a36Sopenharmony_ci
14562306a36Sopenharmony_ci		if (ret_val) {
14662306a36Sopenharmony_ci			hw_dbg(hw, " sfp module setup not complete\n");
14762306a36Sopenharmony_ci			return -EIO;
14862306a36Sopenharmony_ci		}
14962306a36Sopenharmony_ci	}
15062306a36Sopenharmony_ci
15162306a36Sopenharmony_ci	return 0;
15262306a36Sopenharmony_ci
15362306a36Sopenharmony_cisetup_sfp_err:
15462306a36Sopenharmony_ci	/* Release the semaphore */
15562306a36Sopenharmony_ci	hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_MAC_CSR_SM);
15662306a36Sopenharmony_ci	/* Delay obtaining semaphore again to allow FW access,
15762306a36Sopenharmony_ci	 * semaphore_delay is in ms usleep_range needs us.
15862306a36Sopenharmony_ci	 */
15962306a36Sopenharmony_ci	usleep_range(hw->eeprom.semaphore_delay * 1000,
16062306a36Sopenharmony_ci		     hw->eeprom.semaphore_delay * 2000);
16162306a36Sopenharmony_ci	hw_err(hw, "eeprom read at offset %d failed\n", data_offset);
16262306a36Sopenharmony_ci	return -EIO;
16362306a36Sopenharmony_ci}
16462306a36Sopenharmony_ci
16562306a36Sopenharmony_ci/**
16662306a36Sopenharmony_ci *  prot_autoc_read_82599 - Hides MAC differences needed for AUTOC read
16762306a36Sopenharmony_ci *  @hw: pointer to hardware structure
16862306a36Sopenharmony_ci *  @locked: Return the if we locked for this read.
16962306a36Sopenharmony_ci *  @reg_val: Value we read from AUTOC
17062306a36Sopenharmony_ci *
17162306a36Sopenharmony_ci *  For this part (82599) we need to wrap read-modify-writes with a possible
17262306a36Sopenharmony_ci *  FW/SW lock.  It is assumed this lock will be freed with the next
17362306a36Sopenharmony_ci *  prot_autoc_write_82599().  Note, that locked can only be true in cases
17462306a36Sopenharmony_ci *  where this function doesn't return an error.
17562306a36Sopenharmony_ci **/
17662306a36Sopenharmony_cistatic s32 prot_autoc_read_82599(struct ixgbe_hw *hw, bool *locked,
17762306a36Sopenharmony_ci				 u32 *reg_val)
17862306a36Sopenharmony_ci{
17962306a36Sopenharmony_ci	s32 ret_val;
18062306a36Sopenharmony_ci
18162306a36Sopenharmony_ci	*locked = false;
18262306a36Sopenharmony_ci	/* If LESM is on then we need to hold the SW/FW semaphore. */
18362306a36Sopenharmony_ci	if (ixgbe_verify_lesm_fw_enabled_82599(hw)) {
18462306a36Sopenharmony_ci		ret_val = hw->mac.ops.acquire_swfw_sync(hw,
18562306a36Sopenharmony_ci					IXGBE_GSSR_MAC_CSR_SM);
18662306a36Sopenharmony_ci		if (ret_val)
18762306a36Sopenharmony_ci			return -EBUSY;
18862306a36Sopenharmony_ci
18962306a36Sopenharmony_ci		*locked = true;
19062306a36Sopenharmony_ci	}
19162306a36Sopenharmony_ci
19262306a36Sopenharmony_ci	*reg_val = IXGBE_READ_REG(hw, IXGBE_AUTOC);
19362306a36Sopenharmony_ci	return 0;
19462306a36Sopenharmony_ci}
19562306a36Sopenharmony_ci
19662306a36Sopenharmony_ci/**
19762306a36Sopenharmony_ci * prot_autoc_write_82599 - Hides MAC differences needed for AUTOC write
19862306a36Sopenharmony_ci * @hw: pointer to hardware structure
19962306a36Sopenharmony_ci * @autoc: value to write to AUTOC
20062306a36Sopenharmony_ci * @locked: bool to indicate whether the SW/FW lock was already taken by
20162306a36Sopenharmony_ci *	     previous proc_autoc_read_82599.
20262306a36Sopenharmony_ci *
20362306a36Sopenharmony_ci * This part (82599) may need to hold a the SW/FW lock around all writes to
20462306a36Sopenharmony_ci * AUTOC. Likewise after a write we need to do a pipeline reset.
20562306a36Sopenharmony_ci **/
20662306a36Sopenharmony_cistatic s32 prot_autoc_write_82599(struct ixgbe_hw *hw, u32 autoc, bool locked)
20762306a36Sopenharmony_ci{
20862306a36Sopenharmony_ci	s32 ret_val = 0;
20962306a36Sopenharmony_ci
21062306a36Sopenharmony_ci	/* Blocked by MNG FW so bail */
21162306a36Sopenharmony_ci	if (ixgbe_check_reset_blocked(hw))
21262306a36Sopenharmony_ci		goto out;
21362306a36Sopenharmony_ci
21462306a36Sopenharmony_ci	/* We only need to get the lock if:
21562306a36Sopenharmony_ci	 *  - We didn't do it already (in the read part of a read-modify-write)
21662306a36Sopenharmony_ci	 *  - LESM is enabled.
21762306a36Sopenharmony_ci	 */
21862306a36Sopenharmony_ci	if (!locked && ixgbe_verify_lesm_fw_enabled_82599(hw)) {
21962306a36Sopenharmony_ci		ret_val = hw->mac.ops.acquire_swfw_sync(hw,
22062306a36Sopenharmony_ci					IXGBE_GSSR_MAC_CSR_SM);
22162306a36Sopenharmony_ci		if (ret_val)
22262306a36Sopenharmony_ci			return -EBUSY;
22362306a36Sopenharmony_ci
22462306a36Sopenharmony_ci		locked = true;
22562306a36Sopenharmony_ci	}
22662306a36Sopenharmony_ci
22762306a36Sopenharmony_ci	IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc);
22862306a36Sopenharmony_ci	ret_val = ixgbe_reset_pipeline_82599(hw);
22962306a36Sopenharmony_ci
23062306a36Sopenharmony_ciout:
23162306a36Sopenharmony_ci	/* Free the SW/FW semaphore as we either grabbed it here or
23262306a36Sopenharmony_ci	 * already had it when this function was called.
23362306a36Sopenharmony_ci	 */
23462306a36Sopenharmony_ci	if (locked)
23562306a36Sopenharmony_ci		hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_MAC_CSR_SM);
23662306a36Sopenharmony_ci
23762306a36Sopenharmony_ci	return ret_val;
23862306a36Sopenharmony_ci}
23962306a36Sopenharmony_ci
24062306a36Sopenharmony_cistatic s32 ixgbe_get_invariants_82599(struct ixgbe_hw *hw)
24162306a36Sopenharmony_ci{
24262306a36Sopenharmony_ci	struct ixgbe_mac_info *mac = &hw->mac;
24362306a36Sopenharmony_ci
24462306a36Sopenharmony_ci	ixgbe_init_mac_link_ops_82599(hw);
24562306a36Sopenharmony_ci
24662306a36Sopenharmony_ci	mac->mcft_size = IXGBE_82599_MC_TBL_SIZE;
24762306a36Sopenharmony_ci	mac->vft_size = IXGBE_82599_VFT_TBL_SIZE;
24862306a36Sopenharmony_ci	mac->num_rar_entries = IXGBE_82599_RAR_ENTRIES;
24962306a36Sopenharmony_ci	mac->rx_pb_size = IXGBE_82599_RX_PB_SIZE;
25062306a36Sopenharmony_ci	mac->max_rx_queues = IXGBE_82599_MAX_RX_QUEUES;
25162306a36Sopenharmony_ci	mac->max_tx_queues = IXGBE_82599_MAX_TX_QUEUES;
25262306a36Sopenharmony_ci	mac->max_msix_vectors = ixgbe_get_pcie_msix_count_generic(hw);
25362306a36Sopenharmony_ci
25462306a36Sopenharmony_ci	return 0;
25562306a36Sopenharmony_ci}
25662306a36Sopenharmony_ci
25762306a36Sopenharmony_ci/**
25862306a36Sopenharmony_ci *  ixgbe_init_phy_ops_82599 - PHY/SFP specific init
25962306a36Sopenharmony_ci *  @hw: pointer to hardware structure
26062306a36Sopenharmony_ci *
26162306a36Sopenharmony_ci *  Initialize any function pointers that were not able to be
26262306a36Sopenharmony_ci *  set during get_invariants because the PHY/SFP type was
26362306a36Sopenharmony_ci *  not known.  Perform the SFP init if necessary.
26462306a36Sopenharmony_ci *
26562306a36Sopenharmony_ci **/
26662306a36Sopenharmony_cistatic s32 ixgbe_init_phy_ops_82599(struct ixgbe_hw *hw)
26762306a36Sopenharmony_ci{
26862306a36Sopenharmony_ci	struct ixgbe_mac_info *mac = &hw->mac;
26962306a36Sopenharmony_ci	struct ixgbe_phy_info *phy = &hw->phy;
27062306a36Sopenharmony_ci	s32 ret_val;
27162306a36Sopenharmony_ci	u32 esdp;
27262306a36Sopenharmony_ci
27362306a36Sopenharmony_ci	if (hw->device_id == IXGBE_DEV_ID_82599_QSFP_SF_QP) {
27462306a36Sopenharmony_ci		/* Store flag indicating I2C bus access control unit. */
27562306a36Sopenharmony_ci		hw->phy.qsfp_shared_i2c_bus = true;
27662306a36Sopenharmony_ci
27762306a36Sopenharmony_ci		/* Initialize access to QSFP+ I2C bus */
27862306a36Sopenharmony_ci		esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
27962306a36Sopenharmony_ci		esdp |= IXGBE_ESDP_SDP0_DIR;
28062306a36Sopenharmony_ci		esdp &= ~IXGBE_ESDP_SDP1_DIR;
28162306a36Sopenharmony_ci		esdp &= ~IXGBE_ESDP_SDP0;
28262306a36Sopenharmony_ci		esdp &= ~IXGBE_ESDP_SDP0_NATIVE;
28362306a36Sopenharmony_ci		esdp &= ~IXGBE_ESDP_SDP1_NATIVE;
28462306a36Sopenharmony_ci		IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
28562306a36Sopenharmony_ci		IXGBE_WRITE_FLUSH(hw);
28662306a36Sopenharmony_ci
28762306a36Sopenharmony_ci		phy->ops.read_i2c_byte = &ixgbe_read_i2c_byte_82599;
28862306a36Sopenharmony_ci		phy->ops.write_i2c_byte = &ixgbe_write_i2c_byte_82599;
28962306a36Sopenharmony_ci	}
29062306a36Sopenharmony_ci
29162306a36Sopenharmony_ci	/* Identify the PHY or SFP module */
29262306a36Sopenharmony_ci	ret_val = phy->ops.identify(hw);
29362306a36Sopenharmony_ci
29462306a36Sopenharmony_ci	/* Setup function pointers based on detected SFP module and speeds */
29562306a36Sopenharmony_ci	ixgbe_init_mac_link_ops_82599(hw);
29662306a36Sopenharmony_ci
29762306a36Sopenharmony_ci	/* If copper media, overwrite with copper function pointers */
29862306a36Sopenharmony_ci	if (mac->ops.get_media_type(hw) == ixgbe_media_type_copper) {
29962306a36Sopenharmony_ci		mac->ops.setup_link = &ixgbe_setup_copper_link_82599;
30062306a36Sopenharmony_ci		mac->ops.get_link_capabilities =
30162306a36Sopenharmony_ci			&ixgbe_get_copper_link_capabilities_generic;
30262306a36Sopenharmony_ci	}
30362306a36Sopenharmony_ci
30462306a36Sopenharmony_ci	/* Set necessary function pointers based on phy type */
30562306a36Sopenharmony_ci	switch (hw->phy.type) {
30662306a36Sopenharmony_ci	case ixgbe_phy_tn:
30762306a36Sopenharmony_ci		phy->ops.check_link = &ixgbe_check_phy_link_tnx;
30862306a36Sopenharmony_ci		phy->ops.setup_link = &ixgbe_setup_phy_link_tnx;
30962306a36Sopenharmony_ci		break;
31062306a36Sopenharmony_ci	default:
31162306a36Sopenharmony_ci		break;
31262306a36Sopenharmony_ci	}
31362306a36Sopenharmony_ci
31462306a36Sopenharmony_ci	return ret_val;
31562306a36Sopenharmony_ci}
31662306a36Sopenharmony_ci
31762306a36Sopenharmony_ci/**
31862306a36Sopenharmony_ci *  ixgbe_get_link_capabilities_82599 - Determines link capabilities
31962306a36Sopenharmony_ci *  @hw: pointer to hardware structure
32062306a36Sopenharmony_ci *  @speed: pointer to link speed
32162306a36Sopenharmony_ci *  @autoneg: true when autoneg or autotry is enabled
32262306a36Sopenharmony_ci *
32362306a36Sopenharmony_ci *  Determines the link capabilities by reading the AUTOC register.
32462306a36Sopenharmony_ci **/
32562306a36Sopenharmony_cistatic s32 ixgbe_get_link_capabilities_82599(struct ixgbe_hw *hw,
32662306a36Sopenharmony_ci					     ixgbe_link_speed *speed,
32762306a36Sopenharmony_ci					     bool *autoneg)
32862306a36Sopenharmony_ci{
32962306a36Sopenharmony_ci	u32 autoc = 0;
33062306a36Sopenharmony_ci
33162306a36Sopenharmony_ci	/* Determine 1G link capabilities off of SFP+ type */
33262306a36Sopenharmony_ci	if (hw->phy.sfp_type == ixgbe_sfp_type_1g_cu_core0 ||
33362306a36Sopenharmony_ci	    hw->phy.sfp_type == ixgbe_sfp_type_1g_cu_core1 ||
33462306a36Sopenharmony_ci	    hw->phy.sfp_type == ixgbe_sfp_type_1g_lx_core0 ||
33562306a36Sopenharmony_ci	    hw->phy.sfp_type == ixgbe_sfp_type_1g_lx_core1 ||
33662306a36Sopenharmony_ci	    hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core0 ||
33762306a36Sopenharmony_ci	    hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core1) {
33862306a36Sopenharmony_ci		*speed = IXGBE_LINK_SPEED_1GB_FULL;
33962306a36Sopenharmony_ci		*autoneg = true;
34062306a36Sopenharmony_ci		return 0;
34162306a36Sopenharmony_ci	}
34262306a36Sopenharmony_ci
34362306a36Sopenharmony_ci	/*
34462306a36Sopenharmony_ci	 * Determine link capabilities based on the stored value of AUTOC,
34562306a36Sopenharmony_ci	 * which represents EEPROM defaults.  If AUTOC value has not been
34662306a36Sopenharmony_ci	 * stored, use the current register value.
34762306a36Sopenharmony_ci	 */
34862306a36Sopenharmony_ci	if (hw->mac.orig_link_settings_stored)
34962306a36Sopenharmony_ci		autoc = hw->mac.orig_autoc;
35062306a36Sopenharmony_ci	else
35162306a36Sopenharmony_ci		autoc = IXGBE_READ_REG(hw, IXGBE_AUTOC);
35262306a36Sopenharmony_ci
35362306a36Sopenharmony_ci	switch (autoc & IXGBE_AUTOC_LMS_MASK) {
35462306a36Sopenharmony_ci	case IXGBE_AUTOC_LMS_1G_LINK_NO_AN:
35562306a36Sopenharmony_ci		*speed = IXGBE_LINK_SPEED_1GB_FULL;
35662306a36Sopenharmony_ci		*autoneg = false;
35762306a36Sopenharmony_ci		break;
35862306a36Sopenharmony_ci
35962306a36Sopenharmony_ci	case IXGBE_AUTOC_LMS_10G_LINK_NO_AN:
36062306a36Sopenharmony_ci		*speed = IXGBE_LINK_SPEED_10GB_FULL;
36162306a36Sopenharmony_ci		*autoneg = false;
36262306a36Sopenharmony_ci		break;
36362306a36Sopenharmony_ci
36462306a36Sopenharmony_ci	case IXGBE_AUTOC_LMS_1G_AN:
36562306a36Sopenharmony_ci		*speed = IXGBE_LINK_SPEED_1GB_FULL;
36662306a36Sopenharmony_ci		*autoneg = true;
36762306a36Sopenharmony_ci		break;
36862306a36Sopenharmony_ci
36962306a36Sopenharmony_ci	case IXGBE_AUTOC_LMS_10G_SERIAL:
37062306a36Sopenharmony_ci		*speed = IXGBE_LINK_SPEED_10GB_FULL;
37162306a36Sopenharmony_ci		*autoneg = false;
37262306a36Sopenharmony_ci		break;
37362306a36Sopenharmony_ci
37462306a36Sopenharmony_ci	case IXGBE_AUTOC_LMS_KX4_KX_KR:
37562306a36Sopenharmony_ci	case IXGBE_AUTOC_LMS_KX4_KX_KR_1G_AN:
37662306a36Sopenharmony_ci		*speed = IXGBE_LINK_SPEED_UNKNOWN;
37762306a36Sopenharmony_ci		if (autoc & IXGBE_AUTOC_KR_SUPP)
37862306a36Sopenharmony_ci			*speed |= IXGBE_LINK_SPEED_10GB_FULL;
37962306a36Sopenharmony_ci		if (autoc & IXGBE_AUTOC_KX4_SUPP)
38062306a36Sopenharmony_ci			*speed |= IXGBE_LINK_SPEED_10GB_FULL;
38162306a36Sopenharmony_ci		if (autoc & IXGBE_AUTOC_KX_SUPP)
38262306a36Sopenharmony_ci			*speed |= IXGBE_LINK_SPEED_1GB_FULL;
38362306a36Sopenharmony_ci		*autoneg = true;
38462306a36Sopenharmony_ci		break;
38562306a36Sopenharmony_ci
38662306a36Sopenharmony_ci	case IXGBE_AUTOC_LMS_KX4_KX_KR_SGMII:
38762306a36Sopenharmony_ci		*speed = IXGBE_LINK_SPEED_100_FULL;
38862306a36Sopenharmony_ci		if (autoc & IXGBE_AUTOC_KR_SUPP)
38962306a36Sopenharmony_ci			*speed |= IXGBE_LINK_SPEED_10GB_FULL;
39062306a36Sopenharmony_ci		if (autoc & IXGBE_AUTOC_KX4_SUPP)
39162306a36Sopenharmony_ci			*speed |= IXGBE_LINK_SPEED_10GB_FULL;
39262306a36Sopenharmony_ci		if (autoc & IXGBE_AUTOC_KX_SUPP)
39362306a36Sopenharmony_ci			*speed |= IXGBE_LINK_SPEED_1GB_FULL;
39462306a36Sopenharmony_ci		*autoneg = true;
39562306a36Sopenharmony_ci		break;
39662306a36Sopenharmony_ci
39762306a36Sopenharmony_ci	case IXGBE_AUTOC_LMS_SGMII_1G_100M:
39862306a36Sopenharmony_ci		*speed = IXGBE_LINK_SPEED_1GB_FULL | IXGBE_LINK_SPEED_100_FULL;
39962306a36Sopenharmony_ci		*autoneg = false;
40062306a36Sopenharmony_ci		break;
40162306a36Sopenharmony_ci
40262306a36Sopenharmony_ci	default:
40362306a36Sopenharmony_ci		return -EIO;
40462306a36Sopenharmony_ci	}
40562306a36Sopenharmony_ci
40662306a36Sopenharmony_ci	if (hw->phy.multispeed_fiber) {
40762306a36Sopenharmony_ci		*speed |= IXGBE_LINK_SPEED_10GB_FULL |
40862306a36Sopenharmony_ci			  IXGBE_LINK_SPEED_1GB_FULL;
40962306a36Sopenharmony_ci
41062306a36Sopenharmony_ci		/* QSFP must not enable auto-negotiation */
41162306a36Sopenharmony_ci		if (hw->phy.media_type == ixgbe_media_type_fiber_qsfp)
41262306a36Sopenharmony_ci			*autoneg = false;
41362306a36Sopenharmony_ci		else
41462306a36Sopenharmony_ci			*autoneg = true;
41562306a36Sopenharmony_ci	}
41662306a36Sopenharmony_ci
41762306a36Sopenharmony_ci	return 0;
41862306a36Sopenharmony_ci}
41962306a36Sopenharmony_ci
42062306a36Sopenharmony_ci/**
42162306a36Sopenharmony_ci *  ixgbe_get_media_type_82599 - Get media type
42262306a36Sopenharmony_ci *  @hw: pointer to hardware structure
42362306a36Sopenharmony_ci *
42462306a36Sopenharmony_ci *  Returns the media type (fiber, copper, backplane)
42562306a36Sopenharmony_ci **/
42662306a36Sopenharmony_cistatic enum ixgbe_media_type ixgbe_get_media_type_82599(struct ixgbe_hw *hw)
42762306a36Sopenharmony_ci{
42862306a36Sopenharmony_ci	/* Detect if there is a copper PHY attached. */
42962306a36Sopenharmony_ci	switch (hw->phy.type) {
43062306a36Sopenharmony_ci	case ixgbe_phy_cu_unknown:
43162306a36Sopenharmony_ci	case ixgbe_phy_tn:
43262306a36Sopenharmony_ci		return ixgbe_media_type_copper;
43362306a36Sopenharmony_ci
43462306a36Sopenharmony_ci	default:
43562306a36Sopenharmony_ci		break;
43662306a36Sopenharmony_ci	}
43762306a36Sopenharmony_ci
43862306a36Sopenharmony_ci	switch (hw->device_id) {
43962306a36Sopenharmony_ci	case IXGBE_DEV_ID_82599_KX4:
44062306a36Sopenharmony_ci	case IXGBE_DEV_ID_82599_KX4_MEZZ:
44162306a36Sopenharmony_ci	case IXGBE_DEV_ID_82599_COMBO_BACKPLANE:
44262306a36Sopenharmony_ci	case IXGBE_DEV_ID_82599_KR:
44362306a36Sopenharmony_ci	case IXGBE_DEV_ID_82599_BACKPLANE_FCOE:
44462306a36Sopenharmony_ci	case IXGBE_DEV_ID_82599_XAUI_LOM:
44562306a36Sopenharmony_ci		/* Default device ID is mezzanine card KX/KX4 */
44662306a36Sopenharmony_ci		return ixgbe_media_type_backplane;
44762306a36Sopenharmony_ci
44862306a36Sopenharmony_ci	case IXGBE_DEV_ID_82599_SFP:
44962306a36Sopenharmony_ci	case IXGBE_DEV_ID_82599_SFP_FCOE:
45062306a36Sopenharmony_ci	case IXGBE_DEV_ID_82599_SFP_EM:
45162306a36Sopenharmony_ci	case IXGBE_DEV_ID_82599_SFP_SF2:
45262306a36Sopenharmony_ci	case IXGBE_DEV_ID_82599_SFP_SF_QP:
45362306a36Sopenharmony_ci	case IXGBE_DEV_ID_82599EN_SFP:
45462306a36Sopenharmony_ci		return ixgbe_media_type_fiber;
45562306a36Sopenharmony_ci
45662306a36Sopenharmony_ci	case IXGBE_DEV_ID_82599_CX4:
45762306a36Sopenharmony_ci		return ixgbe_media_type_cx4;
45862306a36Sopenharmony_ci
45962306a36Sopenharmony_ci	case IXGBE_DEV_ID_82599_T3_LOM:
46062306a36Sopenharmony_ci		return ixgbe_media_type_copper;
46162306a36Sopenharmony_ci
46262306a36Sopenharmony_ci	case IXGBE_DEV_ID_82599_LS:
46362306a36Sopenharmony_ci		return ixgbe_media_type_fiber_lco;
46462306a36Sopenharmony_ci
46562306a36Sopenharmony_ci	case IXGBE_DEV_ID_82599_QSFP_SF_QP:
46662306a36Sopenharmony_ci		return ixgbe_media_type_fiber_qsfp;
46762306a36Sopenharmony_ci
46862306a36Sopenharmony_ci	default:
46962306a36Sopenharmony_ci		return ixgbe_media_type_unknown;
47062306a36Sopenharmony_ci	}
47162306a36Sopenharmony_ci}
47262306a36Sopenharmony_ci
47362306a36Sopenharmony_ci/**
47462306a36Sopenharmony_ci * ixgbe_stop_mac_link_on_d3_82599 - Disables link on D3
47562306a36Sopenharmony_ci * @hw: pointer to hardware structure
47662306a36Sopenharmony_ci *
47762306a36Sopenharmony_ci * Disables link, should be called during D3 power down sequence.
47862306a36Sopenharmony_ci *
47962306a36Sopenharmony_ci **/
48062306a36Sopenharmony_cistatic void ixgbe_stop_mac_link_on_d3_82599(struct ixgbe_hw *hw)
48162306a36Sopenharmony_ci{
48262306a36Sopenharmony_ci	u32 autoc2_reg;
48362306a36Sopenharmony_ci	u16 ee_ctrl_2 = 0;
48462306a36Sopenharmony_ci
48562306a36Sopenharmony_ci	hw->eeprom.ops.read(hw, IXGBE_EEPROM_CTRL_2, &ee_ctrl_2);
48662306a36Sopenharmony_ci
48762306a36Sopenharmony_ci	if (!ixgbe_mng_present(hw) && !hw->wol_enabled &&
48862306a36Sopenharmony_ci	    ee_ctrl_2 & IXGBE_EEPROM_CCD_BIT) {
48962306a36Sopenharmony_ci		autoc2_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC2);
49062306a36Sopenharmony_ci		autoc2_reg |= IXGBE_AUTOC2_LINK_DISABLE_ON_D3_MASK;
49162306a36Sopenharmony_ci		IXGBE_WRITE_REG(hw, IXGBE_AUTOC2, autoc2_reg);
49262306a36Sopenharmony_ci	}
49362306a36Sopenharmony_ci}
49462306a36Sopenharmony_ci
49562306a36Sopenharmony_ci/**
49662306a36Sopenharmony_ci *  ixgbe_start_mac_link_82599 - Setup MAC link settings
49762306a36Sopenharmony_ci *  @hw: pointer to hardware structure
49862306a36Sopenharmony_ci *  @autoneg_wait_to_complete: true when waiting for completion is needed
49962306a36Sopenharmony_ci *
50062306a36Sopenharmony_ci *  Configures link settings based on values in the ixgbe_hw struct.
50162306a36Sopenharmony_ci *  Restarts the link.  Performs autonegotiation if needed.
50262306a36Sopenharmony_ci **/
50362306a36Sopenharmony_cistatic s32 ixgbe_start_mac_link_82599(struct ixgbe_hw *hw,
50462306a36Sopenharmony_ci			       bool autoneg_wait_to_complete)
50562306a36Sopenharmony_ci{
50662306a36Sopenharmony_ci	u32 autoc_reg;
50762306a36Sopenharmony_ci	u32 links_reg;
50862306a36Sopenharmony_ci	u32 i;
50962306a36Sopenharmony_ci	s32 status = 0;
51062306a36Sopenharmony_ci	bool got_lock = false;
51162306a36Sopenharmony_ci
51262306a36Sopenharmony_ci	if (ixgbe_verify_lesm_fw_enabled_82599(hw)) {
51362306a36Sopenharmony_ci		status = hw->mac.ops.acquire_swfw_sync(hw,
51462306a36Sopenharmony_ci						IXGBE_GSSR_MAC_CSR_SM);
51562306a36Sopenharmony_ci		if (status)
51662306a36Sopenharmony_ci			return status;
51762306a36Sopenharmony_ci
51862306a36Sopenharmony_ci		got_lock = true;
51962306a36Sopenharmony_ci	}
52062306a36Sopenharmony_ci
52162306a36Sopenharmony_ci	/* Restart link */
52262306a36Sopenharmony_ci	ixgbe_reset_pipeline_82599(hw);
52362306a36Sopenharmony_ci
52462306a36Sopenharmony_ci	if (got_lock)
52562306a36Sopenharmony_ci		hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_MAC_CSR_SM);
52662306a36Sopenharmony_ci
52762306a36Sopenharmony_ci	/* Only poll for autoneg to complete if specified to do so */
52862306a36Sopenharmony_ci	if (autoneg_wait_to_complete) {
52962306a36Sopenharmony_ci		autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC);
53062306a36Sopenharmony_ci		if ((autoc_reg & IXGBE_AUTOC_LMS_MASK) ==
53162306a36Sopenharmony_ci		     IXGBE_AUTOC_LMS_KX4_KX_KR ||
53262306a36Sopenharmony_ci		    (autoc_reg & IXGBE_AUTOC_LMS_MASK) ==
53362306a36Sopenharmony_ci		     IXGBE_AUTOC_LMS_KX4_KX_KR_1G_AN ||
53462306a36Sopenharmony_ci		    (autoc_reg & IXGBE_AUTOC_LMS_MASK) ==
53562306a36Sopenharmony_ci		     IXGBE_AUTOC_LMS_KX4_KX_KR_SGMII) {
53662306a36Sopenharmony_ci			links_reg = 0; /* Just in case Autoneg time = 0 */
53762306a36Sopenharmony_ci			for (i = 0; i < IXGBE_AUTO_NEG_TIME; i++) {
53862306a36Sopenharmony_ci				links_reg = IXGBE_READ_REG(hw, IXGBE_LINKS);
53962306a36Sopenharmony_ci				if (links_reg & IXGBE_LINKS_KX_AN_COMP)
54062306a36Sopenharmony_ci					break;
54162306a36Sopenharmony_ci				msleep(100);
54262306a36Sopenharmony_ci			}
54362306a36Sopenharmony_ci			if (!(links_reg & IXGBE_LINKS_KX_AN_COMP)) {
54462306a36Sopenharmony_ci				status = -EIO;
54562306a36Sopenharmony_ci				hw_dbg(hw, "Autoneg did not complete.\n");
54662306a36Sopenharmony_ci			}
54762306a36Sopenharmony_ci		}
54862306a36Sopenharmony_ci	}
54962306a36Sopenharmony_ci
55062306a36Sopenharmony_ci	/* Add delay to filter out noises during initial link setup */
55162306a36Sopenharmony_ci	msleep(50);
55262306a36Sopenharmony_ci
55362306a36Sopenharmony_ci	return status;
55462306a36Sopenharmony_ci}
55562306a36Sopenharmony_ci
55662306a36Sopenharmony_ci/**
55762306a36Sopenharmony_ci *  ixgbe_disable_tx_laser_multispeed_fiber - Disable Tx laser
55862306a36Sopenharmony_ci *  @hw: pointer to hardware structure
55962306a36Sopenharmony_ci *
56062306a36Sopenharmony_ci *  The base drivers may require better control over SFP+ module
56162306a36Sopenharmony_ci *  PHY states.  This includes selectively shutting down the Tx
56262306a36Sopenharmony_ci *  laser on the PHY, effectively halting physical link.
56362306a36Sopenharmony_ci **/
56462306a36Sopenharmony_cistatic void ixgbe_disable_tx_laser_multispeed_fiber(struct ixgbe_hw *hw)
56562306a36Sopenharmony_ci{
56662306a36Sopenharmony_ci	u32 esdp_reg = IXGBE_READ_REG(hw, IXGBE_ESDP);
56762306a36Sopenharmony_ci
56862306a36Sopenharmony_ci	/* Blocked by MNG FW so bail */
56962306a36Sopenharmony_ci	if (ixgbe_check_reset_blocked(hw))
57062306a36Sopenharmony_ci		return;
57162306a36Sopenharmony_ci
57262306a36Sopenharmony_ci	/* Disable tx laser; allow 100us to go dark per spec */
57362306a36Sopenharmony_ci	esdp_reg |= IXGBE_ESDP_SDP3;
57462306a36Sopenharmony_ci	IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp_reg);
57562306a36Sopenharmony_ci	IXGBE_WRITE_FLUSH(hw);
57662306a36Sopenharmony_ci	udelay(100);
57762306a36Sopenharmony_ci}
57862306a36Sopenharmony_ci
57962306a36Sopenharmony_ci/**
58062306a36Sopenharmony_ci *  ixgbe_enable_tx_laser_multispeed_fiber - Enable Tx laser
58162306a36Sopenharmony_ci *  @hw: pointer to hardware structure
58262306a36Sopenharmony_ci *
58362306a36Sopenharmony_ci *  The base drivers may require better control over SFP+ module
58462306a36Sopenharmony_ci *  PHY states.  This includes selectively turning on the Tx
58562306a36Sopenharmony_ci *  laser on the PHY, effectively starting physical link.
58662306a36Sopenharmony_ci **/
58762306a36Sopenharmony_cistatic void ixgbe_enable_tx_laser_multispeed_fiber(struct ixgbe_hw *hw)
58862306a36Sopenharmony_ci{
58962306a36Sopenharmony_ci	u32 esdp_reg = IXGBE_READ_REG(hw, IXGBE_ESDP);
59062306a36Sopenharmony_ci
59162306a36Sopenharmony_ci	/* Enable tx laser; allow 100ms to light up */
59262306a36Sopenharmony_ci	esdp_reg &= ~IXGBE_ESDP_SDP3;
59362306a36Sopenharmony_ci	IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp_reg);
59462306a36Sopenharmony_ci	IXGBE_WRITE_FLUSH(hw);
59562306a36Sopenharmony_ci	msleep(100);
59662306a36Sopenharmony_ci}
59762306a36Sopenharmony_ci
59862306a36Sopenharmony_ci/**
59962306a36Sopenharmony_ci *  ixgbe_flap_tx_laser_multispeed_fiber - Flap Tx laser
60062306a36Sopenharmony_ci *  @hw: pointer to hardware structure
60162306a36Sopenharmony_ci *
60262306a36Sopenharmony_ci *  When the driver changes the link speeds that it can support,
60362306a36Sopenharmony_ci *  it sets autotry_restart to true to indicate that we need to
60462306a36Sopenharmony_ci *  initiate a new autotry session with the link partner.  To do
60562306a36Sopenharmony_ci *  so, we set the speed then disable and re-enable the tx laser, to
60662306a36Sopenharmony_ci *  alert the link partner that it also needs to restart autotry on its
60762306a36Sopenharmony_ci *  end.  This is consistent with true clause 37 autoneg, which also
60862306a36Sopenharmony_ci *  involves a loss of signal.
60962306a36Sopenharmony_ci **/
61062306a36Sopenharmony_cistatic void ixgbe_flap_tx_laser_multispeed_fiber(struct ixgbe_hw *hw)
61162306a36Sopenharmony_ci{
61262306a36Sopenharmony_ci	/* Blocked by MNG FW so bail */
61362306a36Sopenharmony_ci	if (ixgbe_check_reset_blocked(hw))
61462306a36Sopenharmony_ci		return;
61562306a36Sopenharmony_ci
61662306a36Sopenharmony_ci	if (hw->mac.autotry_restart) {
61762306a36Sopenharmony_ci		ixgbe_disable_tx_laser_multispeed_fiber(hw);
61862306a36Sopenharmony_ci		ixgbe_enable_tx_laser_multispeed_fiber(hw);
61962306a36Sopenharmony_ci		hw->mac.autotry_restart = false;
62062306a36Sopenharmony_ci	}
62162306a36Sopenharmony_ci}
62262306a36Sopenharmony_ci
62362306a36Sopenharmony_ci/**
62462306a36Sopenharmony_ci * ixgbe_set_hard_rate_select_speed - Set module link speed
62562306a36Sopenharmony_ci * @hw: pointer to hardware structure
62662306a36Sopenharmony_ci * @speed: link speed to set
62762306a36Sopenharmony_ci *
62862306a36Sopenharmony_ci * Set module link speed via RS0/RS1 rate select pins.
62962306a36Sopenharmony_ci */
63062306a36Sopenharmony_cistatic void
63162306a36Sopenharmony_ciixgbe_set_hard_rate_select_speed(struct ixgbe_hw *hw, ixgbe_link_speed speed)
63262306a36Sopenharmony_ci{
63362306a36Sopenharmony_ci	u32 esdp_reg = IXGBE_READ_REG(hw, IXGBE_ESDP);
63462306a36Sopenharmony_ci
63562306a36Sopenharmony_ci	switch (speed) {
63662306a36Sopenharmony_ci	case IXGBE_LINK_SPEED_10GB_FULL:
63762306a36Sopenharmony_ci		esdp_reg |= (IXGBE_ESDP_SDP5_DIR | IXGBE_ESDP_SDP5);
63862306a36Sopenharmony_ci		break;
63962306a36Sopenharmony_ci	case IXGBE_LINK_SPEED_1GB_FULL:
64062306a36Sopenharmony_ci		esdp_reg &= ~IXGBE_ESDP_SDP5;
64162306a36Sopenharmony_ci		esdp_reg |= IXGBE_ESDP_SDP5_DIR;
64262306a36Sopenharmony_ci		break;
64362306a36Sopenharmony_ci	default:
64462306a36Sopenharmony_ci		hw_dbg(hw, "Invalid fixed module speed\n");
64562306a36Sopenharmony_ci		return;
64662306a36Sopenharmony_ci	}
64762306a36Sopenharmony_ci
64862306a36Sopenharmony_ci	IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp_reg);
64962306a36Sopenharmony_ci	IXGBE_WRITE_FLUSH(hw);
65062306a36Sopenharmony_ci}
65162306a36Sopenharmony_ci
65262306a36Sopenharmony_ci/**
65362306a36Sopenharmony_ci *  ixgbe_setup_mac_link_smartspeed - Set MAC link speed using SmartSpeed
65462306a36Sopenharmony_ci *  @hw: pointer to hardware structure
65562306a36Sopenharmony_ci *  @speed: new link speed
65662306a36Sopenharmony_ci *  @autoneg_wait_to_complete: true when waiting for completion is needed
65762306a36Sopenharmony_ci *
65862306a36Sopenharmony_ci *  Implements the Intel SmartSpeed algorithm.
65962306a36Sopenharmony_ci **/
66062306a36Sopenharmony_cistatic s32 ixgbe_setup_mac_link_smartspeed(struct ixgbe_hw *hw,
66162306a36Sopenharmony_ci				     ixgbe_link_speed speed,
66262306a36Sopenharmony_ci				     bool autoneg_wait_to_complete)
66362306a36Sopenharmony_ci{
66462306a36Sopenharmony_ci	s32 status = 0;
66562306a36Sopenharmony_ci	ixgbe_link_speed link_speed = IXGBE_LINK_SPEED_UNKNOWN;
66662306a36Sopenharmony_ci	s32 i, j;
66762306a36Sopenharmony_ci	bool link_up = false;
66862306a36Sopenharmony_ci	u32 autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC);
66962306a36Sopenharmony_ci
67062306a36Sopenharmony_ci	 /* Set autoneg_advertised value based on input link speed */
67162306a36Sopenharmony_ci	hw->phy.autoneg_advertised = 0;
67262306a36Sopenharmony_ci
67362306a36Sopenharmony_ci	if (speed & IXGBE_LINK_SPEED_10GB_FULL)
67462306a36Sopenharmony_ci		hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_10GB_FULL;
67562306a36Sopenharmony_ci
67662306a36Sopenharmony_ci	if (speed & IXGBE_LINK_SPEED_1GB_FULL)
67762306a36Sopenharmony_ci		hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_1GB_FULL;
67862306a36Sopenharmony_ci
67962306a36Sopenharmony_ci	if (speed & IXGBE_LINK_SPEED_100_FULL)
68062306a36Sopenharmony_ci		hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_100_FULL;
68162306a36Sopenharmony_ci
68262306a36Sopenharmony_ci	/*
68362306a36Sopenharmony_ci	 * Implement Intel SmartSpeed algorithm.  SmartSpeed will reduce the
68462306a36Sopenharmony_ci	 * autoneg advertisement if link is unable to be established at the
68562306a36Sopenharmony_ci	 * highest negotiated rate.  This can sometimes happen due to integrity
68662306a36Sopenharmony_ci	 * issues with the physical media connection.
68762306a36Sopenharmony_ci	 */
68862306a36Sopenharmony_ci
68962306a36Sopenharmony_ci	/* First, try to get link with full advertisement */
69062306a36Sopenharmony_ci	hw->phy.smart_speed_active = false;
69162306a36Sopenharmony_ci	for (j = 0; j < IXGBE_SMARTSPEED_MAX_RETRIES; j++) {
69262306a36Sopenharmony_ci		status = ixgbe_setup_mac_link_82599(hw, speed,
69362306a36Sopenharmony_ci						    autoneg_wait_to_complete);
69462306a36Sopenharmony_ci		if (status != 0)
69562306a36Sopenharmony_ci			goto out;
69662306a36Sopenharmony_ci
69762306a36Sopenharmony_ci		/*
69862306a36Sopenharmony_ci		 * Wait for the controller to acquire link.  Per IEEE 802.3ap,
69962306a36Sopenharmony_ci		 * Section 73.10.2, we may have to wait up to 500ms if KR is
70062306a36Sopenharmony_ci		 * attempted, or 200ms if KX/KX4/BX/BX4 is attempted, per
70162306a36Sopenharmony_ci		 * Table 9 in the AN MAS.
70262306a36Sopenharmony_ci		 */
70362306a36Sopenharmony_ci		for (i = 0; i < 5; i++) {
70462306a36Sopenharmony_ci			mdelay(100);
70562306a36Sopenharmony_ci
70662306a36Sopenharmony_ci			/* If we have link, just jump out */
70762306a36Sopenharmony_ci			status = hw->mac.ops.check_link(hw, &link_speed,
70862306a36Sopenharmony_ci							&link_up, false);
70962306a36Sopenharmony_ci			if (status != 0)
71062306a36Sopenharmony_ci				goto out;
71162306a36Sopenharmony_ci
71262306a36Sopenharmony_ci			if (link_up)
71362306a36Sopenharmony_ci				goto out;
71462306a36Sopenharmony_ci		}
71562306a36Sopenharmony_ci	}
71662306a36Sopenharmony_ci
71762306a36Sopenharmony_ci	/*
71862306a36Sopenharmony_ci	 * We didn't get link.  If we advertised KR plus one of KX4/KX
71962306a36Sopenharmony_ci	 * (or BX4/BX), then disable KR and try again.
72062306a36Sopenharmony_ci	 */
72162306a36Sopenharmony_ci	if (((autoc_reg & IXGBE_AUTOC_KR_SUPP) == 0) ||
72262306a36Sopenharmony_ci	    ((autoc_reg & IXGBE_AUTOC_KX4_KX_SUPP_MASK) == 0))
72362306a36Sopenharmony_ci		goto out;
72462306a36Sopenharmony_ci
72562306a36Sopenharmony_ci	/* Turn SmartSpeed on to disable KR support */
72662306a36Sopenharmony_ci	hw->phy.smart_speed_active = true;
72762306a36Sopenharmony_ci	status = ixgbe_setup_mac_link_82599(hw, speed,
72862306a36Sopenharmony_ci					    autoneg_wait_to_complete);
72962306a36Sopenharmony_ci	if (status != 0)
73062306a36Sopenharmony_ci		goto out;
73162306a36Sopenharmony_ci
73262306a36Sopenharmony_ci	/*
73362306a36Sopenharmony_ci	 * Wait for the controller to acquire link.  600ms will allow for
73462306a36Sopenharmony_ci	 * the AN link_fail_inhibit_timer as well for multiple cycles of
73562306a36Sopenharmony_ci	 * parallel detect, both 10g and 1g. This allows for the maximum
73662306a36Sopenharmony_ci	 * connect attempts as defined in the AN MAS table 73-7.
73762306a36Sopenharmony_ci	 */
73862306a36Sopenharmony_ci	for (i = 0; i < 6; i++) {
73962306a36Sopenharmony_ci		mdelay(100);
74062306a36Sopenharmony_ci
74162306a36Sopenharmony_ci		/* If we have link, just jump out */
74262306a36Sopenharmony_ci		status = hw->mac.ops.check_link(hw, &link_speed,
74362306a36Sopenharmony_ci						&link_up, false);
74462306a36Sopenharmony_ci		if (status != 0)
74562306a36Sopenharmony_ci			goto out;
74662306a36Sopenharmony_ci
74762306a36Sopenharmony_ci		if (link_up)
74862306a36Sopenharmony_ci			goto out;
74962306a36Sopenharmony_ci	}
75062306a36Sopenharmony_ci
75162306a36Sopenharmony_ci	/* We didn't get link.  Turn SmartSpeed back off. */
75262306a36Sopenharmony_ci	hw->phy.smart_speed_active = false;
75362306a36Sopenharmony_ci	status = ixgbe_setup_mac_link_82599(hw, speed,
75462306a36Sopenharmony_ci					    autoneg_wait_to_complete);
75562306a36Sopenharmony_ci
75662306a36Sopenharmony_ciout:
75762306a36Sopenharmony_ci	if (link_up && (link_speed == IXGBE_LINK_SPEED_1GB_FULL))
75862306a36Sopenharmony_ci		hw_dbg(hw, "Smartspeed has downgraded the link speed from the maximum advertised\n");
75962306a36Sopenharmony_ci	return status;
76062306a36Sopenharmony_ci}
76162306a36Sopenharmony_ci
76262306a36Sopenharmony_ci/**
76362306a36Sopenharmony_ci *  ixgbe_setup_mac_link_82599 - Set MAC link speed
76462306a36Sopenharmony_ci *  @hw: pointer to hardware structure
76562306a36Sopenharmony_ci *  @speed: new link speed
76662306a36Sopenharmony_ci *  @autoneg_wait_to_complete: true when waiting for completion is needed
76762306a36Sopenharmony_ci *
76862306a36Sopenharmony_ci *  Set the link speed in the AUTOC register and restarts link.
76962306a36Sopenharmony_ci **/
77062306a36Sopenharmony_cistatic s32 ixgbe_setup_mac_link_82599(struct ixgbe_hw *hw,
77162306a36Sopenharmony_ci				      ixgbe_link_speed speed,
77262306a36Sopenharmony_ci				      bool autoneg_wait_to_complete)
77362306a36Sopenharmony_ci{
77462306a36Sopenharmony_ci	bool autoneg = false;
77562306a36Sopenharmony_ci	s32 status;
77662306a36Sopenharmony_ci	u32 pma_pmd_1g, link_mode, links_reg, i;
77762306a36Sopenharmony_ci	u32 autoc2 = IXGBE_READ_REG(hw, IXGBE_AUTOC2);
77862306a36Sopenharmony_ci	u32 pma_pmd_10g_serial = autoc2 & IXGBE_AUTOC2_10G_SERIAL_PMA_PMD_MASK;
77962306a36Sopenharmony_ci	ixgbe_link_speed link_capabilities = IXGBE_LINK_SPEED_UNKNOWN;
78062306a36Sopenharmony_ci
78162306a36Sopenharmony_ci	/* holds the value of AUTOC register at this current point in time */
78262306a36Sopenharmony_ci	u32 current_autoc = IXGBE_READ_REG(hw, IXGBE_AUTOC);
78362306a36Sopenharmony_ci	/* holds the cached value of AUTOC register */
78462306a36Sopenharmony_ci	u32 orig_autoc = 0;
78562306a36Sopenharmony_ci	/* temporary variable used for comparison purposes */
78662306a36Sopenharmony_ci	u32 autoc = current_autoc;
78762306a36Sopenharmony_ci
78862306a36Sopenharmony_ci	/* Check to see if speed passed in is supported. */
78962306a36Sopenharmony_ci	status = hw->mac.ops.get_link_capabilities(hw, &link_capabilities,
79062306a36Sopenharmony_ci						   &autoneg);
79162306a36Sopenharmony_ci	if (status)
79262306a36Sopenharmony_ci		return status;
79362306a36Sopenharmony_ci
79462306a36Sopenharmony_ci	speed &= link_capabilities;
79562306a36Sopenharmony_ci
79662306a36Sopenharmony_ci	if (speed == IXGBE_LINK_SPEED_UNKNOWN)
79762306a36Sopenharmony_ci		return -EINVAL;
79862306a36Sopenharmony_ci
79962306a36Sopenharmony_ci	/* Use stored value (EEPROM defaults) of AUTOC to find KR/KX4 support*/
80062306a36Sopenharmony_ci	if (hw->mac.orig_link_settings_stored)
80162306a36Sopenharmony_ci		orig_autoc = hw->mac.orig_autoc;
80262306a36Sopenharmony_ci	else
80362306a36Sopenharmony_ci		orig_autoc = autoc;
80462306a36Sopenharmony_ci
80562306a36Sopenharmony_ci	link_mode = autoc & IXGBE_AUTOC_LMS_MASK;
80662306a36Sopenharmony_ci	pma_pmd_1g = autoc & IXGBE_AUTOC_1G_PMA_PMD_MASK;
80762306a36Sopenharmony_ci
80862306a36Sopenharmony_ci	if (link_mode == IXGBE_AUTOC_LMS_KX4_KX_KR ||
80962306a36Sopenharmony_ci	    link_mode == IXGBE_AUTOC_LMS_KX4_KX_KR_1G_AN ||
81062306a36Sopenharmony_ci	    link_mode == IXGBE_AUTOC_LMS_KX4_KX_KR_SGMII) {
81162306a36Sopenharmony_ci		/* Set KX4/KX/KR support according to speed requested */
81262306a36Sopenharmony_ci		autoc &= ~(IXGBE_AUTOC_KX4_KX_SUPP_MASK | IXGBE_AUTOC_KR_SUPP);
81362306a36Sopenharmony_ci		if (speed & IXGBE_LINK_SPEED_10GB_FULL) {
81462306a36Sopenharmony_ci			if (orig_autoc & IXGBE_AUTOC_KX4_SUPP)
81562306a36Sopenharmony_ci				autoc |= IXGBE_AUTOC_KX4_SUPP;
81662306a36Sopenharmony_ci			if ((orig_autoc & IXGBE_AUTOC_KR_SUPP) &&
81762306a36Sopenharmony_ci			    (hw->phy.smart_speed_active == false))
81862306a36Sopenharmony_ci				autoc |= IXGBE_AUTOC_KR_SUPP;
81962306a36Sopenharmony_ci		}
82062306a36Sopenharmony_ci		if (speed & IXGBE_LINK_SPEED_1GB_FULL)
82162306a36Sopenharmony_ci			autoc |= IXGBE_AUTOC_KX_SUPP;
82262306a36Sopenharmony_ci	} else if ((pma_pmd_1g == IXGBE_AUTOC_1G_SFI) &&
82362306a36Sopenharmony_ci		   (link_mode == IXGBE_AUTOC_LMS_1G_LINK_NO_AN ||
82462306a36Sopenharmony_ci		    link_mode == IXGBE_AUTOC_LMS_1G_AN)) {
82562306a36Sopenharmony_ci		/* Switch from 1G SFI to 10G SFI if requested */
82662306a36Sopenharmony_ci		if ((speed == IXGBE_LINK_SPEED_10GB_FULL) &&
82762306a36Sopenharmony_ci		    (pma_pmd_10g_serial == IXGBE_AUTOC2_10G_SFI)) {
82862306a36Sopenharmony_ci			autoc &= ~IXGBE_AUTOC_LMS_MASK;
82962306a36Sopenharmony_ci			autoc |= IXGBE_AUTOC_LMS_10G_SERIAL;
83062306a36Sopenharmony_ci		}
83162306a36Sopenharmony_ci	} else if ((pma_pmd_10g_serial == IXGBE_AUTOC2_10G_SFI) &&
83262306a36Sopenharmony_ci		   (link_mode == IXGBE_AUTOC_LMS_10G_SERIAL)) {
83362306a36Sopenharmony_ci		/* Switch from 10G SFI to 1G SFI if requested */
83462306a36Sopenharmony_ci		if ((speed == IXGBE_LINK_SPEED_1GB_FULL) &&
83562306a36Sopenharmony_ci		    (pma_pmd_1g == IXGBE_AUTOC_1G_SFI)) {
83662306a36Sopenharmony_ci			autoc &= ~IXGBE_AUTOC_LMS_MASK;
83762306a36Sopenharmony_ci			if (autoneg)
83862306a36Sopenharmony_ci				autoc |= IXGBE_AUTOC_LMS_1G_AN;
83962306a36Sopenharmony_ci			else
84062306a36Sopenharmony_ci				autoc |= IXGBE_AUTOC_LMS_1G_LINK_NO_AN;
84162306a36Sopenharmony_ci		}
84262306a36Sopenharmony_ci	}
84362306a36Sopenharmony_ci
84462306a36Sopenharmony_ci	if (autoc != current_autoc) {
84562306a36Sopenharmony_ci		/* Restart link */
84662306a36Sopenharmony_ci		status = hw->mac.ops.prot_autoc_write(hw, autoc, false);
84762306a36Sopenharmony_ci		if (status)
84862306a36Sopenharmony_ci			return status;
84962306a36Sopenharmony_ci
85062306a36Sopenharmony_ci		/* Only poll for autoneg to complete if specified to do so */
85162306a36Sopenharmony_ci		if (autoneg_wait_to_complete) {
85262306a36Sopenharmony_ci			if (link_mode == IXGBE_AUTOC_LMS_KX4_KX_KR ||
85362306a36Sopenharmony_ci			    link_mode == IXGBE_AUTOC_LMS_KX4_KX_KR_1G_AN ||
85462306a36Sopenharmony_ci			    link_mode == IXGBE_AUTOC_LMS_KX4_KX_KR_SGMII) {
85562306a36Sopenharmony_ci				links_reg = 0; /*Just in case Autoneg time=0*/
85662306a36Sopenharmony_ci				for (i = 0; i < IXGBE_AUTO_NEG_TIME; i++) {
85762306a36Sopenharmony_ci					links_reg =
85862306a36Sopenharmony_ci					       IXGBE_READ_REG(hw, IXGBE_LINKS);
85962306a36Sopenharmony_ci					if (links_reg & IXGBE_LINKS_KX_AN_COMP)
86062306a36Sopenharmony_ci						break;
86162306a36Sopenharmony_ci					msleep(100);
86262306a36Sopenharmony_ci				}
86362306a36Sopenharmony_ci				if (!(links_reg & IXGBE_LINKS_KX_AN_COMP)) {
86462306a36Sopenharmony_ci					status = -EIO;
86562306a36Sopenharmony_ci					hw_dbg(hw, "Autoneg did not complete.\n");
86662306a36Sopenharmony_ci				}
86762306a36Sopenharmony_ci			}
86862306a36Sopenharmony_ci		}
86962306a36Sopenharmony_ci
87062306a36Sopenharmony_ci		/* Add delay to filter out noises during initial link setup */
87162306a36Sopenharmony_ci		msleep(50);
87262306a36Sopenharmony_ci	}
87362306a36Sopenharmony_ci
87462306a36Sopenharmony_ci	return status;
87562306a36Sopenharmony_ci}
87662306a36Sopenharmony_ci
87762306a36Sopenharmony_ci/**
87862306a36Sopenharmony_ci *  ixgbe_setup_copper_link_82599 - Set the PHY autoneg advertised field
87962306a36Sopenharmony_ci *  @hw: pointer to hardware structure
88062306a36Sopenharmony_ci *  @speed: new link speed
88162306a36Sopenharmony_ci *  @autoneg_wait_to_complete: true if waiting is needed to complete
88262306a36Sopenharmony_ci *
88362306a36Sopenharmony_ci *  Restarts link on PHY and MAC based on settings passed in.
88462306a36Sopenharmony_ci **/
88562306a36Sopenharmony_cistatic s32 ixgbe_setup_copper_link_82599(struct ixgbe_hw *hw,
88662306a36Sopenharmony_ci					 ixgbe_link_speed speed,
88762306a36Sopenharmony_ci					 bool autoneg_wait_to_complete)
88862306a36Sopenharmony_ci{
88962306a36Sopenharmony_ci	s32 status;
89062306a36Sopenharmony_ci
89162306a36Sopenharmony_ci	/* Setup the PHY according to input speed */
89262306a36Sopenharmony_ci	status = hw->phy.ops.setup_link_speed(hw, speed,
89362306a36Sopenharmony_ci					      autoneg_wait_to_complete);
89462306a36Sopenharmony_ci	/* Set up MAC */
89562306a36Sopenharmony_ci	ixgbe_start_mac_link_82599(hw, autoneg_wait_to_complete);
89662306a36Sopenharmony_ci
89762306a36Sopenharmony_ci	return status;
89862306a36Sopenharmony_ci}
89962306a36Sopenharmony_ci
90062306a36Sopenharmony_ci/**
90162306a36Sopenharmony_ci *  ixgbe_reset_hw_82599 - Perform hardware reset
90262306a36Sopenharmony_ci *  @hw: pointer to hardware structure
90362306a36Sopenharmony_ci *
90462306a36Sopenharmony_ci *  Resets the hardware by resetting the transmit and receive units, masks
90562306a36Sopenharmony_ci *  and clears all interrupts, perform a PHY reset, and perform a link (MAC)
90662306a36Sopenharmony_ci *  reset.
90762306a36Sopenharmony_ci **/
90862306a36Sopenharmony_cistatic s32 ixgbe_reset_hw_82599(struct ixgbe_hw *hw)
90962306a36Sopenharmony_ci{
91062306a36Sopenharmony_ci	ixgbe_link_speed link_speed;
91162306a36Sopenharmony_ci	s32 status;
91262306a36Sopenharmony_ci	u32 ctrl, i, autoc, autoc2;
91362306a36Sopenharmony_ci	u32 curr_lms;
91462306a36Sopenharmony_ci	bool link_up = false;
91562306a36Sopenharmony_ci
91662306a36Sopenharmony_ci	/* Call adapter stop to disable tx/rx and clear interrupts */
91762306a36Sopenharmony_ci	status = hw->mac.ops.stop_adapter(hw);
91862306a36Sopenharmony_ci	if (status)
91962306a36Sopenharmony_ci		return status;
92062306a36Sopenharmony_ci
92162306a36Sopenharmony_ci	/* flush pending Tx transactions */
92262306a36Sopenharmony_ci	ixgbe_clear_tx_pending(hw);
92362306a36Sopenharmony_ci
92462306a36Sopenharmony_ci	/* PHY ops must be identified and initialized prior to reset */
92562306a36Sopenharmony_ci
92662306a36Sopenharmony_ci	/* Identify PHY and related function pointers */
92762306a36Sopenharmony_ci	status = hw->phy.ops.init(hw);
92862306a36Sopenharmony_ci
92962306a36Sopenharmony_ci	if (status == -EOPNOTSUPP)
93062306a36Sopenharmony_ci		return status;
93162306a36Sopenharmony_ci
93262306a36Sopenharmony_ci	/* Setup SFP module if there is one present. */
93362306a36Sopenharmony_ci	if (hw->phy.sfp_setup_needed) {
93462306a36Sopenharmony_ci		status = hw->mac.ops.setup_sfp(hw);
93562306a36Sopenharmony_ci		hw->phy.sfp_setup_needed = false;
93662306a36Sopenharmony_ci	}
93762306a36Sopenharmony_ci
93862306a36Sopenharmony_ci	if (status == -EOPNOTSUPP)
93962306a36Sopenharmony_ci		return status;
94062306a36Sopenharmony_ci
94162306a36Sopenharmony_ci	/* Reset PHY */
94262306a36Sopenharmony_ci	if (hw->phy.reset_disable == false && hw->phy.ops.reset != NULL)
94362306a36Sopenharmony_ci		hw->phy.ops.reset(hw);
94462306a36Sopenharmony_ci
94562306a36Sopenharmony_ci	/* remember AUTOC from before we reset */
94662306a36Sopenharmony_ci	curr_lms = IXGBE_READ_REG(hw, IXGBE_AUTOC) & IXGBE_AUTOC_LMS_MASK;
94762306a36Sopenharmony_ci
94862306a36Sopenharmony_cimac_reset_top:
94962306a36Sopenharmony_ci	/*
95062306a36Sopenharmony_ci	 * Issue global reset to the MAC. Needs to be SW reset if link is up.
95162306a36Sopenharmony_ci	 * If link reset is used when link is up, it might reset the PHY when
95262306a36Sopenharmony_ci	 * mng is using it.  If link is down or the flag to force full link
95362306a36Sopenharmony_ci	 * reset is set, then perform link reset.
95462306a36Sopenharmony_ci	 */
95562306a36Sopenharmony_ci	ctrl = IXGBE_CTRL_LNK_RST;
95662306a36Sopenharmony_ci	if (!hw->force_full_reset) {
95762306a36Sopenharmony_ci		hw->mac.ops.check_link(hw, &link_speed, &link_up, false);
95862306a36Sopenharmony_ci		if (link_up)
95962306a36Sopenharmony_ci			ctrl = IXGBE_CTRL_RST;
96062306a36Sopenharmony_ci	}
96162306a36Sopenharmony_ci
96262306a36Sopenharmony_ci	ctrl |= IXGBE_READ_REG(hw, IXGBE_CTRL);
96362306a36Sopenharmony_ci	IXGBE_WRITE_REG(hw, IXGBE_CTRL, ctrl);
96462306a36Sopenharmony_ci	IXGBE_WRITE_FLUSH(hw);
96562306a36Sopenharmony_ci	usleep_range(1000, 1200);
96662306a36Sopenharmony_ci
96762306a36Sopenharmony_ci	/* Poll for reset bit to self-clear indicating reset is complete */
96862306a36Sopenharmony_ci	for (i = 0; i < 10; i++) {
96962306a36Sopenharmony_ci		ctrl = IXGBE_READ_REG(hw, IXGBE_CTRL);
97062306a36Sopenharmony_ci		if (!(ctrl & IXGBE_CTRL_RST_MASK))
97162306a36Sopenharmony_ci			break;
97262306a36Sopenharmony_ci		udelay(1);
97362306a36Sopenharmony_ci	}
97462306a36Sopenharmony_ci
97562306a36Sopenharmony_ci	if (ctrl & IXGBE_CTRL_RST_MASK) {
97662306a36Sopenharmony_ci		status = -EIO;
97762306a36Sopenharmony_ci		hw_dbg(hw, "Reset polling failed to complete.\n");
97862306a36Sopenharmony_ci	}
97962306a36Sopenharmony_ci
98062306a36Sopenharmony_ci	msleep(50);
98162306a36Sopenharmony_ci
98262306a36Sopenharmony_ci	/*
98362306a36Sopenharmony_ci	 * Double resets are required for recovery from certain error
98462306a36Sopenharmony_ci	 * conditions.  Between resets, it is necessary to stall to allow time
98562306a36Sopenharmony_ci	 * for any pending HW events to complete.
98662306a36Sopenharmony_ci	 */
98762306a36Sopenharmony_ci	if (hw->mac.flags & IXGBE_FLAGS_DOUBLE_RESET_REQUIRED) {
98862306a36Sopenharmony_ci		hw->mac.flags &= ~IXGBE_FLAGS_DOUBLE_RESET_REQUIRED;
98962306a36Sopenharmony_ci		goto mac_reset_top;
99062306a36Sopenharmony_ci	}
99162306a36Sopenharmony_ci
99262306a36Sopenharmony_ci	/*
99362306a36Sopenharmony_ci	 * Store the original AUTOC/AUTOC2 values if they have not been
99462306a36Sopenharmony_ci	 * stored off yet.  Otherwise restore the stored original
99562306a36Sopenharmony_ci	 * values since the reset operation sets back to defaults.
99662306a36Sopenharmony_ci	 */
99762306a36Sopenharmony_ci	autoc = IXGBE_READ_REG(hw, IXGBE_AUTOC);
99862306a36Sopenharmony_ci	autoc2 = IXGBE_READ_REG(hw, IXGBE_AUTOC2);
99962306a36Sopenharmony_ci
100062306a36Sopenharmony_ci	/* Enable link if disabled in NVM */
100162306a36Sopenharmony_ci	if (autoc2 & IXGBE_AUTOC2_LINK_DISABLE_MASK) {
100262306a36Sopenharmony_ci		autoc2 &= ~IXGBE_AUTOC2_LINK_DISABLE_MASK;
100362306a36Sopenharmony_ci		IXGBE_WRITE_REG(hw, IXGBE_AUTOC2, autoc2);
100462306a36Sopenharmony_ci		IXGBE_WRITE_FLUSH(hw);
100562306a36Sopenharmony_ci	}
100662306a36Sopenharmony_ci
100762306a36Sopenharmony_ci	if (hw->mac.orig_link_settings_stored == false) {
100862306a36Sopenharmony_ci		hw->mac.orig_autoc = autoc;
100962306a36Sopenharmony_ci		hw->mac.orig_autoc2 = autoc2;
101062306a36Sopenharmony_ci		hw->mac.orig_link_settings_stored = true;
101162306a36Sopenharmony_ci	} else {
101262306a36Sopenharmony_ci
101362306a36Sopenharmony_ci		/* If MNG FW is running on a multi-speed device that
101462306a36Sopenharmony_ci		 * doesn't autoneg with out driver support we need to
101562306a36Sopenharmony_ci		 * leave LMS in the state it was before we MAC reset.
101662306a36Sopenharmony_ci		 * Likewise if we support WoL we don't want change the
101762306a36Sopenharmony_ci		 * LMS state either.
101862306a36Sopenharmony_ci		 */
101962306a36Sopenharmony_ci		if ((hw->phy.multispeed_fiber && ixgbe_mng_enabled(hw)) ||
102062306a36Sopenharmony_ci		    hw->wol_enabled)
102162306a36Sopenharmony_ci			hw->mac.orig_autoc =
102262306a36Sopenharmony_ci				(hw->mac.orig_autoc & ~IXGBE_AUTOC_LMS_MASK) |
102362306a36Sopenharmony_ci				curr_lms;
102462306a36Sopenharmony_ci
102562306a36Sopenharmony_ci		if (autoc != hw->mac.orig_autoc) {
102662306a36Sopenharmony_ci			status = hw->mac.ops.prot_autoc_write(hw,
102762306a36Sopenharmony_ci							hw->mac.orig_autoc,
102862306a36Sopenharmony_ci							false);
102962306a36Sopenharmony_ci			if (status)
103062306a36Sopenharmony_ci				return status;
103162306a36Sopenharmony_ci		}
103262306a36Sopenharmony_ci
103362306a36Sopenharmony_ci		if ((autoc2 & IXGBE_AUTOC2_UPPER_MASK) !=
103462306a36Sopenharmony_ci		    (hw->mac.orig_autoc2 & IXGBE_AUTOC2_UPPER_MASK)) {
103562306a36Sopenharmony_ci			autoc2 &= ~IXGBE_AUTOC2_UPPER_MASK;
103662306a36Sopenharmony_ci			autoc2 |= (hw->mac.orig_autoc2 &
103762306a36Sopenharmony_ci				   IXGBE_AUTOC2_UPPER_MASK);
103862306a36Sopenharmony_ci			IXGBE_WRITE_REG(hw, IXGBE_AUTOC2, autoc2);
103962306a36Sopenharmony_ci		}
104062306a36Sopenharmony_ci	}
104162306a36Sopenharmony_ci
104262306a36Sopenharmony_ci	/* Store the permanent mac address */
104362306a36Sopenharmony_ci	hw->mac.ops.get_mac_addr(hw, hw->mac.perm_addr);
104462306a36Sopenharmony_ci
104562306a36Sopenharmony_ci	/*
104662306a36Sopenharmony_ci	 * Store MAC address from RAR0, clear receive address registers, and
104762306a36Sopenharmony_ci	 * clear the multicast table.  Also reset num_rar_entries to 128,
104862306a36Sopenharmony_ci	 * since we modify this value when programming the SAN MAC address.
104962306a36Sopenharmony_ci	 */
105062306a36Sopenharmony_ci	hw->mac.num_rar_entries = IXGBE_82599_RAR_ENTRIES;
105162306a36Sopenharmony_ci	hw->mac.ops.init_rx_addrs(hw);
105262306a36Sopenharmony_ci
105362306a36Sopenharmony_ci	/* Store the permanent SAN mac address */
105462306a36Sopenharmony_ci	hw->mac.ops.get_san_mac_addr(hw, hw->mac.san_addr);
105562306a36Sopenharmony_ci
105662306a36Sopenharmony_ci	/* Add the SAN MAC address to the RAR only if it's a valid address */
105762306a36Sopenharmony_ci	if (is_valid_ether_addr(hw->mac.san_addr)) {
105862306a36Sopenharmony_ci		/* Save the SAN MAC RAR index */
105962306a36Sopenharmony_ci		hw->mac.san_mac_rar_index = hw->mac.num_rar_entries - 1;
106062306a36Sopenharmony_ci
106162306a36Sopenharmony_ci		hw->mac.ops.set_rar(hw, hw->mac.san_mac_rar_index,
106262306a36Sopenharmony_ci				    hw->mac.san_addr, 0, IXGBE_RAH_AV);
106362306a36Sopenharmony_ci
106462306a36Sopenharmony_ci		/* clear VMDq pool/queue selection for this RAR */
106562306a36Sopenharmony_ci		hw->mac.ops.clear_vmdq(hw, hw->mac.san_mac_rar_index,
106662306a36Sopenharmony_ci				       IXGBE_CLEAR_VMDQ_ALL);
106762306a36Sopenharmony_ci
106862306a36Sopenharmony_ci		/* Reserve the last RAR for the SAN MAC address */
106962306a36Sopenharmony_ci		hw->mac.num_rar_entries--;
107062306a36Sopenharmony_ci	}
107162306a36Sopenharmony_ci
107262306a36Sopenharmony_ci	/* Store the alternative WWNN/WWPN prefix */
107362306a36Sopenharmony_ci	hw->mac.ops.get_wwn_prefix(hw, &hw->mac.wwnn_prefix,
107462306a36Sopenharmony_ci				       &hw->mac.wwpn_prefix);
107562306a36Sopenharmony_ci
107662306a36Sopenharmony_ci	return status;
107762306a36Sopenharmony_ci}
107862306a36Sopenharmony_ci
107962306a36Sopenharmony_ci/**
108062306a36Sopenharmony_ci * ixgbe_fdir_check_cmd_complete - poll to check whether FDIRCMD is complete
108162306a36Sopenharmony_ci * @hw: pointer to hardware structure
108262306a36Sopenharmony_ci * @fdircmd: current value of FDIRCMD register
108362306a36Sopenharmony_ci */
108462306a36Sopenharmony_cistatic s32 ixgbe_fdir_check_cmd_complete(struct ixgbe_hw *hw, u32 *fdircmd)
108562306a36Sopenharmony_ci{
108662306a36Sopenharmony_ci	int i;
108762306a36Sopenharmony_ci
108862306a36Sopenharmony_ci	for (i = 0; i < IXGBE_FDIRCMD_CMD_POLL; i++) {
108962306a36Sopenharmony_ci		*fdircmd = IXGBE_READ_REG(hw, IXGBE_FDIRCMD);
109062306a36Sopenharmony_ci		if (!(*fdircmd & IXGBE_FDIRCMD_CMD_MASK))
109162306a36Sopenharmony_ci			return 0;
109262306a36Sopenharmony_ci		udelay(10);
109362306a36Sopenharmony_ci	}
109462306a36Sopenharmony_ci
109562306a36Sopenharmony_ci	return -EIO;
109662306a36Sopenharmony_ci}
109762306a36Sopenharmony_ci
109862306a36Sopenharmony_ci/**
109962306a36Sopenharmony_ci *  ixgbe_reinit_fdir_tables_82599 - Reinitialize Flow Director tables.
110062306a36Sopenharmony_ci *  @hw: pointer to hardware structure
110162306a36Sopenharmony_ci **/
110262306a36Sopenharmony_cis32 ixgbe_reinit_fdir_tables_82599(struct ixgbe_hw *hw)
110362306a36Sopenharmony_ci{
110462306a36Sopenharmony_ci	int i;
110562306a36Sopenharmony_ci	u32 fdirctrl = IXGBE_READ_REG(hw, IXGBE_FDIRCTRL);
110662306a36Sopenharmony_ci	u32 fdircmd;
110762306a36Sopenharmony_ci	s32 err;
110862306a36Sopenharmony_ci
110962306a36Sopenharmony_ci	fdirctrl &= ~IXGBE_FDIRCTRL_INIT_DONE;
111062306a36Sopenharmony_ci
111162306a36Sopenharmony_ci	/*
111262306a36Sopenharmony_ci	 * Before starting reinitialization process,
111362306a36Sopenharmony_ci	 * FDIRCMD.CMD must be zero.
111462306a36Sopenharmony_ci	 */
111562306a36Sopenharmony_ci	err = ixgbe_fdir_check_cmd_complete(hw, &fdircmd);
111662306a36Sopenharmony_ci	if (err) {
111762306a36Sopenharmony_ci		hw_dbg(hw, "Flow Director previous command did not complete, aborting table re-initialization.\n");
111862306a36Sopenharmony_ci		return err;
111962306a36Sopenharmony_ci	}
112062306a36Sopenharmony_ci
112162306a36Sopenharmony_ci	IXGBE_WRITE_REG(hw, IXGBE_FDIRFREE, 0);
112262306a36Sopenharmony_ci	IXGBE_WRITE_FLUSH(hw);
112362306a36Sopenharmony_ci	/*
112462306a36Sopenharmony_ci	 * 82599 adapters flow director init flow cannot be restarted,
112562306a36Sopenharmony_ci	 * Workaround 82599 silicon errata by performing the following steps
112662306a36Sopenharmony_ci	 * before re-writing the FDIRCTRL control register with the same value.
112762306a36Sopenharmony_ci	 * - write 1 to bit 8 of FDIRCMD register &
112862306a36Sopenharmony_ci	 * - write 0 to bit 8 of FDIRCMD register
112962306a36Sopenharmony_ci	 */
113062306a36Sopenharmony_ci	IXGBE_WRITE_REG(hw, IXGBE_FDIRCMD,
113162306a36Sopenharmony_ci			(IXGBE_READ_REG(hw, IXGBE_FDIRCMD) |
113262306a36Sopenharmony_ci			 IXGBE_FDIRCMD_CLEARHT));
113362306a36Sopenharmony_ci	IXGBE_WRITE_FLUSH(hw);
113462306a36Sopenharmony_ci	IXGBE_WRITE_REG(hw, IXGBE_FDIRCMD,
113562306a36Sopenharmony_ci			(IXGBE_READ_REG(hw, IXGBE_FDIRCMD) &
113662306a36Sopenharmony_ci			 ~IXGBE_FDIRCMD_CLEARHT));
113762306a36Sopenharmony_ci	IXGBE_WRITE_FLUSH(hw);
113862306a36Sopenharmony_ci	/*
113962306a36Sopenharmony_ci	 * Clear FDIR Hash register to clear any leftover hashes
114062306a36Sopenharmony_ci	 * waiting to be programmed.
114162306a36Sopenharmony_ci	 */
114262306a36Sopenharmony_ci	IXGBE_WRITE_REG(hw, IXGBE_FDIRHASH, 0x00);
114362306a36Sopenharmony_ci	IXGBE_WRITE_FLUSH(hw);
114462306a36Sopenharmony_ci
114562306a36Sopenharmony_ci	IXGBE_WRITE_REG(hw, IXGBE_FDIRCTRL, fdirctrl);
114662306a36Sopenharmony_ci	IXGBE_WRITE_FLUSH(hw);
114762306a36Sopenharmony_ci
114862306a36Sopenharmony_ci	/* Poll init-done after we write FDIRCTRL register */
114962306a36Sopenharmony_ci	for (i = 0; i < IXGBE_FDIR_INIT_DONE_POLL; i++) {
115062306a36Sopenharmony_ci		if (IXGBE_READ_REG(hw, IXGBE_FDIRCTRL) &
115162306a36Sopenharmony_ci				   IXGBE_FDIRCTRL_INIT_DONE)
115262306a36Sopenharmony_ci			break;
115362306a36Sopenharmony_ci		usleep_range(1000, 2000);
115462306a36Sopenharmony_ci	}
115562306a36Sopenharmony_ci	if (i >= IXGBE_FDIR_INIT_DONE_POLL) {
115662306a36Sopenharmony_ci		hw_dbg(hw, "Flow Director Signature poll time exceeded!\n");
115762306a36Sopenharmony_ci		return -EIO;
115862306a36Sopenharmony_ci	}
115962306a36Sopenharmony_ci
116062306a36Sopenharmony_ci	/* Clear FDIR statistics registers (read to clear) */
116162306a36Sopenharmony_ci	IXGBE_READ_REG(hw, IXGBE_FDIRUSTAT);
116262306a36Sopenharmony_ci	IXGBE_READ_REG(hw, IXGBE_FDIRFSTAT);
116362306a36Sopenharmony_ci	IXGBE_READ_REG(hw, IXGBE_FDIRMATCH);
116462306a36Sopenharmony_ci	IXGBE_READ_REG(hw, IXGBE_FDIRMISS);
116562306a36Sopenharmony_ci	IXGBE_READ_REG(hw, IXGBE_FDIRLEN);
116662306a36Sopenharmony_ci
116762306a36Sopenharmony_ci	return 0;
116862306a36Sopenharmony_ci}
116962306a36Sopenharmony_ci
117062306a36Sopenharmony_ci/**
117162306a36Sopenharmony_ci *  ixgbe_fdir_enable_82599 - Initialize Flow Director control registers
117262306a36Sopenharmony_ci *  @hw: pointer to hardware structure
117362306a36Sopenharmony_ci *  @fdirctrl: value to write to flow director control register
117462306a36Sopenharmony_ci **/
117562306a36Sopenharmony_cistatic void ixgbe_fdir_enable_82599(struct ixgbe_hw *hw, u32 fdirctrl)
117662306a36Sopenharmony_ci{
117762306a36Sopenharmony_ci	int i;
117862306a36Sopenharmony_ci
117962306a36Sopenharmony_ci	/* Prime the keys for hashing */
118062306a36Sopenharmony_ci	IXGBE_WRITE_REG(hw, IXGBE_FDIRHKEY, IXGBE_ATR_BUCKET_HASH_KEY);
118162306a36Sopenharmony_ci	IXGBE_WRITE_REG(hw, IXGBE_FDIRSKEY, IXGBE_ATR_SIGNATURE_HASH_KEY);
118262306a36Sopenharmony_ci
118362306a36Sopenharmony_ci	/*
118462306a36Sopenharmony_ci	 * Poll init-done after we write the register.  Estimated times:
118562306a36Sopenharmony_ci	 *      10G: PBALLOC = 11b, timing is 60us
118662306a36Sopenharmony_ci	 *       1G: PBALLOC = 11b, timing is 600us
118762306a36Sopenharmony_ci	 *     100M: PBALLOC = 11b, timing is 6ms
118862306a36Sopenharmony_ci	 *
118962306a36Sopenharmony_ci	 *     Multiple these timings by 4 if under full Rx load
119062306a36Sopenharmony_ci	 *
119162306a36Sopenharmony_ci	 * So we'll poll for IXGBE_FDIR_INIT_DONE_POLL times, sleeping for
119262306a36Sopenharmony_ci	 * 1 msec per poll time.  If we're at line rate and drop to 100M, then
119362306a36Sopenharmony_ci	 * this might not finish in our poll time, but we can live with that
119462306a36Sopenharmony_ci	 * for now.
119562306a36Sopenharmony_ci	 */
119662306a36Sopenharmony_ci	IXGBE_WRITE_REG(hw, IXGBE_FDIRCTRL, fdirctrl);
119762306a36Sopenharmony_ci	IXGBE_WRITE_FLUSH(hw);
119862306a36Sopenharmony_ci	for (i = 0; i < IXGBE_FDIR_INIT_DONE_POLL; i++) {
119962306a36Sopenharmony_ci		if (IXGBE_READ_REG(hw, IXGBE_FDIRCTRL) &
120062306a36Sopenharmony_ci				   IXGBE_FDIRCTRL_INIT_DONE)
120162306a36Sopenharmony_ci			break;
120262306a36Sopenharmony_ci		usleep_range(1000, 2000);
120362306a36Sopenharmony_ci	}
120462306a36Sopenharmony_ci
120562306a36Sopenharmony_ci	if (i >= IXGBE_FDIR_INIT_DONE_POLL)
120662306a36Sopenharmony_ci		hw_dbg(hw, "Flow Director poll time exceeded!\n");
120762306a36Sopenharmony_ci}
120862306a36Sopenharmony_ci
120962306a36Sopenharmony_ci/**
121062306a36Sopenharmony_ci *  ixgbe_init_fdir_signature_82599 - Initialize Flow Director signature filters
121162306a36Sopenharmony_ci *  @hw: pointer to hardware structure
121262306a36Sopenharmony_ci *  @fdirctrl: value to write to flow director control register, initially
121362306a36Sopenharmony_ci *             contains just the value of the Rx packet buffer allocation
121462306a36Sopenharmony_ci **/
121562306a36Sopenharmony_cis32 ixgbe_init_fdir_signature_82599(struct ixgbe_hw *hw, u32 fdirctrl)
121662306a36Sopenharmony_ci{
121762306a36Sopenharmony_ci	/*
121862306a36Sopenharmony_ci	 * Continue setup of fdirctrl register bits:
121962306a36Sopenharmony_ci	 *  Move the flexible bytes to use the ethertype - shift 6 words
122062306a36Sopenharmony_ci	 *  Set the maximum length per hash bucket to 0xA filters
122162306a36Sopenharmony_ci	 *  Send interrupt when 64 filters are left
122262306a36Sopenharmony_ci	 */
122362306a36Sopenharmony_ci	fdirctrl |= (0x6 << IXGBE_FDIRCTRL_FLEX_SHIFT) |
122462306a36Sopenharmony_ci		    (0xA << IXGBE_FDIRCTRL_MAX_LENGTH_SHIFT) |
122562306a36Sopenharmony_ci		    (4 << IXGBE_FDIRCTRL_FULL_THRESH_SHIFT);
122662306a36Sopenharmony_ci
122762306a36Sopenharmony_ci	/* write hashes and fdirctrl register, poll for completion */
122862306a36Sopenharmony_ci	ixgbe_fdir_enable_82599(hw, fdirctrl);
122962306a36Sopenharmony_ci
123062306a36Sopenharmony_ci	return 0;
123162306a36Sopenharmony_ci}
123262306a36Sopenharmony_ci
123362306a36Sopenharmony_ci/**
123462306a36Sopenharmony_ci *  ixgbe_init_fdir_perfect_82599 - Initialize Flow Director perfect filters
123562306a36Sopenharmony_ci *  @hw: pointer to hardware structure
123662306a36Sopenharmony_ci *  @fdirctrl: value to write to flow director control register, initially
123762306a36Sopenharmony_ci *             contains just the value of the Rx packet buffer allocation
123862306a36Sopenharmony_ci **/
123962306a36Sopenharmony_cis32 ixgbe_init_fdir_perfect_82599(struct ixgbe_hw *hw, u32 fdirctrl)
124062306a36Sopenharmony_ci{
124162306a36Sopenharmony_ci	/*
124262306a36Sopenharmony_ci	 * Continue setup of fdirctrl register bits:
124362306a36Sopenharmony_ci	 *  Turn perfect match filtering on
124462306a36Sopenharmony_ci	 *  Initialize the drop queue
124562306a36Sopenharmony_ci	 *  Move the flexible bytes to use the ethertype - shift 6 words
124662306a36Sopenharmony_ci	 *  Set the maximum length per hash bucket to 0xA filters
124762306a36Sopenharmony_ci	 *  Send interrupt when 64 (0x4 * 16) filters are left
124862306a36Sopenharmony_ci	 */
124962306a36Sopenharmony_ci	fdirctrl |= IXGBE_FDIRCTRL_PERFECT_MATCH |
125062306a36Sopenharmony_ci		    (IXGBE_FDIR_DROP_QUEUE << IXGBE_FDIRCTRL_DROP_Q_SHIFT) |
125162306a36Sopenharmony_ci		    (0x6 << IXGBE_FDIRCTRL_FLEX_SHIFT) |
125262306a36Sopenharmony_ci		    (0xA << IXGBE_FDIRCTRL_MAX_LENGTH_SHIFT) |
125362306a36Sopenharmony_ci		    (4 << IXGBE_FDIRCTRL_FULL_THRESH_SHIFT);
125462306a36Sopenharmony_ci
125562306a36Sopenharmony_ci	/* write hashes and fdirctrl register, poll for completion */
125662306a36Sopenharmony_ci	ixgbe_fdir_enable_82599(hw, fdirctrl);
125762306a36Sopenharmony_ci
125862306a36Sopenharmony_ci	return 0;
125962306a36Sopenharmony_ci}
126062306a36Sopenharmony_ci
126162306a36Sopenharmony_ci/*
126262306a36Sopenharmony_ci * These defines allow us to quickly generate all of the necessary instructions
126362306a36Sopenharmony_ci * in the function below by simply calling out IXGBE_COMPUTE_SIG_HASH_ITERATION
126462306a36Sopenharmony_ci * for values 0 through 15
126562306a36Sopenharmony_ci */
126662306a36Sopenharmony_ci#define IXGBE_ATR_COMMON_HASH_KEY \
126762306a36Sopenharmony_ci		(IXGBE_ATR_BUCKET_HASH_KEY & IXGBE_ATR_SIGNATURE_HASH_KEY)
126862306a36Sopenharmony_ci#define IXGBE_COMPUTE_SIG_HASH_ITERATION(_n) \
126962306a36Sopenharmony_cido { \
127062306a36Sopenharmony_ci	u32 n = (_n); \
127162306a36Sopenharmony_ci	if (IXGBE_ATR_COMMON_HASH_KEY & BIT(n)) \
127262306a36Sopenharmony_ci		common_hash ^= lo_hash_dword >> n; \
127362306a36Sopenharmony_ci	else if (IXGBE_ATR_BUCKET_HASH_KEY & BIT(n)) \
127462306a36Sopenharmony_ci		bucket_hash ^= lo_hash_dword >> n; \
127562306a36Sopenharmony_ci	else if (IXGBE_ATR_SIGNATURE_HASH_KEY & BIT(n)) \
127662306a36Sopenharmony_ci		sig_hash ^= lo_hash_dword << (16 - n); \
127762306a36Sopenharmony_ci	if (IXGBE_ATR_COMMON_HASH_KEY & BIT(n + 16)) \
127862306a36Sopenharmony_ci		common_hash ^= hi_hash_dword >> n; \
127962306a36Sopenharmony_ci	else if (IXGBE_ATR_BUCKET_HASH_KEY & BIT(n + 16)) \
128062306a36Sopenharmony_ci		bucket_hash ^= hi_hash_dword >> n; \
128162306a36Sopenharmony_ci	else if (IXGBE_ATR_SIGNATURE_HASH_KEY & BIT(n + 16)) \
128262306a36Sopenharmony_ci		sig_hash ^= hi_hash_dword << (16 - n); \
128362306a36Sopenharmony_ci} while (0)
128462306a36Sopenharmony_ci
128562306a36Sopenharmony_ci/**
128662306a36Sopenharmony_ci *  ixgbe_atr_compute_sig_hash_82599 - Compute the signature hash
128762306a36Sopenharmony_ci *  @input: input bitstream to compute the hash on
128862306a36Sopenharmony_ci *  @common: compressed common input dword
128962306a36Sopenharmony_ci *
129062306a36Sopenharmony_ci *  This function is almost identical to the function above but contains
129162306a36Sopenharmony_ci *  several optimizations such as unwinding all of the loops, letting the
129262306a36Sopenharmony_ci *  compiler work out all of the conditional ifs since the keys are static
129362306a36Sopenharmony_ci *  defines, and computing two keys at once since the hashed dword stream
129462306a36Sopenharmony_ci *  will be the same for both keys.
129562306a36Sopenharmony_ci **/
129662306a36Sopenharmony_cistatic u32 ixgbe_atr_compute_sig_hash_82599(union ixgbe_atr_hash_dword input,
129762306a36Sopenharmony_ci					    union ixgbe_atr_hash_dword common)
129862306a36Sopenharmony_ci{
129962306a36Sopenharmony_ci	u32 hi_hash_dword, lo_hash_dword, flow_vm_vlan;
130062306a36Sopenharmony_ci	u32 sig_hash = 0, bucket_hash = 0, common_hash = 0;
130162306a36Sopenharmony_ci
130262306a36Sopenharmony_ci	/* record the flow_vm_vlan bits as they are a key part to the hash */
130362306a36Sopenharmony_ci	flow_vm_vlan = ntohl(input.dword);
130462306a36Sopenharmony_ci
130562306a36Sopenharmony_ci	/* generate common hash dword */
130662306a36Sopenharmony_ci	hi_hash_dword = ntohl(common.dword);
130762306a36Sopenharmony_ci
130862306a36Sopenharmony_ci	/* low dword is word swapped version of common */
130962306a36Sopenharmony_ci	lo_hash_dword = (hi_hash_dword >> 16) | (hi_hash_dword << 16);
131062306a36Sopenharmony_ci
131162306a36Sopenharmony_ci	/* apply flow ID/VM pool/VLAN ID bits to hash words */
131262306a36Sopenharmony_ci	hi_hash_dword ^= flow_vm_vlan ^ (flow_vm_vlan >> 16);
131362306a36Sopenharmony_ci
131462306a36Sopenharmony_ci	/* Process bits 0 and 16 */
131562306a36Sopenharmony_ci	IXGBE_COMPUTE_SIG_HASH_ITERATION(0);
131662306a36Sopenharmony_ci
131762306a36Sopenharmony_ci	/*
131862306a36Sopenharmony_ci	 * apply flow ID/VM pool/VLAN ID bits to lo hash dword, we had to
131962306a36Sopenharmony_ci	 * delay this because bit 0 of the stream should not be processed
132062306a36Sopenharmony_ci	 * so we do not add the vlan until after bit 0 was processed
132162306a36Sopenharmony_ci	 */
132262306a36Sopenharmony_ci	lo_hash_dword ^= flow_vm_vlan ^ (flow_vm_vlan << 16);
132362306a36Sopenharmony_ci
132462306a36Sopenharmony_ci	/* Process remaining 30 bit of the key */
132562306a36Sopenharmony_ci	IXGBE_COMPUTE_SIG_HASH_ITERATION(1);
132662306a36Sopenharmony_ci	IXGBE_COMPUTE_SIG_HASH_ITERATION(2);
132762306a36Sopenharmony_ci	IXGBE_COMPUTE_SIG_HASH_ITERATION(3);
132862306a36Sopenharmony_ci	IXGBE_COMPUTE_SIG_HASH_ITERATION(4);
132962306a36Sopenharmony_ci	IXGBE_COMPUTE_SIG_HASH_ITERATION(5);
133062306a36Sopenharmony_ci	IXGBE_COMPUTE_SIG_HASH_ITERATION(6);
133162306a36Sopenharmony_ci	IXGBE_COMPUTE_SIG_HASH_ITERATION(7);
133262306a36Sopenharmony_ci	IXGBE_COMPUTE_SIG_HASH_ITERATION(8);
133362306a36Sopenharmony_ci	IXGBE_COMPUTE_SIG_HASH_ITERATION(9);
133462306a36Sopenharmony_ci	IXGBE_COMPUTE_SIG_HASH_ITERATION(10);
133562306a36Sopenharmony_ci	IXGBE_COMPUTE_SIG_HASH_ITERATION(11);
133662306a36Sopenharmony_ci	IXGBE_COMPUTE_SIG_HASH_ITERATION(12);
133762306a36Sopenharmony_ci	IXGBE_COMPUTE_SIG_HASH_ITERATION(13);
133862306a36Sopenharmony_ci	IXGBE_COMPUTE_SIG_HASH_ITERATION(14);
133962306a36Sopenharmony_ci	IXGBE_COMPUTE_SIG_HASH_ITERATION(15);
134062306a36Sopenharmony_ci
134162306a36Sopenharmony_ci	/* combine common_hash result with signature and bucket hashes */
134262306a36Sopenharmony_ci	bucket_hash ^= common_hash;
134362306a36Sopenharmony_ci	bucket_hash &= IXGBE_ATR_HASH_MASK;
134462306a36Sopenharmony_ci
134562306a36Sopenharmony_ci	sig_hash ^= common_hash << 16;
134662306a36Sopenharmony_ci	sig_hash &= IXGBE_ATR_HASH_MASK << 16;
134762306a36Sopenharmony_ci
134862306a36Sopenharmony_ci	/* return completed signature hash */
134962306a36Sopenharmony_ci	return sig_hash ^ bucket_hash;
135062306a36Sopenharmony_ci}
135162306a36Sopenharmony_ci
135262306a36Sopenharmony_ci/**
135362306a36Sopenharmony_ci *  ixgbe_fdir_add_signature_filter_82599 - Adds a signature hash filter
135462306a36Sopenharmony_ci *  @hw: pointer to hardware structure
135562306a36Sopenharmony_ci *  @input: unique input dword
135662306a36Sopenharmony_ci *  @common: compressed common input dword
135762306a36Sopenharmony_ci *  @queue: queue index to direct traffic to
135862306a36Sopenharmony_ci *
135962306a36Sopenharmony_ci * Note that the tunnel bit in input must not be set when the hardware
136062306a36Sopenharmony_ci * tunneling support does not exist.
136162306a36Sopenharmony_ci **/
136262306a36Sopenharmony_cis32 ixgbe_fdir_add_signature_filter_82599(struct ixgbe_hw *hw,
136362306a36Sopenharmony_ci					  union ixgbe_atr_hash_dword input,
136462306a36Sopenharmony_ci					  union ixgbe_atr_hash_dword common,
136562306a36Sopenharmony_ci					  u8 queue)
136662306a36Sopenharmony_ci{
136762306a36Sopenharmony_ci	u64 fdirhashcmd;
136862306a36Sopenharmony_ci	u8 flow_type;
136962306a36Sopenharmony_ci	bool tunnel;
137062306a36Sopenharmony_ci	u32 fdircmd;
137162306a36Sopenharmony_ci
137262306a36Sopenharmony_ci	/*
137362306a36Sopenharmony_ci	 * Get the flow_type in order to program FDIRCMD properly
137462306a36Sopenharmony_ci	 * lowest 2 bits are FDIRCMD.L4TYPE, third lowest bit is FDIRCMD.IPV6
137562306a36Sopenharmony_ci	 */
137662306a36Sopenharmony_ci	tunnel = !!(input.formatted.flow_type & IXGBE_ATR_L4TYPE_TUNNEL_MASK);
137762306a36Sopenharmony_ci	flow_type = input.formatted.flow_type &
137862306a36Sopenharmony_ci		    (IXGBE_ATR_L4TYPE_TUNNEL_MASK - 1);
137962306a36Sopenharmony_ci	switch (flow_type) {
138062306a36Sopenharmony_ci	case IXGBE_ATR_FLOW_TYPE_TCPV4:
138162306a36Sopenharmony_ci	case IXGBE_ATR_FLOW_TYPE_UDPV4:
138262306a36Sopenharmony_ci	case IXGBE_ATR_FLOW_TYPE_SCTPV4:
138362306a36Sopenharmony_ci	case IXGBE_ATR_FLOW_TYPE_TCPV6:
138462306a36Sopenharmony_ci	case IXGBE_ATR_FLOW_TYPE_UDPV6:
138562306a36Sopenharmony_ci	case IXGBE_ATR_FLOW_TYPE_SCTPV6:
138662306a36Sopenharmony_ci		break;
138762306a36Sopenharmony_ci	default:
138862306a36Sopenharmony_ci		hw_dbg(hw, " Error on flow type input\n");
138962306a36Sopenharmony_ci		return -EIO;
139062306a36Sopenharmony_ci	}
139162306a36Sopenharmony_ci
139262306a36Sopenharmony_ci	/* configure FDIRCMD register */
139362306a36Sopenharmony_ci	fdircmd = IXGBE_FDIRCMD_CMD_ADD_FLOW | IXGBE_FDIRCMD_FILTER_UPDATE |
139462306a36Sopenharmony_ci		  IXGBE_FDIRCMD_LAST | IXGBE_FDIRCMD_QUEUE_EN;
139562306a36Sopenharmony_ci	fdircmd |= (u32)flow_type << IXGBE_FDIRCMD_FLOW_TYPE_SHIFT;
139662306a36Sopenharmony_ci	fdircmd |= (u32)queue << IXGBE_FDIRCMD_RX_QUEUE_SHIFT;
139762306a36Sopenharmony_ci	if (tunnel)
139862306a36Sopenharmony_ci		fdircmd |= IXGBE_FDIRCMD_TUNNEL_FILTER;
139962306a36Sopenharmony_ci
140062306a36Sopenharmony_ci	/*
140162306a36Sopenharmony_ci	 * The lower 32-bits of fdirhashcmd is for FDIRHASH, the upper 32-bits
140262306a36Sopenharmony_ci	 * is for FDIRCMD.  Then do a 64-bit register write from FDIRHASH.
140362306a36Sopenharmony_ci	 */
140462306a36Sopenharmony_ci	fdirhashcmd = (u64)fdircmd << 32;
140562306a36Sopenharmony_ci	fdirhashcmd |= ixgbe_atr_compute_sig_hash_82599(input, common);
140662306a36Sopenharmony_ci	IXGBE_WRITE_REG64(hw, IXGBE_FDIRHASH, fdirhashcmd);
140762306a36Sopenharmony_ci
140862306a36Sopenharmony_ci	hw_dbg(hw, "Tx Queue=%x hash=%x\n", queue, (u32)fdirhashcmd);
140962306a36Sopenharmony_ci
141062306a36Sopenharmony_ci	return 0;
141162306a36Sopenharmony_ci}
141262306a36Sopenharmony_ci
141362306a36Sopenharmony_ci#define IXGBE_COMPUTE_BKT_HASH_ITERATION(_n) \
141462306a36Sopenharmony_cido { \
141562306a36Sopenharmony_ci	u32 n = (_n); \
141662306a36Sopenharmony_ci	if (IXGBE_ATR_BUCKET_HASH_KEY & BIT(n)) \
141762306a36Sopenharmony_ci		bucket_hash ^= lo_hash_dword >> n; \
141862306a36Sopenharmony_ci	if (IXGBE_ATR_BUCKET_HASH_KEY & BIT(n + 16)) \
141962306a36Sopenharmony_ci		bucket_hash ^= hi_hash_dword >> n; \
142062306a36Sopenharmony_ci} while (0)
142162306a36Sopenharmony_ci
142262306a36Sopenharmony_ci/**
142362306a36Sopenharmony_ci *  ixgbe_atr_compute_perfect_hash_82599 - Compute the perfect filter hash
142462306a36Sopenharmony_ci *  @input: input bitstream to compute the hash on
142562306a36Sopenharmony_ci *  @input_mask: mask for the input bitstream
142662306a36Sopenharmony_ci *
142762306a36Sopenharmony_ci *  This function serves two main purposes.  First it applies the input_mask
142862306a36Sopenharmony_ci *  to the atr_input resulting in a cleaned up atr_input data stream.
142962306a36Sopenharmony_ci *  Secondly it computes the hash and stores it in the bkt_hash field at
143062306a36Sopenharmony_ci *  the end of the input byte stream.  This way it will be available for
143162306a36Sopenharmony_ci *  future use without needing to recompute the hash.
143262306a36Sopenharmony_ci **/
143362306a36Sopenharmony_civoid ixgbe_atr_compute_perfect_hash_82599(union ixgbe_atr_input *input,
143462306a36Sopenharmony_ci					  union ixgbe_atr_input *input_mask)
143562306a36Sopenharmony_ci{
143662306a36Sopenharmony_ci
143762306a36Sopenharmony_ci	u32 hi_hash_dword, lo_hash_dword, flow_vm_vlan;
143862306a36Sopenharmony_ci	u32 bucket_hash = 0;
143962306a36Sopenharmony_ci	__be32 hi_dword = 0;
144062306a36Sopenharmony_ci	int i;
144162306a36Sopenharmony_ci
144262306a36Sopenharmony_ci	/* Apply masks to input data */
144362306a36Sopenharmony_ci	for (i = 0; i <= 10; i++)
144462306a36Sopenharmony_ci		input->dword_stream[i] &= input_mask->dword_stream[i];
144562306a36Sopenharmony_ci
144662306a36Sopenharmony_ci	/* record the flow_vm_vlan bits as they are a key part to the hash */
144762306a36Sopenharmony_ci	flow_vm_vlan = ntohl(input->dword_stream[0]);
144862306a36Sopenharmony_ci
144962306a36Sopenharmony_ci	/* generate common hash dword */
145062306a36Sopenharmony_ci	for (i = 1; i <= 10; i++)
145162306a36Sopenharmony_ci		hi_dword ^= input->dword_stream[i];
145262306a36Sopenharmony_ci	hi_hash_dword = ntohl(hi_dword);
145362306a36Sopenharmony_ci
145462306a36Sopenharmony_ci	/* low dword is word swapped version of common */
145562306a36Sopenharmony_ci	lo_hash_dword = (hi_hash_dword >> 16) | (hi_hash_dword << 16);
145662306a36Sopenharmony_ci
145762306a36Sopenharmony_ci	/* apply flow ID/VM pool/VLAN ID bits to hash words */
145862306a36Sopenharmony_ci	hi_hash_dword ^= flow_vm_vlan ^ (flow_vm_vlan >> 16);
145962306a36Sopenharmony_ci
146062306a36Sopenharmony_ci	/* Process bits 0 and 16 */
146162306a36Sopenharmony_ci	IXGBE_COMPUTE_BKT_HASH_ITERATION(0);
146262306a36Sopenharmony_ci
146362306a36Sopenharmony_ci	/*
146462306a36Sopenharmony_ci	 * apply flow ID/VM pool/VLAN ID bits to lo hash dword, we had to
146562306a36Sopenharmony_ci	 * delay this because bit 0 of the stream should not be processed
146662306a36Sopenharmony_ci	 * so we do not add the vlan until after bit 0 was processed
146762306a36Sopenharmony_ci	 */
146862306a36Sopenharmony_ci	lo_hash_dword ^= flow_vm_vlan ^ (flow_vm_vlan << 16);
146962306a36Sopenharmony_ci
147062306a36Sopenharmony_ci	/* Process remaining 30 bit of the key */
147162306a36Sopenharmony_ci	for (i = 1; i <= 15; i++)
147262306a36Sopenharmony_ci		IXGBE_COMPUTE_BKT_HASH_ITERATION(i);
147362306a36Sopenharmony_ci
147462306a36Sopenharmony_ci	/*
147562306a36Sopenharmony_ci	 * Limit hash to 13 bits since max bucket count is 8K.
147662306a36Sopenharmony_ci	 * Store result at the end of the input stream.
147762306a36Sopenharmony_ci	 */
147862306a36Sopenharmony_ci	input->formatted.bkt_hash = (__force __be16)(bucket_hash & 0x1FFF);
147962306a36Sopenharmony_ci}
148062306a36Sopenharmony_ci
148162306a36Sopenharmony_ci/**
148262306a36Sopenharmony_ci *  ixgbe_get_fdirtcpm_82599 - generate a tcp port from atr_input_masks
148362306a36Sopenharmony_ci *  @input_mask: mask to be bit swapped
148462306a36Sopenharmony_ci *
148562306a36Sopenharmony_ci *  The source and destination port masks for flow director are bit swapped
148662306a36Sopenharmony_ci *  in that bit 15 effects bit 0, 14 effects 1, 13, 2 etc.  In order to
148762306a36Sopenharmony_ci *  generate a correctly swapped value we need to bit swap the mask and that
148862306a36Sopenharmony_ci *  is what is accomplished by this function.
148962306a36Sopenharmony_ci **/
149062306a36Sopenharmony_cistatic u32 ixgbe_get_fdirtcpm_82599(union ixgbe_atr_input *input_mask)
149162306a36Sopenharmony_ci{
149262306a36Sopenharmony_ci	u32 mask = ntohs(input_mask->formatted.dst_port);
149362306a36Sopenharmony_ci
149462306a36Sopenharmony_ci	mask <<= IXGBE_FDIRTCPM_DPORTM_SHIFT;
149562306a36Sopenharmony_ci	mask |= ntohs(input_mask->formatted.src_port);
149662306a36Sopenharmony_ci	mask = ((mask & 0x55555555) << 1) | ((mask & 0xAAAAAAAA) >> 1);
149762306a36Sopenharmony_ci	mask = ((mask & 0x33333333) << 2) | ((mask & 0xCCCCCCCC) >> 2);
149862306a36Sopenharmony_ci	mask = ((mask & 0x0F0F0F0F) << 4) | ((mask & 0xF0F0F0F0) >> 4);
149962306a36Sopenharmony_ci	return ((mask & 0x00FF00FF) << 8) | ((mask & 0xFF00FF00) >> 8);
150062306a36Sopenharmony_ci}
150162306a36Sopenharmony_ci
150262306a36Sopenharmony_ci/*
150362306a36Sopenharmony_ci * These two macros are meant to address the fact that we have registers
150462306a36Sopenharmony_ci * that are either all or in part big-endian.  As a result on big-endian
150562306a36Sopenharmony_ci * systems we will end up byte swapping the value to little-endian before
150662306a36Sopenharmony_ci * it is byte swapped again and written to the hardware in the original
150762306a36Sopenharmony_ci * big-endian format.
150862306a36Sopenharmony_ci */
150962306a36Sopenharmony_ci#define IXGBE_STORE_AS_BE32(_value) \
151062306a36Sopenharmony_ci	(((u32)(_value) >> 24) | (((u32)(_value) & 0x00FF0000) >> 8) | \
151162306a36Sopenharmony_ci	 (((u32)(_value) & 0x0000FF00) << 8) | ((u32)(_value) << 24))
151262306a36Sopenharmony_ci
151362306a36Sopenharmony_ci#define IXGBE_WRITE_REG_BE32(a, reg, value) \
151462306a36Sopenharmony_ci	IXGBE_WRITE_REG((a), (reg), IXGBE_STORE_AS_BE32(ntohl(value)))
151562306a36Sopenharmony_ci
151662306a36Sopenharmony_ci#define IXGBE_STORE_AS_BE16(_value) __swab16(ntohs((_value)))
151762306a36Sopenharmony_ci
151862306a36Sopenharmony_cis32 ixgbe_fdir_set_input_mask_82599(struct ixgbe_hw *hw,
151962306a36Sopenharmony_ci				    union ixgbe_atr_input *input_mask)
152062306a36Sopenharmony_ci{
152162306a36Sopenharmony_ci	/* mask IPv6 since it is currently not supported */
152262306a36Sopenharmony_ci	u32 fdirm = IXGBE_FDIRM_DIPv6;
152362306a36Sopenharmony_ci	u32 fdirtcpm;
152462306a36Sopenharmony_ci
152562306a36Sopenharmony_ci	/*
152662306a36Sopenharmony_ci	 * Program the relevant mask registers.  If src/dst_port or src/dst_addr
152762306a36Sopenharmony_ci	 * are zero, then assume a full mask for that field.  Also assume that
152862306a36Sopenharmony_ci	 * a VLAN of 0 is unspecified, so mask that out as well.  L4type
152962306a36Sopenharmony_ci	 * cannot be masked out in this implementation.
153062306a36Sopenharmony_ci	 *
153162306a36Sopenharmony_ci	 * This also assumes IPv4 only.  IPv6 masking isn't supported at this
153262306a36Sopenharmony_ci	 * point in time.
153362306a36Sopenharmony_ci	 */
153462306a36Sopenharmony_ci
153562306a36Sopenharmony_ci	/* verify bucket hash is cleared on hash generation */
153662306a36Sopenharmony_ci	if (input_mask->formatted.bkt_hash)
153762306a36Sopenharmony_ci		hw_dbg(hw, " bucket hash should always be 0 in mask\n");
153862306a36Sopenharmony_ci
153962306a36Sopenharmony_ci	/* Program FDIRM and verify partial masks */
154062306a36Sopenharmony_ci	switch (input_mask->formatted.vm_pool & 0x7F) {
154162306a36Sopenharmony_ci	case 0x0:
154262306a36Sopenharmony_ci		fdirm |= IXGBE_FDIRM_POOL;
154362306a36Sopenharmony_ci		break;
154462306a36Sopenharmony_ci	case 0x7F:
154562306a36Sopenharmony_ci		break;
154662306a36Sopenharmony_ci	default:
154762306a36Sopenharmony_ci		hw_dbg(hw, " Error on vm pool mask\n");
154862306a36Sopenharmony_ci		return -EIO;
154962306a36Sopenharmony_ci	}
155062306a36Sopenharmony_ci
155162306a36Sopenharmony_ci	switch (input_mask->formatted.flow_type & IXGBE_ATR_L4TYPE_MASK) {
155262306a36Sopenharmony_ci	case 0x0:
155362306a36Sopenharmony_ci		fdirm |= IXGBE_FDIRM_L4P;
155462306a36Sopenharmony_ci		if (input_mask->formatted.dst_port ||
155562306a36Sopenharmony_ci		    input_mask->formatted.src_port) {
155662306a36Sopenharmony_ci			hw_dbg(hw, " Error on src/dst port mask\n");
155762306a36Sopenharmony_ci			return -EIO;
155862306a36Sopenharmony_ci		}
155962306a36Sopenharmony_ci		break;
156062306a36Sopenharmony_ci	case IXGBE_ATR_L4TYPE_MASK:
156162306a36Sopenharmony_ci		break;
156262306a36Sopenharmony_ci	default:
156362306a36Sopenharmony_ci		hw_dbg(hw, " Error on flow type mask\n");
156462306a36Sopenharmony_ci		return -EIO;
156562306a36Sopenharmony_ci	}
156662306a36Sopenharmony_ci
156762306a36Sopenharmony_ci	switch (ntohs(input_mask->formatted.vlan_id) & 0xEFFF) {
156862306a36Sopenharmony_ci	case 0x0000:
156962306a36Sopenharmony_ci		/* mask VLAN ID */
157062306a36Sopenharmony_ci		fdirm |= IXGBE_FDIRM_VLANID;
157162306a36Sopenharmony_ci		fallthrough;
157262306a36Sopenharmony_ci	case 0x0FFF:
157362306a36Sopenharmony_ci		/* mask VLAN priority */
157462306a36Sopenharmony_ci		fdirm |= IXGBE_FDIRM_VLANP;
157562306a36Sopenharmony_ci		break;
157662306a36Sopenharmony_ci	case 0xE000:
157762306a36Sopenharmony_ci		/* mask VLAN ID only */
157862306a36Sopenharmony_ci		fdirm |= IXGBE_FDIRM_VLANID;
157962306a36Sopenharmony_ci		fallthrough;
158062306a36Sopenharmony_ci	case 0xEFFF:
158162306a36Sopenharmony_ci		/* no VLAN fields masked */
158262306a36Sopenharmony_ci		break;
158362306a36Sopenharmony_ci	default:
158462306a36Sopenharmony_ci		hw_dbg(hw, " Error on VLAN mask\n");
158562306a36Sopenharmony_ci		return -EIO;
158662306a36Sopenharmony_ci	}
158762306a36Sopenharmony_ci
158862306a36Sopenharmony_ci	switch ((__force u16)input_mask->formatted.flex_bytes & 0xFFFF) {
158962306a36Sopenharmony_ci	case 0x0000:
159062306a36Sopenharmony_ci		/* Mask Flex Bytes */
159162306a36Sopenharmony_ci		fdirm |= IXGBE_FDIRM_FLEX;
159262306a36Sopenharmony_ci		fallthrough;
159362306a36Sopenharmony_ci	case 0xFFFF:
159462306a36Sopenharmony_ci		break;
159562306a36Sopenharmony_ci	default:
159662306a36Sopenharmony_ci		hw_dbg(hw, " Error on flexible byte mask\n");
159762306a36Sopenharmony_ci		return -EIO;
159862306a36Sopenharmony_ci	}
159962306a36Sopenharmony_ci
160062306a36Sopenharmony_ci	/* Now mask VM pool and destination IPv6 - bits 5 and 2 */
160162306a36Sopenharmony_ci	IXGBE_WRITE_REG(hw, IXGBE_FDIRM, fdirm);
160262306a36Sopenharmony_ci
160362306a36Sopenharmony_ci	/* store the TCP/UDP port masks, bit reversed from port layout */
160462306a36Sopenharmony_ci	fdirtcpm = ixgbe_get_fdirtcpm_82599(input_mask);
160562306a36Sopenharmony_ci
160662306a36Sopenharmony_ci	/* write both the same so that UDP and TCP use the same mask */
160762306a36Sopenharmony_ci	IXGBE_WRITE_REG(hw, IXGBE_FDIRTCPM, ~fdirtcpm);
160862306a36Sopenharmony_ci	IXGBE_WRITE_REG(hw, IXGBE_FDIRUDPM, ~fdirtcpm);
160962306a36Sopenharmony_ci
161062306a36Sopenharmony_ci	/* also use it for SCTP */
161162306a36Sopenharmony_ci	switch (hw->mac.type) {
161262306a36Sopenharmony_ci	case ixgbe_mac_X550:
161362306a36Sopenharmony_ci	case ixgbe_mac_X550EM_x:
161462306a36Sopenharmony_ci	case ixgbe_mac_x550em_a:
161562306a36Sopenharmony_ci		IXGBE_WRITE_REG(hw, IXGBE_FDIRSCTPM, ~fdirtcpm);
161662306a36Sopenharmony_ci		break;
161762306a36Sopenharmony_ci	default:
161862306a36Sopenharmony_ci		break;
161962306a36Sopenharmony_ci	}
162062306a36Sopenharmony_ci
162162306a36Sopenharmony_ci	/* store source and destination IP masks (big-enian) */
162262306a36Sopenharmony_ci	IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRSIP4M,
162362306a36Sopenharmony_ci			     ~input_mask->formatted.src_ip[0]);
162462306a36Sopenharmony_ci	IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRDIP4M,
162562306a36Sopenharmony_ci			     ~input_mask->formatted.dst_ip[0]);
162662306a36Sopenharmony_ci
162762306a36Sopenharmony_ci	return 0;
162862306a36Sopenharmony_ci}
162962306a36Sopenharmony_ci
163062306a36Sopenharmony_cis32 ixgbe_fdir_write_perfect_filter_82599(struct ixgbe_hw *hw,
163162306a36Sopenharmony_ci					  union ixgbe_atr_input *input,
163262306a36Sopenharmony_ci					  u16 soft_id, u8 queue)
163362306a36Sopenharmony_ci{
163462306a36Sopenharmony_ci	u32 fdirport, fdirvlan, fdirhash, fdircmd;
163562306a36Sopenharmony_ci	s32 err;
163662306a36Sopenharmony_ci
163762306a36Sopenharmony_ci	/* currently IPv6 is not supported, must be programmed with 0 */
163862306a36Sopenharmony_ci	IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRSIPv6(0),
163962306a36Sopenharmony_ci			     input->formatted.src_ip[0]);
164062306a36Sopenharmony_ci	IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRSIPv6(1),
164162306a36Sopenharmony_ci			     input->formatted.src_ip[1]);
164262306a36Sopenharmony_ci	IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRSIPv6(2),
164362306a36Sopenharmony_ci			     input->formatted.src_ip[2]);
164462306a36Sopenharmony_ci
164562306a36Sopenharmony_ci	/* record the source address (big-endian) */
164662306a36Sopenharmony_ci	IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRIPSA, input->formatted.src_ip[0]);
164762306a36Sopenharmony_ci
164862306a36Sopenharmony_ci	/* record the first 32 bits of the destination address (big-endian) */
164962306a36Sopenharmony_ci	IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRIPDA, input->formatted.dst_ip[0]);
165062306a36Sopenharmony_ci
165162306a36Sopenharmony_ci	/* record source and destination port (little-endian)*/
165262306a36Sopenharmony_ci	fdirport = be16_to_cpu(input->formatted.dst_port);
165362306a36Sopenharmony_ci	fdirport <<= IXGBE_FDIRPORT_DESTINATION_SHIFT;
165462306a36Sopenharmony_ci	fdirport |= be16_to_cpu(input->formatted.src_port);
165562306a36Sopenharmony_ci	IXGBE_WRITE_REG(hw, IXGBE_FDIRPORT, fdirport);
165662306a36Sopenharmony_ci
165762306a36Sopenharmony_ci	/* record vlan (little-endian) and flex_bytes(big-endian) */
165862306a36Sopenharmony_ci	fdirvlan = IXGBE_STORE_AS_BE16(input->formatted.flex_bytes);
165962306a36Sopenharmony_ci	fdirvlan <<= IXGBE_FDIRVLAN_FLEX_SHIFT;
166062306a36Sopenharmony_ci	fdirvlan |= ntohs(input->formatted.vlan_id);
166162306a36Sopenharmony_ci	IXGBE_WRITE_REG(hw, IXGBE_FDIRVLAN, fdirvlan);
166262306a36Sopenharmony_ci
166362306a36Sopenharmony_ci	/* configure FDIRHASH register */
166462306a36Sopenharmony_ci	fdirhash = (__force u32)input->formatted.bkt_hash;
166562306a36Sopenharmony_ci	fdirhash |= soft_id << IXGBE_FDIRHASH_SIG_SW_INDEX_SHIFT;
166662306a36Sopenharmony_ci	IXGBE_WRITE_REG(hw, IXGBE_FDIRHASH, fdirhash);
166762306a36Sopenharmony_ci
166862306a36Sopenharmony_ci	/*
166962306a36Sopenharmony_ci	 * flush all previous writes to make certain registers are
167062306a36Sopenharmony_ci	 * programmed prior to issuing the command
167162306a36Sopenharmony_ci	 */
167262306a36Sopenharmony_ci	IXGBE_WRITE_FLUSH(hw);
167362306a36Sopenharmony_ci
167462306a36Sopenharmony_ci	/* configure FDIRCMD register */
167562306a36Sopenharmony_ci	fdircmd = IXGBE_FDIRCMD_CMD_ADD_FLOW | IXGBE_FDIRCMD_FILTER_UPDATE |
167662306a36Sopenharmony_ci		  IXGBE_FDIRCMD_LAST | IXGBE_FDIRCMD_QUEUE_EN;
167762306a36Sopenharmony_ci	if (queue == IXGBE_FDIR_DROP_QUEUE)
167862306a36Sopenharmony_ci		fdircmd |= IXGBE_FDIRCMD_DROP;
167962306a36Sopenharmony_ci	fdircmd |= input->formatted.flow_type << IXGBE_FDIRCMD_FLOW_TYPE_SHIFT;
168062306a36Sopenharmony_ci	fdircmd |= (u32)queue << IXGBE_FDIRCMD_RX_QUEUE_SHIFT;
168162306a36Sopenharmony_ci	fdircmd |= (u32)input->formatted.vm_pool << IXGBE_FDIRCMD_VT_POOL_SHIFT;
168262306a36Sopenharmony_ci
168362306a36Sopenharmony_ci	IXGBE_WRITE_REG(hw, IXGBE_FDIRCMD, fdircmd);
168462306a36Sopenharmony_ci	err = ixgbe_fdir_check_cmd_complete(hw, &fdircmd);
168562306a36Sopenharmony_ci	if (err) {
168662306a36Sopenharmony_ci		hw_dbg(hw, "Flow Director command did not complete!\n");
168762306a36Sopenharmony_ci		return err;
168862306a36Sopenharmony_ci	}
168962306a36Sopenharmony_ci
169062306a36Sopenharmony_ci	return 0;
169162306a36Sopenharmony_ci}
169262306a36Sopenharmony_ci
169362306a36Sopenharmony_cis32 ixgbe_fdir_erase_perfect_filter_82599(struct ixgbe_hw *hw,
169462306a36Sopenharmony_ci					  union ixgbe_atr_input *input,
169562306a36Sopenharmony_ci					  u16 soft_id)
169662306a36Sopenharmony_ci{
169762306a36Sopenharmony_ci	u32 fdirhash;
169862306a36Sopenharmony_ci	u32 fdircmd;
169962306a36Sopenharmony_ci	s32 err;
170062306a36Sopenharmony_ci
170162306a36Sopenharmony_ci	/* configure FDIRHASH register */
170262306a36Sopenharmony_ci	fdirhash = (__force u32)input->formatted.bkt_hash;
170362306a36Sopenharmony_ci	fdirhash |= soft_id << IXGBE_FDIRHASH_SIG_SW_INDEX_SHIFT;
170462306a36Sopenharmony_ci	IXGBE_WRITE_REG(hw, IXGBE_FDIRHASH, fdirhash);
170562306a36Sopenharmony_ci
170662306a36Sopenharmony_ci	/* flush hash to HW */
170762306a36Sopenharmony_ci	IXGBE_WRITE_FLUSH(hw);
170862306a36Sopenharmony_ci
170962306a36Sopenharmony_ci	/* Query if filter is present */
171062306a36Sopenharmony_ci	IXGBE_WRITE_REG(hw, IXGBE_FDIRCMD, IXGBE_FDIRCMD_CMD_QUERY_REM_FILT);
171162306a36Sopenharmony_ci
171262306a36Sopenharmony_ci	err = ixgbe_fdir_check_cmd_complete(hw, &fdircmd);
171362306a36Sopenharmony_ci	if (err) {
171462306a36Sopenharmony_ci		hw_dbg(hw, "Flow Director command did not complete!\n");
171562306a36Sopenharmony_ci		return err;
171662306a36Sopenharmony_ci	}
171762306a36Sopenharmony_ci
171862306a36Sopenharmony_ci	/* if filter exists in hardware then remove it */
171962306a36Sopenharmony_ci	if (fdircmd & IXGBE_FDIRCMD_FILTER_VALID) {
172062306a36Sopenharmony_ci		IXGBE_WRITE_REG(hw, IXGBE_FDIRHASH, fdirhash);
172162306a36Sopenharmony_ci		IXGBE_WRITE_FLUSH(hw);
172262306a36Sopenharmony_ci		IXGBE_WRITE_REG(hw, IXGBE_FDIRCMD,
172362306a36Sopenharmony_ci				IXGBE_FDIRCMD_CMD_REMOVE_FLOW);
172462306a36Sopenharmony_ci	}
172562306a36Sopenharmony_ci
172662306a36Sopenharmony_ci	return 0;
172762306a36Sopenharmony_ci}
172862306a36Sopenharmony_ci
172962306a36Sopenharmony_ci/**
173062306a36Sopenharmony_ci *  ixgbe_read_analog_reg8_82599 - Reads 8 bit Omer analog register
173162306a36Sopenharmony_ci *  @hw: pointer to hardware structure
173262306a36Sopenharmony_ci *  @reg: analog register to read
173362306a36Sopenharmony_ci *  @val: read value
173462306a36Sopenharmony_ci *
173562306a36Sopenharmony_ci *  Performs read operation to Omer analog register specified.
173662306a36Sopenharmony_ci **/
173762306a36Sopenharmony_cistatic s32 ixgbe_read_analog_reg8_82599(struct ixgbe_hw *hw, u32 reg, u8 *val)
173862306a36Sopenharmony_ci{
173962306a36Sopenharmony_ci	u32  core_ctl;
174062306a36Sopenharmony_ci
174162306a36Sopenharmony_ci	IXGBE_WRITE_REG(hw, IXGBE_CORECTL, IXGBE_CORECTL_WRITE_CMD |
174262306a36Sopenharmony_ci			(reg << 8));
174362306a36Sopenharmony_ci	IXGBE_WRITE_FLUSH(hw);
174462306a36Sopenharmony_ci	udelay(10);
174562306a36Sopenharmony_ci	core_ctl = IXGBE_READ_REG(hw, IXGBE_CORECTL);
174662306a36Sopenharmony_ci	*val = (u8)core_ctl;
174762306a36Sopenharmony_ci
174862306a36Sopenharmony_ci	return 0;
174962306a36Sopenharmony_ci}
175062306a36Sopenharmony_ci
175162306a36Sopenharmony_ci/**
175262306a36Sopenharmony_ci *  ixgbe_write_analog_reg8_82599 - Writes 8 bit Omer analog register
175362306a36Sopenharmony_ci *  @hw: pointer to hardware structure
175462306a36Sopenharmony_ci *  @reg: atlas register to write
175562306a36Sopenharmony_ci *  @val: value to write
175662306a36Sopenharmony_ci *
175762306a36Sopenharmony_ci *  Performs write operation to Omer analog register specified.
175862306a36Sopenharmony_ci **/
175962306a36Sopenharmony_cistatic s32 ixgbe_write_analog_reg8_82599(struct ixgbe_hw *hw, u32 reg, u8 val)
176062306a36Sopenharmony_ci{
176162306a36Sopenharmony_ci	u32  core_ctl;
176262306a36Sopenharmony_ci
176362306a36Sopenharmony_ci	core_ctl = (reg << 8) | val;
176462306a36Sopenharmony_ci	IXGBE_WRITE_REG(hw, IXGBE_CORECTL, core_ctl);
176562306a36Sopenharmony_ci	IXGBE_WRITE_FLUSH(hw);
176662306a36Sopenharmony_ci	udelay(10);
176762306a36Sopenharmony_ci
176862306a36Sopenharmony_ci	return 0;
176962306a36Sopenharmony_ci}
177062306a36Sopenharmony_ci
177162306a36Sopenharmony_ci/**
177262306a36Sopenharmony_ci *  ixgbe_start_hw_82599 - Prepare hardware for Tx/Rx
177362306a36Sopenharmony_ci *  @hw: pointer to hardware structure
177462306a36Sopenharmony_ci *
177562306a36Sopenharmony_ci *  Starts the hardware using the generic start_hw function
177662306a36Sopenharmony_ci *  and the generation start_hw function.
177762306a36Sopenharmony_ci *  Then performs revision-specific operations, if any.
177862306a36Sopenharmony_ci **/
177962306a36Sopenharmony_cistatic s32 ixgbe_start_hw_82599(struct ixgbe_hw *hw)
178062306a36Sopenharmony_ci{
178162306a36Sopenharmony_ci	s32 ret_val = 0;
178262306a36Sopenharmony_ci
178362306a36Sopenharmony_ci	ret_val = ixgbe_start_hw_generic(hw);
178462306a36Sopenharmony_ci	if (ret_val)
178562306a36Sopenharmony_ci		return ret_val;
178662306a36Sopenharmony_ci
178762306a36Sopenharmony_ci	ret_val = ixgbe_start_hw_gen2(hw);
178862306a36Sopenharmony_ci	if (ret_val)
178962306a36Sopenharmony_ci		return ret_val;
179062306a36Sopenharmony_ci
179162306a36Sopenharmony_ci	/* We need to run link autotry after the driver loads */
179262306a36Sopenharmony_ci	hw->mac.autotry_restart = true;
179362306a36Sopenharmony_ci
179462306a36Sopenharmony_ci	return ixgbe_verify_fw_version_82599(hw);
179562306a36Sopenharmony_ci}
179662306a36Sopenharmony_ci
179762306a36Sopenharmony_ci/**
179862306a36Sopenharmony_ci *  ixgbe_identify_phy_82599 - Get physical layer module
179962306a36Sopenharmony_ci *  @hw: pointer to hardware structure
180062306a36Sopenharmony_ci *
180162306a36Sopenharmony_ci *  Determines the physical layer module found on the current adapter.
180262306a36Sopenharmony_ci *  If PHY already detected, maintains current PHY type in hw struct,
180362306a36Sopenharmony_ci *  otherwise executes the PHY detection routine.
180462306a36Sopenharmony_ci **/
180562306a36Sopenharmony_cistatic s32 ixgbe_identify_phy_82599(struct ixgbe_hw *hw)
180662306a36Sopenharmony_ci{
180762306a36Sopenharmony_ci	s32 status;
180862306a36Sopenharmony_ci
180962306a36Sopenharmony_ci	/* Detect PHY if not unknown - returns success if already detected. */
181062306a36Sopenharmony_ci	status = ixgbe_identify_phy_generic(hw);
181162306a36Sopenharmony_ci	if (status) {
181262306a36Sopenharmony_ci		/* 82599 10GBASE-T requires an external PHY */
181362306a36Sopenharmony_ci		if (hw->mac.ops.get_media_type(hw) == ixgbe_media_type_copper)
181462306a36Sopenharmony_ci			return status;
181562306a36Sopenharmony_ci		status = ixgbe_identify_module_generic(hw);
181662306a36Sopenharmony_ci	}
181762306a36Sopenharmony_ci
181862306a36Sopenharmony_ci	/* Set PHY type none if no PHY detected */
181962306a36Sopenharmony_ci	if (hw->phy.type == ixgbe_phy_unknown) {
182062306a36Sopenharmony_ci		hw->phy.type = ixgbe_phy_none;
182162306a36Sopenharmony_ci		status = 0;
182262306a36Sopenharmony_ci	}
182362306a36Sopenharmony_ci
182462306a36Sopenharmony_ci	/* Return error if SFP module has been detected but is not supported */
182562306a36Sopenharmony_ci	if (hw->phy.type == ixgbe_phy_sfp_unsupported)
182662306a36Sopenharmony_ci		return -EOPNOTSUPP;
182762306a36Sopenharmony_ci
182862306a36Sopenharmony_ci	return status;
182962306a36Sopenharmony_ci}
183062306a36Sopenharmony_ci
183162306a36Sopenharmony_ci/**
183262306a36Sopenharmony_ci *  ixgbe_enable_rx_dma_82599 - Enable the Rx DMA unit on 82599
183362306a36Sopenharmony_ci *  @hw: pointer to hardware structure
183462306a36Sopenharmony_ci *  @regval: register value to write to RXCTRL
183562306a36Sopenharmony_ci *
183662306a36Sopenharmony_ci *  Enables the Rx DMA unit for 82599
183762306a36Sopenharmony_ci **/
183862306a36Sopenharmony_cistatic s32 ixgbe_enable_rx_dma_82599(struct ixgbe_hw *hw, u32 regval)
183962306a36Sopenharmony_ci{
184062306a36Sopenharmony_ci	/*
184162306a36Sopenharmony_ci	 * Workaround for 82599 silicon errata when enabling the Rx datapath.
184262306a36Sopenharmony_ci	 * If traffic is incoming before we enable the Rx unit, it could hang
184362306a36Sopenharmony_ci	 * the Rx DMA unit.  Therefore, make sure the security engine is
184462306a36Sopenharmony_ci	 * completely disabled prior to enabling the Rx unit.
184562306a36Sopenharmony_ci	 */
184662306a36Sopenharmony_ci	hw->mac.ops.disable_rx_buff(hw);
184762306a36Sopenharmony_ci
184862306a36Sopenharmony_ci	if (regval & IXGBE_RXCTRL_RXEN)
184962306a36Sopenharmony_ci		hw->mac.ops.enable_rx(hw);
185062306a36Sopenharmony_ci	else
185162306a36Sopenharmony_ci		hw->mac.ops.disable_rx(hw);
185262306a36Sopenharmony_ci
185362306a36Sopenharmony_ci	hw->mac.ops.enable_rx_buff(hw);
185462306a36Sopenharmony_ci
185562306a36Sopenharmony_ci	return 0;
185662306a36Sopenharmony_ci}
185762306a36Sopenharmony_ci
185862306a36Sopenharmony_ci/**
185962306a36Sopenharmony_ci *  ixgbe_verify_fw_version_82599 - verify fw version for 82599
186062306a36Sopenharmony_ci *  @hw: pointer to hardware structure
186162306a36Sopenharmony_ci *
186262306a36Sopenharmony_ci *  Verifies that installed the firmware version is 0.6 or higher
186362306a36Sopenharmony_ci *  for SFI devices. All 82599 SFI devices should have version 0.6 or higher.
186462306a36Sopenharmony_ci *
186562306a36Sopenharmony_ci *  Return: -EACCES if the FW is not present or if the FW version is
186662306a36Sopenharmony_ci *  not supported.
186762306a36Sopenharmony_ci **/
186862306a36Sopenharmony_cistatic s32 ixgbe_verify_fw_version_82599(struct ixgbe_hw *hw)
186962306a36Sopenharmony_ci{
187062306a36Sopenharmony_ci	u16 fw_offset, fw_ptp_cfg_offset;
187162306a36Sopenharmony_ci	s32 status = -EACCES;
187262306a36Sopenharmony_ci	u16 offset;
187362306a36Sopenharmony_ci	u16 fw_version = 0;
187462306a36Sopenharmony_ci
187562306a36Sopenharmony_ci	/* firmware check is only necessary for SFI devices */
187662306a36Sopenharmony_ci	if (hw->phy.media_type != ixgbe_media_type_fiber)
187762306a36Sopenharmony_ci		return 0;
187862306a36Sopenharmony_ci
187962306a36Sopenharmony_ci	/* get the offset to the Firmware Module block */
188062306a36Sopenharmony_ci	offset = IXGBE_FW_PTR;
188162306a36Sopenharmony_ci	if (hw->eeprom.ops.read(hw, offset, &fw_offset))
188262306a36Sopenharmony_ci		goto fw_version_err;
188362306a36Sopenharmony_ci
188462306a36Sopenharmony_ci	if (fw_offset == 0 || fw_offset == 0xFFFF)
188562306a36Sopenharmony_ci		return -EACCES;
188662306a36Sopenharmony_ci
188762306a36Sopenharmony_ci	/* get the offset to the Pass Through Patch Configuration block */
188862306a36Sopenharmony_ci	offset = fw_offset + IXGBE_FW_PASSTHROUGH_PATCH_CONFIG_PTR;
188962306a36Sopenharmony_ci	if (hw->eeprom.ops.read(hw, offset, &fw_ptp_cfg_offset))
189062306a36Sopenharmony_ci		goto fw_version_err;
189162306a36Sopenharmony_ci
189262306a36Sopenharmony_ci	if (fw_ptp_cfg_offset == 0 || fw_ptp_cfg_offset == 0xFFFF)
189362306a36Sopenharmony_ci		return -EACCES;
189462306a36Sopenharmony_ci
189562306a36Sopenharmony_ci	/* get the firmware version */
189662306a36Sopenharmony_ci	offset = fw_ptp_cfg_offset + IXGBE_FW_PATCH_VERSION_4;
189762306a36Sopenharmony_ci	if (hw->eeprom.ops.read(hw, offset, &fw_version))
189862306a36Sopenharmony_ci		goto fw_version_err;
189962306a36Sopenharmony_ci
190062306a36Sopenharmony_ci	if (fw_version > 0x5)
190162306a36Sopenharmony_ci		status = 0;
190262306a36Sopenharmony_ci
190362306a36Sopenharmony_ci	return status;
190462306a36Sopenharmony_ci
190562306a36Sopenharmony_cifw_version_err:
190662306a36Sopenharmony_ci	hw_err(hw, "eeprom read at offset %d failed\n", offset);
190762306a36Sopenharmony_ci	return -EACCES;
190862306a36Sopenharmony_ci}
190962306a36Sopenharmony_ci
191062306a36Sopenharmony_ci/**
191162306a36Sopenharmony_ci *  ixgbe_verify_lesm_fw_enabled_82599 - Checks LESM FW module state.
191262306a36Sopenharmony_ci *  @hw: pointer to hardware structure
191362306a36Sopenharmony_ci *
191462306a36Sopenharmony_ci *  Returns true if the LESM FW module is present and enabled. Otherwise
191562306a36Sopenharmony_ci *  returns false. Smart Speed must be disabled if LESM FW module is enabled.
191662306a36Sopenharmony_ci **/
191762306a36Sopenharmony_cistatic bool ixgbe_verify_lesm_fw_enabled_82599(struct ixgbe_hw *hw)
191862306a36Sopenharmony_ci{
191962306a36Sopenharmony_ci	u16 fw_offset, fw_lesm_param_offset, fw_lesm_state;
192062306a36Sopenharmony_ci	s32 status;
192162306a36Sopenharmony_ci
192262306a36Sopenharmony_ci	/* get the offset to the Firmware Module block */
192362306a36Sopenharmony_ci	status = hw->eeprom.ops.read(hw, IXGBE_FW_PTR, &fw_offset);
192462306a36Sopenharmony_ci
192562306a36Sopenharmony_ci	if (status || fw_offset == 0 || fw_offset == 0xFFFF)
192662306a36Sopenharmony_ci		return false;
192762306a36Sopenharmony_ci
192862306a36Sopenharmony_ci	/* get the offset to the LESM Parameters block */
192962306a36Sopenharmony_ci	status = hw->eeprom.ops.read(hw, (fw_offset +
193062306a36Sopenharmony_ci				     IXGBE_FW_LESM_PARAMETERS_PTR),
193162306a36Sopenharmony_ci				     &fw_lesm_param_offset);
193262306a36Sopenharmony_ci
193362306a36Sopenharmony_ci	if (status ||
193462306a36Sopenharmony_ci	    fw_lesm_param_offset == 0 || fw_lesm_param_offset == 0xFFFF)
193562306a36Sopenharmony_ci		return false;
193662306a36Sopenharmony_ci
193762306a36Sopenharmony_ci	/* get the lesm state word */
193862306a36Sopenharmony_ci	status = hw->eeprom.ops.read(hw, (fw_lesm_param_offset +
193962306a36Sopenharmony_ci				     IXGBE_FW_LESM_STATE_1),
194062306a36Sopenharmony_ci				     &fw_lesm_state);
194162306a36Sopenharmony_ci
194262306a36Sopenharmony_ci	if (!status && (fw_lesm_state & IXGBE_FW_LESM_STATE_ENABLED))
194362306a36Sopenharmony_ci		return true;
194462306a36Sopenharmony_ci
194562306a36Sopenharmony_ci	return false;
194662306a36Sopenharmony_ci}
194762306a36Sopenharmony_ci
194862306a36Sopenharmony_ci/**
194962306a36Sopenharmony_ci *  ixgbe_read_eeprom_buffer_82599 - Read EEPROM word(s) using
195062306a36Sopenharmony_ci *  fastest available method
195162306a36Sopenharmony_ci *
195262306a36Sopenharmony_ci *  @hw: pointer to hardware structure
195362306a36Sopenharmony_ci *  @offset: offset of  word in EEPROM to read
195462306a36Sopenharmony_ci *  @words: number of words
195562306a36Sopenharmony_ci *  @data: word(s) read from the EEPROM
195662306a36Sopenharmony_ci *
195762306a36Sopenharmony_ci *  Retrieves 16 bit word(s) read from EEPROM
195862306a36Sopenharmony_ci **/
195962306a36Sopenharmony_cistatic s32 ixgbe_read_eeprom_buffer_82599(struct ixgbe_hw *hw, u16 offset,
196062306a36Sopenharmony_ci					  u16 words, u16 *data)
196162306a36Sopenharmony_ci{
196262306a36Sopenharmony_ci	struct ixgbe_eeprom_info *eeprom = &hw->eeprom;
196362306a36Sopenharmony_ci
196462306a36Sopenharmony_ci	/* If EEPROM is detected and can be addressed using 14 bits,
196562306a36Sopenharmony_ci	 * use EERD otherwise use bit bang
196662306a36Sopenharmony_ci	 */
196762306a36Sopenharmony_ci	if (eeprom->type == ixgbe_eeprom_spi &&
196862306a36Sopenharmony_ci	    offset + (words - 1) <= IXGBE_EERD_MAX_ADDR)
196962306a36Sopenharmony_ci		return ixgbe_read_eerd_buffer_generic(hw, offset, words, data);
197062306a36Sopenharmony_ci
197162306a36Sopenharmony_ci	return ixgbe_read_eeprom_buffer_bit_bang_generic(hw, offset, words,
197262306a36Sopenharmony_ci							 data);
197362306a36Sopenharmony_ci}
197462306a36Sopenharmony_ci
197562306a36Sopenharmony_ci/**
197662306a36Sopenharmony_ci *  ixgbe_read_eeprom_82599 - Read EEPROM word using
197762306a36Sopenharmony_ci *  fastest available method
197862306a36Sopenharmony_ci *
197962306a36Sopenharmony_ci *  @hw: pointer to hardware structure
198062306a36Sopenharmony_ci *  @offset: offset of  word in the EEPROM to read
198162306a36Sopenharmony_ci *  @data: word read from the EEPROM
198262306a36Sopenharmony_ci *
198362306a36Sopenharmony_ci *  Reads a 16 bit word from the EEPROM
198462306a36Sopenharmony_ci **/
198562306a36Sopenharmony_cistatic s32 ixgbe_read_eeprom_82599(struct ixgbe_hw *hw,
198662306a36Sopenharmony_ci				   u16 offset, u16 *data)
198762306a36Sopenharmony_ci{
198862306a36Sopenharmony_ci	struct ixgbe_eeprom_info *eeprom = &hw->eeprom;
198962306a36Sopenharmony_ci
199062306a36Sopenharmony_ci	/*
199162306a36Sopenharmony_ci	 * If EEPROM is detected and can be addressed using 14 bits,
199262306a36Sopenharmony_ci	 * use EERD otherwise use bit bang
199362306a36Sopenharmony_ci	 */
199462306a36Sopenharmony_ci	if (eeprom->type == ixgbe_eeprom_spi && offset <= IXGBE_EERD_MAX_ADDR)
199562306a36Sopenharmony_ci		return ixgbe_read_eerd_generic(hw, offset, data);
199662306a36Sopenharmony_ci
199762306a36Sopenharmony_ci	return ixgbe_read_eeprom_bit_bang_generic(hw, offset, data);
199862306a36Sopenharmony_ci}
199962306a36Sopenharmony_ci
200062306a36Sopenharmony_ci/**
200162306a36Sopenharmony_ci * ixgbe_reset_pipeline_82599 - perform pipeline reset
200262306a36Sopenharmony_ci *
200362306a36Sopenharmony_ci * @hw: pointer to hardware structure
200462306a36Sopenharmony_ci *
200562306a36Sopenharmony_ci * Reset pipeline by asserting Restart_AN together with LMS change to ensure
200662306a36Sopenharmony_ci * full pipeline reset.  Note - We must hold the SW/FW semaphore before writing
200762306a36Sopenharmony_ci * to AUTOC, so this function assumes the semaphore is held.
200862306a36Sopenharmony_ci **/
200962306a36Sopenharmony_cistatic s32 ixgbe_reset_pipeline_82599(struct ixgbe_hw *hw)
201062306a36Sopenharmony_ci{
201162306a36Sopenharmony_ci	s32 ret_val;
201262306a36Sopenharmony_ci	u32 anlp1_reg = 0;
201362306a36Sopenharmony_ci	u32 i, autoc_reg, autoc2_reg;
201462306a36Sopenharmony_ci
201562306a36Sopenharmony_ci	/* Enable link if disabled in NVM */
201662306a36Sopenharmony_ci	autoc2_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC2);
201762306a36Sopenharmony_ci	if (autoc2_reg & IXGBE_AUTOC2_LINK_DISABLE_MASK) {
201862306a36Sopenharmony_ci		autoc2_reg &= ~IXGBE_AUTOC2_LINK_DISABLE_MASK;
201962306a36Sopenharmony_ci		IXGBE_WRITE_REG(hw, IXGBE_AUTOC2, autoc2_reg);
202062306a36Sopenharmony_ci		IXGBE_WRITE_FLUSH(hw);
202162306a36Sopenharmony_ci	}
202262306a36Sopenharmony_ci
202362306a36Sopenharmony_ci	autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC);
202462306a36Sopenharmony_ci	autoc_reg |= IXGBE_AUTOC_AN_RESTART;
202562306a36Sopenharmony_ci
202662306a36Sopenharmony_ci	/* Write AUTOC register with toggled LMS[2] bit and Restart_AN */
202762306a36Sopenharmony_ci	IXGBE_WRITE_REG(hw, IXGBE_AUTOC,
202862306a36Sopenharmony_ci			autoc_reg ^ (0x4 << IXGBE_AUTOC_LMS_SHIFT));
202962306a36Sopenharmony_ci
203062306a36Sopenharmony_ci	/* Wait for AN to leave state 0 */
203162306a36Sopenharmony_ci	for (i = 0; i < 10; i++) {
203262306a36Sopenharmony_ci		usleep_range(4000, 8000);
203362306a36Sopenharmony_ci		anlp1_reg = IXGBE_READ_REG(hw, IXGBE_ANLP1);
203462306a36Sopenharmony_ci		if (anlp1_reg & IXGBE_ANLP1_AN_STATE_MASK)
203562306a36Sopenharmony_ci			break;
203662306a36Sopenharmony_ci	}
203762306a36Sopenharmony_ci
203862306a36Sopenharmony_ci	if (!(anlp1_reg & IXGBE_ANLP1_AN_STATE_MASK)) {
203962306a36Sopenharmony_ci		hw_dbg(hw, "auto negotiation not completed\n");
204062306a36Sopenharmony_ci		ret_val = -EIO;
204162306a36Sopenharmony_ci		goto reset_pipeline_out;
204262306a36Sopenharmony_ci	}
204362306a36Sopenharmony_ci
204462306a36Sopenharmony_ci	ret_val = 0;
204562306a36Sopenharmony_ci
204662306a36Sopenharmony_cireset_pipeline_out:
204762306a36Sopenharmony_ci	/* Write AUTOC register with original LMS field and Restart_AN */
204862306a36Sopenharmony_ci	IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc_reg);
204962306a36Sopenharmony_ci	IXGBE_WRITE_FLUSH(hw);
205062306a36Sopenharmony_ci
205162306a36Sopenharmony_ci	return ret_val;
205262306a36Sopenharmony_ci}
205362306a36Sopenharmony_ci
205462306a36Sopenharmony_ci/**
205562306a36Sopenharmony_ci *  ixgbe_read_i2c_byte_82599 - Reads 8 bit word over I2C
205662306a36Sopenharmony_ci *  @hw: pointer to hardware structure
205762306a36Sopenharmony_ci *  @byte_offset: byte offset to read
205862306a36Sopenharmony_ci *  @dev_addr: address to read from
205962306a36Sopenharmony_ci *  @data: value read
206062306a36Sopenharmony_ci *
206162306a36Sopenharmony_ci *  Performs byte read operation to SFP module's EEPROM over I2C interface at
206262306a36Sopenharmony_ci *  a specified device address.
206362306a36Sopenharmony_ci **/
206462306a36Sopenharmony_cistatic s32 ixgbe_read_i2c_byte_82599(struct ixgbe_hw *hw, u8 byte_offset,
206562306a36Sopenharmony_ci				     u8 dev_addr, u8 *data)
206662306a36Sopenharmony_ci{
206762306a36Sopenharmony_ci	u32 esdp;
206862306a36Sopenharmony_ci	s32 status;
206962306a36Sopenharmony_ci	s32 timeout = 200;
207062306a36Sopenharmony_ci
207162306a36Sopenharmony_ci	if (hw->phy.qsfp_shared_i2c_bus == true) {
207262306a36Sopenharmony_ci		/* Acquire I2C bus ownership. */
207362306a36Sopenharmony_ci		esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
207462306a36Sopenharmony_ci		esdp |= IXGBE_ESDP_SDP0;
207562306a36Sopenharmony_ci		IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
207662306a36Sopenharmony_ci		IXGBE_WRITE_FLUSH(hw);
207762306a36Sopenharmony_ci
207862306a36Sopenharmony_ci		while (timeout) {
207962306a36Sopenharmony_ci			esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
208062306a36Sopenharmony_ci			if (esdp & IXGBE_ESDP_SDP1)
208162306a36Sopenharmony_ci				break;
208262306a36Sopenharmony_ci
208362306a36Sopenharmony_ci			usleep_range(5000, 10000);
208462306a36Sopenharmony_ci			timeout--;
208562306a36Sopenharmony_ci		}
208662306a36Sopenharmony_ci
208762306a36Sopenharmony_ci		if (!timeout) {
208862306a36Sopenharmony_ci			hw_dbg(hw, "Driver can't access resource, acquiring I2C bus timeout.\n");
208962306a36Sopenharmony_ci			status = -EIO;
209062306a36Sopenharmony_ci			goto release_i2c_access;
209162306a36Sopenharmony_ci		}
209262306a36Sopenharmony_ci	}
209362306a36Sopenharmony_ci
209462306a36Sopenharmony_ci	status = ixgbe_read_i2c_byte_generic(hw, byte_offset, dev_addr, data);
209562306a36Sopenharmony_ci
209662306a36Sopenharmony_cirelease_i2c_access:
209762306a36Sopenharmony_ci	if (hw->phy.qsfp_shared_i2c_bus == true) {
209862306a36Sopenharmony_ci		/* Release I2C bus ownership. */
209962306a36Sopenharmony_ci		esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
210062306a36Sopenharmony_ci		esdp &= ~IXGBE_ESDP_SDP0;
210162306a36Sopenharmony_ci		IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
210262306a36Sopenharmony_ci		IXGBE_WRITE_FLUSH(hw);
210362306a36Sopenharmony_ci	}
210462306a36Sopenharmony_ci
210562306a36Sopenharmony_ci	return status;
210662306a36Sopenharmony_ci}
210762306a36Sopenharmony_ci
210862306a36Sopenharmony_ci/**
210962306a36Sopenharmony_ci *  ixgbe_write_i2c_byte_82599 - Writes 8 bit word over I2C
211062306a36Sopenharmony_ci *  @hw: pointer to hardware structure
211162306a36Sopenharmony_ci *  @byte_offset: byte offset to write
211262306a36Sopenharmony_ci *  @dev_addr: address to write to
211362306a36Sopenharmony_ci *  @data: value to write
211462306a36Sopenharmony_ci *
211562306a36Sopenharmony_ci *  Performs byte write operation to SFP module's EEPROM over I2C interface at
211662306a36Sopenharmony_ci *  a specified device address.
211762306a36Sopenharmony_ci **/
211862306a36Sopenharmony_cistatic s32 ixgbe_write_i2c_byte_82599(struct ixgbe_hw *hw, u8 byte_offset,
211962306a36Sopenharmony_ci				      u8 dev_addr, u8 data)
212062306a36Sopenharmony_ci{
212162306a36Sopenharmony_ci	u32 esdp;
212262306a36Sopenharmony_ci	s32 status;
212362306a36Sopenharmony_ci	s32 timeout = 200;
212462306a36Sopenharmony_ci
212562306a36Sopenharmony_ci	if (hw->phy.qsfp_shared_i2c_bus == true) {
212662306a36Sopenharmony_ci		/* Acquire I2C bus ownership. */
212762306a36Sopenharmony_ci		esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
212862306a36Sopenharmony_ci		esdp |= IXGBE_ESDP_SDP0;
212962306a36Sopenharmony_ci		IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
213062306a36Sopenharmony_ci		IXGBE_WRITE_FLUSH(hw);
213162306a36Sopenharmony_ci
213262306a36Sopenharmony_ci		while (timeout) {
213362306a36Sopenharmony_ci			esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
213462306a36Sopenharmony_ci			if (esdp & IXGBE_ESDP_SDP1)
213562306a36Sopenharmony_ci				break;
213662306a36Sopenharmony_ci
213762306a36Sopenharmony_ci			usleep_range(5000, 10000);
213862306a36Sopenharmony_ci			timeout--;
213962306a36Sopenharmony_ci		}
214062306a36Sopenharmony_ci
214162306a36Sopenharmony_ci		if (!timeout) {
214262306a36Sopenharmony_ci			hw_dbg(hw, "Driver can't access resource, acquiring I2C bus timeout.\n");
214362306a36Sopenharmony_ci			status = -EIO;
214462306a36Sopenharmony_ci			goto release_i2c_access;
214562306a36Sopenharmony_ci		}
214662306a36Sopenharmony_ci	}
214762306a36Sopenharmony_ci
214862306a36Sopenharmony_ci	status = ixgbe_write_i2c_byte_generic(hw, byte_offset, dev_addr, data);
214962306a36Sopenharmony_ci
215062306a36Sopenharmony_cirelease_i2c_access:
215162306a36Sopenharmony_ci	if (hw->phy.qsfp_shared_i2c_bus == true) {
215262306a36Sopenharmony_ci		/* Release I2C bus ownership. */
215362306a36Sopenharmony_ci		esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
215462306a36Sopenharmony_ci		esdp &= ~IXGBE_ESDP_SDP0;
215562306a36Sopenharmony_ci		IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
215662306a36Sopenharmony_ci		IXGBE_WRITE_FLUSH(hw);
215762306a36Sopenharmony_ci	}
215862306a36Sopenharmony_ci
215962306a36Sopenharmony_ci	return status;
216062306a36Sopenharmony_ci}
216162306a36Sopenharmony_ci
216262306a36Sopenharmony_cistatic const struct ixgbe_mac_operations mac_ops_82599 = {
216362306a36Sopenharmony_ci	.init_hw                = &ixgbe_init_hw_generic,
216462306a36Sopenharmony_ci	.reset_hw               = &ixgbe_reset_hw_82599,
216562306a36Sopenharmony_ci	.start_hw               = &ixgbe_start_hw_82599,
216662306a36Sopenharmony_ci	.clear_hw_cntrs         = &ixgbe_clear_hw_cntrs_generic,
216762306a36Sopenharmony_ci	.get_media_type         = &ixgbe_get_media_type_82599,
216862306a36Sopenharmony_ci	.enable_rx_dma          = &ixgbe_enable_rx_dma_82599,
216962306a36Sopenharmony_ci	.disable_rx_buff	= &ixgbe_disable_rx_buff_generic,
217062306a36Sopenharmony_ci	.enable_rx_buff		= &ixgbe_enable_rx_buff_generic,
217162306a36Sopenharmony_ci	.get_mac_addr           = &ixgbe_get_mac_addr_generic,
217262306a36Sopenharmony_ci	.get_san_mac_addr       = &ixgbe_get_san_mac_addr_generic,
217362306a36Sopenharmony_ci	.get_device_caps        = &ixgbe_get_device_caps_generic,
217462306a36Sopenharmony_ci	.get_wwn_prefix         = &ixgbe_get_wwn_prefix_generic,
217562306a36Sopenharmony_ci	.stop_adapter           = &ixgbe_stop_adapter_generic,
217662306a36Sopenharmony_ci	.get_bus_info           = &ixgbe_get_bus_info_generic,
217762306a36Sopenharmony_ci	.set_lan_id             = &ixgbe_set_lan_id_multi_port_pcie,
217862306a36Sopenharmony_ci	.read_analog_reg8       = &ixgbe_read_analog_reg8_82599,
217962306a36Sopenharmony_ci	.write_analog_reg8      = &ixgbe_write_analog_reg8_82599,
218062306a36Sopenharmony_ci	.stop_link_on_d3	= &ixgbe_stop_mac_link_on_d3_82599,
218162306a36Sopenharmony_ci	.setup_link             = &ixgbe_setup_mac_link_82599,
218262306a36Sopenharmony_ci	.set_rxpba		= &ixgbe_set_rxpba_generic,
218362306a36Sopenharmony_ci	.check_link             = &ixgbe_check_mac_link_generic,
218462306a36Sopenharmony_ci	.get_link_capabilities  = &ixgbe_get_link_capabilities_82599,
218562306a36Sopenharmony_ci	.led_on                 = &ixgbe_led_on_generic,
218662306a36Sopenharmony_ci	.led_off                = &ixgbe_led_off_generic,
218762306a36Sopenharmony_ci	.init_led_link_act	= ixgbe_init_led_link_act_generic,
218862306a36Sopenharmony_ci	.blink_led_start        = &ixgbe_blink_led_start_generic,
218962306a36Sopenharmony_ci	.blink_led_stop         = &ixgbe_blink_led_stop_generic,
219062306a36Sopenharmony_ci	.set_rar                = &ixgbe_set_rar_generic,
219162306a36Sopenharmony_ci	.clear_rar              = &ixgbe_clear_rar_generic,
219262306a36Sopenharmony_ci	.set_vmdq               = &ixgbe_set_vmdq_generic,
219362306a36Sopenharmony_ci	.set_vmdq_san_mac	= &ixgbe_set_vmdq_san_mac_generic,
219462306a36Sopenharmony_ci	.clear_vmdq             = &ixgbe_clear_vmdq_generic,
219562306a36Sopenharmony_ci	.init_rx_addrs          = &ixgbe_init_rx_addrs_generic,
219662306a36Sopenharmony_ci	.update_mc_addr_list    = &ixgbe_update_mc_addr_list_generic,
219762306a36Sopenharmony_ci	.enable_mc              = &ixgbe_enable_mc_generic,
219862306a36Sopenharmony_ci	.disable_mc             = &ixgbe_disable_mc_generic,
219962306a36Sopenharmony_ci	.clear_vfta             = &ixgbe_clear_vfta_generic,
220062306a36Sopenharmony_ci	.set_vfta               = &ixgbe_set_vfta_generic,
220162306a36Sopenharmony_ci	.fc_enable              = &ixgbe_fc_enable_generic,
220262306a36Sopenharmony_ci	.setup_fc		= ixgbe_setup_fc_generic,
220362306a36Sopenharmony_ci	.fc_autoneg		= ixgbe_fc_autoneg,
220462306a36Sopenharmony_ci	.set_fw_drv_ver         = &ixgbe_set_fw_drv_ver_generic,
220562306a36Sopenharmony_ci	.init_uta_tables        = &ixgbe_init_uta_tables_generic,
220662306a36Sopenharmony_ci	.setup_sfp              = &ixgbe_setup_sfp_modules_82599,
220762306a36Sopenharmony_ci	.set_mac_anti_spoofing  = &ixgbe_set_mac_anti_spoofing,
220862306a36Sopenharmony_ci	.set_vlan_anti_spoofing = &ixgbe_set_vlan_anti_spoofing,
220962306a36Sopenharmony_ci	.acquire_swfw_sync      = &ixgbe_acquire_swfw_sync,
221062306a36Sopenharmony_ci	.release_swfw_sync      = &ixgbe_release_swfw_sync,
221162306a36Sopenharmony_ci	.init_swfw_sync		= NULL,
221262306a36Sopenharmony_ci	.get_thermal_sensor_data = &ixgbe_get_thermal_sensor_data_generic,
221362306a36Sopenharmony_ci	.init_thermal_sensor_thresh = &ixgbe_init_thermal_sensor_thresh_generic,
221462306a36Sopenharmony_ci	.prot_autoc_read	= &prot_autoc_read_82599,
221562306a36Sopenharmony_ci	.prot_autoc_write	= &prot_autoc_write_82599,
221662306a36Sopenharmony_ci	.enable_rx		= &ixgbe_enable_rx_generic,
221762306a36Sopenharmony_ci	.disable_rx		= &ixgbe_disable_rx_generic,
221862306a36Sopenharmony_ci};
221962306a36Sopenharmony_ci
222062306a36Sopenharmony_cistatic const struct ixgbe_eeprom_operations eeprom_ops_82599 = {
222162306a36Sopenharmony_ci	.init_params		= &ixgbe_init_eeprom_params_generic,
222262306a36Sopenharmony_ci	.read			= &ixgbe_read_eeprom_82599,
222362306a36Sopenharmony_ci	.read_buffer		= &ixgbe_read_eeprom_buffer_82599,
222462306a36Sopenharmony_ci	.write			= &ixgbe_write_eeprom_generic,
222562306a36Sopenharmony_ci	.write_buffer		= &ixgbe_write_eeprom_buffer_bit_bang_generic,
222662306a36Sopenharmony_ci	.calc_checksum		= &ixgbe_calc_eeprom_checksum_generic,
222762306a36Sopenharmony_ci	.validate_checksum	= &ixgbe_validate_eeprom_checksum_generic,
222862306a36Sopenharmony_ci	.update_checksum	= &ixgbe_update_eeprom_checksum_generic,
222962306a36Sopenharmony_ci};
223062306a36Sopenharmony_ci
223162306a36Sopenharmony_cistatic const struct ixgbe_phy_operations phy_ops_82599 = {
223262306a36Sopenharmony_ci	.identify		= &ixgbe_identify_phy_82599,
223362306a36Sopenharmony_ci	.identify_sfp		= &ixgbe_identify_module_generic,
223462306a36Sopenharmony_ci	.init			= &ixgbe_init_phy_ops_82599,
223562306a36Sopenharmony_ci	.reset			= &ixgbe_reset_phy_generic,
223662306a36Sopenharmony_ci	.read_reg		= &ixgbe_read_phy_reg_generic,
223762306a36Sopenharmony_ci	.write_reg		= &ixgbe_write_phy_reg_generic,
223862306a36Sopenharmony_ci	.setup_link		= &ixgbe_setup_phy_link_generic,
223962306a36Sopenharmony_ci	.setup_link_speed	= &ixgbe_setup_phy_link_speed_generic,
224062306a36Sopenharmony_ci	.read_i2c_byte		= &ixgbe_read_i2c_byte_generic,
224162306a36Sopenharmony_ci	.write_i2c_byte		= &ixgbe_write_i2c_byte_generic,
224262306a36Sopenharmony_ci	.read_i2c_sff8472	= &ixgbe_read_i2c_sff8472_generic,
224362306a36Sopenharmony_ci	.read_i2c_eeprom	= &ixgbe_read_i2c_eeprom_generic,
224462306a36Sopenharmony_ci	.write_i2c_eeprom	= &ixgbe_write_i2c_eeprom_generic,
224562306a36Sopenharmony_ci	.check_overtemp		= &ixgbe_tn_check_overtemp,
224662306a36Sopenharmony_ci};
224762306a36Sopenharmony_ci
224862306a36Sopenharmony_ciconst struct ixgbe_info ixgbe_82599_info = {
224962306a36Sopenharmony_ci	.mac                    = ixgbe_mac_82599EB,
225062306a36Sopenharmony_ci	.get_invariants         = &ixgbe_get_invariants_82599,
225162306a36Sopenharmony_ci	.mac_ops                = &mac_ops_82599,
225262306a36Sopenharmony_ci	.eeprom_ops             = &eeprom_ops_82599,
225362306a36Sopenharmony_ci	.phy_ops                = &phy_ops_82599,
225462306a36Sopenharmony_ci	.mbx_ops                = &mbx_ops_generic,
225562306a36Sopenharmony_ci	.mvals			= ixgbe_mvals_8259X,
225662306a36Sopenharmony_ci};
2257