xref: /openbsd-src/sys/dev/pci/ixgbe_82599.c (revision d7a8f9551cb981b54aef80e20f6224cb41369551)
1*d7a8f955Sjmatthew /*	$OpenBSD: ixgbe_82599.c,v 1.19 2020/03/02 01:59:01 jmatthew Exp $	*/
2117577f7Sjsg 
3117577f7Sjsg /******************************************************************************
4*d7a8f955Sjmatthew   SPDX-License-Identifier: BSD-3-Clause
5117577f7Sjsg 
6*d7a8f955Sjmatthew   Copyright (c) 2001-2017, Intel Corporation
7117577f7Sjsg   All rights reserved.
8117577f7Sjsg 
9117577f7Sjsg   Redistribution and use in source and binary forms, with or without
10117577f7Sjsg   modification, are permitted provided that the following conditions are met:
11117577f7Sjsg 
12117577f7Sjsg    1. Redistributions of source code must retain the above copyright notice,
13117577f7Sjsg       this list of conditions and the following disclaimer.
14117577f7Sjsg 
15117577f7Sjsg    2. Redistributions in binary form must reproduce the above copyright
16117577f7Sjsg       notice, this list of conditions and the following disclaimer in the
17117577f7Sjsg       documentation and/or other materials provided with the distribution.
18117577f7Sjsg 
19117577f7Sjsg    3. Neither the name of the Intel Corporation nor the names of its
20117577f7Sjsg       contributors may be used to endorse or promote products derived from
21117577f7Sjsg       this software without specific prior written permission.
22117577f7Sjsg 
23117577f7Sjsg   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24117577f7Sjsg   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25117577f7Sjsg   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26117577f7Sjsg   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
27117577f7Sjsg   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28117577f7Sjsg   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29117577f7Sjsg   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30117577f7Sjsg   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
31117577f7Sjsg   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32117577f7Sjsg   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33117577f7Sjsg   POSSIBILITY OF SUCH DAMAGE.
34117577f7Sjsg 
35117577f7Sjsg ******************************************************************************/
36*d7a8f955Sjmatthew /*$FreeBSD: head/sys/dev/ixgbe/ixgbe_82599.c 326022 2017-11-20 19:36:21Z pfg $*/
37*d7a8f955Sjmatthew 
38117577f7Sjsg 
39117577f7Sjsg #include <dev/pci/ixgbe.h>
40117577f7Sjsg #include <dev/pci/ixgbe_type.h>
41117577f7Sjsg 
429e435848Smikeb #define IXGBE_82599_MAX_TX_QUEUES 128
439e435848Smikeb #define IXGBE_82599_MAX_RX_QUEUES 128
449e435848Smikeb #define IXGBE_82599_RAR_ENTRIES   128
459e435848Smikeb #define IXGBE_82599_MC_TBL_SIZE   128
469e435848Smikeb #define IXGBE_82599_VFT_TBL_SIZE  128
479e435848Smikeb #define IXGBE_82599_RX_PB_SIZE	  512
489e435848Smikeb 
49117577f7Sjsg int32_t ixgbe_get_link_capabilities_82599(struct ixgbe_hw *hw,
50117577f7Sjsg 					  ixgbe_link_speed *speed,
5111efaf7fSmikeb 					  bool *autoneg);
52117577f7Sjsg enum ixgbe_media_type ixgbe_get_media_type_82599(struct ixgbe_hw *hw);
539feba5bbSclaudio void ixgbe_disable_tx_laser_multispeed_fiber(struct ixgbe_hw *hw);
549feba5bbSclaudio void ixgbe_enable_tx_laser_multispeed_fiber(struct ixgbe_hw *hw);
559feba5bbSclaudio void ixgbe_flap_tx_laser_multispeed_fiber(struct ixgbe_hw *hw);
562f63561bSmikeb void ixgbe_set_hard_rate_select_speed(struct ixgbe_hw *hw,
5711efaf7fSmikeb 				      ixgbe_link_speed speed);
58117577f7Sjsg int32_t ixgbe_setup_mac_link_smartspeed(struct ixgbe_hw *hw,
5911efaf7fSmikeb 					ixgbe_link_speed speed,
6011efaf7fSmikeb 					bool autoneg_wait_to_complete);
61117577f7Sjsg int32_t ixgbe_start_mac_link_82599(struct ixgbe_hw *hw,
6211efaf7fSmikeb 				   bool autoneg_wait_to_complete);
63117577f7Sjsg int32_t ixgbe_setup_mac_link_82599(struct ixgbe_hw *hw,
64117577f7Sjsg 				   ixgbe_link_speed speed,
6511efaf7fSmikeb 				   bool autoneg_wait_to_complete);
66117577f7Sjsg int32_t ixgbe_setup_sfp_modules_82599(struct ixgbe_hw *hw);
67117577f7Sjsg void ixgbe_init_mac_link_ops_82599(struct ixgbe_hw *hw);
68117577f7Sjsg int32_t ixgbe_reset_hw_82599(struct ixgbe_hw *hw);
6911efaf7fSmikeb int32_t ixgbe_read_analog_reg8_82599(struct ixgbe_hw *hw, uint32_t reg,
7011efaf7fSmikeb 				     uint8_t *val);
7111efaf7fSmikeb int32_t ixgbe_write_analog_reg8_82599(struct ixgbe_hw *hw, uint32_t reg,
7211efaf7fSmikeb 				      uint8_t val);
73c7fa8c00Smikeb int32_t ixgbe_start_hw_82599(struct ixgbe_hw *hw);
74117577f7Sjsg int32_t ixgbe_identify_phy_82599(struct ixgbe_hw *hw);
75117577f7Sjsg int32_t ixgbe_init_phy_ops_82599(struct ixgbe_hw *hw);
76*d7a8f955Sjmatthew uint64_t ixgbe_get_supported_physical_layer_82599(struct ixgbe_hw *hw);
77117577f7Sjsg int32_t ixgbe_enable_rx_dma_82599(struct ixgbe_hw *hw, uint32_t regval);
78276d64b7Smikeb int32_t prot_autoc_read_82599(struct ixgbe_hw *, bool *locked, uint32_t *reg_val);
79276d64b7Smikeb int32_t prot_autoc_write_82599(struct ixgbe_hw *, uint32_t reg_val, bool locked);
802f63561bSmikeb 
812f63561bSmikeb void ixgbe_stop_mac_link_on_d3_82599(struct ixgbe_hw *hw);
822f63561bSmikeb 
832f63561bSmikeb int32_t ixgbe_setup_copper_link_82599(struct ixgbe_hw *hw,
842f63561bSmikeb 				      ixgbe_link_speed speed,
852f63561bSmikeb 				      bool autoneg_wait_to_complete);
862f63561bSmikeb 
87117577f7Sjsg int32_t ixgbe_verify_fw_version_82599(struct ixgbe_hw *hw);
8811efaf7fSmikeb bool ixgbe_verify_lesm_fw_enabled_82599(struct ixgbe_hw *hw);
892f63561bSmikeb int32_t ixgbe_reset_pipeline_82599(struct ixgbe_hw *hw);
9011efaf7fSmikeb int32_t ixgbe_read_eeprom_82599(struct ixgbe_hw *hw,
9111efaf7fSmikeb 				uint16_t offset, uint16_t *data);
922f63561bSmikeb int32_t ixgbe_read_i2c_byte_82599(struct ixgbe_hw *hw, uint8_t byte_offset,
932f63561bSmikeb 				  uint8_t dev_addr, uint8_t *data);
942f63561bSmikeb int32_t ixgbe_write_i2c_byte_82599(struct ixgbe_hw *hw, uint8_t byte_offset,
952f63561bSmikeb 				   uint8_t dev_addr, uint8_t data);
96117577f7Sjsg 
ixgbe_init_mac_link_ops_82599(struct ixgbe_hw * hw)97117577f7Sjsg void ixgbe_init_mac_link_ops_82599(struct ixgbe_hw *hw)
98117577f7Sjsg {
99117577f7Sjsg 	struct ixgbe_mac_info *mac = &hw->mac;
100117577f7Sjsg 
101117577f7Sjsg 	DEBUGFUNC("ixgbe_init_mac_link_ops_82599");
102117577f7Sjsg 
10311efaf7fSmikeb 	/*
10411efaf7fSmikeb 	 * enable the laser control functions for SFP+ fiber
10511efaf7fSmikeb 	 * and MNG not enabled
10611efaf7fSmikeb 	 */
10711efaf7fSmikeb 	if ((mac->ops.get_media_type(hw) == ixgbe_media_type_fiber) &&
1082f63561bSmikeb 	    !ixgbe_mng_enabled(hw)) {
1099feba5bbSclaudio 		mac->ops.disable_tx_laser =
1109e435848Smikeb 				       ixgbe_disable_tx_laser_multispeed_fiber;
1119feba5bbSclaudio 		mac->ops.enable_tx_laser =
1129e435848Smikeb 					ixgbe_enable_tx_laser_multispeed_fiber;
1139e435848Smikeb 		mac->ops.flap_tx_laser = ixgbe_flap_tx_laser_multispeed_fiber;
1149feba5bbSclaudio 
1159feba5bbSclaudio 	} else {
1169feba5bbSclaudio 		mac->ops.disable_tx_laser = NULL;
1179feba5bbSclaudio 		mac->ops.enable_tx_laser = NULL;
1189feba5bbSclaudio 		mac->ops.flap_tx_laser = NULL;
1199feba5bbSclaudio 	}
1209feba5bbSclaudio 
121117577f7Sjsg 	if (hw->phy.multispeed_fiber) {
122117577f7Sjsg 		/* Set up dual speed SFP+ support */
1239e435848Smikeb 		mac->ops.setup_link = ixgbe_setup_mac_link_multispeed_fiber;
1242f63561bSmikeb 		mac->ops.setup_mac_link = ixgbe_setup_mac_link_82599;
1252f63561bSmikeb 		mac->ops.set_rate_select_speed =
1262f63561bSmikeb 					       ixgbe_set_hard_rate_select_speed;
1272f63561bSmikeb 		if (ixgbe_get_media_type(hw) == ixgbe_media_type_fiber_fixed)
1282f63561bSmikeb 			mac->ops.set_rate_select_speed =
1292f63561bSmikeb 					       ixgbe_set_soft_rate_select_speed;
130117577f7Sjsg 	} else {
13111efaf7fSmikeb 		if ((ixgbe_get_media_type(hw) == ixgbe_media_type_backplane) &&
132117577f7Sjsg 		     (hw->phy.smart_speed == ixgbe_smart_speed_auto ||
1339feba5bbSclaudio 		      hw->phy.smart_speed == ixgbe_smart_speed_on) &&
1349feba5bbSclaudio 		      !ixgbe_verify_lesm_fw_enabled_82599(hw)) {
1359e435848Smikeb 			mac->ops.setup_link = ixgbe_setup_mac_link_smartspeed;
1369feba5bbSclaudio 		} else {
1379e435848Smikeb 			mac->ops.setup_link = ixgbe_setup_mac_link_82599;
138117577f7Sjsg 		}
139117577f7Sjsg 	}
1409feba5bbSclaudio }
141117577f7Sjsg 
142117577f7Sjsg /**
143117577f7Sjsg  *  ixgbe_init_phy_ops_82599 - PHY/SFP specific init
144117577f7Sjsg  *  @hw: pointer to hardware structure
145117577f7Sjsg  *
146117577f7Sjsg  *  Initialize any function pointers that were not able to be
147117577f7Sjsg  *  set during init_shared_code because the PHY/SFP type was
148117577f7Sjsg  *  not known.  Perform the SFP init if necessary.
149117577f7Sjsg  *
150117577f7Sjsg  **/
ixgbe_init_phy_ops_82599(struct ixgbe_hw * hw)151117577f7Sjsg int32_t ixgbe_init_phy_ops_82599(struct ixgbe_hw *hw)
152117577f7Sjsg {
153117577f7Sjsg 	struct ixgbe_mac_info *mac = &hw->mac;
154117577f7Sjsg 	struct ixgbe_phy_info *phy = &hw->phy;
155117577f7Sjsg 	int32_t ret_val = IXGBE_SUCCESS;
1562f63561bSmikeb 	uint32_t esdp;
157117577f7Sjsg 
158117577f7Sjsg 	DEBUGFUNC("ixgbe_init_phy_ops_82599");
159117577f7Sjsg 
1602f63561bSmikeb 	if (hw->device_id == IXGBE_DEV_ID_82599_QSFP_SF_QP) {
1612f63561bSmikeb 		/* Store flag indicating I2C bus access control unit. */
1622f63561bSmikeb 		hw->phy.qsfp_shared_i2c_bus = TRUE;
1632f63561bSmikeb 
1642f63561bSmikeb 		/* Initialize access to QSFP+ I2C bus */
1652f63561bSmikeb 		esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
1662f63561bSmikeb 		esdp |= IXGBE_ESDP_SDP0_DIR;
1672f63561bSmikeb 		esdp &= ~IXGBE_ESDP_SDP1_DIR;
1682f63561bSmikeb 		esdp &= ~IXGBE_ESDP_SDP0;
1692f63561bSmikeb 		esdp &= ~IXGBE_ESDP_SDP0_NATIVE;
1702f63561bSmikeb 		esdp &= ~IXGBE_ESDP_SDP1_NATIVE;
1712f63561bSmikeb 		IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
1722f63561bSmikeb 		IXGBE_WRITE_FLUSH(hw);
1732f63561bSmikeb 
1742f63561bSmikeb 		phy->ops.read_i2c_byte = ixgbe_read_i2c_byte_82599;
1752f63561bSmikeb 		phy->ops.write_i2c_byte = ixgbe_write_i2c_byte_82599;
1762f63561bSmikeb 	}
177117577f7Sjsg 	/* Identify the PHY or SFP module */
178117577f7Sjsg 	ret_val = phy->ops.identify(hw);
179117577f7Sjsg 	if (ret_val == IXGBE_ERR_SFP_NOT_SUPPORTED)
180117577f7Sjsg 		goto init_phy_ops_out;
181117577f7Sjsg 
182117577f7Sjsg 	/* Setup function pointers based on detected SFP module and speeds */
183117577f7Sjsg 	ixgbe_init_mac_link_ops_82599(hw);
184117577f7Sjsg 	if (hw->phy.sfp_type != ixgbe_sfp_type_unknown)
185117577f7Sjsg 		hw->phy.ops.reset = NULL;
186117577f7Sjsg 
187117577f7Sjsg 	/* If copper media, overwrite with copper function pointers */
188117577f7Sjsg 	if (mac->ops.get_media_type(hw) == ixgbe_media_type_copper) {
1899e435848Smikeb 		mac->ops.setup_link = ixgbe_setup_copper_link_82599;
190117577f7Sjsg 		mac->ops.get_link_capabilities =
1919e435848Smikeb 				  ixgbe_get_copper_link_capabilities_generic;
192117577f7Sjsg 	}
193117577f7Sjsg 
1949e435848Smikeb 	/* Set necessary function pointers based on PHY type */
195117577f7Sjsg 	switch (hw->phy.type) {
196117577f7Sjsg 	case ixgbe_phy_tn:
1979e435848Smikeb 		phy->ops.setup_link = ixgbe_setup_phy_link_tnx;
1989e435848Smikeb 		phy->ops.check_link = ixgbe_check_phy_link_tnx;
199117577f7Sjsg 		phy->ops.get_firmware_version =
2009e435848Smikeb 			     ixgbe_get_phy_firmware_version_tnx;
201117577f7Sjsg 		break;
202117577f7Sjsg 	default:
203117577f7Sjsg 		break;
204117577f7Sjsg 	}
205117577f7Sjsg init_phy_ops_out:
206117577f7Sjsg 	return ret_val;
207117577f7Sjsg }
208117577f7Sjsg 
ixgbe_setup_sfp_modules_82599(struct ixgbe_hw * hw)209117577f7Sjsg int32_t ixgbe_setup_sfp_modules_82599(struct ixgbe_hw *hw)
210117577f7Sjsg {
211117577f7Sjsg 	int32_t ret_val = IXGBE_SUCCESS;
212117577f7Sjsg 	uint16_t list_offset, data_offset, data_value;
213117577f7Sjsg 
214117577f7Sjsg 	DEBUGFUNC("ixgbe_setup_sfp_modules_82599");
215117577f7Sjsg 
216117577f7Sjsg 	if (hw->phy.sfp_type != ixgbe_sfp_type_unknown) {
217117577f7Sjsg 		ixgbe_init_mac_link_ops_82599(hw);
218117577f7Sjsg 
219117577f7Sjsg 		hw->phy.ops.reset = NULL;
220117577f7Sjsg 
221117577f7Sjsg 		ret_val = ixgbe_get_sfp_init_sequence_offsets(hw, &list_offset,
222117577f7Sjsg 							      &data_offset);
223117577f7Sjsg 		if (ret_val != IXGBE_SUCCESS)
224117577f7Sjsg 			goto setup_sfp_out;
225117577f7Sjsg 
226117577f7Sjsg 		/* PHY config will finish before releasing the semaphore */
2277b6f6093Smikeb 		ret_val = hw->mac.ops.acquire_swfw_sync(hw,
2287b6f6093Smikeb 							IXGBE_GSSR_MAC_CSR_SM);
229117577f7Sjsg 		if (ret_val != IXGBE_SUCCESS) {
230117577f7Sjsg 			ret_val = IXGBE_ERR_SWFW_SYNC;
231117577f7Sjsg 			goto setup_sfp_out;
232117577f7Sjsg 		}
233117577f7Sjsg 
23411efaf7fSmikeb 		if (hw->eeprom.ops.read(hw, ++data_offset, &data_value))
23511efaf7fSmikeb 			goto setup_sfp_err;
236117577f7Sjsg 		while (data_value != 0xffff) {
237117577f7Sjsg 			IXGBE_WRITE_REG(hw, IXGBE_CORECTL, data_value);
238117577f7Sjsg 			IXGBE_WRITE_FLUSH(hw);
23911efaf7fSmikeb 			if (hw->eeprom.ops.read(hw, ++data_offset, &data_value))
24011efaf7fSmikeb 				goto setup_sfp_err;
241117577f7Sjsg 		}
242117577f7Sjsg 
243117577f7Sjsg 		/* Release the semaphore */
2447b6f6093Smikeb 		hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_MAC_CSR_SM);
245276d64b7Smikeb 		/* Delay obtaining semaphore again to allow FW access
246276d64b7Smikeb 		 * prot_autoc_write uses the semaphore too.
247276d64b7Smikeb 		 */
248117577f7Sjsg 		msec_delay(hw->eeprom.semaphore_delay);
2499feba5bbSclaudio 
25011efaf7fSmikeb 		/* Restart DSP and set SFI mode */
251276d64b7Smikeb 		ret_val = hw->mac.ops.prot_autoc_write(hw,
252276d64b7Smikeb 			hw->mac.orig_autoc | IXGBE_AUTOC_LMS_10G_SERIAL,
253276d64b7Smikeb 			FALSE);
25411efaf7fSmikeb 
25511efaf7fSmikeb 		if (ret_val) {
2569feba5bbSclaudio 			DEBUGOUT("sfp module setup not complete\n");
2579feba5bbSclaudio 			ret_val = IXGBE_ERR_SFP_SETUP_NOT_COMPLETE;
2589feba5bbSclaudio 			goto setup_sfp_out;
2599feba5bbSclaudio 		}
2609feba5bbSclaudio 
261117577f7Sjsg 	}
262117577f7Sjsg 
263117577f7Sjsg setup_sfp_out:
264117577f7Sjsg 	return ret_val;
26511efaf7fSmikeb 
26611efaf7fSmikeb setup_sfp_err:
26711efaf7fSmikeb 	/* Release the semaphore */
26811efaf7fSmikeb 	hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_MAC_CSR_SM);
26911efaf7fSmikeb 	/* Delay obtaining semaphore again to allow FW access */
27011efaf7fSmikeb 	msec_delay(hw->eeprom.semaphore_delay);
27111efaf7fSmikeb 	ERROR_REPORT2(IXGBE_ERROR_INVALID_STATE,
27211efaf7fSmikeb 		      "eeprom read at offset %d failed", data_offset);
27311efaf7fSmikeb 	return IXGBE_ERR_PHY;
274117577f7Sjsg }
275117577f7Sjsg 
276117577f7Sjsg /**
277276d64b7Smikeb  *  prot_autoc_read_82599 - Hides MAC differences needed for AUTOC read
278276d64b7Smikeb  *  @hw: pointer to hardware structure
279276d64b7Smikeb  *  @locked: Return the if we locked for this read.
280276d64b7Smikeb  *  @reg_val: Value we read from AUTOC
281276d64b7Smikeb  *
282276d64b7Smikeb  *  For this part (82599) we need to wrap read-modify-writes with a possible
283276d64b7Smikeb  *  FW/SW lock.  It is assumed this lock will be freed with the next
284276d64b7Smikeb  *  prot_autoc_write_82599().
285276d64b7Smikeb  */
prot_autoc_read_82599(struct ixgbe_hw * hw,bool * locked,uint32_t * reg_val)286276d64b7Smikeb int32_t prot_autoc_read_82599(struct ixgbe_hw *hw, bool *locked,
287276d64b7Smikeb     uint32_t *reg_val)
288276d64b7Smikeb {
289276d64b7Smikeb 	int32_t ret_val;
290276d64b7Smikeb 
291276d64b7Smikeb 	*locked = FALSE;
292276d64b7Smikeb 	 /* If LESM is on then we need to hold the SW/FW semaphore. */
293276d64b7Smikeb 	if (ixgbe_verify_lesm_fw_enabled_82599(hw)) {
294276d64b7Smikeb 		ret_val = hw->mac.ops.acquire_swfw_sync(hw,
295276d64b7Smikeb 					IXGBE_GSSR_MAC_CSR_SM);
296276d64b7Smikeb 		if (ret_val != IXGBE_SUCCESS)
297276d64b7Smikeb 			return IXGBE_ERR_SWFW_SYNC;
298276d64b7Smikeb 
299276d64b7Smikeb 		*locked = TRUE;
300276d64b7Smikeb 	}
301276d64b7Smikeb 
302276d64b7Smikeb 	*reg_val = IXGBE_READ_REG(hw, IXGBE_AUTOC);
303276d64b7Smikeb 	return IXGBE_SUCCESS;
304276d64b7Smikeb }
305276d64b7Smikeb 
306276d64b7Smikeb /**
307276d64b7Smikeb  * prot_autoc_write_82599 - Hides MAC differences needed for AUTOC write
308276d64b7Smikeb  * @hw: pointer to hardware structure
309*d7a8f955Sjmatthew  * @autoc: value to write to AUTOC
310276d64b7Smikeb  * @locked: bool to indicate whether the SW/FW lock was already taken by
311276d64b7Smikeb  *           previous proc_autoc_read_82599.
312276d64b7Smikeb  *
313276d64b7Smikeb  * This part (82599) may need to hold the SW/FW lock around all writes to
314276d64b7Smikeb  * AUTOC. Likewise after a write we need to do a pipeline reset.
315276d64b7Smikeb  */
prot_autoc_write_82599(struct ixgbe_hw * hw,uint32_t autoc,bool locked)316276d64b7Smikeb int32_t prot_autoc_write_82599(struct ixgbe_hw *hw, uint32_t autoc, bool locked)
317276d64b7Smikeb {
318276d64b7Smikeb 	int32_t ret_val = IXGBE_SUCCESS;
319276d64b7Smikeb 
320276d64b7Smikeb 	/* Blocked by MNG FW so bail */
321276d64b7Smikeb 	if (ixgbe_check_reset_blocked(hw))
322276d64b7Smikeb 		goto out;
323276d64b7Smikeb 
324276d64b7Smikeb 	/* We only need to get the lock if:
325276d64b7Smikeb 	 *  - We didn't do it already (in the read part of a read-modify-write)
326276d64b7Smikeb 	 *  - LESM is enabled.
327276d64b7Smikeb 	 */
328276d64b7Smikeb 	if (!locked && ixgbe_verify_lesm_fw_enabled_82599(hw)) {
329276d64b7Smikeb 		ret_val = hw->mac.ops.acquire_swfw_sync(hw,
330276d64b7Smikeb 					IXGBE_GSSR_MAC_CSR_SM);
331276d64b7Smikeb 		if (ret_val != IXGBE_SUCCESS)
332276d64b7Smikeb 			return IXGBE_ERR_SWFW_SYNC;
333276d64b7Smikeb 
334276d64b7Smikeb 		locked = TRUE;
335276d64b7Smikeb 	}
336276d64b7Smikeb 
337276d64b7Smikeb 	IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc);
338276d64b7Smikeb 	ret_val = ixgbe_reset_pipeline_82599(hw);
339276d64b7Smikeb 
340276d64b7Smikeb out:
341276d64b7Smikeb 	/* Free the SW/FW semaphore as we either grabbed it here or
342276d64b7Smikeb 	 * already had it when this function was called.
343276d64b7Smikeb 	 */
344276d64b7Smikeb 	if (locked)
345276d64b7Smikeb 		hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_MAC_CSR_SM);
346276d64b7Smikeb 
347276d64b7Smikeb 	return ret_val;
348276d64b7Smikeb }
349276d64b7Smikeb 
350276d64b7Smikeb /**
351117577f7Sjsg  *  ixgbe_init_ops_82599 - Inits func ptrs and MAC type
352117577f7Sjsg  *  @hw: pointer to hardware structure
353117577f7Sjsg  *
354117577f7Sjsg  *  Initialize the function pointers and assign the MAC type for 82599.
355117577f7Sjsg  *  Does not touch the hardware.
356117577f7Sjsg  **/
357117577f7Sjsg 
ixgbe_init_ops_82599(struct ixgbe_hw * hw)358117577f7Sjsg int32_t ixgbe_init_ops_82599(struct ixgbe_hw *hw)
359117577f7Sjsg {
360117577f7Sjsg 	struct ixgbe_mac_info *mac = &hw->mac;
361117577f7Sjsg 	struct ixgbe_phy_info *phy = &hw->phy;
36211efaf7fSmikeb 	struct ixgbe_eeprom_info *eeprom = &hw->eeprom;
363117577f7Sjsg 	int32_t ret_val;
364117577f7Sjsg 
365117577f7Sjsg 	DEBUGFUNC("ixgbe_init_ops_82599");
366117577f7Sjsg 
367*d7a8f955Sjmatthew 	ixgbe_init_phy_ops_generic(hw);
368117577f7Sjsg 	ret_val = ixgbe_init_ops_generic(hw);
369117577f7Sjsg 
370117577f7Sjsg 	/* PHY */
3719e435848Smikeb 	phy->ops.identify = ixgbe_identify_phy_82599;
3729e435848Smikeb 	phy->ops.init = ixgbe_init_phy_ops_82599;
373117577f7Sjsg 
374117577f7Sjsg 	/* MAC */
3759e435848Smikeb 	mac->ops.reset_hw = ixgbe_reset_hw_82599;
3769e435848Smikeb 	mac->ops.get_media_type = ixgbe_get_media_type_82599;
377117577f7Sjsg 	mac->ops.get_supported_physical_layer =
3789e435848Smikeb 				    ixgbe_get_supported_physical_layer_82599;
3799e435848Smikeb 	mac->ops.disable_sec_rx_path = ixgbe_disable_sec_rx_path_generic;
3809e435848Smikeb 	mac->ops.enable_sec_rx_path = ixgbe_enable_sec_rx_path_generic;
3819e435848Smikeb 	mac->ops.enable_rx_dma = ixgbe_enable_rx_dma_82599;
3829e435848Smikeb 	mac->ops.read_analog_reg8 = ixgbe_read_analog_reg8_82599;
3839e435848Smikeb 	mac->ops.write_analog_reg8 = ixgbe_write_analog_reg8_82599;
3849e435848Smikeb 	mac->ops.start_hw = ixgbe_start_hw_82599;
385*d7a8f955Sjmatthew 	mac->ops.get_device_caps = ixgbe_get_device_caps_generic;
386276d64b7Smikeb 	mac->ops.prot_autoc_read = prot_autoc_read_82599;
387276d64b7Smikeb 	mac->ops.prot_autoc_write = prot_autoc_write_82599;
388276d64b7Smikeb 
389117577f7Sjsg 	/* RAR, Multicast, VLAN */
3909e435848Smikeb 	mac->ops.set_vmdq = ixgbe_set_vmdq_generic;
3919e435848Smikeb 	mac->ops.clear_vmdq = ixgbe_clear_vmdq_generic;
3929e435848Smikeb 	mac->ops.insert_mac_addr = ixgbe_insert_mac_addr_generic;
393117577f7Sjsg 	mac->rar_highwater = 1;
3949e435848Smikeb 	mac->ops.set_vfta = ixgbe_set_vfta_generic;
3959e435848Smikeb 	mac->ops.set_vlvf = ixgbe_set_vlvf_generic;
3969e435848Smikeb 	mac->ops.clear_vfta = ixgbe_clear_vfta_generic;
3979e435848Smikeb 	mac->ops.init_uta_tables = ixgbe_init_uta_tables_generic;
3989e435848Smikeb 	mac->ops.setup_sfp = ixgbe_setup_sfp_modules_82599;
39911efaf7fSmikeb 
400117577f7Sjsg 	/* Link */
4019e435848Smikeb 	mac->ops.get_link_capabilities = ixgbe_get_link_capabilities_82599;
4029e435848Smikeb 	mac->ops.check_link = ixgbe_check_mac_link_generic;
4032f63561bSmikeb 	mac->ops.stop_mac_link_on_d3 = ixgbe_stop_mac_link_on_d3_82599;
404117577f7Sjsg 	ixgbe_init_mac_link_ops_82599(hw);
405117577f7Sjsg 
4069e435848Smikeb 	mac->mcft_size		= IXGBE_82599_MC_TBL_SIZE;
4079e435848Smikeb 	mac->vft_size		= IXGBE_82599_VFT_TBL_SIZE;
4089e435848Smikeb 	mac->num_rar_entries	= IXGBE_82599_RAR_ENTRIES;
4099e435848Smikeb 	mac->rx_pb_size		= IXGBE_82599_RX_PB_SIZE;
4109e435848Smikeb 	mac->max_rx_queues	= IXGBE_82599_MAX_RX_QUEUES;
4112f63561bSmikeb 	mac->max_tx_queues	= IXGBE_82599_MAX_TX_QUEUES;
41211efaf7fSmikeb 	mac->max_msix_vectors	= 0 /*ixgbe_get_pcie_msix_count_generic(hw)*/;
413117577f7Sjsg 
414*d7a8f955Sjmatthew 	mac->arc_subsystem_valid = !!(IXGBE_READ_REG(hw, IXGBE_FWSM_BY_MAC(hw))
415*d7a8f955Sjmatthew 				      & IXGBE_FWSM_MODE_MASK);
416*d7a8f955Sjmatthew 
4179feba5bbSclaudio 	hw->mbx.ops.init_params = ixgbe_init_mbx_params_pf;
418117577f7Sjsg 
41911efaf7fSmikeb 	/* EEPROM */
4209e435848Smikeb 	eeprom->ops.read = ixgbe_read_eeprom_82599;
42111efaf7fSmikeb 
422117577f7Sjsg 	return ret_val;
423117577f7Sjsg }
424117577f7Sjsg 
425117577f7Sjsg /**
426117577f7Sjsg  *  ixgbe_get_link_capabilities_82599 - Determines link capabilities
427117577f7Sjsg  *  @hw: pointer to hardware structure
428117577f7Sjsg  *  @speed: pointer to link speed
42911efaf7fSmikeb  *  @autoneg: TRUE when autoneg or autotry is enabled
430117577f7Sjsg  *
431117577f7Sjsg  *  Determines the link capabilities by reading the AUTOC register.
432117577f7Sjsg  **/
ixgbe_get_link_capabilities_82599(struct ixgbe_hw * hw,ixgbe_link_speed * speed,bool * autoneg)433117577f7Sjsg int32_t ixgbe_get_link_capabilities_82599(struct ixgbe_hw *hw,
434117577f7Sjsg 				      ixgbe_link_speed *speed,
43511efaf7fSmikeb 				      bool *autoneg)
436117577f7Sjsg {
437117577f7Sjsg 	int32_t status = IXGBE_SUCCESS;
438117577f7Sjsg 	uint32_t autoc = 0;
439117577f7Sjsg 
440117577f7Sjsg 	DEBUGFUNC("ixgbe_get_link_capabilities_82599");
441117577f7Sjsg 
4429feba5bbSclaudio 	/* Check if 1G SFP module. */
4439feba5bbSclaudio 	if (hw->phy.sfp_type == ixgbe_sfp_type_1g_cu_core0 ||
44411efaf7fSmikeb 	    hw->phy.sfp_type == ixgbe_sfp_type_1g_cu_core1 ||
44502e97872Ssthen 	    hw->phy.sfp_type == ixgbe_sfp_type_1g_lx_core0 ||
44602e97872Ssthen 	    hw->phy.sfp_type == ixgbe_sfp_type_1g_lx_core1 ||
44711efaf7fSmikeb 	    hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core0 ||
44811efaf7fSmikeb 	    hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core1) {
4499feba5bbSclaudio 		*speed = IXGBE_LINK_SPEED_1GB_FULL;
45011efaf7fSmikeb 		*autoneg = TRUE;
4519feba5bbSclaudio 		goto out;
4529feba5bbSclaudio 	}
4539feba5bbSclaudio 
454117577f7Sjsg 	/*
455117577f7Sjsg 	 * Determine link capabilities based on the stored value of AUTOC,
456117577f7Sjsg 	 * which represents EEPROM defaults.  If AUTOC value has not
457117577f7Sjsg 	 * been stored, use the current register values.
458117577f7Sjsg 	 */
459117577f7Sjsg 	if (hw->mac.orig_link_settings_stored)
460117577f7Sjsg 		autoc = hw->mac.orig_autoc;
461117577f7Sjsg 	else
462117577f7Sjsg 		autoc = IXGBE_READ_REG(hw, IXGBE_AUTOC);
463117577f7Sjsg 
464117577f7Sjsg 	switch (autoc & IXGBE_AUTOC_LMS_MASK) {
465117577f7Sjsg 	case IXGBE_AUTOC_LMS_1G_LINK_NO_AN:
466117577f7Sjsg 		*speed = IXGBE_LINK_SPEED_1GB_FULL;
46711efaf7fSmikeb 		*autoneg = FALSE;
468117577f7Sjsg 		break;
469117577f7Sjsg 
470117577f7Sjsg 	case IXGBE_AUTOC_LMS_10G_LINK_NO_AN:
471117577f7Sjsg 		*speed = IXGBE_LINK_SPEED_10GB_FULL;
47211efaf7fSmikeb 		*autoneg = FALSE;
473117577f7Sjsg 		break;
474117577f7Sjsg 
475117577f7Sjsg 	case IXGBE_AUTOC_LMS_1G_AN:
476117577f7Sjsg 		*speed = IXGBE_LINK_SPEED_1GB_FULL;
47711efaf7fSmikeb 		*autoneg = TRUE;
478117577f7Sjsg 		break;
479117577f7Sjsg 
480117577f7Sjsg 	case IXGBE_AUTOC_LMS_10G_SERIAL:
481117577f7Sjsg 		*speed = IXGBE_LINK_SPEED_10GB_FULL;
48211efaf7fSmikeb 		*autoneg = FALSE;
483117577f7Sjsg 		break;
484117577f7Sjsg 
485117577f7Sjsg 	case IXGBE_AUTOC_LMS_KX4_KX_KR:
486117577f7Sjsg 	case IXGBE_AUTOC_LMS_KX4_KX_KR_1G_AN:
487117577f7Sjsg 		*speed = IXGBE_LINK_SPEED_UNKNOWN;
488117577f7Sjsg 		if (autoc & IXGBE_AUTOC_KR_SUPP)
489117577f7Sjsg 			*speed |= IXGBE_LINK_SPEED_10GB_FULL;
490117577f7Sjsg 		if (autoc & IXGBE_AUTOC_KX4_SUPP)
491117577f7Sjsg 			*speed |= IXGBE_LINK_SPEED_10GB_FULL;
492117577f7Sjsg 		if (autoc & IXGBE_AUTOC_KX_SUPP)
493117577f7Sjsg 			*speed |= IXGBE_LINK_SPEED_1GB_FULL;
49411efaf7fSmikeb 		*autoneg = TRUE;
495117577f7Sjsg 		break;
496117577f7Sjsg 
497117577f7Sjsg 	case IXGBE_AUTOC_LMS_KX4_KX_KR_SGMII:
498117577f7Sjsg 		*speed = IXGBE_LINK_SPEED_100_FULL;
499117577f7Sjsg 		if (autoc & IXGBE_AUTOC_KR_SUPP)
500117577f7Sjsg 			*speed |= IXGBE_LINK_SPEED_10GB_FULL;
501117577f7Sjsg 		if (autoc & IXGBE_AUTOC_KX4_SUPP)
502117577f7Sjsg 			*speed |= IXGBE_LINK_SPEED_10GB_FULL;
503117577f7Sjsg 		if (autoc & IXGBE_AUTOC_KX_SUPP)
504117577f7Sjsg 			*speed |= IXGBE_LINK_SPEED_1GB_FULL;
50511efaf7fSmikeb 		*autoneg = TRUE;
506117577f7Sjsg 		break;
507117577f7Sjsg 
508117577f7Sjsg 	case IXGBE_AUTOC_LMS_SGMII_1G_100M:
509117577f7Sjsg 		*speed = IXGBE_LINK_SPEED_1GB_FULL | IXGBE_LINK_SPEED_100_FULL;
51011efaf7fSmikeb 		*autoneg = FALSE;
511117577f7Sjsg 		break;
512117577f7Sjsg 
513117577f7Sjsg 	default:
514117577f7Sjsg 		status = IXGBE_ERR_LINK_SETUP;
515117577f7Sjsg 		goto out;
516117577f7Sjsg 		break;
517117577f7Sjsg 	}
518117577f7Sjsg 
519117577f7Sjsg 	if (hw->phy.multispeed_fiber) {
520117577f7Sjsg 		*speed |= IXGBE_LINK_SPEED_10GB_FULL |
521117577f7Sjsg 			  IXGBE_LINK_SPEED_1GB_FULL;
5222f63561bSmikeb 
5232f63561bSmikeb 		/* QSFP must not enable full auto-negotiation
5242f63561bSmikeb 		 * Limited autoneg is enabled at 1G
5252f63561bSmikeb 		 */
5262f63561bSmikeb 		if (hw->phy.media_type == ixgbe_media_type_fiber_qsfp)
5272f63561bSmikeb 			*autoneg = FALSE;
5282f63561bSmikeb 		else
52911efaf7fSmikeb 			*autoneg = TRUE;
530117577f7Sjsg 	}
531117577f7Sjsg 
532117577f7Sjsg out:
533117577f7Sjsg 	return status;
534117577f7Sjsg }
535117577f7Sjsg 
536117577f7Sjsg /**
537117577f7Sjsg  *  ixgbe_get_media_type_82599 - Get media type
538117577f7Sjsg  *  @hw: pointer to hardware structure
539117577f7Sjsg  *
540117577f7Sjsg  *  Returns the media type (fiber, copper, backplane)
541117577f7Sjsg  **/
ixgbe_get_media_type_82599(struct ixgbe_hw * hw)542117577f7Sjsg enum ixgbe_media_type ixgbe_get_media_type_82599(struct ixgbe_hw *hw)
543117577f7Sjsg {
544117577f7Sjsg 	enum ixgbe_media_type media_type;
545117577f7Sjsg 
546117577f7Sjsg 	DEBUGFUNC("ixgbe_get_media_type_82599");
547117577f7Sjsg 
548117577f7Sjsg 	/* Detect if there is a copper PHY attached. */
5499feba5bbSclaudio 	switch (hw->phy.type) {
5509feba5bbSclaudio 	case ixgbe_phy_cu_unknown:
5519feba5bbSclaudio 	case ixgbe_phy_tn:
552117577f7Sjsg 		media_type = ixgbe_media_type_copper;
553117577f7Sjsg 		goto out;
5549feba5bbSclaudio 	default:
5559feba5bbSclaudio 		break;
556117577f7Sjsg 	}
557117577f7Sjsg 
558117577f7Sjsg 	switch (hw->device_id) {
559117577f7Sjsg 	case IXGBE_DEV_ID_82599_KX4:
560117577f7Sjsg 	case IXGBE_DEV_ID_82599_KX4_MEZZ:
561117577f7Sjsg 	case IXGBE_DEV_ID_82599_COMBO_BACKPLANE:
562c7fa8c00Smikeb 	case IXGBE_DEV_ID_82599_KR:
5639feba5bbSclaudio 	case IXGBE_DEV_ID_82599_BACKPLANE_FCOE:
564117577f7Sjsg 	case IXGBE_DEV_ID_82599_XAUI_LOM:
565117577f7Sjsg 		/* Default device ID is mezzanine card KX/KX4 */
566117577f7Sjsg 		media_type = ixgbe_media_type_backplane;
567117577f7Sjsg 		break;
568117577f7Sjsg 	case IXGBE_DEV_ID_82599_SFP:
5699feba5bbSclaudio 	case IXGBE_DEV_ID_82599_SFP_FCOE:
570c7fa8c00Smikeb 	case IXGBE_DEV_ID_82599_SFP_EM:
5713964484eSmikeb 	case IXGBE_DEV_ID_82599_SFP_SF2:
57211efaf7fSmikeb 	case IXGBE_DEV_ID_82599_SFP_SF_QP:
573c7fa8c00Smikeb 	case IXGBE_DEV_ID_82599EN_SFP:
574117577f7Sjsg 		media_type = ixgbe_media_type_fiber;
575117577f7Sjsg 		break;
576117577f7Sjsg 	case IXGBE_DEV_ID_82599_CX4:
577117577f7Sjsg 		media_type = ixgbe_media_type_cx4;
578117577f7Sjsg 		break;
5799feba5bbSclaudio 	case IXGBE_DEV_ID_82599_T3_LOM:
5809feba5bbSclaudio 		media_type = ixgbe_media_type_copper;
5819feba5bbSclaudio 		break;
5822f63561bSmikeb 	case IXGBE_DEV_ID_82599_QSFP_SF_QP:
5832f63561bSmikeb 		media_type = ixgbe_media_type_fiber_qsfp;
5842f63561bSmikeb 		break;
58511efaf7fSmikeb 	case IXGBE_DEV_ID_82599_BYPASS:
58611efaf7fSmikeb 		media_type = ixgbe_media_type_fiber_fixed;
58711efaf7fSmikeb 		hw->phy.multispeed_fiber = TRUE;
58811efaf7fSmikeb 		break;
589117577f7Sjsg 	default:
590117577f7Sjsg 		media_type = ixgbe_media_type_unknown;
591117577f7Sjsg 		break;
592117577f7Sjsg 	}
593117577f7Sjsg out:
594117577f7Sjsg 	return media_type;
595117577f7Sjsg }
596117577f7Sjsg 
597117577f7Sjsg /**
59811efaf7fSmikeb  *  ixgbe_stop_mac_link_on_d3_82599 - Disables link on D3
59911efaf7fSmikeb  *  @hw: pointer to hardware structure
60011efaf7fSmikeb  *
60111efaf7fSmikeb  *  Disables link during D3 power down sequence.
60211efaf7fSmikeb  *
60311efaf7fSmikeb  **/
ixgbe_stop_mac_link_on_d3_82599(struct ixgbe_hw * hw)60411efaf7fSmikeb void ixgbe_stop_mac_link_on_d3_82599(struct ixgbe_hw *hw)
60511efaf7fSmikeb {
60611efaf7fSmikeb 	uint32_t autoc2_reg;
60711efaf7fSmikeb 	uint16_t ee_ctrl_2 = 0;
60811efaf7fSmikeb 
60911efaf7fSmikeb 	DEBUGFUNC("ixgbe_stop_mac_link_on_d3_82599");
610*d7a8f955Sjmatthew 	if (hw->eeprom.ops.read)
611*d7a8f955Sjmatthew 		hw->eeprom.ops.read(hw, IXGBE_EEPROM_CTRL_2, &ee_ctrl_2);
61211efaf7fSmikeb 
613*d7a8f955Sjmatthew 	if (!ixgbe_mng_present(hw) && !hw->wol_enabled &&
614*d7a8f955Sjmatthew 	    ee_ctrl_2 & IXGBE_EEPROM_CCD_BIT) {
61511efaf7fSmikeb 		autoc2_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC2);
61611efaf7fSmikeb 		autoc2_reg |= IXGBE_AUTOC2_LINK_DISABLE_ON_D3_MASK;
61711efaf7fSmikeb 		IXGBE_WRITE_REG(hw, IXGBE_AUTOC2, autoc2_reg);
61811efaf7fSmikeb 	}
61911efaf7fSmikeb }
62011efaf7fSmikeb 
62111efaf7fSmikeb /**
622117577f7Sjsg  *  ixgbe_start_mac_link_82599 - Setup MAC link settings
623117577f7Sjsg  *  @hw: pointer to hardware structure
624c7fa8c00Smikeb  *  @autoneg_wait_to_complete: TRUE when waiting for completion is needed
625117577f7Sjsg  *
626117577f7Sjsg  *  Configures link settings based on values in the ixgbe_hw struct.
627117577f7Sjsg  *  Restarts the link.  Performs autonegotiation if needed.
628117577f7Sjsg  **/
ixgbe_start_mac_link_82599(struct ixgbe_hw * hw,bool autoneg_wait_to_complete)629117577f7Sjsg int32_t ixgbe_start_mac_link_82599(struct ixgbe_hw *hw,
63011efaf7fSmikeb 				   bool autoneg_wait_to_complete)
631117577f7Sjsg {
632117577f7Sjsg 	uint32_t autoc_reg;
633117577f7Sjsg 	uint32_t links_reg;
634117577f7Sjsg 	uint32_t i;
635117577f7Sjsg 	int32_t status = IXGBE_SUCCESS;
63611efaf7fSmikeb 	bool got_lock = FALSE;
637117577f7Sjsg 
638117577f7Sjsg 	DEBUGFUNC("ixgbe_start_mac_link_82599");
639117577f7Sjsg 
640117577f7Sjsg 
64111efaf7fSmikeb 	/*  reset_pipeline requires us to hold this lock as it writes to
64211efaf7fSmikeb 	 *  AUTOC.
64311efaf7fSmikeb 	 */
64411efaf7fSmikeb 	if (ixgbe_verify_lesm_fw_enabled_82599(hw)) {
64511efaf7fSmikeb 		status = hw->mac.ops.acquire_swfw_sync(hw,
64611efaf7fSmikeb 						       IXGBE_GSSR_MAC_CSR_SM);
64711efaf7fSmikeb 		if (status != IXGBE_SUCCESS)
64811efaf7fSmikeb 			goto out;
64911efaf7fSmikeb 
65011efaf7fSmikeb 		got_lock = TRUE;
65111efaf7fSmikeb 	}
65211efaf7fSmikeb 
653117577f7Sjsg 	/* Restart link */
65411efaf7fSmikeb 	ixgbe_reset_pipeline_82599(hw);
65511efaf7fSmikeb 
65611efaf7fSmikeb 	if (got_lock)
65711efaf7fSmikeb 		hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_MAC_CSR_SM);
658117577f7Sjsg 
659117577f7Sjsg 	/* Only poll for autoneg to complete if specified to do so */
660117577f7Sjsg 	if (autoneg_wait_to_complete) {
66111efaf7fSmikeb 		autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC);
662117577f7Sjsg 		if ((autoc_reg & IXGBE_AUTOC_LMS_MASK) ==
663117577f7Sjsg 		     IXGBE_AUTOC_LMS_KX4_KX_KR ||
664117577f7Sjsg 		    (autoc_reg & IXGBE_AUTOC_LMS_MASK) ==
6659feba5bbSclaudio 		     IXGBE_AUTOC_LMS_KX4_KX_KR_1G_AN ||
6669feba5bbSclaudio 		    (autoc_reg & IXGBE_AUTOC_LMS_MASK) ==
667117577f7Sjsg 		     IXGBE_AUTOC_LMS_KX4_KX_KR_SGMII) {
668117577f7Sjsg 			links_reg = 0; /* Just in case Autoneg time = 0 */
669117577f7Sjsg 			for (i = 0; i < IXGBE_AUTO_NEG_TIME; i++) {
670117577f7Sjsg 				links_reg = IXGBE_READ_REG(hw, IXGBE_LINKS);
671117577f7Sjsg 				if (links_reg & IXGBE_LINKS_KX_AN_COMP)
672117577f7Sjsg 					break;
673117577f7Sjsg 				msec_delay(100);
674117577f7Sjsg 			}
675117577f7Sjsg 			if (!(links_reg & IXGBE_LINKS_KX_AN_COMP)) {
676117577f7Sjsg 				status = IXGBE_ERR_AUTONEG_NOT_COMPLETE;
677117577f7Sjsg 				DEBUGOUT("Autoneg did not complete.\n");
678117577f7Sjsg 			}
679117577f7Sjsg 		}
680117577f7Sjsg 	}
681117577f7Sjsg 
682117577f7Sjsg 	/* Add delay to filter out noises during initial link setup */
683117577f7Sjsg 	msec_delay(50);
684117577f7Sjsg 
68511efaf7fSmikeb out:
686117577f7Sjsg 	return status;
687117577f7Sjsg }
688117577f7Sjsg 
689117577f7Sjsg /**
6909feba5bbSclaudio  *  ixgbe_disable_tx_laser_multispeed_fiber - Disable Tx laser
6919feba5bbSclaudio  *  @hw: pointer to hardware structure
6929feba5bbSclaudio  *
6939feba5bbSclaudio  *  The base drivers may require better control over SFP+ module
6949feba5bbSclaudio  *  PHY states.  This includes selectively shutting down the Tx
6959feba5bbSclaudio  *  laser on the PHY, effectively halting physical link.
6969feba5bbSclaudio  **/
ixgbe_disable_tx_laser_multispeed_fiber(struct ixgbe_hw * hw)6979feba5bbSclaudio void ixgbe_disable_tx_laser_multispeed_fiber(struct ixgbe_hw *hw)
6989feba5bbSclaudio {
6999feba5bbSclaudio 	uint32_t esdp_reg = IXGBE_READ_REG(hw, IXGBE_ESDP);
7009feba5bbSclaudio 
7012f63561bSmikeb 	/* Blocked by MNG FW so bail */
7022f63561bSmikeb 	if (ixgbe_check_reset_blocked(hw))
7032f63561bSmikeb 		return;
7042f63561bSmikeb 
7059e435848Smikeb 	/* Disable Tx laser; allow 100us to go dark per spec */
7069feba5bbSclaudio 	esdp_reg |= IXGBE_ESDP_SDP3;
7079feba5bbSclaudio 	IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp_reg);
7089feba5bbSclaudio 	IXGBE_WRITE_FLUSH(hw);
7099feba5bbSclaudio 	usec_delay(100);
7109feba5bbSclaudio }
7119feba5bbSclaudio 
7129feba5bbSclaudio /**
7139feba5bbSclaudio  *  ixgbe_enable_tx_laser_multispeed_fiber - Enable Tx laser
7149feba5bbSclaudio  *  @hw: pointer to hardware structure
7159feba5bbSclaudio  *
7169feba5bbSclaudio  *  The base drivers may require better control over SFP+ module
7179feba5bbSclaudio  *  PHY states.  This includes selectively turning on the Tx
7189feba5bbSclaudio  *  laser on the PHY, effectively starting physical link.
7199feba5bbSclaudio  **/
ixgbe_enable_tx_laser_multispeed_fiber(struct ixgbe_hw * hw)7209feba5bbSclaudio void ixgbe_enable_tx_laser_multispeed_fiber(struct ixgbe_hw *hw)
7219feba5bbSclaudio {
7229feba5bbSclaudio 	uint32_t esdp_reg = IXGBE_READ_REG(hw, IXGBE_ESDP);
7239feba5bbSclaudio 
7249e435848Smikeb 	/* Enable Tx laser; allow 100ms to light up */
7259feba5bbSclaudio 	esdp_reg &= ~IXGBE_ESDP_SDP3;
7269feba5bbSclaudio 	IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp_reg);
7279feba5bbSclaudio 	IXGBE_WRITE_FLUSH(hw);
7289feba5bbSclaudio 	msec_delay(100);
7299feba5bbSclaudio }
7309feba5bbSclaudio 
7319feba5bbSclaudio /**
7329feba5bbSclaudio  *  ixgbe_flap_tx_laser_multispeed_fiber - Flap Tx laser
7339feba5bbSclaudio  *  @hw: pointer to hardware structure
7349feba5bbSclaudio  *
7359feba5bbSclaudio  *  When the driver changes the link speeds that it can support,
7369feba5bbSclaudio  *  it sets autotry_restart to TRUE to indicate that we need to
7379feba5bbSclaudio  *  initiate a new autotry session with the link partner.  To do
7389e435848Smikeb  *  so, we set the speed then disable and re-enable the Tx laser, to
7399feba5bbSclaudio  *  alert the link partner that it also needs to restart autotry on its
7409feba5bbSclaudio  *  end.  This is consistent with TRUE clause 37 autoneg, which also
7419feba5bbSclaudio  *  involves a loss of signal.
7429feba5bbSclaudio  **/
ixgbe_flap_tx_laser_multispeed_fiber(struct ixgbe_hw * hw)7439feba5bbSclaudio void ixgbe_flap_tx_laser_multispeed_fiber(struct ixgbe_hw *hw)
7449feba5bbSclaudio {
7459feba5bbSclaudio 	DEBUGFUNC("ixgbe_flap_tx_laser_multispeed_fiber");
7469feba5bbSclaudio 
7472f63561bSmikeb 	/* Blocked by MNG FW so bail */
7482f63561bSmikeb 	if (ixgbe_check_reset_blocked(hw))
7492f63561bSmikeb 		return;
7502f63561bSmikeb 
7519feba5bbSclaudio 	if (hw->mac.autotry_restart) {
7529feba5bbSclaudio 		ixgbe_disable_tx_laser_multispeed_fiber(hw);
7539feba5bbSclaudio 		ixgbe_enable_tx_laser_multispeed_fiber(hw);
7549feba5bbSclaudio 		hw->mac.autotry_restart = FALSE;
7559feba5bbSclaudio 	}
7569feba5bbSclaudio }
7579feba5bbSclaudio 
7589feba5bbSclaudio /**
7592f63561bSmikeb  *  ixgbe_set_hard_rate_select_speed - Set module link speed
76011efaf7fSmikeb  *  @hw: pointer to hardware structure
76111efaf7fSmikeb  *  @speed: link speed to set
76211efaf7fSmikeb  *
7632f63561bSmikeb  *  Set module link speed via RS0/RS1 rate select pins.
76411efaf7fSmikeb  */
ixgbe_set_hard_rate_select_speed(struct ixgbe_hw * hw,ixgbe_link_speed speed)7652f63561bSmikeb void ixgbe_set_hard_rate_select_speed(struct ixgbe_hw *hw,
76611efaf7fSmikeb 				      ixgbe_link_speed speed)
76711efaf7fSmikeb {
7682f63561bSmikeb 	uint32_t esdp_reg = IXGBE_READ_REG(hw, IXGBE_ESDP);
76911efaf7fSmikeb 
77011efaf7fSmikeb 	switch (speed) {
77111efaf7fSmikeb 	case IXGBE_LINK_SPEED_10GB_FULL:
7722f63561bSmikeb 		esdp_reg |= (IXGBE_ESDP_SDP5_DIR | IXGBE_ESDP_SDP5);
77311efaf7fSmikeb 		break;
77411efaf7fSmikeb 	case IXGBE_LINK_SPEED_1GB_FULL:
7752f63561bSmikeb 		esdp_reg &= ~IXGBE_ESDP_SDP5;
7762f63561bSmikeb 		esdp_reg |= IXGBE_ESDP_SDP5_DIR;
77711efaf7fSmikeb 		break;
77811efaf7fSmikeb 	default:
77911efaf7fSmikeb 		DEBUGOUT("Invalid fixed module speed\n");
78011efaf7fSmikeb 		return;
78111efaf7fSmikeb 	}
78211efaf7fSmikeb 
783117577f7Sjsg 	IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp_reg);
7849feba5bbSclaudio 	IXGBE_WRITE_FLUSH(hw);
78511efaf7fSmikeb }
786117577f7Sjsg 
787117577f7Sjsg /**
788117577f7Sjsg  *  ixgbe_setup_mac_link_smartspeed - Set MAC link speed using SmartSpeed
789117577f7Sjsg  *  @hw: pointer to hardware structure
790117577f7Sjsg  *  @speed: new link speed
791117577f7Sjsg  *  @autoneg_wait_to_complete: TRUE when waiting for completion is needed
792117577f7Sjsg  *
793117577f7Sjsg  *  Implements the Intel SmartSpeed algorithm.
794117577f7Sjsg  **/
ixgbe_setup_mac_link_smartspeed(struct ixgbe_hw * hw,ixgbe_link_speed speed,bool autoneg_wait_to_complete)795117577f7Sjsg int32_t ixgbe_setup_mac_link_smartspeed(struct ixgbe_hw *hw,
79611efaf7fSmikeb 					ixgbe_link_speed speed,
79711efaf7fSmikeb 					bool autoneg_wait_to_complete)
798117577f7Sjsg {
799117577f7Sjsg 	int32_t status = IXGBE_SUCCESS;
80011efaf7fSmikeb 	ixgbe_link_speed link_speed = IXGBE_LINK_SPEED_UNKNOWN;
801117577f7Sjsg 	int32_t i, j;
80211efaf7fSmikeb 	bool link_up = FALSE;
803117577f7Sjsg 	uint32_t autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC);
804117577f7Sjsg 
805117577f7Sjsg 	DEBUGFUNC("ixgbe_setup_mac_link_smartspeed");
806117577f7Sjsg 
807117577f7Sjsg 	 /* Set autoneg_advertised value based on input link speed */
808117577f7Sjsg 	hw->phy.autoneg_advertised = 0;
809117577f7Sjsg 
810117577f7Sjsg 	if (speed & IXGBE_LINK_SPEED_10GB_FULL)
811117577f7Sjsg 		hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_10GB_FULL;
812117577f7Sjsg 
813117577f7Sjsg 	if (speed & IXGBE_LINK_SPEED_1GB_FULL)
814117577f7Sjsg 		hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_1GB_FULL;
815117577f7Sjsg 
816117577f7Sjsg 	if (speed & IXGBE_LINK_SPEED_100_FULL)
817117577f7Sjsg 		hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_100_FULL;
818117577f7Sjsg 
819117577f7Sjsg 	/*
820117577f7Sjsg 	 * Implement Intel SmartSpeed algorithm.  SmartSpeed will reduce the
821117577f7Sjsg 	 * autoneg advertisement if link is unable to be established at the
822117577f7Sjsg 	 * highest negotiated rate.  This can sometimes happen due to integrity
823117577f7Sjsg 	 * issues with the physical media connection.
824117577f7Sjsg 	 */
825117577f7Sjsg 
826117577f7Sjsg 	/* First, try to get link with full advertisement */
827117577f7Sjsg 	hw->phy.smart_speed_active = FALSE;
828117577f7Sjsg 	for (j = 0; j < IXGBE_SMARTSPEED_MAX_RETRIES; j++) {
82911efaf7fSmikeb 		status = ixgbe_setup_mac_link_82599(hw, speed,
830117577f7Sjsg 						    autoneg_wait_to_complete);
831117577f7Sjsg 		if (status != IXGBE_SUCCESS)
832117577f7Sjsg 			goto out;
833117577f7Sjsg 
834117577f7Sjsg 		/*
835117577f7Sjsg 		 * Wait for the controller to acquire link.  Per IEEE 802.3ap,
836117577f7Sjsg 		 * Section 73.10.2, we may have to wait up to 500ms if KR is
837117577f7Sjsg 		 * attempted, or 200ms if KX/KX4/BX/BX4 is attempted, per
838117577f7Sjsg 		 * Table 9 in the AN MAS.
839117577f7Sjsg 		 */
840117577f7Sjsg 		for (i = 0; i < 5; i++) {
841117577f7Sjsg 			msec_delay(100);
842117577f7Sjsg 
843117577f7Sjsg 			/* If we have link, just jump out */
84411efaf7fSmikeb 			status = ixgbe_check_link(hw, &link_speed, &link_up,
845117577f7Sjsg 						  FALSE);
846117577f7Sjsg 			if (status != IXGBE_SUCCESS)
847117577f7Sjsg 				goto out;
848117577f7Sjsg 
849117577f7Sjsg 			if (link_up)
850117577f7Sjsg 				goto out;
851117577f7Sjsg 		}
852117577f7Sjsg 	}
853117577f7Sjsg 
854117577f7Sjsg 	/*
855117577f7Sjsg 	 * We didn't get link.  If we advertised KR plus one of KX4/KX
856117577f7Sjsg 	 * (or BX4/BX), then disable KR and try again.
857117577f7Sjsg 	 */
858117577f7Sjsg 	if (((autoc_reg & IXGBE_AUTOC_KR_SUPP) == 0) ||
859117577f7Sjsg 	    ((autoc_reg & IXGBE_AUTOC_KX4_KX_SUPP_MASK) == 0))
860117577f7Sjsg 		goto out;
861117577f7Sjsg 
862117577f7Sjsg 	/* Turn SmartSpeed on to disable KR support */
863117577f7Sjsg 	hw->phy.smart_speed_active = TRUE;
86411efaf7fSmikeb 	status = ixgbe_setup_mac_link_82599(hw, speed,
865117577f7Sjsg 					    autoneg_wait_to_complete);
866117577f7Sjsg 	if (status != IXGBE_SUCCESS)
867117577f7Sjsg 		goto out;
868117577f7Sjsg 
869117577f7Sjsg 	/*
870117577f7Sjsg 	 * Wait for the controller to acquire link.  600ms will allow for
871117577f7Sjsg 	 * the AN link_fail_inhibit_timer as well for multiple cycles of
872117577f7Sjsg 	 * parallel detect, both 10g and 1g. This allows for the maximum
873117577f7Sjsg 	 * connect attempts as defined in the AN MAS table 73-7.
874117577f7Sjsg 	 */
875117577f7Sjsg 	for (i = 0; i < 6; i++) {
876117577f7Sjsg 		msec_delay(100);
877117577f7Sjsg 
878117577f7Sjsg 		/* If we have link, just jump out */
87911efaf7fSmikeb 		status = ixgbe_check_link(hw, &link_speed, &link_up, FALSE);
880117577f7Sjsg 		if (status != IXGBE_SUCCESS)
881117577f7Sjsg 			goto out;
882117577f7Sjsg 
883117577f7Sjsg 		if (link_up)
884117577f7Sjsg 			goto out;
885117577f7Sjsg 	}
886117577f7Sjsg 
887117577f7Sjsg 	/* We didn't get link.  Turn SmartSpeed back off. */
888117577f7Sjsg 	hw->phy.smart_speed_active = FALSE;
88911efaf7fSmikeb 	status = ixgbe_setup_mac_link_82599(hw, speed,
890117577f7Sjsg 					    autoneg_wait_to_complete);
891117577f7Sjsg 
892117577f7Sjsg out:
8939feba5bbSclaudio 	if (link_up && (link_speed == IXGBE_LINK_SPEED_1GB_FULL))
8949feba5bbSclaudio 		DEBUGOUT("Smartspeed has downgraded the link speed "
8959feba5bbSclaudio 		"from the maximum advertised\n");
896117577f7Sjsg 	return status;
897117577f7Sjsg }
898117577f7Sjsg 
899117577f7Sjsg /**
900117577f7Sjsg  *  ixgbe_setup_mac_link_82599 - Set MAC link speed
901117577f7Sjsg  *  @hw: pointer to hardware structure
902117577f7Sjsg  *  @speed: new link speed
903117577f7Sjsg  *  @autoneg_wait_to_complete: TRUE when waiting for completion is needed
904117577f7Sjsg  *
905117577f7Sjsg  *  Set the link speed in the AUTOC register and restarts link.
906117577f7Sjsg  **/
ixgbe_setup_mac_link_82599(struct ixgbe_hw * hw,ixgbe_link_speed speed,bool autoneg_wait_to_complete)907117577f7Sjsg int32_t ixgbe_setup_mac_link_82599(struct ixgbe_hw *hw,
90811efaf7fSmikeb 				   ixgbe_link_speed speed,
90911efaf7fSmikeb 				   bool autoneg_wait_to_complete)
910117577f7Sjsg {
91111efaf7fSmikeb 	bool autoneg = FALSE;
912117577f7Sjsg 	int32_t status = IXGBE_SUCCESS;
913276d64b7Smikeb 	uint32_t pma_pmd_1g, link_mode;
914276d64b7Smikeb 	/* holds the value of AUTOC register at this current point in time */
915276d64b7Smikeb 	uint32_t current_autoc = IXGBE_READ_REG(hw, IXGBE_AUTOC);
916276d64b7Smikeb 	/* holds the cached value of AUTOC register */
917117577f7Sjsg 	uint32_t orig_autoc = 0;
918276d64b7Smikeb 	/* Temporary variable used for comparison purposes */
919276d64b7Smikeb 	uint32_t autoc = current_autoc;
920276d64b7Smikeb 	uint32_t autoc2 = IXGBE_READ_REG(hw, IXGBE_AUTOC2);
921117577f7Sjsg 	uint32_t pma_pmd_10g_serial = autoc2 & IXGBE_AUTOC2_10G_SERIAL_PMA_PMD_MASK;
922117577f7Sjsg 	uint32_t links_reg;
923117577f7Sjsg 	uint32_t i;
924117577f7Sjsg 	ixgbe_link_speed link_capabilities = IXGBE_LINK_SPEED_UNKNOWN;
925117577f7Sjsg 
926117577f7Sjsg 	DEBUGFUNC("ixgbe_setup_mac_link_82599");
927117577f7Sjsg 
928117577f7Sjsg 	/* Check to see if speed passed in is supported. */
929*d7a8f955Sjmatthew 	status = hw->mac.ops.get_link_capabilities(hw, &link_capabilities,
9302f63561bSmikeb 	    &autoneg);
93111efaf7fSmikeb 	if (status)
932117577f7Sjsg 		goto out;
933117577f7Sjsg 
934117577f7Sjsg 	speed &= link_capabilities;
935117577f7Sjsg 
936117577f7Sjsg 	if (speed == IXGBE_LINK_SPEED_UNKNOWN) {
937117577f7Sjsg 		status = IXGBE_ERR_LINK_SETUP;
938117577f7Sjsg 		goto out;
939117577f7Sjsg 	}
940117577f7Sjsg 
941117577f7Sjsg 	/* Use stored value (EEPROM defaults) of AUTOC to find KR/KX4 support*/
942117577f7Sjsg 	if (hw->mac.orig_link_settings_stored)
943276d64b7Smikeb 		orig_autoc = hw->mac.orig_autoc;
944117577f7Sjsg 	else
945117577f7Sjsg 		orig_autoc = autoc;
946276d64b7Smikeb 
94711efaf7fSmikeb 	link_mode = autoc & IXGBE_AUTOC_LMS_MASK;
94811efaf7fSmikeb 	pma_pmd_1g = autoc & IXGBE_AUTOC_1G_PMA_PMD_MASK;
949117577f7Sjsg 
950117577f7Sjsg 	if (link_mode == IXGBE_AUTOC_LMS_KX4_KX_KR ||
951117577f7Sjsg 	    link_mode == IXGBE_AUTOC_LMS_KX4_KX_KR_1G_AN ||
952117577f7Sjsg 	    link_mode == IXGBE_AUTOC_LMS_KX4_KX_KR_SGMII) {
953117577f7Sjsg 		/* Set KX4/KX/KR support according to speed requested */
954117577f7Sjsg 		autoc &= ~(IXGBE_AUTOC_KX4_KX_SUPP_MASK | IXGBE_AUTOC_KR_SUPP);
955c7fa8c00Smikeb 		if (speed & IXGBE_LINK_SPEED_10GB_FULL) {
956117577f7Sjsg 			if (orig_autoc & IXGBE_AUTOC_KX4_SUPP)
957117577f7Sjsg 				autoc |= IXGBE_AUTOC_KX4_SUPP;
958117577f7Sjsg 			if ((orig_autoc & IXGBE_AUTOC_KR_SUPP) &&
959117577f7Sjsg 			    (hw->phy.smart_speed_active == FALSE))
960117577f7Sjsg 				autoc |= IXGBE_AUTOC_KR_SUPP;
961c7fa8c00Smikeb 		}
962117577f7Sjsg 		if (speed & IXGBE_LINK_SPEED_1GB_FULL)
963117577f7Sjsg 			autoc |= IXGBE_AUTOC_KX_SUPP;
964117577f7Sjsg 	} else if ((pma_pmd_1g == IXGBE_AUTOC_1G_SFI) &&
965117577f7Sjsg 		   (link_mode == IXGBE_AUTOC_LMS_1G_LINK_NO_AN ||
966117577f7Sjsg 		    link_mode == IXGBE_AUTOC_LMS_1G_AN)) {
967117577f7Sjsg 		/* Switch from 1G SFI to 10G SFI if requested */
968117577f7Sjsg 		if ((speed == IXGBE_LINK_SPEED_10GB_FULL) &&
969117577f7Sjsg 		    (pma_pmd_10g_serial == IXGBE_AUTOC2_10G_SFI)) {
970117577f7Sjsg 			autoc &= ~IXGBE_AUTOC_LMS_MASK;
971117577f7Sjsg 			autoc |= IXGBE_AUTOC_LMS_10G_SERIAL;
972117577f7Sjsg 		}
973117577f7Sjsg 	} else if ((pma_pmd_10g_serial == IXGBE_AUTOC2_10G_SFI) &&
974117577f7Sjsg 		   (link_mode == IXGBE_AUTOC_LMS_10G_SERIAL)) {
975117577f7Sjsg 		/* Switch from 10G SFI to 1G SFI if requested */
976117577f7Sjsg 		if ((speed == IXGBE_LINK_SPEED_1GB_FULL) &&
977117577f7Sjsg 		    (pma_pmd_1g == IXGBE_AUTOC_1G_SFI)) {
978117577f7Sjsg 			autoc &= ~IXGBE_AUTOC_LMS_MASK;
9792f63561bSmikeb 			if (autoneg || hw->phy.type == ixgbe_phy_qsfp_intel)
980117577f7Sjsg 				autoc |= IXGBE_AUTOC_LMS_1G_AN;
981117577f7Sjsg 			else
982117577f7Sjsg 				autoc |= IXGBE_AUTOC_LMS_1G_LINK_NO_AN;
983117577f7Sjsg 		}
984117577f7Sjsg 	}
985117577f7Sjsg 
986276d64b7Smikeb 	if (autoc != current_autoc) {
987117577f7Sjsg 		/* Restart link */
988276d64b7Smikeb 		status = hw->mac.ops.prot_autoc_write(hw, autoc, FALSE);
989276d64b7Smikeb 		if (status != IXGBE_SUCCESS)
990276d64b7Smikeb 			goto out;
991117577f7Sjsg 
992117577f7Sjsg 		/* Only poll for autoneg to complete if specified to do so */
993117577f7Sjsg 		if (autoneg_wait_to_complete) {
994117577f7Sjsg 			if (link_mode == IXGBE_AUTOC_LMS_KX4_KX_KR ||
995117577f7Sjsg 			    link_mode == IXGBE_AUTOC_LMS_KX4_KX_KR_1G_AN ||
996117577f7Sjsg 			    link_mode == IXGBE_AUTOC_LMS_KX4_KX_KR_SGMII) {
997117577f7Sjsg 				links_reg = 0; /*Just in case Autoneg time=0*/
998117577f7Sjsg 				for (i = 0; i < IXGBE_AUTO_NEG_TIME; i++) {
999117577f7Sjsg 					links_reg =
1000117577f7Sjsg 					       IXGBE_READ_REG(hw, IXGBE_LINKS);
1001117577f7Sjsg 					if (links_reg & IXGBE_LINKS_KX_AN_COMP)
1002117577f7Sjsg 						break;
1003117577f7Sjsg 					msec_delay(100);
1004117577f7Sjsg 				}
1005117577f7Sjsg 				if (!(links_reg & IXGBE_LINKS_KX_AN_COMP)) {
1006117577f7Sjsg 					status =
1007117577f7Sjsg 						IXGBE_ERR_AUTONEG_NOT_COMPLETE;
1008117577f7Sjsg 					DEBUGOUT("Autoneg did not complete.\n");
1009117577f7Sjsg 				}
1010117577f7Sjsg 			}
1011117577f7Sjsg 		}
1012117577f7Sjsg 
1013117577f7Sjsg 		/* Add delay to filter out noises during initial link setup */
1014117577f7Sjsg 		msec_delay(50);
1015117577f7Sjsg 	}
1016117577f7Sjsg 
1017117577f7Sjsg out:
1018117577f7Sjsg 	return status;
1019117577f7Sjsg }
1020117577f7Sjsg 
1021117577f7Sjsg /**
1022117577f7Sjsg  *  ixgbe_setup_copper_link_82599 - Set the PHY autoneg advertised field
1023117577f7Sjsg  *  @hw: pointer to hardware structure
1024117577f7Sjsg  *  @speed: new link speed
1025117577f7Sjsg  *  @autoneg_wait_to_complete: TRUE if waiting is needed to complete
1026117577f7Sjsg  *
1027117577f7Sjsg  *  Restarts link on PHY and MAC based on settings passed in.
1028117577f7Sjsg  **/
ixgbe_setup_copper_link_82599(struct ixgbe_hw * hw,ixgbe_link_speed speed,bool autoneg_wait_to_complete)1029117577f7Sjsg int32_t ixgbe_setup_copper_link_82599(struct ixgbe_hw *hw,
1030117577f7Sjsg 				      ixgbe_link_speed speed,
103111efaf7fSmikeb 				      bool autoneg_wait_to_complete)
1032117577f7Sjsg {
1033117577f7Sjsg 	int32_t status;
1034117577f7Sjsg 
1035117577f7Sjsg 	DEBUGFUNC("ixgbe_setup_copper_link_82599");
1036117577f7Sjsg 
1037117577f7Sjsg 	/* Setup the PHY according to input speed */
103811efaf7fSmikeb 	status = hw->phy.ops.setup_link_speed(hw, speed,
1039117577f7Sjsg 					      autoneg_wait_to_complete);
1040117577f7Sjsg 	/* Set up MAC */
1041117577f7Sjsg 	ixgbe_start_mac_link_82599(hw, autoneg_wait_to_complete);
1042117577f7Sjsg 
1043117577f7Sjsg 	return status;
1044117577f7Sjsg }
104511efaf7fSmikeb 
1046117577f7Sjsg /**
1047117577f7Sjsg  *  ixgbe_reset_hw_82599 - Perform hardware reset
1048117577f7Sjsg  *  @hw: pointer to hardware structure
1049117577f7Sjsg  *
1050117577f7Sjsg  *  Resets the hardware by resetting the transmit and receive units, masks
1051117577f7Sjsg  *  and clears all interrupts, perform a PHY reset, and perform a link (MAC)
1052117577f7Sjsg  *  reset.
1053117577f7Sjsg  **/
ixgbe_reset_hw_82599(struct ixgbe_hw * hw)1054117577f7Sjsg int32_t ixgbe_reset_hw_82599(struct ixgbe_hw *hw)
1055117577f7Sjsg {
105611efaf7fSmikeb 	ixgbe_link_speed link_speed;
105711efaf7fSmikeb 	int32_t status;
1058276d64b7Smikeb 	uint32_t ctrl = 0;
1059276d64b7Smikeb 	uint32_t i, autoc, autoc2;
106011efaf7fSmikeb 	uint32_t curr_lms;
106111efaf7fSmikeb 	bool link_up = FALSE;
1062117577f7Sjsg 
1063117577f7Sjsg 	DEBUGFUNC("ixgbe_reset_hw_82599");
1064117577f7Sjsg 
1065117577f7Sjsg 	/* Call adapter stop to disable tx/rx and clear interrupts */
106611efaf7fSmikeb 	status = hw->mac.ops.stop_adapter(hw);
106711efaf7fSmikeb 	if (status != IXGBE_SUCCESS)
106811efaf7fSmikeb 		goto reset_hw_out;
106911efaf7fSmikeb 
107011efaf7fSmikeb 	/* flush pending Tx transactions */
107111efaf7fSmikeb 	ixgbe_clear_tx_pending(hw);
1072117577f7Sjsg 
1073117577f7Sjsg 	/* PHY ops must be identified and initialized prior to reset */
1074117577f7Sjsg 
1075117577f7Sjsg 	/* Identify PHY and related function pointers */
1076117577f7Sjsg 	status = hw->phy.ops.init(hw);
1077117577f7Sjsg 
1078117577f7Sjsg 	if (status == IXGBE_ERR_SFP_NOT_SUPPORTED)
1079117577f7Sjsg 		goto reset_hw_out;
1080117577f7Sjsg 
1081117577f7Sjsg 	/* Setup SFP module if there is one present. */
1082117577f7Sjsg 	if (hw->phy.sfp_setup_needed) {
1083117577f7Sjsg 		status = hw->mac.ops.setup_sfp(hw);
1084117577f7Sjsg 		hw->phy.sfp_setup_needed = FALSE;
1085117577f7Sjsg 	}
1086117577f7Sjsg 
1087117577f7Sjsg 	if (status == IXGBE_ERR_SFP_NOT_SUPPORTED)
1088117577f7Sjsg 		goto reset_hw_out;
1089117577f7Sjsg 
1090117577f7Sjsg 	/* Reset PHY */
1091117577f7Sjsg 	if (hw->phy.reset_disable == FALSE && hw->phy.ops.reset != NULL)
1092117577f7Sjsg 		hw->phy.ops.reset(hw);
1093117577f7Sjsg 
109411efaf7fSmikeb 	/* remember AUTOC from before we reset */
1095276d64b7Smikeb 	curr_lms = IXGBE_READ_REG(hw, IXGBE_AUTOC) & IXGBE_AUTOC_LMS_MASK;
1096117577f7Sjsg 
10979feba5bbSclaudio mac_reset_top:
1098117577f7Sjsg 	/*
109911efaf7fSmikeb 	 * Issue global reset to the MAC.  Needs to be SW reset if link is up.
110011efaf7fSmikeb 	 * If link reset is used when link is up, it might reset the PHY when
110111efaf7fSmikeb 	 * mng is using it.  If link is down or the flag to force full link
110211efaf7fSmikeb 	 * reset is set, then perform link reset.
1103117577f7Sjsg 	 */
110411efaf7fSmikeb 	ctrl = IXGBE_CTRL_LNK_RST;
110511efaf7fSmikeb 	if (!hw->force_full_reset) {
110611efaf7fSmikeb 		hw->mac.ops.check_link(hw, &link_speed, &link_up, FALSE);
110711efaf7fSmikeb 		if (link_up)
110811efaf7fSmikeb 			ctrl = IXGBE_CTRL_RST;
110911efaf7fSmikeb 	}
111011efaf7fSmikeb 
111111efaf7fSmikeb 	ctrl |= IXGBE_READ_REG(hw, IXGBE_CTRL);
111211efaf7fSmikeb 	IXGBE_WRITE_REG(hw, IXGBE_CTRL, ctrl);
1113117577f7Sjsg 	IXGBE_WRITE_FLUSH(hw);
1114117577f7Sjsg 
11159e435848Smikeb 	/* Poll for reset bit to self-clear meaning reset is complete */
1116117577f7Sjsg 	for (i = 0; i < 10; i++) {
1117117577f7Sjsg 		usec_delay(1);
1118117577f7Sjsg 		ctrl = IXGBE_READ_REG(hw, IXGBE_CTRL);
111911efaf7fSmikeb 		if (!(ctrl & IXGBE_CTRL_RST_MASK))
1120117577f7Sjsg 			break;
1121117577f7Sjsg 	}
112211efaf7fSmikeb 
112311efaf7fSmikeb 	if (ctrl & IXGBE_CTRL_RST_MASK) {
1124117577f7Sjsg 		status = IXGBE_ERR_RESET_FAILED;
1125117577f7Sjsg 		DEBUGOUT("Reset polling failed to complete.\n");
1126117577f7Sjsg 	}
11279feba5bbSclaudio 
1128c7fa8c00Smikeb 	msec_delay(50);
1129c7fa8c00Smikeb 
11309feba5bbSclaudio 	/*
11319feba5bbSclaudio 	 * Double resets are required for recovery from certain error
11329e435848Smikeb 	 * conditions.  Between resets, it is necessary to stall to
11339e435848Smikeb 	 * allow time for any pending HW events to complete.
11349feba5bbSclaudio 	 */
11359feba5bbSclaudio 	if (hw->mac.flags & IXGBE_FLAGS_DOUBLE_RESET_REQUIRED) {
11369feba5bbSclaudio 		hw->mac.flags &= ~IXGBE_FLAGS_DOUBLE_RESET_REQUIRED;
11379feba5bbSclaudio 		goto mac_reset_top;
11389feba5bbSclaudio 	}
1139117577f7Sjsg 
1140117577f7Sjsg 	/*
1141117577f7Sjsg 	 * Store the original AUTOC/AUTOC2 values if they have not been
1142117577f7Sjsg 	 * stored off yet.  Otherwise restore the stored original
1143117577f7Sjsg 	 * values since the reset operation sets back to defaults.
1144117577f7Sjsg 	 */
1145276d64b7Smikeb 	autoc = IXGBE_READ_REG(hw, IXGBE_AUTOC);
1146117577f7Sjsg 	autoc2 = IXGBE_READ_REG(hw, IXGBE_AUTOC2);
114711efaf7fSmikeb 
114811efaf7fSmikeb 	/* Enable link if disabled in NVM */
114911efaf7fSmikeb 	if (autoc2 & IXGBE_AUTOC2_LINK_DISABLE_MASK) {
115011efaf7fSmikeb 		autoc2 &= ~IXGBE_AUTOC2_LINK_DISABLE_MASK;
115111efaf7fSmikeb 		IXGBE_WRITE_REG(hw, IXGBE_AUTOC2, autoc2);
115211efaf7fSmikeb 		IXGBE_WRITE_FLUSH(hw);
115311efaf7fSmikeb 	}
115411efaf7fSmikeb 
1155117577f7Sjsg 	if (hw->mac.orig_link_settings_stored == FALSE) {
1156276d64b7Smikeb 		hw->mac.orig_autoc = autoc;
1157117577f7Sjsg 		hw->mac.orig_autoc2 = autoc2;
1158117577f7Sjsg 		hw->mac.orig_link_settings_stored = TRUE;
1159117577f7Sjsg 	} else {
116011efaf7fSmikeb 
116111efaf7fSmikeb 		/* If MNG FW is running on a multi-speed device that
116211efaf7fSmikeb 		 * doesn't autoneg with out driver support we need to
116311efaf7fSmikeb 		 * leave LMS in the state it was before we MAC reset.
116411efaf7fSmikeb 		 * Likewise if we support WoL we don't want change the
116511efaf7fSmikeb 		 * LMS state.
116611efaf7fSmikeb 		 */
1167*d7a8f955Sjmatthew 		if ((hw->phy.multispeed_fiber && ixgbe_mng_enabled(hw)) ||
1168*d7a8f955Sjmatthew 		    hw->wol_enabled)
116911efaf7fSmikeb 			hw->mac.orig_autoc =
117011efaf7fSmikeb 				(hw->mac.orig_autoc & ~IXGBE_AUTOC_LMS_MASK) |
117111efaf7fSmikeb 				curr_lms;
117211efaf7fSmikeb 
1173276d64b7Smikeb 		if (autoc != hw->mac.orig_autoc) {
1174276d64b7Smikeb 			status = hw->mac.ops.prot_autoc_write(hw,
1175276d64b7Smikeb 							hw->mac.orig_autoc,
1176276d64b7Smikeb 							FALSE);
1177276d64b7Smikeb 			if (status != IXGBE_SUCCESS)
117811efaf7fSmikeb 				goto reset_hw_out;
117911efaf7fSmikeb 		}
118011efaf7fSmikeb 
1181117577f7Sjsg 		if ((autoc2 & IXGBE_AUTOC2_UPPER_MASK) !=
1182117577f7Sjsg 		    (hw->mac.orig_autoc2 & IXGBE_AUTOC2_UPPER_MASK)) {
1183117577f7Sjsg 			autoc2 &= ~IXGBE_AUTOC2_UPPER_MASK;
1184117577f7Sjsg 			autoc2 |= (hw->mac.orig_autoc2 &
1185117577f7Sjsg 				   IXGBE_AUTOC2_UPPER_MASK);
1186117577f7Sjsg 			IXGBE_WRITE_REG(hw, IXGBE_AUTOC2, autoc2);
1187117577f7Sjsg 		}
1188117577f7Sjsg 	}
1189117577f7Sjsg 
1190117577f7Sjsg 	/* Store the permanent mac address */
1191117577f7Sjsg 	hw->mac.ops.get_mac_addr(hw, hw->mac.perm_addr);
1192117577f7Sjsg 
1193117577f7Sjsg 	/*
1194117577f7Sjsg 	 * Store MAC address from RAR0, clear receive address registers, and
1195117577f7Sjsg 	 * clear the multicast table.  Also reset num_rar_entries to 128,
1196117577f7Sjsg 	 * since we modify this value when programming the SAN MAC address.
1197117577f7Sjsg 	 */
1198117577f7Sjsg 	hw->mac.num_rar_entries = 128;
1199117577f7Sjsg 	hw->mac.ops.init_rx_addrs(hw);
1200117577f7Sjsg 
1201117577f7Sjsg reset_hw_out:
1202117577f7Sjsg 	return status;
1203117577f7Sjsg }
1204117577f7Sjsg 
1205117577f7Sjsg /**
1206117577f7Sjsg  *  ixgbe_read_analog_reg8_82599 - Reads 8 bit Omer analog register
1207117577f7Sjsg  *  @hw: pointer to hardware structure
1208117577f7Sjsg  *  @reg: analog register to read
1209117577f7Sjsg  *  @val: read value
1210117577f7Sjsg  *
1211117577f7Sjsg  *  Performs read operation to Omer analog register specified.
1212117577f7Sjsg  **/
ixgbe_read_analog_reg8_82599(struct ixgbe_hw * hw,uint32_t reg,uint8_t * val)121311efaf7fSmikeb int32_t ixgbe_read_analog_reg8_82599(struct ixgbe_hw *hw, uint32_t reg,
121411efaf7fSmikeb 				     uint8_t *val)
1215117577f7Sjsg {
1216117577f7Sjsg 	uint32_t  core_ctl;
1217117577f7Sjsg 
1218117577f7Sjsg 	DEBUGFUNC("ixgbe_read_analog_reg8_82599");
1219117577f7Sjsg 
1220117577f7Sjsg 	IXGBE_WRITE_REG(hw, IXGBE_CORECTL, IXGBE_CORECTL_WRITE_CMD |
1221117577f7Sjsg 			(reg << 8));
1222117577f7Sjsg 	IXGBE_WRITE_FLUSH(hw);
1223117577f7Sjsg 	usec_delay(10);
1224117577f7Sjsg 	core_ctl = IXGBE_READ_REG(hw, IXGBE_CORECTL);
1225117577f7Sjsg 	*val = (uint8_t)core_ctl;
1226117577f7Sjsg 
1227117577f7Sjsg 	return IXGBE_SUCCESS;
1228117577f7Sjsg }
1229117577f7Sjsg 
1230117577f7Sjsg /**
1231117577f7Sjsg  *  ixgbe_write_analog_reg8_82599 - Writes 8 bit Omer analog register
1232117577f7Sjsg  *  @hw: pointer to hardware structure
1233117577f7Sjsg  *  @reg: atlas register to write
1234117577f7Sjsg  *  @val: value to write
1235117577f7Sjsg  *
1236117577f7Sjsg  *  Performs write operation to Omer analog register specified.
1237117577f7Sjsg  **/
ixgbe_write_analog_reg8_82599(struct ixgbe_hw * hw,uint32_t reg,uint8_t val)123811efaf7fSmikeb int32_t ixgbe_write_analog_reg8_82599(struct ixgbe_hw *hw, uint32_t reg,
123911efaf7fSmikeb 				      uint8_t val)
1240117577f7Sjsg {
1241117577f7Sjsg 	uint32_t  core_ctl;
1242117577f7Sjsg 
1243117577f7Sjsg 	DEBUGFUNC("ixgbe_write_analog_reg8_82599");
1244117577f7Sjsg 
1245117577f7Sjsg 	core_ctl = (reg << 8) | val;
1246117577f7Sjsg 	IXGBE_WRITE_REG(hw, IXGBE_CORECTL, core_ctl);
1247117577f7Sjsg 	IXGBE_WRITE_FLUSH(hw);
1248117577f7Sjsg 	usec_delay(10);
1249117577f7Sjsg 
1250117577f7Sjsg 	return IXGBE_SUCCESS;
1251117577f7Sjsg }
1252117577f7Sjsg 
1253117577f7Sjsg /**
1254c7fa8c00Smikeb  *  ixgbe_start_hw_82599 - Prepare hardware for Tx/Rx
1255117577f7Sjsg  *  @hw: pointer to hardware structure
1256117577f7Sjsg  *
12579feba5bbSclaudio  *  Starts the hardware using the generic start_hw function
12589feba5bbSclaudio  *  and the generation start_hw function.
12599feba5bbSclaudio  *  Then performs revision-specific operations, if any.
1260117577f7Sjsg  **/
ixgbe_start_hw_82599(struct ixgbe_hw * hw)1261c7fa8c00Smikeb int32_t ixgbe_start_hw_82599(struct ixgbe_hw *hw)
1262117577f7Sjsg {
1263117577f7Sjsg 	int32_t ret_val = IXGBE_SUCCESS;
1264117577f7Sjsg 
126511efaf7fSmikeb 	DEBUGFUNC("ixgbe_start_hw_82599");
1266117577f7Sjsg 
1267117577f7Sjsg 	ret_val = ixgbe_start_hw_generic(hw);
12689feba5bbSclaudio 	if (ret_val != IXGBE_SUCCESS)
12699feba5bbSclaudio 		goto out;
1270117577f7Sjsg 
12719feba5bbSclaudio 	ret_val = ixgbe_start_hw_gen2(hw);
12729feba5bbSclaudio 	if (ret_val != IXGBE_SUCCESS)
12739feba5bbSclaudio 		goto out;
1274117577f7Sjsg 
1275117577f7Sjsg 	/* We need to run link autotry after the driver loads */
1276117577f7Sjsg 	hw->mac.autotry_restart = TRUE;
1277117577f7Sjsg 
1278117577f7Sjsg 	if (ret_val == IXGBE_SUCCESS)
1279117577f7Sjsg 		ret_val = ixgbe_verify_fw_version_82599(hw);
12809feba5bbSclaudio out:
1281117577f7Sjsg 	return ret_val;
1282117577f7Sjsg }
1283117577f7Sjsg 
1284117577f7Sjsg /**
1285117577f7Sjsg  *  ixgbe_identify_phy_82599 - Get physical layer module
1286117577f7Sjsg  *  @hw: pointer to hardware structure
1287117577f7Sjsg  *
1288117577f7Sjsg  *  Determines the physical layer module found on the current adapter.
1289117577f7Sjsg  *  If PHY already detected, maintains current PHY type in hw struct,
1290117577f7Sjsg  *  otherwise executes the PHY detection routine.
1291117577f7Sjsg  **/
ixgbe_identify_phy_82599(struct ixgbe_hw * hw)1292117577f7Sjsg int32_t ixgbe_identify_phy_82599(struct ixgbe_hw *hw)
1293117577f7Sjsg {
12942f63561bSmikeb 	int32_t status;
1295117577f7Sjsg 
1296117577f7Sjsg 	DEBUGFUNC("ixgbe_identify_phy_82599");
1297117577f7Sjsg 
1298117577f7Sjsg 	/* Detect PHY if not unknown - returns success if already detected. */
1299117577f7Sjsg 	status = ixgbe_identify_phy_generic(hw);
13009feba5bbSclaudio 	if (status != IXGBE_SUCCESS) {
13019feba5bbSclaudio 		/* 82599 10GBASE-T requires an external PHY */
13029feba5bbSclaudio 		if (hw->mac.ops.get_media_type(hw) == ixgbe_media_type_copper)
13032f63561bSmikeb 			return status;
13049feba5bbSclaudio 		else
130511efaf7fSmikeb 			status = ixgbe_identify_module_generic(hw);
13069feba5bbSclaudio 	}
13079feba5bbSclaudio 
1308117577f7Sjsg 	/* Set PHY type none if no PHY detected */
1309117577f7Sjsg 	if (hw->phy.type == ixgbe_phy_unknown) {
1310117577f7Sjsg 		hw->phy.type = ixgbe_phy_none;
13112f63561bSmikeb 		return IXGBE_SUCCESS;
1312117577f7Sjsg 	}
1313117577f7Sjsg 
1314117577f7Sjsg 	/* Return error if SFP module has been detected but is not supported */
1315117577f7Sjsg 	if (hw->phy.type == ixgbe_phy_sfp_unsupported)
13162f63561bSmikeb 		return IXGBE_ERR_SFP_NOT_SUPPORTED;
1317117577f7Sjsg 
1318117577f7Sjsg 	return status;
1319117577f7Sjsg }
1320117577f7Sjsg 
1321117577f7Sjsg /**
1322117577f7Sjsg  *  ixgbe_get_supported_physical_layer_82599 - Returns physical layer type
1323117577f7Sjsg  *  @hw: pointer to hardware structure
1324117577f7Sjsg  *
1325117577f7Sjsg  *  Determines physical layer capabilities of the current configuration.
1326117577f7Sjsg  **/
ixgbe_get_supported_physical_layer_82599(struct ixgbe_hw * hw)1327*d7a8f955Sjmatthew uint64_t ixgbe_get_supported_physical_layer_82599(struct ixgbe_hw *hw)
1328117577f7Sjsg {
1329*d7a8f955Sjmatthew 	uint64_t physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN;
1330117577f7Sjsg 	uint32_t autoc = IXGBE_READ_REG(hw, IXGBE_AUTOC);
1331117577f7Sjsg 	uint32_t autoc2 = IXGBE_READ_REG(hw, IXGBE_AUTOC2);
1332117577f7Sjsg 	uint32_t pma_pmd_10g_serial = autoc2 & IXGBE_AUTOC2_10G_SERIAL_PMA_PMD_MASK;
1333117577f7Sjsg 	uint32_t pma_pmd_10g_parallel = autoc & IXGBE_AUTOC_10G_PMA_PMD_MASK;
1334117577f7Sjsg 	uint32_t pma_pmd_1g = autoc & IXGBE_AUTOC_1G_PMA_PMD_MASK;
1335117577f7Sjsg 	uint16_t ext_ability = 0;
1336117577f7Sjsg 
1337117577f7Sjsg 	DEBUGFUNC("ixgbe_get_support_physical_layer_82599");
1338117577f7Sjsg 
1339117577f7Sjsg 	hw->phy.ops.identify(hw);
1340117577f7Sjsg 
13419feba5bbSclaudio 	switch (hw->phy.type) {
13429feba5bbSclaudio 	case ixgbe_phy_tn:
13439feba5bbSclaudio 	case ixgbe_phy_cu_unknown:
1344117577f7Sjsg 		hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_EXT_ABILITY,
1345117577f7Sjsg 		IXGBE_MDIO_PMA_PMD_DEV_TYPE, &ext_ability);
1346117577f7Sjsg 		if (ext_ability & IXGBE_MDIO_PHY_10GBASET_ABILITY)
1347117577f7Sjsg 			physical_layer |= IXGBE_PHYSICAL_LAYER_10GBASE_T;
1348117577f7Sjsg 		if (ext_ability & IXGBE_MDIO_PHY_1000BASET_ABILITY)
1349117577f7Sjsg 			physical_layer |= IXGBE_PHYSICAL_LAYER_1000BASE_T;
1350117577f7Sjsg 		if (ext_ability & IXGBE_MDIO_PHY_100BASETX_ABILITY)
1351117577f7Sjsg 			physical_layer |= IXGBE_PHYSICAL_LAYER_100BASE_TX;
1352117577f7Sjsg 		goto out;
13539feba5bbSclaudio 	default:
13549feba5bbSclaudio 		break;
1355117577f7Sjsg 	}
1356117577f7Sjsg 
1357117577f7Sjsg 	switch (autoc & IXGBE_AUTOC_LMS_MASK) {
1358117577f7Sjsg 	case IXGBE_AUTOC_LMS_1G_AN:
1359117577f7Sjsg 	case IXGBE_AUTOC_LMS_1G_LINK_NO_AN:
1360117577f7Sjsg 		if (pma_pmd_1g == IXGBE_AUTOC_1G_KX_BX) {
1361117577f7Sjsg 			physical_layer = IXGBE_PHYSICAL_LAYER_1000BASE_KX |
1362117577f7Sjsg 			    IXGBE_PHYSICAL_LAYER_1000BASE_BX;
1363117577f7Sjsg 			goto out;
1364117577f7Sjsg 		} else
1365117577f7Sjsg 			/* SFI mode so read SFP module */
1366117577f7Sjsg 			goto sfp_check;
1367117577f7Sjsg 		break;
1368117577f7Sjsg 	case IXGBE_AUTOC_LMS_10G_LINK_NO_AN:
1369117577f7Sjsg 		if (pma_pmd_10g_parallel == IXGBE_AUTOC_10G_CX4)
1370117577f7Sjsg 			physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_CX4;
1371117577f7Sjsg 		else if (pma_pmd_10g_parallel == IXGBE_AUTOC_10G_KX4)
1372117577f7Sjsg 			physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_KX4;
1373117577f7Sjsg 		else if (pma_pmd_10g_parallel == IXGBE_AUTOC_10G_XAUI)
1374117577f7Sjsg 			physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_XAUI;
1375117577f7Sjsg 		goto out;
1376117577f7Sjsg 		break;
1377117577f7Sjsg 	case IXGBE_AUTOC_LMS_10G_SERIAL:
1378117577f7Sjsg 		if (pma_pmd_10g_serial == IXGBE_AUTOC2_10G_KR) {
1379117577f7Sjsg 			physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_KR;
1380117577f7Sjsg 			goto out;
1381117577f7Sjsg 		} else if (pma_pmd_10g_serial == IXGBE_AUTOC2_10G_SFI)
1382117577f7Sjsg 			goto sfp_check;
1383117577f7Sjsg 		break;
1384117577f7Sjsg 	case IXGBE_AUTOC_LMS_KX4_KX_KR:
1385117577f7Sjsg 	case IXGBE_AUTOC_LMS_KX4_KX_KR_1G_AN:
1386117577f7Sjsg 		if (autoc & IXGBE_AUTOC_KX_SUPP)
1387117577f7Sjsg 			physical_layer |= IXGBE_PHYSICAL_LAYER_1000BASE_KX;
1388117577f7Sjsg 		if (autoc & IXGBE_AUTOC_KX4_SUPP)
1389117577f7Sjsg 			physical_layer |= IXGBE_PHYSICAL_LAYER_10GBASE_KX4;
1390117577f7Sjsg 		if (autoc & IXGBE_AUTOC_KR_SUPP)
1391117577f7Sjsg 			physical_layer |= IXGBE_PHYSICAL_LAYER_10GBASE_KR;
1392117577f7Sjsg 		goto out;
1393117577f7Sjsg 		break;
1394117577f7Sjsg 	default:
1395117577f7Sjsg 		goto out;
1396117577f7Sjsg 		break;
1397117577f7Sjsg 	}
1398117577f7Sjsg 
1399117577f7Sjsg sfp_check:
1400117577f7Sjsg 	/* SFP check must be done last since DA modules are sometimes used to
1401117577f7Sjsg 	 * test KR mode -  we need to id KR mode correctly before SFP module.
1402117577f7Sjsg 	 * Call identify_sfp because the pluggable module may have changed */
14032f63561bSmikeb 	physical_layer = ixgbe_get_supported_phy_sfp_layer_generic(hw);
1404117577f7Sjsg out:
1405117577f7Sjsg 	return physical_layer;
1406117577f7Sjsg }
1407117577f7Sjsg 
1408117577f7Sjsg /**
1409117577f7Sjsg  *  ixgbe_enable_rx_dma_82599 - Enable the Rx DMA unit on 82599
1410117577f7Sjsg  *  @hw: pointer to hardware structure
1411117577f7Sjsg  *  @regval: register value to write to RXCTRL
1412117577f7Sjsg  *
1413117577f7Sjsg  *  Enables the Rx DMA unit for 82599
1414117577f7Sjsg  **/
ixgbe_enable_rx_dma_82599(struct ixgbe_hw * hw,uint32_t regval)1415117577f7Sjsg int32_t ixgbe_enable_rx_dma_82599(struct ixgbe_hw *hw, uint32_t regval)
1416117577f7Sjsg {
1417117577f7Sjsg 
1418117577f7Sjsg 	DEBUGFUNC("ixgbe_enable_rx_dma_82599");
1419117577f7Sjsg 
1420117577f7Sjsg 	/*
1421117577f7Sjsg 	 * Workaround for 82599 silicon errata when enabling the Rx datapath.
1422117577f7Sjsg 	 * If traffic is incoming before we enable the Rx unit, it could hang
1423117577f7Sjsg 	 * the Rx DMA unit.  Therefore, make sure the security engine is
1424117577f7Sjsg 	 * completely disabled prior to enabling the Rx unit.
1425117577f7Sjsg 	 */
1426117577f7Sjsg 
142711efaf7fSmikeb 	hw->mac.ops.disable_sec_rx_path(hw);
1428117577f7Sjsg 
14292f63561bSmikeb 	if (regval & IXGBE_RXCTRL_RXEN)
14302f63561bSmikeb 		ixgbe_enable_rx(hw);
14312f63561bSmikeb 	else
14322f63561bSmikeb 		ixgbe_disable_rx(hw);
143311efaf7fSmikeb 
143411efaf7fSmikeb 	hw->mac.ops.enable_sec_rx_path(hw);
1435117577f7Sjsg 
1436117577f7Sjsg 	return IXGBE_SUCCESS;
1437117577f7Sjsg }
1438117577f7Sjsg 
1439117577f7Sjsg /**
14409e435848Smikeb  *  ixgbe_verify_fw_version_82599 - verify FW version for 82599
1441117577f7Sjsg  *  @hw: pointer to hardware structure
1442117577f7Sjsg  *
1443117577f7Sjsg  *  Verifies that installed the firmware version is 0.6 or higher
1444117577f7Sjsg  *  for SFI devices. All 82599 SFI devices should have version 0.6 or higher.
1445117577f7Sjsg  *
1446117577f7Sjsg  *  Returns IXGBE_ERR_EEPROM_VERSION if the FW is not present or
1447117577f7Sjsg  *  if the FW version is not supported.
1448117577f7Sjsg  **/
ixgbe_verify_fw_version_82599(struct ixgbe_hw * hw)1449117577f7Sjsg int32_t ixgbe_verify_fw_version_82599(struct ixgbe_hw *hw)
1450117577f7Sjsg {
1451117577f7Sjsg 	int32_t status = IXGBE_ERR_EEPROM_VERSION;
1452117577f7Sjsg 	uint16_t fw_offset, fw_ptp_cfg_offset;
145311efaf7fSmikeb 	uint16_t fw_version;
1454117577f7Sjsg 
1455117577f7Sjsg 	DEBUGFUNC("ixgbe_verify_fw_version_82599");
1456117577f7Sjsg 
1457117577f7Sjsg 	/* firmware check is only necessary for SFI devices */
1458117577f7Sjsg 	if (hw->phy.media_type != ixgbe_media_type_fiber) {
1459117577f7Sjsg 		status = IXGBE_SUCCESS;
1460117577f7Sjsg 		goto fw_version_out;
1461117577f7Sjsg 	}
1462117577f7Sjsg 
1463117577f7Sjsg 	/* get the offset to the Firmware Module block */
146411efaf7fSmikeb 	if (hw->eeprom.ops.read(hw, IXGBE_FW_PTR, &fw_offset)) {
146511efaf7fSmikeb 		ERROR_REPORT2(IXGBE_ERROR_INVALID_STATE,
146611efaf7fSmikeb 			      "eeprom read at offset %d failed", IXGBE_FW_PTR);
146711efaf7fSmikeb 		return IXGBE_ERR_EEPROM_VERSION;
146811efaf7fSmikeb 	}
1469117577f7Sjsg 
1470117577f7Sjsg 	if ((fw_offset == 0) || (fw_offset == 0xFFFF))
1471117577f7Sjsg 		goto fw_version_out;
1472117577f7Sjsg 
1473117577f7Sjsg 	/* get the offset to the Pass Through Patch Configuration block */
147411efaf7fSmikeb 	if (hw->eeprom.ops.read(hw, (fw_offset +
1475117577f7Sjsg 				 IXGBE_FW_PASSTHROUGH_PATCH_CONFIG_PTR),
147611efaf7fSmikeb 				 &fw_ptp_cfg_offset)) {
147711efaf7fSmikeb 		ERROR_REPORT2(IXGBE_ERROR_INVALID_STATE,
147811efaf7fSmikeb 			      "eeprom read at offset %d failed",
147911efaf7fSmikeb 			      fw_offset +
148011efaf7fSmikeb 			      IXGBE_FW_PASSTHROUGH_PATCH_CONFIG_PTR);
148111efaf7fSmikeb 		return IXGBE_ERR_EEPROM_VERSION;
148211efaf7fSmikeb 	}
1483117577f7Sjsg 
1484117577f7Sjsg 	if ((fw_ptp_cfg_offset == 0) || (fw_ptp_cfg_offset == 0xFFFF))
1485117577f7Sjsg 		goto fw_version_out;
1486117577f7Sjsg 
1487117577f7Sjsg 	/* get the firmware version */
148811efaf7fSmikeb 	if (hw->eeprom.ops.read(hw, (fw_ptp_cfg_offset +
148911efaf7fSmikeb 			    IXGBE_FW_PATCH_VERSION_4), &fw_version)) {
149011efaf7fSmikeb 		ERROR_REPORT2(IXGBE_ERROR_INVALID_STATE,
149111efaf7fSmikeb 			      "eeprom read at offset %d failed",
149211efaf7fSmikeb 			      fw_ptp_cfg_offset + IXGBE_FW_PATCH_VERSION_4);
149311efaf7fSmikeb 		return IXGBE_ERR_EEPROM_VERSION;
149411efaf7fSmikeb 	}
1495117577f7Sjsg 
1496117577f7Sjsg 	if (fw_version > 0x5)
1497117577f7Sjsg 		status = IXGBE_SUCCESS;
1498117577f7Sjsg 
1499117577f7Sjsg fw_version_out:
1500117577f7Sjsg 	return status;
1501117577f7Sjsg }
15029feba5bbSclaudio 
15039feba5bbSclaudio /**
15049feba5bbSclaudio  *  ixgbe_verify_lesm_fw_enabled_82599 - Checks LESM FW module state.
15059feba5bbSclaudio  *  @hw: pointer to hardware structure
15069feba5bbSclaudio  *
15079feba5bbSclaudio  *  Returns TRUE if the LESM FW module is present and enabled. Otherwise
15089feba5bbSclaudio  *  returns FALSE. Smart Speed must be disabled if LESM FW module is enabled.
15099feba5bbSclaudio  **/
ixgbe_verify_lesm_fw_enabled_82599(struct ixgbe_hw * hw)151011efaf7fSmikeb bool ixgbe_verify_lesm_fw_enabled_82599(struct ixgbe_hw *hw)
15119feba5bbSclaudio {
151211efaf7fSmikeb 	bool lesm_enabled = FALSE;
15139feba5bbSclaudio 	uint16_t fw_offset, fw_lesm_param_offset, fw_lesm_state;
15149feba5bbSclaudio 	int32_t status;
15159feba5bbSclaudio 
15169feba5bbSclaudio 	DEBUGFUNC("ixgbe_verify_lesm_fw_enabled_82599");
15179feba5bbSclaudio 
15189feba5bbSclaudio 	/* get the offset to the Firmware Module block */
15199feba5bbSclaudio 	status = hw->eeprom.ops.read(hw, IXGBE_FW_PTR, &fw_offset);
15209feba5bbSclaudio 
15219feba5bbSclaudio 	if ((status != IXGBE_SUCCESS) ||
15229feba5bbSclaudio 	    (fw_offset == 0) || (fw_offset == 0xFFFF))
15239feba5bbSclaudio 		goto out;
15249feba5bbSclaudio 
15259feba5bbSclaudio 	/* get the offset to the LESM Parameters block */
15269feba5bbSclaudio 	status = hw->eeprom.ops.read(hw, (fw_offset +
15279feba5bbSclaudio 				     IXGBE_FW_LESM_PARAMETERS_PTR),
15289feba5bbSclaudio 				     &fw_lesm_param_offset);
15299feba5bbSclaudio 
15309feba5bbSclaudio 	if ((status != IXGBE_SUCCESS) ||
15319feba5bbSclaudio 	    (fw_lesm_param_offset == 0) || (fw_lesm_param_offset == 0xFFFF))
15329feba5bbSclaudio 		goto out;
15339feba5bbSclaudio 
15349e435848Smikeb 	/* get the LESM state word */
15359feba5bbSclaudio 	status = hw->eeprom.ops.read(hw, (fw_lesm_param_offset +
15369feba5bbSclaudio 				     IXGBE_FW_LESM_STATE_1),
15379feba5bbSclaudio 				     &fw_lesm_state);
15389feba5bbSclaudio 
15399feba5bbSclaudio 	if ((status == IXGBE_SUCCESS) &&
15409feba5bbSclaudio 	    (fw_lesm_state & IXGBE_FW_LESM_STATE_ENABLED))
15419feba5bbSclaudio 		lesm_enabled = TRUE;
15429feba5bbSclaudio 
15439feba5bbSclaudio out:
15449feba5bbSclaudio 	return lesm_enabled;
15459feba5bbSclaudio }
154611efaf7fSmikeb 
154711efaf7fSmikeb /**
154811efaf7fSmikeb  *  ixgbe_read_eeprom_82599 - Read EEPROM word using
154911efaf7fSmikeb  *  fastest available method
155011efaf7fSmikeb  *
155111efaf7fSmikeb  *  @hw: pointer to hardware structure
155211efaf7fSmikeb  *  @offset: offset of  word in the EEPROM to read
155311efaf7fSmikeb  *  @data: word read from the EEPROM
155411efaf7fSmikeb  *
155511efaf7fSmikeb  *  Reads a 16 bit word from the EEPROM
155611efaf7fSmikeb  **/
ixgbe_read_eeprom_82599(struct ixgbe_hw * hw,uint16_t offset,uint16_t * data)155711efaf7fSmikeb int32_t ixgbe_read_eeprom_82599(struct ixgbe_hw *hw,
155811efaf7fSmikeb 				uint16_t offset, uint16_t *data)
155911efaf7fSmikeb {
156011efaf7fSmikeb 	struct ixgbe_eeprom_info *eeprom = &hw->eeprom;
156111efaf7fSmikeb 	int32_t ret_val = IXGBE_ERR_CONFIG;
156211efaf7fSmikeb 
156311efaf7fSmikeb 	DEBUGFUNC("ixgbe_read_eeprom_82599");
156411efaf7fSmikeb 
156511efaf7fSmikeb 	/*
156611efaf7fSmikeb 	 * If EEPROM is detected and can be addressed using 14 bits,
156711efaf7fSmikeb 	 * use EERD otherwise use bit bang
156811efaf7fSmikeb 	 */
156911efaf7fSmikeb 	if ((eeprom->type == ixgbe_eeprom_spi) &&
157011efaf7fSmikeb 	    (offset <= IXGBE_EERD_MAX_ADDR))
157111efaf7fSmikeb 		ret_val = ixgbe_read_eerd_generic(hw, offset, data);
157211efaf7fSmikeb 	else
157311efaf7fSmikeb 		ret_val = ixgbe_read_eeprom_bit_bang_generic(hw, offset, data);
157411efaf7fSmikeb 
157511efaf7fSmikeb 	return ret_val;
157611efaf7fSmikeb }
157711efaf7fSmikeb 
157811efaf7fSmikeb /**
157911efaf7fSmikeb  * ixgbe_reset_pipeline_82599 - perform pipeline reset
158011efaf7fSmikeb  *
158111efaf7fSmikeb  *  @hw: pointer to hardware structure
158211efaf7fSmikeb  *
158311efaf7fSmikeb  * Reset pipeline by asserting Restart_AN together with LMS change to ensure
15849e435848Smikeb  * full pipeline reset.  This function assumes the SW/FW lock is held.
158511efaf7fSmikeb  **/
ixgbe_reset_pipeline_82599(struct ixgbe_hw * hw)158611efaf7fSmikeb int32_t ixgbe_reset_pipeline_82599(struct ixgbe_hw *hw)
158711efaf7fSmikeb {
158811efaf7fSmikeb 	int32_t ret_val;
158911efaf7fSmikeb 	uint32_t anlp1_reg = 0;
159011efaf7fSmikeb 	uint32_t i, autoc_reg, autoc2_reg;
159111efaf7fSmikeb 
159211efaf7fSmikeb 	/* Enable link if disabled in NVM */
159311efaf7fSmikeb 	autoc2_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC2);
159411efaf7fSmikeb 	if (autoc2_reg & IXGBE_AUTOC2_LINK_DISABLE_MASK) {
159511efaf7fSmikeb 		autoc2_reg &= ~IXGBE_AUTOC2_LINK_DISABLE_MASK;
159611efaf7fSmikeb 		IXGBE_WRITE_REG(hw, IXGBE_AUTOC2, autoc2_reg);
159711efaf7fSmikeb 		IXGBE_WRITE_FLUSH(hw);
159811efaf7fSmikeb 	}
159911efaf7fSmikeb 
1600276d64b7Smikeb 	autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC);
160111efaf7fSmikeb 	autoc_reg |= IXGBE_AUTOC_AN_RESTART;
160211efaf7fSmikeb 	/* Write AUTOC register with toggled LMS[2] bit and Restart_AN */
1603276d64b7Smikeb 	IXGBE_WRITE_REG(hw, IXGBE_AUTOC,
1604276d64b7Smikeb 			autoc_reg ^ (0x4 << IXGBE_AUTOC_LMS_SHIFT));
160511efaf7fSmikeb 	/* Wait for AN to leave state 0 */
160611efaf7fSmikeb 	for (i = 0; i < 10; i++) {
160711efaf7fSmikeb 		msec_delay(4);
160811efaf7fSmikeb 		anlp1_reg = IXGBE_READ_REG(hw, IXGBE_ANLP1);
160911efaf7fSmikeb 		if (anlp1_reg & IXGBE_ANLP1_AN_STATE_MASK)
161011efaf7fSmikeb 			break;
161111efaf7fSmikeb 	}
161211efaf7fSmikeb 
161311efaf7fSmikeb 	if (!(anlp1_reg & IXGBE_ANLP1_AN_STATE_MASK)) {
161411efaf7fSmikeb 		DEBUGOUT("auto negotiation not completed\n");
161511efaf7fSmikeb 		ret_val = IXGBE_ERR_RESET_FAILED;
161611efaf7fSmikeb 		goto reset_pipeline_out;
161711efaf7fSmikeb 	}
161811efaf7fSmikeb 
161911efaf7fSmikeb 	ret_val = IXGBE_SUCCESS;
162011efaf7fSmikeb 
162111efaf7fSmikeb reset_pipeline_out:
162211efaf7fSmikeb 	/* Write AUTOC register with original LMS field and Restart_AN */
162311efaf7fSmikeb 	IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc_reg);
162411efaf7fSmikeb 	IXGBE_WRITE_FLUSH(hw);
162511efaf7fSmikeb 
162611efaf7fSmikeb 	return ret_val;
162711efaf7fSmikeb }
16282f63561bSmikeb 
16292f63561bSmikeb /**
16302f63561bSmikeb  *  ixgbe_read_i2c_byte_82599 - Reads 8 bit word over I2C
16312f63561bSmikeb  *  @hw: pointer to hardware structure
16322f63561bSmikeb  *  @byte_offset: byte offset to read
1633*d7a8f955Sjmatthew  *  @dev_addr: address to read from
16342f63561bSmikeb  *  @data: value read
16352f63561bSmikeb  *
16362f63561bSmikeb  *  Performs byte read operation to SFP module's EEPROM over I2C interface at
16372f63561bSmikeb  *  a specified device address.
16382f63561bSmikeb  **/
ixgbe_read_i2c_byte_82599(struct ixgbe_hw * hw,uint8_t byte_offset,uint8_t dev_addr,uint8_t * data)16392f63561bSmikeb int32_t ixgbe_read_i2c_byte_82599(struct ixgbe_hw *hw, uint8_t byte_offset,
16402f63561bSmikeb 				  uint8_t dev_addr, uint8_t *data)
16412f63561bSmikeb {
16422f63561bSmikeb 	uint32_t esdp;
16432f63561bSmikeb 	int32_t status;
16442f63561bSmikeb 	int32_t timeout = 200;
16452f63561bSmikeb 
16462f63561bSmikeb 	DEBUGFUNC("ixgbe_read_i2c_byte_82599");
16472f63561bSmikeb 
16482f63561bSmikeb 	if (hw->phy.qsfp_shared_i2c_bus == TRUE) {
16492f63561bSmikeb 		/* Acquire I2C bus ownership. */
16502f63561bSmikeb 		esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
16512f63561bSmikeb 		esdp |= IXGBE_ESDP_SDP0;
16522f63561bSmikeb 		IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
16532f63561bSmikeb 		IXGBE_WRITE_FLUSH(hw);
16542f63561bSmikeb 
16552f63561bSmikeb 		while (timeout) {
16562f63561bSmikeb 			esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
16572f63561bSmikeb 			if (esdp & IXGBE_ESDP_SDP1)
16582f63561bSmikeb 				break;
16592f63561bSmikeb 
16602f63561bSmikeb 			msec_delay(5);
16612f63561bSmikeb 			timeout--;
16622f63561bSmikeb 		}
16632f63561bSmikeb 
16642f63561bSmikeb 		if (!timeout) {
16652f63561bSmikeb 			DEBUGOUT("Driver can't access resource,"
16662f63561bSmikeb 				 " acquiring I2C bus timeout.\n");
16672f63561bSmikeb 			status = IXGBE_ERR_I2C;
16682f63561bSmikeb 			goto release_i2c_access;
16692f63561bSmikeb 		}
16702f63561bSmikeb 	}
16712f63561bSmikeb 
16722f63561bSmikeb 	status = ixgbe_read_i2c_byte_generic(hw, byte_offset, dev_addr, data);
16732f63561bSmikeb 
16742f63561bSmikeb release_i2c_access:
16752f63561bSmikeb 
16762f63561bSmikeb 	if (hw->phy.qsfp_shared_i2c_bus == TRUE) {
16772f63561bSmikeb 		/* Release I2C bus ownership. */
16782f63561bSmikeb 		esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
16792f63561bSmikeb 		esdp &= ~IXGBE_ESDP_SDP0;
16802f63561bSmikeb 		IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
16812f63561bSmikeb 		IXGBE_WRITE_FLUSH(hw);
16822f63561bSmikeb 	}
16832f63561bSmikeb 
16842f63561bSmikeb 	return status;
16852f63561bSmikeb }
16862f63561bSmikeb 
16872f63561bSmikeb /**
16882f63561bSmikeb  *  ixgbe_write_i2c_byte_82599 - Writes 8 bit word over I2C
16892f63561bSmikeb  *  @hw: pointer to hardware structure
16902f63561bSmikeb  *  @byte_offset: byte offset to write
1691*d7a8f955Sjmatthew  *  @dev_addr: address to read from
16922f63561bSmikeb  *  @data: value to write
16932f63561bSmikeb  *
16942f63561bSmikeb  *  Performs byte write operation to SFP module's EEPROM over I2C interface at
16952f63561bSmikeb  *  a specified device address.
16962f63561bSmikeb  **/
ixgbe_write_i2c_byte_82599(struct ixgbe_hw * hw,uint8_t byte_offset,uint8_t dev_addr,uint8_t data)16972f63561bSmikeb int32_t ixgbe_write_i2c_byte_82599(struct ixgbe_hw *hw, uint8_t byte_offset,
16982f63561bSmikeb 				   uint8_t dev_addr, uint8_t data)
16992f63561bSmikeb {
17002f63561bSmikeb 	uint32_t esdp;
17012f63561bSmikeb 	int32_t status;
17022f63561bSmikeb 	int32_t timeout = 200;
17032f63561bSmikeb 
17042f63561bSmikeb 	DEBUGFUNC("ixgbe_write_i2c_byte_82599");
17052f63561bSmikeb 
17062f63561bSmikeb 	if (hw->phy.qsfp_shared_i2c_bus == TRUE) {
17072f63561bSmikeb 		/* Acquire I2C bus ownership. */
17082f63561bSmikeb 		esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
17092f63561bSmikeb 		esdp |= IXGBE_ESDP_SDP0;
17102f63561bSmikeb 		IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
17112f63561bSmikeb 		IXGBE_WRITE_FLUSH(hw);
17122f63561bSmikeb 
17132f63561bSmikeb 		while (timeout) {
17142f63561bSmikeb 			esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
17152f63561bSmikeb 			if (esdp & IXGBE_ESDP_SDP1)
17162f63561bSmikeb 				break;
17172f63561bSmikeb 
17182f63561bSmikeb 			msec_delay(5);
17192f63561bSmikeb 			timeout--;
17202f63561bSmikeb 		}
17212f63561bSmikeb 
17222f63561bSmikeb 		if (!timeout) {
17232f63561bSmikeb 			DEBUGOUT("Driver can't access resource,"
17242f63561bSmikeb 				 " acquiring I2C bus timeout.\n");
17252f63561bSmikeb 			status = IXGBE_ERR_I2C;
17262f63561bSmikeb 			goto release_i2c_access;
17272f63561bSmikeb 		}
17282f63561bSmikeb 	}
17292f63561bSmikeb 
17302f63561bSmikeb 	status = ixgbe_write_i2c_byte_generic(hw, byte_offset, dev_addr, data);
17312f63561bSmikeb 
17322f63561bSmikeb release_i2c_access:
17332f63561bSmikeb 
17342f63561bSmikeb 	if (hw->phy.qsfp_shared_i2c_bus == TRUE) {
17352f63561bSmikeb 		/* Release I2C bus ownership. */
17362f63561bSmikeb 		esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
17372f63561bSmikeb 		esdp &= ~IXGBE_ESDP_SDP0;
17382f63561bSmikeb 		IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
17392f63561bSmikeb 		IXGBE_WRITE_FLUSH(hw);
17402f63561bSmikeb 	}
17412f63561bSmikeb 
17422f63561bSmikeb 	return status;
17432f63561bSmikeb }
1744